aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2012-02-11 23:51:47 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2012-02-11 23:51:47 +0000
commit5b9cc5df25c2198f270dd1d5c438fdce70d4051d (patch)
tree8d2c36bd9fe0e47cc5ce4e5a2fd02d8dd0e31f7f /lib/Sema/SemaTemplateInstantiateDecl.cpp
parentecfcd5655758955d8958dc2a7a7b2c8eff2395b7 (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.cpp170
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,