diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-11 23:51:47 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-11 23:51:47 +0000 |
commit | 5b9cc5df25c2198f270dd1d5c438fdce70d4051d (patch) | |
tree | 8d2c36bd9fe0e47cc5ce4e5a2fd02d8dd0e31f7f /lib/Sema/SemaTemplateInstantiateDecl.cpp | |
parent | ecfcd5655758955d8958dc2a7a7b2c8eff2395b7 (diff) |
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150318 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 170 |
1 files changed, 59 insertions, 111 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3cf816a332..7449c62fee 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -252,66 +252,6 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { return Inst; } -/// \brief Instantiate an initializer, breaking it into separate -/// initialization arguments. -/// -/// \param Init The initializer to instantiate. -/// -/// \param TemplateArgs Template arguments to be substituted into the -/// initializer. -/// -/// \param NewArgs Will be filled in with the instantiation arguments. -/// -/// \returns true if an error occurred, false otherwise -bool Sema::InstantiateInitializer(Expr *Init, - const MultiLevelTemplateArgumentList &TemplateArgs, - SourceLocation &LParenLoc, - ASTOwningVector<Expr*> &NewArgs, - SourceLocation &RParenLoc) { - NewArgs.clear(); - LParenLoc = SourceLocation(); - RParenLoc = SourceLocation(); - - if (!Init) - return false; - - if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) - Init = ExprTemp->getSubExpr(); - - while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) - Init = Binder->getSubExpr(); - - if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) - Init = ICE->getSubExprAsWritten(); - - if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { - LParenLoc = ParenList->getLParenLoc(); - RParenLoc = ParenList->getRParenLoc(); - return SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(), - true, TemplateArgs, NewArgs); - } - - if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { - if (!isa<CXXTemporaryObjectExpr>(Construct)) { - if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, - TemplateArgs, NewArgs)) - return true; - - // FIXME: Fake locations! - LParenLoc = PP.getLocForEndOfToken(Init->getLocStart()); - RParenLoc = LParenLoc; - return false; - } - } - - ExprResult Result = SubstExpr(Init, TemplateArgs); - if (Result.isInvalid()) - return true; - - NewArgs.push_back(Result.takeAs<Expr>()); - return false; -} - Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // If this is the variable for an anonymous struct or union, // instantiate the anonymous struct/union type first. @@ -342,7 +282,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { D->getStorageClass(), D->getStorageClassAsWritten()); Var->setThreadSpecified(D->isThreadSpecified()); - Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); + Var->setInitStyle(D->getInitStyle()); Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); Var->setConstexpr(D->isConstexpr()); @@ -403,25 +343,16 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); // Instantiate the initializer. - SourceLocation LParenLoc, RParenLoc; - ASTOwningVector<Expr*> InitArgs(SemaRef); - if (!SemaRef.InstantiateInitializer(D->getInit(), TemplateArgs, LParenLoc, - InitArgs, RParenLoc)) { + ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs, + D->getInitStyle() == VarDecl::CallInit); + if (!Init.isInvalid()) { bool TypeMayContainAuto = true; - if (D->hasCXXDirectInitializer()) { - // Add the direct initializer to the declaration. - SemaRef.AddCXXDirectInitializerToDecl(Var, - LParenLoc, - move_arg(InitArgs), - RParenLoc, - TypeMayContainAuto); - } else if (InitArgs.size() == 0) { + if (Init.get()) { + bool DirectInit = D->isDirectInit(); + SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit, + TypeMayContainAuto); + } else SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto); - } else { - assert(InitArgs.size() == 1); - Expr *Init = InitArgs.take()[0]; - SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto); - } } else { // FIXME: Not too happy about invalidating the declaration // because of a bogus initializer. @@ -2743,18 +2674,6 @@ void Sema::InstantiateStaticDataMemberDefinition( } } -static MultiInitializer CreateMultiInitializer(SmallVectorImpl<Expr*> &Args, - const CXXCtorInitializer *Init) { - // FIXME: This is a hack that will do slightly the wrong thing for an - // initializer of the form foo({...}). - // The right thing to do would be to modify InstantiateInitializer to create - // the MultiInitializer. - if (Args.size() == 1 && isa<InitListExpr>(Args[0])) - return MultiInitializer(Args[0]); - return MultiInitializer(Init->getLParenLoc(), Args.data(), - Args.size(), Init->getRParenLoc()); -} - void Sema::InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, @@ -2774,9 +2693,6 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, if (!Init->isWritten()) continue; - SourceLocation LParenLoc, RParenLoc; - ASTOwningVector<Expr*> NewArgs(*this); - SourceLocation EllipsisLoc; if (Init->isPackExpansion()) { @@ -2804,8 +2720,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); // Instantiate the initializer. - if (InstantiateInitializer(Init->getInit(), TemplateArgs, - LParenLoc, NewArgs, RParenLoc)) { + ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, + /*CXXDirectInit=*/true); + if (TempInit.isInvalid()) { AnyErrors = true; break; } @@ -2821,9 +2738,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } // Build the initializer. - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), - BaseTInfo, MultiInit, + BaseTInfo, TempInit.take(), New->getParent(), SourceLocation()); if (NewInit.isInvalid()) { @@ -2832,15 +2748,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } NewInits.push_back(NewInit.get()); - NewArgs.clear(); } continue; } // Instantiate the initializer. - if (InstantiateInitializer(Init->getInit(), TemplateArgs, - LParenLoc, NewArgs, RParenLoc)) { + ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, + /*CXXDirectInit=*/true); + if (TempInit.isInvalid()) { AnyErrors = true; continue; } @@ -2857,13 +2773,11 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, continue; } - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); - if (Init->isBaseInitializer()) - NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, MultiInit, + NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.take(), New->getParent(), EllipsisLoc); else - NewInit = BuildDelegatingInitializer(TInfo, MultiInit, + NewInit = BuildDelegatingInitializer(TInfo, TempInit.take(), cast<CXXRecordDecl>(CurContext->getParent())); } else if (Init->isMemberInitializer()) { FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl( @@ -2876,8 +2790,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, continue; } - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); - NewInit = BuildMemberInitializer(Member, MultiInit, + NewInit = BuildMemberInitializer(Member, TempInit.take(), Init->getSourceLocation()); } else if (Init->isIndirectMemberInitializer()) { IndirectFieldDecl *IndirectMember = @@ -2891,8 +2804,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, continue; } - MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); - NewInit = BuildMemberInitializer(IndirectMember, MultiInit, + NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(), Init->getSourceLocation()); } @@ -2900,9 +2812,6 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, AnyErrors = true; New->setInvalidDecl(); } else { - // FIXME: It would be nice if ASTOwningVector had a release function. - NewArgs.take(); - NewInits.push_back(NewInit.get()); } } @@ -2915,6 +2824,45 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, AnyErrors); } +ExprResult Sema::SubstInitializer(Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool CXXDirectInit) { + // Initializers are instantiated like expressions, except that various outer + // layers are stripped. + if (!Init) + return Owned(Init); + + if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) + Init = ExprTemp->getSubExpr(); + + while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) + Init = Binder->getSubExpr(); + + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) + Init = ICE->getSubExprAsWritten(); + + // If this is a direct-initializer, we take apart CXXConstructExprs. + // Everything else is passed through. + CXXConstructExpr *Construct; + if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) || + isa<CXXTemporaryObjectExpr>(Construct)) + return SubstExpr(Init, TemplateArgs); + + ASTOwningVector<Expr*> NewArgs(*this); + if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, + TemplateArgs, NewArgs)) + return ExprError(); + + // Treat an empty initializer like none. + if (NewArgs.empty()) + return Owned((Expr*)0); + + // Build a ParenListExpr to represent anything else. + // FIXME: Fake locations! + SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart()); + return ActOnParenListExpr(Loc, Loc, move_arg(NewArgs)); +} + // TODO: this could be templated if the various decl types used the // same method name. static bool isInstantiationOf(ClassTemplateDecl *Pattern, |