From a0e500db61f5fcf3ff6de6af1494f0cea9f6f8db Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 12 Mar 2009 16:53:44 +0000 Subject: [PATCH] Straw man for instantiation of expressions. Use it to instantiate the width of bitfields. I'll be burning this down and replacing it with a properly-dispatched implementation like the one used for types. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66796 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 7 ++- lib/Sema/SemaTemplateInstantiate.cpp | 67 +++++++++++++++++++++++- test/SemaTemplate/instantiate-expr-1.cpp | 12 +++++ 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 test/SemaTemplate/instantiate-expr-1.cpp diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 8f033197e4..0ea1be3d7e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1805,6 +1805,11 @@ public: QualType InstantiateType(QualType T, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation Loc, DeclarationName Entity); + + OwningExprResult InstantiateExpr(Expr *E, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs); + bool InstantiateBaseSpecifiers(ClassTemplateSpecializationDecl *ClassTemplateSpec, ClassTemplateDecl *ClassTemplate); @@ -2305,7 +2310,7 @@ struct BlockSemaInfo { template class ExprOwningPtr : public Action::ExprArg { public: - ExprOwningPtr(Sema *S, T *expr) : Action::ExprArg(*S, expr) {}; + ExprOwningPtr(Sema *S, T *expr) : Action::ExprArg(*S, expr) {} void reset(T* p) { Action::ExprArg::operator=(p); } T* get() const { return static_cast(Action::ExprArg::get()); } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 343c00b745..edf7aab926 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -550,6 +550,50 @@ QualType Sema::InstantiateType(QualType T, return Instantiator(T); } +//===----------------------------------------------------------------------===/ +// Template Instantiation for Expressions +//===----------------------------------------------------------------------===/ +Sema::OwningExprResult +Sema::InstantiateExpr(Expr *E, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + if (IntegerLiteral *IL = dyn_cast(E)) + return Owned(new (Context) IntegerLiteral(IL->getValue(), IL->getType(), + IL->getSourceRange().getBegin())); + else if (DeclRefExpr *DRE = dyn_cast(E)) { + Decl *D = DRE->getDecl(); + if (NonTypeTemplateParmDecl *NTTP = dyn_cast(D)) { + assert(NTTP->getDepth() == 0 && "No nested templates yet"); + QualType T = NTTP->getType(); + if (T->isDependentType()) { + // FIXME: We'll be doing this instantiation a lot. Should we + // cache this information in the TemplateArgument itself? + T = InstantiateType(T, TemplateArgs, NumTemplateArgs, + E->getSourceRange().getBegin(), + NTTP->getDeclName()); + if (T.isNull()) + return ExprError(); + } + return Owned(new (Context) IntegerLiteral( + *TemplateArgs[NTTP->getPosition()].getAsIntegral(), + T, E->getSourceRange().getBegin())); + } else + assert(false && "Yes, this is lame"); + } else if (ParenExpr *PE = dyn_cast(E)) { + OwningExprResult SubExpr + = InstantiateExpr(PE->getSubExpr(), TemplateArgs, + NumTemplateArgs); + if (SubExpr.isInvalid()) + return ExprError(); + + return Owned(new (Context) ParenExpr(E->getSourceRange().getBegin(), + E->getSourceRange().getEnd(), + (Expr *)SubExpr.release())); + } else + assert(false && "Yes, this is lame"); + + return ExprError(); +} + /// \brief Instantiate the base class specifiers of the given class /// template specialization. /// @@ -694,6 +738,7 @@ Sema::InstantiateClassTemplateSpecialization( else if (FieldDecl *Field = dyn_cast(*Member)) { // FIXME: Simplified instantiation of fields needs to be made // "real". + bool InvalidDecl = false; QualType T = Field->getType(); if (T->isDependentType()) { T = InstantiateType(T, ClassTemplateSpec->getTemplateArgs(), @@ -710,20 +755,40 @@ Sema::InstantiateClassTemplateSpecialization( Diag(Field->getLocation(), diag::err_field_instantiates_to_function) << T; T = QualType(); + InvalidDecl = true; } } + Expr *BitWidth = Field->getBitWidth(); + if (InvalidDecl) + BitWidth = 0; + if (BitWidth && + (BitWidth->isTypeDependent() || BitWidth->isValueDependent())) { + OwningExprResult InstantiatedBitWidth + = InstantiateExpr(BitWidth, + ClassTemplateSpec->getTemplateArgs(), + ClassTemplateSpec->getNumTemplateArgs()); + if (InstantiatedBitWidth.isInvalid()) { + Invalid = InvalidDecl = true; + BitWidth = 0; + } else + BitWidth = (Expr *)InstantiatedBitWidth.release(); + } + FieldDecl *New = CheckFieldDecl(Field->getDeclName(), T, ClassTemplateSpec, Field->getLocation(), Field->isMutable(), - Field->getBitWidth(), + BitWidth, Field->getAccess(), 0); if (New) { ClassTemplateSpec->addDecl(New); Fields.push_back(New); + if (InvalidDecl) + New->setInvalidDecl(); + if (New->isInvalidDecl()) Invalid = true; } diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp new file mode 100644 index 0000000000..060c1b510c --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-1.cpp @@ -0,0 +1,12 @@ +// RUN: clang -fsyntax-only -verify %s + +template +struct Bitfields { + int simple : I; // expected-error{{bit-field 'simple' has zero width}} + int parens : (J); +}; + +void test_Bitfields(Bitfields<0, 5> *b) { + (void)sizeof(Bitfields<10, 5>); + (void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'struct Bitfields<0, 1>' requested here}} +} -- 2.40.0