[cfe-commits] r94952 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/CodeGen/ lib/Parse/ lib/Sema/ test/CXX/dcl.decl/dcl.init/ test/SemaCXX/ test/SemaTemplate/
Douglas Gregor
dgregor at apple.com
Sun Jan 31 01:12:52 PST 2010
Author: dgregor
Date: Sun Jan 31 03:12:51 2010
New Revision: 94952
URL: http://llvm.org/viewvc/llvm-project?rev=94952&view=rev
Log:
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.
Added:
cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp (with props)
Modified:
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/AST/DeclPrinter.cpp
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/CodeGen/CGClass.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaInit.h
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaCXX/constructor-initializer.cpp
cfe/trunk/test/SemaCXX/copy-assignment.cpp
cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp
cfe/trunk/test/SemaCXX/overload-member-call.cpp
cfe/trunk/test/SemaCXX/overloaded-operator.cpp
cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sun Jan 31 03:12:51 2010
@@ -941,9 +941,9 @@
/// \brief The source location for the field name.
SourceLocation MemberLocation;
- /// Args - The arguments used to initialize the base or member.
- Stmt **Args;
- unsigned NumArgs;
+ /// \brief The argument used to initialize the base or member, which may
+ /// end up constructing an object (when multiple arguments are involved).
+ Stmt *Init;
/// \brief Stores either the constructor to call to initialize this base or
/// member (a CXXConstructorDecl pointer), or stores the anonymous union of
@@ -963,7 +963,7 @@
/// @endcode
/// In above example, BaseOrMember holds the field decl. for anonymous union
/// and AnonUnionMember holds field decl for au_i1.
- llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion;
+ FieldDecl *AnonUnionMember;
/// LParenLoc - Location of the left paren of the ctor-initializer.
SourceLocation LParenLoc;
@@ -975,30 +975,22 @@
/// CXXBaseOrMemberInitializer - Creates a new base-class initializer.
explicit
CXXBaseOrMemberInitializer(ASTContext &Context,
- TypeSourceInfo *TInfo, CXXConstructorDecl *C,
+ TypeSourceInfo *TInfo,
SourceLocation L,
- Expr **Args, unsigned NumArgs,
+ Expr *Init,
SourceLocation R);
/// CXXBaseOrMemberInitializer - Creates a new member initializer.
explicit
CXXBaseOrMemberInitializer(ASTContext &Context,
FieldDecl *Member, SourceLocation MemberLoc,
- CXXConstructorDecl *C, SourceLocation L,
- Expr **Args, unsigned NumArgs,
+ SourceLocation L,
+ Expr *Init,
SourceLocation R);
/// \brief Destroy the base or member initializer.
void Destroy(ASTContext &Context);
- /// arg_iterator - Iterates through the member initialization
- /// arguments.
- typedef ExprIterator arg_iterator;
-
- /// arg_const_iterator - Iterates through the member initialization
- /// arguments.
- typedef ConstExprIterator const_arg_iterator;
-
/// isBaseInitializer - Returns true when this initializer is
/// initializing a base class.
bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); }
@@ -1048,32 +1040,16 @@
SourceRange getSourceRange() const;
FieldDecl *getAnonUnionMember() const {
- return CtorOrAnonUnion.dyn_cast<FieldDecl *>();
+ return AnonUnionMember;
}
void setAnonUnionMember(FieldDecl *anonMember) {
- CtorOrAnonUnion = anonMember;
- }
-
- const CXXConstructorDecl *getConstructor() const {
- return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>();
+ AnonUnionMember = anonMember;
}
SourceLocation getLParenLoc() const { return LParenLoc; }
SourceLocation getRParenLoc() const { return RParenLoc; }
- /// arg_begin() - Retrieve an iterator to the first initializer argument.
- arg_iterator arg_begin() { return Args; }
- /// arg_begin() - Retrieve an iterator to the first initializer argument.
- const_arg_iterator const_arg_begin() const { return Args; }
-
- /// arg_end() - Retrieve an iterator past the last initializer argument.
- arg_iterator arg_end() { return Args + NumArgs; }
- /// arg_end() - Retrieve an iterator past the last initializer argument.
- const_arg_iterator const_arg_end() const { return Args + NumArgs; }
-
- /// getNumArgs - Determine the number of arguments used to
- /// initialize the member or base.
- unsigned getNumArgs() const { return NumArgs; }
+ Expr *getInit() { return static_cast<Expr *>(Init); }
};
/// CXXConstructorDecl - Represents a C++ constructor within a
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Sun Jan 31 03:12:51 2010
@@ -613,6 +613,7 @@
SourceLocation Loc;
bool Elidable : 1;
bool ZeroInitialization : 1;
+ bool BaseInitialization : 1;
Stmt **Args;
unsigned NumArgs;
@@ -621,7 +622,8 @@
SourceLocation Loc,
CXXConstructorDecl *d, bool elidable,
Expr **args, unsigned numargs,
- bool ZeroInitialization = false);
+ bool ZeroInitialization = false,
+ bool BaseInitialization = false);
~CXXConstructExpr() { }
virtual void DoDestroy(ASTContext &C);
@@ -635,7 +637,8 @@
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
Expr **Args, unsigned NumArgs,
- bool ZeroInitialization = false);
+ bool ZeroInitialization = false,
+ bool BaseInitialization = false);
CXXConstructorDecl* getConstructor() const { return Constructor; }
@@ -655,6 +658,11 @@
ZeroInitialization = ZeroInit;
}
+ /// \brief Determines whether this constructor is actually constructing
+ /// a base class (rather than a complete object).
+ bool isBaseInitialization() const { return BaseInitialization; }
+ void setBaseInitialization(bool BI) { BaseInitialization = BI; }
+
typedef ExprIterator arg_iterator;
typedef ConstExprIterator const_arg_iterator;
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Jan 31 03:12:51 2010
@@ -588,6 +588,8 @@
"declaration of reference variable %0 requires an initializer">;
def err_const_var_requires_init : Error<
"declaration of const variable '%0' requires an initializer">;
+def err_reference_without_init : Error<
+ "reference to type %0 requires an initializer">;
def err_reference_has_multiple_inits : Error<
"reference cannot be initialized with multiple values">;
def err_init_non_aggr_init_list : Error<
@@ -880,10 +882,7 @@
"assignment operator">;
def note_first_required_here : Note<
"synthesized method is first required here">;
-def err_null_intialized_reference_member : Error<
- "cannot initialize the member to null in default constructor because "
- "reference member %0 cannot be null-initialized">;
-def err_unintialized_member_in_ctor : Error<
+def err_uninitialized_member_in_ctor : Error<
"%select{|implicit default }0constructor for %1 must explicitly initialize "
"the %select{reference|const}2 member %3">;
@@ -1949,7 +1948,8 @@
def err_array_size_not_integral : Error<
"array size expression must have integral or enumerated type, not %0">;
def err_default_init_const : Error<
- "default initialization of an object of const type %0">;
+ "default initialization of an object of const type %0"
+ "%select{| requires a user-provided default constructor}1">;
def err_delete_operand : Error<"cannot delete expression of type %0">;
def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
"expression of type %0 to a pointer">;
@@ -2252,8 +2252,6 @@
def err_mem_init_not_member_or_class : Error<
"member initializer %0 does not name a non-static data member or base "
"class">;
-def err_mem_initializer_mismatch : Error<
- "Too many arguments for member initializer %0">;
def warn_field_initialized : Warning<
"member '%0' will be initialized after">,
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Sun Jan 31 03:12:51 2010
@@ -1654,9 +1654,12 @@
/// a well-formed program), ColonLoc is the location of the ':' that
/// starts the constructor initializer, and MemInit/NumMemInits
/// contains the individual member (and base) initializers.
+ /// AnyErrors will be true if there were any invalid member initializers
+ /// that are not represented in the list.
virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits){
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors){
}
virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) {}
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Sun Jan 31 03:12:51 2010
@@ -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();
}
Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Sun Jan 31 03:12:51 2010
@@ -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 << ")";
}
}
}
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Sun Jan 31 03:12:51 2010
@@ -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];
Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Sun Jan 31 03:12:51 2010
@@ -811,11 +811,7 @@
llvm::Value *V = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy);
V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8);
V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo());
-
- CGF.EmitCXXConstructorCall(BaseInit->getConstructor(),
- Ctor_Base, V,
- BaseInit->const_arg_begin(),
- BaseInit->const_arg_end());
+ CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true);
}
static void EmitMemberInitializer(CodeGenFunction &CGF,
@@ -846,55 +842,34 @@
// We lose the constructor for anonymous union members, so handle them
// explicitly.
- // FIXME: This is somwhat ugly.
+ // FIXME: This is somwhat ugly, and doesn't seem necessary at all.
if (MemberInit->getAnonUnionMember() && FieldType->getAs<RecordType>()) {
- if (MemberInit->getNumArgs())
- CGF.EmitAggExpr(*MemberInit->arg_begin(), LHS.getAddress(),
+ if (MemberInit->getInit())
+ CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(),
LHS.isVolatileQualified());
else
CGF.EmitAggregateClear(LHS.getAddress(), Field->getType());
return;
}
- if (FieldType->getAs<RecordType>()) {
- assert(MemberInit->getConstructor() &&
- "EmitCtorPrologue - no constructor to initialize member");
- if (Array) {
- const llvm::Type *BasePtr = CGF.ConvertType(FieldType);
- BasePtr = llvm::PointerType::getUnqual(BasePtr);
- llvm::Value *BaseAddrPtr =
- CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
- CGF.EmitCXXAggrConstructorCall(MemberInit->getConstructor(),
- Array, BaseAddrPtr,
- MemberInit->const_arg_begin(),
- MemberInit->const_arg_end());
- }
- else
- CGF.EmitCXXConstructorCall(MemberInit->getConstructor(),
- Ctor_Complete, LHS.getAddress(),
- MemberInit->const_arg_begin(),
- MemberInit->const_arg_end());
- return;
- }
-
- assert(MemberInit->getNumArgs() == 1 && "Initializer count must be 1 only");
- Expr *RhsExpr = *MemberInit->arg_begin();
+ // FIXME: If there's no initializer and the CXXBaseOrMemberInitializer
+ // was implicitly generated, we shouldn't be zeroing memory.
RValue RHS;
if (FieldType->isReferenceType()) {
- RHS = CGF.EmitReferenceBindingToExpr(RhsExpr, FieldType,
- /*IsInitializer=*/true);
+ RHS = CGF.EmitReferenceBindingToExpr(MemberInit->getInit(), FieldType,
+ /*IsInitializer=*/true);
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
- } else if (Array) {
+ } else if (Array && !MemberInit->getInit()) {
CGF.EmitMemSetToZero(LHS.getAddress(), Field->getType());
- } else if (!CGF.hasAggregateLLVMType(RhsExpr->getType())) {
- RHS = RValue::get(CGF.EmitScalarExpr(RhsExpr, true));
+ } else if (!CGF.hasAggregateLLVMType(Field->getType())) {
+ RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true));
CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
- } else if (RhsExpr->getType()->isAnyComplexType()) {
- CGF.EmitComplexExprIntoAddr(RhsExpr, LHS.getAddress(),
+ } else if (MemberInit->getInit()->getType()->isAnyComplexType()) {
+ CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(),
LHS.isVolatileQualified());
} else {
- // Handle member function pointers; other aggregates shouldn't get this far.
- CGF.EmitAggExpr(RhsExpr, LHS.getAddress(), LHS.isVolatileQualified());
+ CGF.EmitAggExpr(MemberInit->getInit(), LHS.getAddress(),
+ LHS.isVolatileQualified(), false, true);
}
}
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun Jan 31 03:12:51 2010
@@ -339,7 +339,9 @@
}
else
// Call the constructor.
- EmitCXXConstructorCall(CD, Ctor_Complete, Dest,
+ EmitCXXConstructorCall(CD,
+ E->isBaseInitialization()? Ctor_Base : Ctor_Complete,
+ Dest,
E->arg_begin(), E->arg_end());
}
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Jan 31 03:12:51 2010
@@ -1550,12 +1550,15 @@
SourceLocation ColonLoc = ConsumeToken();
llvm::SmallVector<MemInitTy*, 4> MemInitializers;
-
+ bool AnyErrors = false;
+
do {
MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
if (!MemInit.isInvalid())
MemInitializers.push_back(MemInit.get());
-
+ else
+ AnyErrors = true;
+
if (Tok.is(tok::comma))
ConsumeToken();
else if (Tok.is(tok::l_brace))
@@ -1569,7 +1572,8 @@
} while (true);
Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
- MemInitializers.data(), MemInitializers.size());
+ MemInitializers.data(), MemInitializers.size(),
+ AnyErrors);
}
/// ParseMemInitializer - Parse a C++ member initializer, which is
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Sun Jan 31 03:12:51 2010
@@ -1911,7 +1911,8 @@
QualType DeclInitType,
CXXConstructorDecl *Constructor,
MultiExprArg Exprs,
- bool RequiresZeroInit = false);
+ bool RequiresZeroInit = false,
+ bool BaseInitialization = false);
// FIXME: Can re remove this and have the above BuildCXXConstructExpr check if
// the constructor can be elidable?
@@ -1920,7 +1921,8 @@
CXXConstructorDecl *Constructor,
bool Elidable,
MultiExprArg Exprs,
- bool RequiresZeroInit = false);
+ bool RequiresZeroInit = false,
+ bool BaseInitialization = false);
OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons,
QualType writtenTy,
@@ -2282,9 +2284,10 @@
CXXRecordDecl *ClassDecl);
bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers,
- bool IsImplicitConstructor);
+ CXXBaseOrMemberInitializer **Initializers,
+ unsigned NumInitializers,
+ bool IsImplicitConstructor,
+ bool AnyErrors);
/// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl,
/// mark all its non-trivial member and base destructor declarations
@@ -2316,7 +2319,8 @@
virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits);
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors);
void CheckCompletedCXXClass(CXXRecordDecl *Record);
virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Jan 31 03:12:51 2010
@@ -1195,10 +1195,6 @@
unsigned NumArgs, SourceLocation IdLoc,
SourceLocation LParenLoc,
SourceLocation RParenLoc) {
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
-
// Diagnose value-uses of fields to initialize themselves, e.g.
// foo(foo)
// where foo is not also a parameter to the constructor.
@@ -1220,65 +1216,80 @@
for (unsigned i = 0; i < NumArgs; i++)
HasDependentArg |= Args[i]->isTypeDependent();
- CXXConstructorDecl *C = 0;
QualType FieldType = Member->getType();
if (const ArrayType *Array = Context.getAsArrayType(FieldType))
FieldType = Array->getElementType();
ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
- if (FieldType->isDependentType()) {
- // Can't check init for dependent type.
- } else if (FieldType->isRecordType()) {
- // Member is a record (struct/union/class), so pass the initializer
- // arguments down to the record's constructor.
- if (!HasDependentArg) {
- C = PerformInitializationByConstructor(FieldType,
- MultiExprArg(*this,
- (void**)Args,
- NumArgs),
- IdLoc,
- SourceRange(IdLoc, RParenLoc),
- Member->getDeclName(),
- InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc),
- ConstructorArgs);
-
- if (C) {
- // Take over the constructor arguments as our own.
- NumArgs = ConstructorArgs.size();
- Args = (Expr **)ConstructorArgs.take();
- }
- }
- } else if (NumArgs != 1 && NumArgs != 0) {
- // The member type is not a record type (or an array of record
- // types), so it can be only be default- or copy-initialized.
- return Diag(IdLoc, diag::err_mem_initializer_mismatch)
- << Member->getDeclName() << SourceRange(IdLoc, RParenLoc);
- } else if (!HasDependentArg) {
- Expr *NewExp;
- if (NumArgs == 0) {
- if (FieldType->isReferenceType()) {
- Diag(IdLoc, diag::err_null_intialized_reference_member)
- << Member->getDeclName();
- return Diag(Member->getLocation(), diag::note_declared_at);
- }
- NewExp = new (Context) CXXZeroInitValueExpr(FieldType, IdLoc, RParenLoc);
- NumArgs = 1;
- }
- else
- NewExp = (Expr*)Args[0];
- if (!Member->isInvalidDecl() &&
- PerformCopyInitialization(NewExp, FieldType, AA_Passing))
- return true;
- Args[0] = NewExp;
+ if (FieldType->isDependentType() || HasDependentArg) {
+ // Can't check initialization for a member of dependent type or when
+ // any of the arguments are type-dependent expressions.
+ OwningExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+
+ // Erase any temporaries within this evaluation context; we're not
+ // going to track them in the AST, since we'll be rebuilding the
+ // ASTs during template instantiation.
+ ExprTemporaries.erase(
+ ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+ ExprTemporaries.end());
+
+ return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+ LParenLoc,
+ Init.takeAs<Expr>(),
+ RParenLoc);
+
}
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
+ if (Member->isInvalidDecl())
+ return true;
- // FIXME: Perform direct initialization of the member.
+ // Initialize the member.
+ InitializedEntity MemberEntity =
+ InitializedEntity::InitializeMember(Member, 0);
+ InitializationKind Kind =
+ InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs);
+
+ OwningExprResult MemberInit =
+ InitSeq.Perform(*this, MemberEntity, Kind,
+ MultiExprArg(*this, (void**)Args, NumArgs), 0);
+ if (MemberInit.isInvalid())
+ return true;
+
+ // C++0x [class.base.init]p7:
+ // The initialization of each base and member constitutes a
+ // full-expression.
+ MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ if (MemberInit.isInvalid())
+ return true;
+
+ // If we are in a dependent context, template instantiation will
+ // perform this type-checking again. Just save the arguments that we
+ // received in a ParenListExpr.
+ // FIXME: This isn't quite ideal, since our ASTs don't capture all
+ // of the information that we have about the member
+ // initializer. However, deconstructing the ASTs is a dicey process,
+ // and this approach is far more likely to get the corner cases right.
+ if (CurContext->isDependentContext()) {
+ // Bump the reference count of all of the arguments.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I]->Retain();
+
+ OwningExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+ return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
+ LParenLoc,
+ Init.takeAs<Expr>(),
+ RParenLoc);
+ }
+
return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc,
- C, LParenLoc, (Expr **)Args,
- NumArgs, RParenLoc);
+ LParenLoc,
+ MemberInit.takeAs<Expr>(),
+ RParenLoc);
}
Sema::MemInitResult
@@ -1291,76 +1302,118 @@
HasDependentArg |= Args[i]->isTypeDependent();
SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getSourceRange().getBegin();
- if (!BaseType->isDependentType()) {
- if (!BaseType->isRecordType())
- return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
- << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
-
- // C++ [class.base.init]p2:
- // [...] Unless the mem-initializer-id names a nonstatic data
- // member of the constructorâs class or a direct or virtual base
- // of that class, the mem-initializer is ill-formed. A
- // mem-initializer-list can initialize a base class using any
- // name that denotes that base class type.
-
- // Check for direct and virtual base classes.
- const CXXBaseSpecifier *DirectBaseSpec = 0;
- const CXXBaseSpecifier *VirtualBaseSpec = 0;
- FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
- VirtualBaseSpec);
-
- // C++ [base.class.init]p2:
- // If a mem-initializer-id is ambiguous because it designates both
- // a direct non-virtual base class and an inherited virtual base
- // class, the mem-initializer is ill-formed.
- if (DirectBaseSpec && VirtualBaseSpec)
- return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
- << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
- // C++ [base.class.init]p2:
- // Unless the mem-initializer-id names a nonstatic data membeer of the
- // constructor's class ot a direst or virtual base of that class, the
- // mem-initializer is ill-formed.
- if (!DirectBaseSpec && !VirtualBaseSpec)
- return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
- << BaseType << ClassDecl->getNameAsCString()
- << BaseTInfo->getTypeLoc().getSourceRange();
- }
-
- CXXConstructorDecl *C = 0;
- ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this);
- if (!BaseType->isDependentType() && !HasDependentArg) {
- DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(BaseType).getUnqualifiedType());
-
- C = PerformInitializationByConstructor(BaseType,
- MultiExprArg(*this,
- (void**)Args, NumArgs),
- BaseLoc,
- SourceRange(BaseLoc, RParenLoc),
- Name,
- InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc),
- ConstructorArgs);
- if (C) {
- // Take over the constructor arguments as our own.
- NumArgs = ConstructorArgs.size();
- Args = (Expr **)ConstructorArgs.take();
- }
+ if (BaseType->isDependentType() || HasDependentArg) {
+ // Can't check initialization for a base of dependent type or when
+ // any of the arguments are type-dependent expressions.
+ OwningExprResult BaseInit
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+
+ // Erase any temporaries within this evaluation context; we're not
+ // going to track them in the AST, since we'll be rebuilding the
+ // ASTs during template instantiation.
+ ExprTemporaries.erase(
+ ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries,
+ ExprTemporaries.end());
+
+ return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+ LParenLoc,
+ BaseInit.takeAs<Expr>(),
+ RParenLoc);
}
+
+ if (!BaseType->isRecordType())
+ return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
+ << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+
+ // C++ [class.base.init]p2:
+ // [...] Unless the mem-initializer-id names a nonstatic data
+ // member of the constructorâs class or a direct or virtual base
+ // of that class, the mem-initializer is ill-formed. A
+ // mem-initializer-list can initialize a base class using any
+ // name that denotes that base class type.
+
+ // Check for direct and virtual base classes.
+ const CXXBaseSpecifier *DirectBaseSpec = 0;
+ const CXXBaseSpecifier *VirtualBaseSpec = 0;
+ FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
+ VirtualBaseSpec);
+
+ // C++ [base.class.init]p2:
+ // If a mem-initializer-id is ambiguous because it designates both
+ // a direct non-virtual base class and an inherited virtual base
+ // class, the mem-initializer is ill-formed.
+ if (DirectBaseSpec && VirtualBaseSpec)
+ return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
+ << BaseType << BaseTInfo->getTypeLoc().getSourceRange();
+ // C++ [base.class.init]p2:
+ // Unless the mem-initializer-id names a nonstatic data membeer of the
+ // constructor's class ot a direst or virtual base of that class, the
+ // mem-initializer is ill-formed.
+ if (!DirectBaseSpec && !VirtualBaseSpec)
+ return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
+ << BaseType << ClassDecl->getNameAsCString()
+ << BaseTInfo->getTypeLoc().getSourceRange();
+
+ CXXBaseSpecifier *BaseSpec
+ = const_cast<CXXBaseSpecifier *>(DirectBaseSpec);
+ if (!BaseSpec)
+ BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec);
+
+ // Initialize the base.
+ InitializedEntity BaseEntity =
+ InitializedEntity::InitializeBase(Context, BaseSpec);
+ InitializationKind Kind =
+ InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc);
+
+ InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs);
+
+ OwningExprResult BaseInit =
+ InitSeq.Perform(*this, BaseEntity, Kind,
+ MultiExprArg(*this, (void**)Args, NumArgs), 0);
+ if (BaseInit.isInvalid())
+ return true;
+
+ // C++0x [class.base.init]p7:
+ // The initialization of each base and member constitutes a
+ // full-expression.
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid())
+ return true;
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
-
- return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, C,
- LParenLoc, (Expr **)Args,
- NumArgs, RParenLoc);
+ // If we are in a dependent context, template instantiation will
+ // perform this type-checking again. Just save the arguments that we
+ // received in a ParenListExpr.
+ // FIXME: This isn't quite ideal, since our ASTs don't capture all
+ // of the information that we have about the base
+ // initializer. However, deconstructing the ASTs is a dicey process,
+ // and this approach is far more likely to get the corner cases right.
+ if (CurContext->isDependentContext()) {
+ // Bump the reference count of all of the arguments.
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I]->Retain();
+
+ OwningExprResult Init
+ = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs,
+ RParenLoc));
+ return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+ LParenLoc,
+ Init.takeAs<Expr>(),
+ RParenLoc);
+ }
+
+ return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo,
+ LParenLoc,
+ BaseInit.takeAs<Expr>(),
+ RParenLoc);
}
bool
Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor,
- CXXBaseOrMemberInitializer **Initializers,
- unsigned NumInitializers,
- bool IsImplicitConstructor) {
+ CXXBaseOrMemberInitializer **Initializers,
+ unsigned NumInitializers,
+ bool IsImplicitConstructor,
+ bool AnyErrors) {
// We need to build the initializer AST according to order of construction
// and not what user specified in the Initializers list.
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext());
@@ -1403,6 +1456,8 @@
AllToInit.push_back(Member);
}
} else {
+ llvm::SmallVector<CXXBaseSpecifier *, 4> BasesToDefaultInit;
+
// Push virtual bases before others.
for (CXXRecordDecl::base_class_iterator VBase =
ClassDecl->vbases_begin(),
@@ -1412,44 +1467,34 @@
if (CXXBaseOrMemberInitializer *Value
= AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) {
AllToInit.push_back(Value);
- }
- else {
- CXXRecordDecl *VBaseDecl =
- cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl());
- assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null");
- CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context);
- if (!Ctor) {
- Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 0 << VBase->getType();
- Diag(VBaseDecl->getLocation(), diag::note_previous_decl)
- << Context.getTagDeclType(VBaseDecl);
+ } else if (!AnyErrors) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeBase(Context, VBase);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid()) {
HadError = true;
continue;
}
- ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
- if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
- Constructor->getLocation(), CtorArgs))
+ // Don't attach synthesized base initializers in a dependent
+ // context; they'll be checked again at template instantiation
+ // time.
+ if (CurContext->isDependentContext())
continue;
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
-
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if
- // necessary.
- // FIXME: Is there any better source-location information we can give?
- ExprTemporaries.clear();
- CXXBaseOrMemberInitializer *Member =
+ CXXBaseOrMemberInitializer *CXXBaseInit =
new (Context) CXXBaseOrMemberInitializer(Context,
Context.getTrivialTypeSourceInfo(VBase->getType(),
SourceLocation()),
- Ctor,
SourceLocation(),
- CtorArgs.takeAs<Expr>(),
- CtorArgs.size(),
+ BaseInit.takeAs<Expr>(),
SourceLocation());
- AllToInit.push_back(Member);
+ AllToInit.push_back(CXXBaseInit);
}
}
@@ -1466,43 +1511,34 @@
= AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) {
AllToInit.push_back(Value);
}
- else {
- CXXRecordDecl *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
- assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null");
- CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context);
- if (!Ctor) {
- Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 0 << Base->getType();
- Diag(BaseDecl->getLocation(), diag::note_previous_decl)
- << Context.getTagDeclType(BaseDecl);
+ else if (!AnyErrors) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeBase(Context, Base);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit));
+ if (BaseInit.isInvalid()) {
HadError = true;
continue;
}
-
- ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
- if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
- Constructor->getLocation(), CtorArgs))
+
+ // Don't attach synthesized base initializers in a dependent
+ // context; they'll be regenerated at template instantiation
+ // time.
+ if (CurContext->isDependentContext())
continue;
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
-
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if
- // necessary.
- // FIXME: Is there any better source-location information we can give?
- ExprTemporaries.clear();
- CXXBaseOrMemberInitializer *Member =
+ CXXBaseOrMemberInitializer *CXXBaseInit =
new (Context) CXXBaseOrMemberInitializer(Context,
Context.getTrivialTypeSourceInfo(Base->getType(),
SourceLocation()),
- Ctor,
SourceLocation(),
- CtorArgs.takeAs<Expr>(),
- CtorArgs.size(),
+ BaseInit.takeAs<Expr>(),
SourceLocation());
- AllToInit.push_back(Member);
+ AllToInit.push_back(CXXBaseInit);
}
}
}
@@ -1535,66 +1571,49 @@
continue;
}
- if ((*Field)->getType()->isDependentType())
+ if ((*Field)->getType()->isDependentType() || AnyErrors)
continue;
QualType FT = Context.getBaseElementType((*Field)->getType());
- if (const RecordType* RT = FT->getAs<RecordType>()) {
- CXXConstructorDecl *Ctor =
- cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context);
- if (!Ctor) {
- Diag(Constructor->getLocation(), diag::err_missing_default_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 1 << (*Field)->getDeclName();
- Diag(Field->getLocation(), diag::note_field_decl);
- Diag(RT->getDecl()->getLocation(), diag::note_previous_decl)
- << Context.getTagDeclType(RT->getDecl());
+ if (FT->getAs<RecordType>()) {
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeMember(*Field);
+ InitializationKind InitKind
+ = InitializationKind::CreateDefault(Constructor->getLocation());
+
+ InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0);
+ OwningExprResult MemberInit = InitSeq.Perform(*this, InitEntity, InitKind,
+ MultiExprArg(*this, 0, 0));
+ MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit));
+ if (MemberInit.isInvalid()) {
HadError = true;
continue;
}
-
- if (FT.isConstQualified() && Ctor->isTrivial()) {
- Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
- << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
- << 1 << (*Field)->getDeclName();
- Diag((*Field)->getLocation(), diag::note_declared_at);
- HadError = true;
- }
-
- // Don't create initializers for trivial constructors, since they don't
- // actually need to be run.
- if (Ctor->isTrivial())
- continue;
-
- ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this);
- if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0),
- Constructor->getLocation(), CtorArgs))
+
+ // Don't attach synthesized member initializers in a dependent
+ // context; they'll be regenerated a template instantiation
+ // time.
+ if (CurContext->isDependentContext())
continue;
- // FIXME: CXXBaseOrMemberInitializer should only contain a single
- // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary.
- ExprTemporaries.clear();
CXXBaseOrMemberInitializer *Member =
new (Context) CXXBaseOrMemberInitializer(Context,
*Field, SourceLocation(),
- Ctor,
SourceLocation(),
- CtorArgs.takeAs<Expr>(),
- CtorArgs.size(),
+ MemberInit.takeAs<Expr>(),
SourceLocation());
AllToInit.push_back(Member);
- MarkDeclarationReferenced(Constructor->getLocation(), Ctor);
}
else if (FT->isReferenceType()) {
- Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
+ Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
<< (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
<< 0 << (*Field)->getDeclName();
Diag((*Field)->getLocation(), diag::note_declared_at);
HadError = true;
}
else if (FT.isConstQualified()) {
- Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor)
+ Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor)
<< (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl)
<< 1 << (*Field)->getDeclName();
Diag((*Field)->getLocation(), diag::note_declared_at);
@@ -1659,7 +1678,8 @@
/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
- MemInitTy **MemInits, unsigned NumMemInits) {
+ MemInitTy **MemInits, unsigned NumMemInits,
+ bool AnyErrors) {
if (!ConstructorDecl)
return;
@@ -1709,7 +1729,7 @@
SetBaseOrMemberInitializers(Constructor,
reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits),
- NumMemInits, false);
+ NumMemInits, false, AnyErrors);
if (Constructor->isDependentContext())
return;
@@ -1860,7 +1880,7 @@
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>()))
- SetBaseOrMemberInitializers(Constructor, 0, 0, false);
+ SetBaseOrMemberInitializers(Constructor, 0, 0, false, false);
}
namespace {
@@ -3673,13 +3693,16 @@
= cast<CXXRecordDecl>(Constructor->getDeclContext());
assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
- if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) {
+ DeclContext *PreviousContext = CurContext;
+ CurContext = Constructor;
+ if (SetBaseOrMemberInitializers(Constructor, 0, 0, true, false)) {
Diag(CurrentLocation, diag::note_member_synthesized_at)
<< CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
Constructor->setInvalidDecl();
} else {
Constructor->setUsed();
}
+ CurContext = PreviousContext;
}
void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
@@ -3688,6 +3711,10 @@
"DefineImplicitDestructor - call it for implicit default dtor");
CXXRecordDecl *ClassDecl = Destructor->getParent();
assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+
+ DeclContext *PreviousContext = CurContext;
+ CurContext = Destructor;
+
// C++ [class.dtor] p5
// Before the implicitly-declared default destructor for a class is
// implicitly defined, all the implicitly-declared default destructors
@@ -3734,8 +3761,11 @@
<< CXXDestructor << Context.getTagDeclType(ClassDecl);
Destructor->setInvalidDecl();
+ CurContext = PreviousContext;
+
return;
}
+ CurContext = PreviousContext;
Destructor->setUsed();
}
@@ -3750,6 +3780,9 @@
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(MethodDecl->getDeclContext());
+ DeclContext *PreviousContext = CurContext;
+ CurContext = MethodDecl;
+
// C++[class.copy] p12
// Before the implicitly-declared copy assignment operator for a class is
// implicitly defined, all implicitly-declared copy assignment operators
@@ -3793,6 +3826,8 @@
}
if (!err)
MethodDecl->setUsed();
+
+ CurContext = PreviousContext;
}
CXXMethodDecl *
@@ -3835,6 +3870,10 @@
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+
+ DeclContext *PreviousContext = CurContext;
+ CurContext = CopyConstructor;
+
// C++ [class.copy] p209
// Before the implicitly-declared copy constructor for a class is
// implicitly defined, all the implicitly-declared copy constructors
@@ -3863,13 +3902,16 @@
}
}
CopyConstructor->setUsed();
+
+ CurContext = PreviousContext;
}
Sema::OwningExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor,
MultiExprArg ExprArgs,
- bool RequiresZeroInit) {
+ bool RequiresZeroInit,
+ bool BaseInitialization) {
bool Elidable = false;
// C++ [class.copy]p15:
@@ -3902,7 +3944,8 @@
}
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
- Elidable, move(ExprArgs), RequiresZeroInit);
+ Elidable, move(ExprArgs), RequiresZeroInit,
+ BaseInitialization);
}
/// BuildCXXConstructExpr - Creates a complete call to a constructor,
@@ -3911,14 +3954,15 @@
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
MultiExprArg ExprArgs,
- bool RequiresZeroInit) {
+ bool RequiresZeroInit,
+ bool BaseInitialization) {
unsigned NumExprs = ExprArgs.size();
Expr **Exprs = (Expr **)ExprArgs.release();
MarkDeclarationReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, Exprs, NumExprs,
- RequiresZeroInit));
+ RequiresZeroInit, BaseInitialization));
}
Sema::OwningExprResult
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sun Jan 31 03:12:51 2010
@@ -2562,7 +2562,18 @@
Result);
return;
}
-
+
+ // C++0x [dcl.init]p6:
+ // If a program calls for the default initialization of an object
+ // of a const-qualified type T, T shall be a class type with a
+ // user-provided default constructor.
+ if (Kind.getKind() == InitializationKind::IK_Default &&
+ Entity.getType().isConstQualified() &&
+ cast<CXXConstructorDecl>(Best->Function)->isImplicit()) {
+ Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
+ return;
+ }
+
// Add the constructor initialization step. Any cv-qualification conversion is
// subsumed by the initialization.
if (Kind.getKind() == InitializationKind::IK_Copy) {
@@ -2635,9 +2646,6 @@
// constructor for T is called (and the initialization is ill-formed if
// T has no accessible default constructor);
if (DestType->isRecordType()) {
- // FIXME: If a program calls for the default initialization of an object of
- // a const-qualified type T, T shall be a class type with a user-provided
- // default constructor.
return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType,
Sequence);
}
@@ -3408,7 +3416,8 @@
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Constructor,
move_arg(ConstructorArgs),
- ConstructorInitRequiresZeroInit);
+ ConstructorInitRequiresZeroInit,
+ Entity.getKind() == InitializedEntity::EK_Base);
if (CurInit.isInvalid())
return S.ExprError();
@@ -3488,8 +3497,13 @@
QualType DestType = Entity.getType();
switch (Failure) {
case FK_TooManyInitsForReference:
- S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
- << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
+ // FIXME: Customize for the initialized entity?
+ if (NumArgs == 0)
+ S.Diag(Kind.getLocation(), diag::err_reference_without_init)
+ << DestType.getNonReferenceType();
+ else // FIXME: diagnostic below could be better!
+ S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+ << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd());
break;
case FK_ArrayNeedsInitList:
@@ -3634,6 +3648,45 @@
break;
case OR_No_Viable_Function:
+ if (Kind.getKind() == InitializationKind::IK_Default &&
+ (Entity.getKind() == InitializedEntity::EK_Base ||
+ Entity.getKind() == InitializedEntity::EK_Member) &&
+ isa<CXXConstructorDecl>(S.CurContext)) {
+ // This is implicit default initialization of a member or
+ // base within a constructor. If no viable function was
+ // found, notify the user that she needs to explicitly
+ // initialize this base/member.
+ CXXConstructorDecl *Constructor
+ = cast<CXXConstructorDecl>(S.CurContext);
+ if (Entity.getKind() == InitializedEntity::EK_Base) {
+ S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*base=*/0
+ << Entity.getType();
+
+ RecordDecl *BaseDecl
+ = Entity.getBaseSpecifier()->getType()->getAs<RecordType>()
+ ->getDecl();
+ S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
+ << S.Context.getTagDeclType(BaseDecl);
+ } else {
+ S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*member=*/1
+ << Entity.getName();
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl);
+
+ if (const RecordType *Record
+ = Entity.getType()->getAs<RecordType>())
+ S.Diag(Record->getDecl()->getLocation(),
+ diag::note_previous_decl)
+ << S.Context.getTagDeclType(Record->getDecl());
+ }
+ break;
+ }
+
S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
<< DestType << ArgsRange;
S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates,
@@ -3664,8 +3717,23 @@
}
case FK_DefaultInitOfConst:
- S.Diag(Kind.getLocation(), diag::err_default_init_const)
- << DestType;
+ if (Entity.getKind() == InitializedEntity::EK_Member &&
+ isa<CXXConstructorDecl>(S.CurContext)) {
+ // This is implicit default-initialization of a const member in
+ // a constructor. Complain that it needs to be explicitly
+ // initialized.
+ CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
+ S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
+ << Constructor->isImplicit()
+ << S.Context.getTypeDeclType(Constructor->getParent())
+ << /*const=*/1
+ << Entity.getName();
+ S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
+ << Entity.getName();
+ } else {
+ S.Diag(Kind.getLocation(), diag::err_default_init_const)
+ << DestType << (bool)DestType->getAs<RecordType>();
+ }
break;
}
Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Sun Jan 31 03:12:51 2010
@@ -66,7 +66,6 @@
/// \brief The entity being initialized is an element of a vector.
/// or vector.
EK_VectorElement
-
};
private:
@@ -95,8 +94,8 @@
/// base class.
CXXBaseSpecifier *Base;
- /// \brief When Kind = EK_ArrayOrVectorElement, the index of the
- /// array or vector element being initialized.
+ /// \brief When Kind = EK_ArrayElement or EK_VectorElement, the
+ /// index of the array or vector element being initialized.
unsigned Index;
};
@@ -201,6 +200,12 @@
/// initialized.
DeclaratorDecl *getDecl() const;
+ /// \brief Retrieve the base specifier.
+ CXXBaseSpecifier *getBaseSpecifier() const {
+ assert(getKind() == EK_Base && "Not a base specifier");
+ return Base;
+ }
+
/// \brief Determine the location of the 'return' keyword when initializing
/// the result of a function call.
SourceLocation getReturnLoc() const {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sun Jan 31 03:12:51 2010
@@ -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
Added: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp?rev=94952&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp (added)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp Sun Jan 31 03:12:51 2010
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// FIXME: Very incomplete!
+
+// If a program calls for the default initialization of an object of a
+// const-qualified type T, T shall be a class type with a
+// user-provided default constructor.
+struct NoUserDefault { };
+struct HasUserDefault { HasUserDefault(); };
+
+void test_const_default_init() {
+ const NoUserDefault x1; // expected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}}
+ const HasUserDefault x2;
+ const int x3; // FIXME: xpected-error{{default initialization of an object of const type 'struct NoUserDefault const' requires a user-provided default constructor}}
+}
Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp
------------------------------------------------------------------------------
svn:keywords = Id
Propchange: cfe/trunk/test/CXX/dcl.decl/dcl.init/p6.cpp
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: cfe/trunk/test/SemaCXX/constructor-initializer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constructor-initializer.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constructor-initializer.cpp (original)
+++ cfe/trunk/test/SemaCXX/constructor-initializer.cpp Sun Jan 31 03:12:51 2010
@@ -104,8 +104,8 @@
};
struct N : M {
- N() : M(1), // expected-error {{no matching constructor for initialization of 'M'}}
- m1(100) { } // expected-error {{no matching constructor for initialization of 'm1'}}
+ N() : M(1), // expected-error {{no matching constructor for initialization of 'struct M'}}
+ m1(100) { } // expected-error {{no matching constructor for initialization of 'struct M'}}
M m1;
};
@@ -116,8 +116,8 @@
};
struct Q {
- Q() : f1(1,2), // expected-error {{Too many arguments for member initializer 'f1'}}
- pf(0.0) { } // expected-error {{incompatible type passing 'double', expected 'float *'}}
+ Q() : f1(1,2), // expected-error {{excess elements in scalar initializer}}
+ pf(0.0) { } // expected-error {{cannot initialize a member subobject of type 'float *' with an rvalue of type 'double'}}
float f1;
float *pf;
Modified: cfe/trunk/test/SemaCXX/copy-assignment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/copy-assignment.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/copy-assignment.cpp (original)
+++ cfe/trunk/test/SemaCXX/copy-assignment.cpp Sun Jan 31 03:12:51 2010
@@ -47,22 +47,22 @@
void test() {
A a, na;
- const A constA;
+ const A constA = A();
ConvertibleToA convertibleToA;
ConvertibleToConstA convertibleToConstA;
B b, nb;
- const B constB;
+ const B constB = B();
ConvertibleToB convertibleToB;
ConvertibleToBref convertibleToBref;
ConvertibleToConstB convertibleToConstB;
ConvertibleToConstBref convertibleToConstBref;
C c, nc;
- const C constC;
+ const C constC = C();
D d, nd;
- const D constD;
+ const D constD = D();
ConvertibleToInt convertibleToInt;
Modified: cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/illegal-member-initialization.cpp Sun Jan 31 03:12:51 2010
@@ -1,9 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
struct A {
- A() : value(), cvalue() { } // expected-error {{cannot initialize the member to null in default constructor because reference member 'value' cannot be null-initialized}} \
- // expected-error {{constructor for 'struct A' must explicitly initialize the reference member 'value'}}
- int &value; // expected-note{{declared at}} {{expected-note{{declared at}}
+ A() : value(), cvalue() { } // expected-error {{reference to type 'int' requires an initializer}}
+ int &value;
const int cvalue;
};
@@ -18,7 +17,7 @@
int &value; // expected-note{{declared at}}
const int cvalue; // expected-note{{declared at}}
B& b; // expected-note{{declared at}}
- const B cb; // expected-note{{declared at}}
+ const B cb; // expected-note{{declared here}}
};
Modified: cfe/trunk/test/SemaCXX/overload-member-call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overload-member-call.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overload-member-call.cpp (original)
+++ cfe/trunk/test/SemaCXX/overload-member-call.cpp Sun Jan 31 03:12:51 2010
@@ -89,7 +89,7 @@
A a;
a.foo(4, "hello"); //expected-error {{no matching member function for call to 'foo'}}
- const A b;
+ const A b = A();
b.bar(0); //expected-error {{no matching member function for call to 'bar'}}
a.baz(b); //expected-error {{no matching member function for call to 'baz'}}
Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Sun Jan 31 03:12:51 2010
@@ -344,7 +344,7 @@
int operator[](unsigned); // expected-note {{candidate}}
};
int test1() {
- const NonConstArray x;
+ const NonConstArray x = NonConstArray();
return x[0]; // expected-error {{no viable overloaded operator[] for type}}
}
Modified: cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp?rev=94952&r1=94951&r2=94952&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-initializers.cpp Sun Jan 31 03:12:51 2010
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -Wall -verify %s
template<typename T> struct A {
- A() : a(1) { } // expected-error{{incompatible type passing 'int', expected 'void *'}}
+ A() : a(1) { } // expected-error{{cannot initialize a member subobject of type 'void *' with an rvalue of type 'int'}}
T a;
};
More information about the cfe-commits
mailing list