Rework base and member initialization in constructors, with several
(necessarily simultaneous) changes:
- CXXBaseOrMemberInitializer now contains only a single initializer
rather than a set of initialiation arguments + a constructor. The
single initializer covers all aspects of initialization, including
constructor calls as necessary but also cleanup of temporaries
created by the initializer (which we never handled
before!).
- Rework + simplify code generation for CXXBaseOrMemberInitializers,
since we can now just emit the initializer as an initializer.
- Switched base and member initialization over to the new
initialization code (InitializationSequence), so that it
- Improved diagnostics for the new initialization code when
initializing bases and members, to match the diagnostics produced
by the previous (special-purpose) code.
- Simplify the representation of type-checked constructor initializers in
templates; instead of keeping the fully-type-checked AST, which is
rather hard to undo at template instantiation time, throw away the
type-checked AST and store the raw expressions in the AST. This
simplifies instantiation, but loses a little but of information in
the AST.
- When type-checking implicit base or member initializers within a
dependent context, don't add the generated initializers into the
AST, because they'll look like they were explicit.
- Record in CXXConstructExpr when the constructor call is to
initialize a base class, so that CodeGen does not have to infer it
from context. This ensures that we call the right kind of
constructor.
There are also a few "opportunity" fixes here that were needed to not
regress, for example:
- Diagnose default-initialization of a const-qualified class that
does not have a user-declared default constructor. We had this
diagnostic specifically for bases and members, but missed it for
variables. That's fixed now.
- When defining the implicit constructors, destructor, and
copy-assignment operator, set the CurContext to that constructor
when we're defining the body.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94952 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a2f1f63..d526962 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1830,7 +1830,8 @@
const MultiLevelTemplateArgumentList &TemplateArgs) {
llvm::SmallVector<MemInitTy*, 4> NewInits;
-
+ bool AnyErrors = false;
+
// Instantiate all the initializers.
for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(),
InitsEnd = Tmpl->init_end();
@@ -1838,26 +1839,38 @@
CXXBaseOrMemberInitializer *Init = *Inits;
ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this);
+ llvm::SmallVector<SourceLocation, 4> CommaLocs;
// Instantiate all the arguments.
- for (ExprIterator Args = Init->arg_begin(), ArgsEnd = Init->arg_end();
- Args != ArgsEnd; ++Args) {
- OwningExprResult NewArg = SubstExpr(*Args, TemplateArgs);
-
- if (NewArg.isInvalid())
- New->setInvalidDecl();
- else
- NewArgs.push_back(NewArg.takeAs<Expr>());
+ Expr *InitE = Init->getInit();
+ if (!InitE) {
+ // Nothing to instantiate;
+ } else if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(InitE)) {
+ if (InstantiateInitializationArguments(*this, ParenList->getExprs(),
+ ParenList->getNumExprs(),
+ TemplateArgs, CommaLocs,
+ NewArgs)) {
+ AnyErrors = true;
+ continue;
+ }
+ } else {
+ OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs);
+ if (InitArg.isInvalid()) {
+ AnyErrors = true;
+ continue;
+ }
+
+ NewArgs.push_back(InitArg.release());
}
-
+
MemInitResult NewInit;
-
if (Init->isBaseInitializer()) {
TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(),
TemplateArgs,
Init->getSourceLocation(),
New->getDeclName());
if (!BaseTInfo) {
+ AnyErrors = true;
New->setInvalidDecl();
continue;
}
@@ -1885,9 +1898,10 @@
Init->getRParenLoc());
}
- if (NewInit.isInvalid())
+ if (NewInit.isInvalid()) {
+ AnyErrors = true;
New->setInvalidDecl();
- else {
+ } else {
// FIXME: It would be nice if ASTOwningVector had a release function.
NewArgs.take();
@@ -1899,7 +1913,8 @@
ActOnMemInitializers(DeclPtrTy::make(New),
/*FIXME: ColonLoc */
SourceLocation(),
- NewInits.data(), NewInits.size());
+ NewInits.data(), NewInits.size(),
+ AnyErrors);
}
// TODO: this could be templated if the various decl types used the