From: Richard Smith Date: Wed, 20 Jul 2011 00:12:52 +0000 (+0000) Subject: Replace r134583's fix for PR10290 with one which also works for non-value-dependent... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ff6f8f038f32d85c32fd984673cea51ef737b22;p=clang Replace r134583's fix for PR10290 with one which also works for non-value-dependent cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135543 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 263c1bd49a..cc55e55ca6 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4894,6 +4894,11 @@ public: void InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, const MultiLevelTemplateArgumentList &TemplateArgs); + bool InstantiateInitializer(Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation &LParenLoc, + ASTOwningVector &NewArgs, + SourceLocation &RParenLoc); NamedDecl *FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d793daf9d8..9ad9a2f0f0 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1234,8 +1234,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, } /// ActOnCXXInClassMemberInitializer - This is invoked after parsing an -/// in-class initializer for a non-static C++ class member. Such parsing -/// is deferred until the class is complete. +/// in-class initializer for a non-static C++ class member, and after +/// instantiating an in-class initializer in a class template. Such actions +/// are deferred until the class is complete. void Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc, Expr *InitExpr) { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 1988f14458..8d52951701 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1806,34 +1806,16 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, FieldDecl *OldField = FieldsWithMemberInitializers[I].first; FieldDecl *NewField = FieldsWithMemberInitializers[I].second; Expr *OldInit = OldField->getInClassInitializer(); - ExprResult NewInit = SubstExpr(OldInit, TemplateArgs); - - // If the initialization is no longer dependent, check it now. - if ((OldField->getType()->isDependentType() || OldInit->isTypeDependent() || - OldInit->isValueDependent()) && - !NewField->getType()->isDependentType() && - !NewInit.get()->isTypeDependent() && - !NewInit.get()->isValueDependent()) { - // FIXME: handle list-initialization - SourceLocation EqualLoc = NewField->getLocation(); - NewInit = PerformCopyInitialization( - InitializedEntity::InitializeMember(NewField), EqualLoc, - NewInit.release()); - - if (!NewInit.isInvalid()) { - CheckImplicitConversions(NewInit.get(), EqualLoc); - - // C++0x [class.base.init]p7: - // The initialization of each base and member constitutes a - // full-expression. - NewInit = MaybeCreateExprWithCleanups(NewInit); - } - } - if (NewInit.isInvalid()) + SourceLocation LParenLoc, RParenLoc; + ASTOwningVector NewArgs(*this); + if (InstantiateInitializer(OldInit, TemplateArgs, LParenLoc, NewArgs, + RParenLoc)) NewField->setInvalidDecl(); - else - NewField->setInClassInitializer(NewInit.release()); + else { + assert(NewArgs.size() == 1 && "wrong number of in-class initializers"); + ActOnCXXInClassMemberInitializer(NewField, LParenLoc, NewArgs[0]); + } } if (!FieldsWithMemberInitializers.empty()) diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 29385e50b8..81fd011ac6 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -239,8 +239,6 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { /// \brief Instantiate an initializer, breaking it into separate /// initialization arguments. /// -/// \param S The semantic analysis object. -/// /// \param Init The initializer to instantiate. /// /// \param TemplateArgs Template arguments to be substituted into the @@ -249,11 +247,11 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { /// \param NewArgs Will be filled in with the instantiation arguments. /// /// \returns true if an error occurred, false otherwise -static bool InstantiateInitializer(Sema &S, Expr *Init, +bool Sema::InstantiateInitializer(Expr *Init, const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation &LParenLoc, - ASTOwningVector &NewArgs, - SourceLocation &RParenLoc) { + SourceLocation &LParenLoc, + ASTOwningVector &NewArgs, + SourceLocation &RParenLoc) { NewArgs.clear(); LParenLoc = SourceLocation(); RParenLoc = SourceLocation(); @@ -273,24 +271,24 @@ static bool InstantiateInitializer(Sema &S, Expr *Init, if (ParenListExpr *ParenList = dyn_cast(Init)) { LParenLoc = ParenList->getLParenLoc(); RParenLoc = ParenList->getRParenLoc(); - return S.SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(), - true, TemplateArgs, NewArgs); + return SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(), + true, TemplateArgs, NewArgs); } if (CXXConstructExpr *Construct = dyn_cast(Init)) { if (!isa(Construct)) { - if (S.SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, - TemplateArgs, NewArgs)) + if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, + TemplateArgs, NewArgs)) return true; // FIXME: Fake locations! - LParenLoc = S.PP.getLocForEndOfToken(Init->getLocStart()); + LParenLoc = PP.getLocForEndOfToken(Init->getLocStart()); RParenLoc = LParenLoc; return false; } } - ExprResult Result = S.SubstExpr(Init, TemplateArgs); + ExprResult Result = SubstExpr(Init, TemplateArgs); if (Result.isInvalid()) return true; @@ -386,8 +384,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // Instantiate the initializer. SourceLocation LParenLoc, RParenLoc; ASTOwningVector InitArgs(SemaRef); - if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc, - InitArgs, RParenLoc)) { + if (!SemaRef.InstantiateInitializer(D->getInit(), TemplateArgs, LParenLoc, + InitArgs, RParenLoc)) { bool TypeMayContainAuto = true; // Attach the initializer to the declaration, if we have one. if (InitArgs.size() == 0) @@ -2689,7 +2687,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); // Instantiate the initializer. - if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, + if (InstantiateInitializer(Init->getInit(), TemplateArgs, LParenLoc, NewArgs, RParenLoc)) { AnyErrors = true; break; @@ -2727,7 +2725,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } // Instantiate the initializer. - if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, + if (InstantiateInitializer(Init->getInit(), TemplateArgs, LParenLoc, NewArgs, RParenLoc)) { AnyErrors = true; continue; diff --git a/test/SemaTemplate/member-inclass-init-value-dependent.cpp b/test/SemaTemplate/member-inclass-init-value-dependent.cpp index d1ae4f2ded..5bff7f2095 100644 --- a/test/SemaTemplate/member-inclass-init-value-dependent.cpp +++ b/test/SemaTemplate/member-inclass-init-value-dependent.cpp @@ -9,3 +9,10 @@ void test() { foo<4> bar; } +struct S { + S(int n); +}; +template struct T { + S s = 0; +}; +T t;