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/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 73f47d9..3d690d1 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -673,42 +673,25 @@
CXXBaseOrMemberInitializer::
CXXBaseOrMemberInitializer(ASTContext &Context,
- TypeSourceInfo *TInfo, CXXConstructorDecl *C,
- SourceLocation L,
- Expr **Args, unsigned NumArgs,
- SourceLocation R)
- : BaseOrMember(TInfo), Args(0), NumArgs(0), CtorOrAnonUnion(C),
+ TypeSourceInfo *TInfo,
+ SourceLocation L, Expr *Init, SourceLocation R)
+ : BaseOrMember(TInfo), Init(Init), AnonUnionMember(0),
LParenLoc(L), RParenLoc(R)
{
- if (NumArgs > 0) {
- this->NumArgs = NumArgs;
- this->Args = new (Context) Stmt*[NumArgs];
- for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
- this->Args[Idx] = Args[Idx];
- }
}
CXXBaseOrMemberInitializer::
CXXBaseOrMemberInitializer(ASTContext &Context,
FieldDecl *Member, SourceLocation MemberLoc,
- CXXConstructorDecl *C, SourceLocation L,
- Expr **Args, unsigned NumArgs,
- SourceLocation R)
- : BaseOrMember(Member), MemberLocation(MemberLoc), Args(0), NumArgs(0),
- CtorOrAnonUnion(C), LParenLoc(L), RParenLoc(R)
+ SourceLocation L, Expr *Init, SourceLocation R)
+ : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init),
+ AnonUnionMember(0), LParenLoc(L), RParenLoc(R)
{
- if (NumArgs > 0) {
- this->NumArgs = NumArgs;
- this->Args = new (Context) Stmt*[NumArgs];
- for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
- this->Args[Idx] = Args[Idx];
- }
}
void CXXBaseOrMemberInitializer::Destroy(ASTContext &Context) {
- for (unsigned I = 0; I != NumArgs; ++I)
- Args[I]->Destroy(Context);
- Context.Deallocate(Args);
+ if (Init)
+ Init->Destroy(Context);
this->~CXXBaseOrMemberInitializer();
}
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 32ac53d..a625865 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -403,32 +404,51 @@
CXXBaseOrMemberInitializer * BMInitializer = (*B);
if (B != CDecl->init_begin())
Out << ", ";
- bool hasArguments = (BMInitializer->arg_begin() !=
- BMInitializer->arg_end());
if (BMInitializer->isMemberInitializer()) {
FieldDecl *FD = BMInitializer->getMember();
Out << FD->getNameAsString();
+ } else {
+ Out << QualType(BMInitializer->getBaseClass(), 0).getAsString();
}
- else // FIXME. skip dependent types for now.
- if (const RecordType *RT =
- BMInitializer->getBaseClass()->getAs<RecordType>()) {
- const CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(RT->getDecl());
- Out << BaseDecl->getNameAsString();
- }
- if (hasArguments) {
- Out << "(";
- for (CXXBaseOrMemberInitializer::const_arg_iterator BE =
- BMInitializer->const_arg_begin(),
- EE = BMInitializer->const_arg_end(); BE != EE; ++BE) {
- if (BE != BMInitializer->const_arg_begin())
- Out<< ", ";
- const Expr *Exp = (*BE);
- Exp->printPretty(Out, Context, 0, Policy, Indentation);
+
+ Out << "(";
+ if (!BMInitializer->getInit()) {
+ // Nothing to print
+ } else {
+ Expr *Init = BMInitializer->getInit();
+ if (CXXExprWithTemporaries *Tmp
+ = dyn_cast<CXXExprWithTemporaries>(Init))
+ Init = Tmp->getSubExpr();
+
+ Init = Init->IgnoreParens();
+
+ Expr *SimpleInit = 0;
+ Expr **Args = 0;
+ unsigned NumArgs = 0;
+ if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
+ Args = ParenList->getExprs();
+ NumArgs = ParenList->getNumExprs();
+ } else if (CXXConstructExpr *Construct
+ = dyn_cast<CXXConstructExpr>(Init)) {
+ Args = Construct->getArgs();
+ NumArgs = Construct->getNumArgs();
+ } else
+ SimpleInit = Init;
+
+ if (SimpleInit)
+ SimpleInit->printPretty(Out, Context, 0, Policy, Indentation);
+ else {
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ if (isa<CXXDefaultArgExpr>(Args[I]))
+ break;
+
+ if (I)
+ Out << ", ";
+ Args[I]->printPretty(Out, Context, 0, Policy, Indentation);
+ }
}
- Out << ")";
- } else
- Out << "()";
+ }
+ Out << ")";
}
}
}
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 3931bbd..70d0891 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -424,22 +424,26 @@
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
- bool ZeroInitialization) {
+ bool ZeroInitialization,
+ bool BaseInitialization) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
- Elidable, Args, NumArgs, ZeroInitialization);
+ Elidable, Args, NumArgs, ZeroInitialization,
+ BaseInitialization);
}
CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool elidable,
Expr **args, unsigned numargs,
- bool ZeroInitialization)
+ bool ZeroInitialization,
+ bool BaseInitialization)
: Expr(SC, T,
T->isDependentType(),
(T->isDependentType() ||
CallExpr::hasAnyValueDependentArguments(args, numargs))),
Constructor(D), Loc(Loc), Elidable(elidable),
- ZeroInitialization(ZeroInitialization), Args(0), NumArgs(numargs)
+ ZeroInitialization(ZeroInitialization),
+ BaseInitialization(BaseInitialization), Args(0), NumArgs(numargs)
{
if (NumArgs) {
Args = new (C) Stmt*[NumArgs];