[cfe-commits] r147145 - in /cfe/trunk: include/clang/Sema/Initialization.h lib/Sema/SemaInit.cpp test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp test/SemaCXX/aggregate-initialization.cpp test/SemaCXX/cxx0x-initializer-constructor.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Thu Dec 22 06:44:04 PST 2011
Author: cornedbee
Date: Thu Dec 22 08:44:04 2011
New Revision: 147145
URL: http://llvm.org/viewvc/llvm-project?rev=147145&view=rev
Log:
List-initialization via constructor part 1. Still needs: pretty-printing, overloading, initializer_list.
Added:
cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
Modified:
cfe/trunk/include/clang/Sema/Initialization.h
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp
cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=147145&r1=147144&r2=147145&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Thu Dec 22 08:44:04 2011
@@ -825,18 +825,19 @@
void AddConversionSequenceStep(const ImplicitConversionSequence &ICS,
QualType T);
- /// \brief Add a list-initialiation step.
+ /// \brief Add a list-initialization step.
void AddListInitializationStep(QualType T);
/// \brief Add a constructor-initialization step.
void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
AccessSpecifier Access,
QualType T,
- bool HadMultipleCandidates);
+ bool HadMultipleCandidates,
+ bool FromInitList);
/// \brief Add a zero-initialization step.
void AddZeroInitializationStep(QualType T);
-
+
/// \brief Add a C assignment step.
//
// FIXME: It isn't clear whether this should ever be needed;
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=147145&r1=147144&r2=147145&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Dec 22 08:44:04 2011
@@ -2701,9 +2701,10 @@
::AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
AccessSpecifier Access,
QualType T,
- bool HadMultipleCandidates) {
+ bool HadMultipleCandidates,
+ bool FromInitList) {
Step S;
- S.Kind = SK_ConstructorInitialization;
+ S.Kind = FromInitList ? SK_ListConstructorCall : SK_ConstructorInitialization;
S.Type = T;
S.Function.HadMultipleCandidates = HadMultipleCandidates;
S.Function.Function = Constructor;
@@ -2815,6 +2816,178 @@
}
}
+/// \brief When initializing from init list via constructor, deal with the
+/// empty init list and std::initializer_list special cases.
+///
+/// \return True if this was a special case, false otherwise.
+static bool TryListConstructionSpecialCases(Sema &S,
+ Expr **Args, unsigned NumArgs,
+ CXXRecordDecl *DestRecordDecl,
+ QualType DestType,
+ InitializationSequence &Sequence) {
+ // C++0x [dcl.init.list]p3:
+ // List-initialization of an object of type T is defined as follows:
+ // - If the initializer list has no elements and T is a class type with
+ // a default constructor, the object is value-initialized.
+ if (NumArgs == 0) {
+ if (CXXConstructorDecl *DefaultConstructor =
+ S.LookupDefaultConstructor(DestRecordDecl)) {
+ if (DefaultConstructor->isDeleted() ||
+ S.isFunctionConsideredUnavailable(DefaultConstructor)) {
+ // Fake an overload resolution failure.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ DeclAccessPair FoundDecl = DeclAccessPair::make(DefaultConstructor,
+ DefaultConstructor->getAccess());
+ if (FunctionTemplateDecl *ConstructorTmpl =
+ dyn_cast<FunctionTemplateDecl>(DefaultConstructor))
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ /*ExplicitArgs*/ 0,
+ Args, NumArgs, CandidateSet,
+ /*SuppressUserConversions*/ false);
+ else
+ S.AddOverloadCandidate(DefaultConstructor, FoundDecl,
+ Args, NumArgs, CandidateSet,
+ /*SuppressUserConversions*/ false);
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ConstructorOverloadFailed,
+ OR_Deleted);
+ } else
+ Sequence.AddConstructorInitializationStep(DefaultConstructor,
+ DefaultConstructor->getAccess(),
+ DestType,
+ /*MultipleCandidates=*/false,
+ /*FromInitList=*/true);
+ return true;
+ }
+ }
+
+ // - Otherwise, if T is a specialization of std::initializer_list, [...]
+ // FIXME: Implement.
+
+ // Not a special case.
+ return false;
+}
+
+/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
+/// enumerates the constructors of the initialized entity and performs overload
+/// resolution to select the best.
+/// If FromInitList is true, this is list-initialization of a non-aggregate
+/// class type.
+static void TryConstructorInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ Expr **Args, unsigned NumArgs,
+ QualType DestType,
+ InitializationSequence &Sequence,
+ bool FromInitList = false) {
+ // Check constructor arguments for self reference.
+ if (DeclaratorDecl *DD = Entity.getDecl())
+ // Parameters arguments are occassionially constructed with itself,
+ // for instance, in recursive functions. Skip them.
+ if (!isa<ParmVarDecl>(DD))
+ for (unsigned i = 0; i < NumArgs; ++i)
+ S.CheckSelfReference(DD, Args[i]);
+
+ // Build the candidate set directly in the initialization sequence
+ // structure, so that it will persist if we fail.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ CandidateSet.clear();
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
+ Kind.getKind() == InitializationKind::IK_Value ||
+ Kind.getKind() == InitializationKind::IK_Default);
+
+ // The type we're constructing needs to be complete.
+ if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
+ Sequence.SetFailed(InitializationSequence::FK_Incomplete);
+ }
+
+ const RecordType *DestRecordType = DestType->getAs<RecordType>();
+ assert(DestRecordType && "Constructor initialization requires record type");
+ CXXRecordDecl *DestRecordDecl
+ = cast<CXXRecordDecl>(DestRecordType->getDecl());
+
+ if (FromInitList &&
+ TryListConstructionSpecialCases(S, Args, NumArgs, DestRecordDecl,
+ DestType, Sequence))
+ return;
+
+ // - Otherwise, if T is a class type, constructors are considered. The
+ // applicable constructors are enumerated, and the best one is chosen
+ // through overload resolution.
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
+ Con != ConEnd; ++Con) {
+ NamedDecl *D = *Con;
+ DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+ bool SuppressUserConversions = false;
+
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
+ if (ConstructorTmpl)
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ else {
+ Constructor = cast<CXXConstructorDecl>(D);
+
+ // If we're performing copy initialization using a copy constructor, we
+ // suppress user-defined conversions on the arguments.
+ // FIXME: Move constructors?
+ if (Kind.getKind() == InitializationKind::IK_Copy &&
+ Constructor->isCopyConstructor())
+ SuppressUserConversions = true;
+ }
+
+ if (!Constructor->isInvalidDecl() &&
+ (AllowExplicit || !Constructor->isExplicit())) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+ /*ExplicitArgs*/ 0,
+ Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+ else
+ S.AddOverloadCandidate(Constructor, FoundDecl,
+ Args, NumArgs, CandidateSet,
+ SuppressUserConversions);
+ }
+ }
+
+ SourceLocation DeclLoc = Kind.getLocation();
+
+ // Perform overload resolution. If it fails, return the failed result.
+ OverloadCandidateSet::iterator Best;
+ if (OverloadingResult Result
+ = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ConstructorOverloadFailed,
+ 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.
+ bool HadMultipleCandidates = (CandidateSet.size() > 1);
+ CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+ Sequence.AddConstructorInitializationStep(CtorDecl,
+ Best->FoundDecl.getAccess(),
+ DestType, HadMultipleCandidates,
+ FromInitList);
+}
+
static bool
ResolveOverloadedFunctionForReferenceBinding(Sema &S,
Expr *Initializer,
@@ -2942,9 +3115,13 @@
TryReferenceListInitialization(S, Entity, Kind, InitList, Sequence);
return;
}
- // FIXME: C++11 defines behavior for this case.
if (DestType->isRecordType() && !DestType->isAggregateType()) {
- Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
+ if (S.getLangOptions().CPlusPlus0x)
+ TryConstructorInitialization(S, Entity, Kind, InitList->getInits(),
+ InitList->getNumInits(), DestType, Sequence,
+ /*FromInitList=*/true);
+ else
+ Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
return;
}
@@ -3420,117 +3597,6 @@
Sequence.AddStringInitStep(Entity.getType());
}
-/// \brief Attempt initialization by constructor (C++ [dcl.init]), which
-/// enumerates the constructors of the initialized entity and performs overload
-/// resolution to select the best.
-static void TryConstructorInitialization(Sema &S,
- const InitializedEntity &Entity,
- const InitializationKind &Kind,
- Expr **Args, unsigned NumArgs,
- QualType DestType,
- InitializationSequence &Sequence) {
- // Check constructor arguments for self reference.
- if (DeclaratorDecl *DD = Entity.getDecl())
- // Parameters arguments are occassionially constructed with itself,
- // for instance, in recursive functions. Skip them.
- if (!isa<ParmVarDecl>(DD))
- for (unsigned i = 0; i < NumArgs; ++i)
- S.CheckSelfReference(DD, Args[i]);
-
- // Build the candidate set directly in the initialization sequence
- // structure, so that it will persist if we fail.
- OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
- CandidateSet.clear();
-
- // Determine whether we are allowed to call explicit constructors or
- // explicit conversion operators.
- bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
- Kind.getKind() == InitializationKind::IK_Value ||
- Kind.getKind() == InitializationKind::IK_Default);
-
- // The type we're constructing needs to be complete.
- if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
- Sequence.SetFailed(InitializationSequence::FK_Incomplete);
- return;
- }
-
- // The type we're converting to is a class type. Enumerate its constructors
- // to see if one is suitable.
- const RecordType *DestRecordType = DestType->getAs<RecordType>();
- assert(DestRecordType && "Constructor initialization requires record type");
- CXXRecordDecl *DestRecordDecl
- = cast<CXXRecordDecl>(DestRecordType->getDecl());
-
- DeclContext::lookup_iterator Con, ConEnd;
- for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl);
- Con != ConEnd; ++Con) {
- NamedDecl *D = *Con;
- DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
- bool SuppressUserConversions = false;
-
- // Find the constructor (which may be a template).
- CXXConstructorDecl *Constructor = 0;
- FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
- if (ConstructorTmpl)
- Constructor = cast<CXXConstructorDecl>(
- ConstructorTmpl->getTemplatedDecl());
- else {
- Constructor = cast<CXXConstructorDecl>(D);
-
- // If we're performing copy initialization using a copy constructor, we
- // suppress user-defined conversions on the arguments.
- // FIXME: Move constructors?
- if (Kind.getKind() == InitializationKind::IK_Copy &&
- Constructor->isCopyConstructor())
- SuppressUserConversions = true;
- }
-
- if (!Constructor->isInvalidDecl() &&
- (AllowExplicit || !Constructor->isExplicit())) {
- if (ConstructorTmpl)
- S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
- /*ExplicitArgs*/ 0,
- Args, NumArgs, CandidateSet,
- SuppressUserConversions);
- else
- S.AddOverloadCandidate(Constructor, FoundDecl,
- Args, NumArgs, CandidateSet,
- SuppressUserConversions);
- }
- }
-
- SourceLocation DeclLoc = Kind.getLocation();
-
- // Perform overload resolution. If it fails, return the failed result.
- OverloadCandidateSet::iterator Best;
- if (OverloadingResult Result
- = CandidateSet.BestViableFunction(S, DeclLoc, Best)) {
- Sequence.SetOverloadFailure(
- InitializationSequence::FK_ConstructorOverloadFailed,
- 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.
- bool HadMultipleCandidates = (CandidateSet.size() > 1);
- CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
- Sequence.AddConstructorInitializationStep(CtorDecl,
- Best->FoundDecl.getAccess(),
- DestType, HadMultipleCandidates);
-}
-
/// \brief Attempt value initialization (C++ [dcl.init]p7).
static void TryValueInitialization(Sema &S,
const InitializedEntity &Entity,
@@ -4526,6 +4592,117 @@
s.Kind == InitializationSequence::SK_BindReferenceToTemporary;
}
+static ExprResult
+PerformConstructorInitialization(Sema &S,
+ const InitializedEntity &Entity,
+ const InitializationKind &Kind,
+ MultiExprArg Args,
+ const InitializationSequence::Step& Step,
+ bool &ConstructorInitRequiresZeroInit) {
+ unsigned NumArgs = Args.size();
+ CXXConstructorDecl *Constructor
+ = cast<CXXConstructorDecl>(Step.Function.Function);
+ bool HadMultipleCandidates = Step.Function.HadMultipleCandidates;
+
+ // Build a call to the selected constructor.
+ ASTOwningVector<Expr*> ConstructorArgs(S);
+ SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
+ ? Kind.getEqualLoc()
+ : Kind.getLocation();
+
+ if (Kind.getKind() == InitializationKind::IK_Default) {
+ // Force even a trivial, implicit default constructor to be
+ // semantically checked. We do this explicitly because we don't build
+ // the definition for completely trivial constructors.
+ CXXRecordDecl *ClassDecl = Constructor->getParent();
+ assert(ClassDecl && "No parent class for constructor.");
+ if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
+ ClassDecl->hasTrivialDefaultConstructor() &&
+ !Constructor->isUsed(false))
+ S.DefineImplicitDefaultConstructor(Loc, Constructor);
+ }
+
+ ExprResult CurInit = S.Owned((Expr *)0);
+
+ // Determine the arguments required to actually perform the constructor
+ // call.
+ if (S.CompleteConstructorCall(Constructor, move(Args),
+ Loc, ConstructorArgs))
+ return ExprError();
+
+
+ if (Entity.getKind() == InitializedEntity::EK_Temporary &&
+ NumArgs != 1 && // FIXME: Hack to work around cast weirdness
+ (Kind.getKind() == InitializationKind::IK_Direct ||
+ Kind.getKind() == InitializationKind::IK_Value)) {
+ // An explicitly-constructed temporary, e.g., X(1, 2).
+ unsigned NumExprs = ConstructorArgs.size();
+ Expr **Exprs = (Expr **)ConstructorArgs.take();
+ S.MarkDeclarationReferenced(Loc, Constructor);
+ S.DiagnoseUseOfDecl(Constructor, Loc);
+
+ TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
+ if (!TSInfo)
+ TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
+
+ CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
+ Constructor,
+ TSInfo,
+ Exprs,
+ NumExprs,
+ Kind.getParenRange(),
+ HadMultipleCandidates,
+ ConstructorInitRequiresZeroInit));
+ } else {
+ CXXConstructExpr::ConstructionKind ConstructKind =
+ CXXConstructExpr::CK_Complete;
+
+ if (Entity.getKind() == InitializedEntity::EK_Base) {
+ ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
+ CXXConstructExpr::CK_VirtualBase :
+ CXXConstructExpr::CK_NonVirtualBase;
+ } else if (Entity.getKind() == InitializedEntity::EK_Delegating) {
+ ConstructKind = CXXConstructExpr::CK_Delegating;
+ }
+
+ // Only get the parenthesis range if it is a direct construction.
+ SourceRange parenRange =
+ Kind.getKind() == InitializationKind::IK_Direct ?
+ Kind.getParenRange() : SourceRange();
+
+ // If the entity allows NRVO, mark the construction as elidable
+ // unconditionally.
+ if (Entity.allowsNRVO())
+ CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ Constructor, /*Elidable=*/true,
+ move_arg(ConstructorArgs),
+ HadMultipleCandidates,
+ ConstructorInitRequiresZeroInit,
+ ConstructKind,
+ parenRange);
+ else
+ CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
+ Constructor,
+ move_arg(ConstructorArgs),
+ HadMultipleCandidates,
+ ConstructorInitRequiresZeroInit,
+ ConstructKind,
+ parenRange);
+ }
+ if (CurInit.isInvalid())
+ return ExprError();
+
+ // Only check access if all of that succeeded.
+ S.CheckConstructorAccess(Loc, Constructor, Entity,
+ Step.Function.FoundDecl.getAccess());
+ S.DiagnoseUseOfDecl(Step.Function.FoundDecl, Loc);
+
+ if (shouldBindAsTemporary(Entity))
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+
+ return move(CurInit);
+}
+
ExprResult
InitializationSequence::Perform(Sema &S,
const InitializedEntity &Entity,
@@ -4910,8 +5087,14 @@
break;
}
- case SK_ListConstructorCall:
- assert(false && "List constructor calls not yet supported.");
+ case SK_ListConstructorCall: {
+ InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
+ MultiExprArg Arg(InitList->getInits(), InitList->getNumInits());
+ CurInit = PerformConstructorInitialization(S, Entity, Kind,
+ move(Arg), *Step,
+ ConstructorInitRequiresZeroInit);
+ break;
+ }
case SK_UnwrapInitList:
CurInit = S.Owned(cast<InitListExpr>(CurInit.take())->getInit(0));
@@ -4929,108 +5112,11 @@
break;
}
- case SK_ConstructorInitialization: {
- unsigned NumArgs = Args.size();
- CXXConstructorDecl *Constructor
- = cast<CXXConstructorDecl>(Step->Function.Function);
- bool HadMultipleCandidates = Step->Function.HadMultipleCandidates;
-
- // Build a call to the selected constructor.
- ASTOwningVector<Expr*> ConstructorArgs(S);
- SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid())
- ? Kind.getEqualLoc()
- : Kind.getLocation();
-
- if (Kind.getKind() == InitializationKind::IK_Default) {
- // Force even a trivial, implicit default constructor to be
- // semantically checked. We do this explicitly because we don't build
- // the definition for completely trivial constructors.
- CXXRecordDecl *ClassDecl = Constructor->getParent();
- assert(ClassDecl && "No parent class for constructor.");
- if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
- ClassDecl->hasTrivialDefaultConstructor() &&
- !Constructor->isUsed(false))
- S.DefineImplicitDefaultConstructor(Loc, Constructor);
- }
-
- // Determine the arguments required to actually perform the constructor
- // call.
- if (S.CompleteConstructorCall(Constructor, move(Args),
- Loc, ConstructorArgs))
- return ExprError();
-
-
- if (Entity.getKind() == InitializedEntity::EK_Temporary &&
- NumArgs != 1 && // FIXME: Hack to work around cast weirdness
- (Kind.getKind() == InitializationKind::IK_Direct ||
- Kind.getKind() == InitializationKind::IK_Value)) {
- // An explicitly-constructed temporary, e.g., X(1, 2).
- unsigned NumExprs = ConstructorArgs.size();
- Expr **Exprs = (Expr **)ConstructorArgs.take();
- S.MarkDeclarationReferenced(Loc, Constructor);
- S.DiagnoseUseOfDecl(Constructor, Loc);
-
- TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
- if (!TSInfo)
- TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc);
-
- CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context,
- Constructor,
- TSInfo,
- Exprs,
- NumExprs,
- Kind.getParenRange(),
- HadMultipleCandidates,
- ConstructorInitRequiresZeroInit));
- } else {
- CXXConstructExpr::ConstructionKind ConstructKind =
- CXXConstructExpr::CK_Complete;
-
- if (Entity.getKind() == InitializedEntity::EK_Base) {
- ConstructKind = Entity.getBaseSpecifier()->isVirtual() ?
- CXXConstructExpr::CK_VirtualBase :
- CXXConstructExpr::CK_NonVirtualBase;
- } else if (Entity.getKind() == InitializedEntity::EK_Delegating) {
- ConstructKind = CXXConstructExpr::CK_Delegating;
- }
-
- // Only get the parenthesis range if it is a direct construction.
- SourceRange parenRange =
- Kind.getKind() == InitializationKind::IK_Direct ?
- Kind.getParenRange() : SourceRange();
-
- // If the entity allows NRVO, mark the construction as elidable
- // unconditionally.
- if (Entity.allowsNRVO())
- CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
- Constructor, /*Elidable=*/true,
- move_arg(ConstructorArgs),
- HadMultipleCandidates,
- ConstructorInitRequiresZeroInit,
- ConstructKind,
- parenRange);
- else
- CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
- Constructor,
- move_arg(ConstructorArgs),
- HadMultipleCandidates,
- ConstructorInitRequiresZeroInit,
- ConstructKind,
- parenRange);
- }
- if (CurInit.isInvalid())
- return ExprError();
-
- // Only check access if all of that succeeded.
- S.CheckConstructorAccess(Loc, Constructor, Entity,
- Step->Function.FoundDecl.getAccess());
- S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc);
-
- if (shouldBindAsTemporary(Entity))
- CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
-
+ case SK_ConstructorInitialization:
+ CurInit = PerformConstructorInitialization(S, Entity, Kind, move(Args),
+ *Step,
+ ConstructorInitRequiresZeroInit);
break;
- }
case SK_ZeroInitialization: {
step_iterator NextStep = Step;
Modified: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp?rev=147145&r1=147144&r2=147145&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp (original)
+++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1-0x.cpp Thu Dec 22 08:44:04 2011
@@ -14,56 +14,56 @@
Aggr ag = { b };
// with no user-provided constructors, ...
-struct NonAggr1a {
- NonAggr1a(int, int);
+struct NonAggr1a { // expected-note 2 {{candidate constructor}}
+ NonAggr1a(int, int); // expected-note {{candidate constructor}}
int k;
};
// In C++0x, 'user-provided' is only defined for special member functions, so
// this type is considered to be an aggregate. This is considered to be
// a language defect.
-NonAggr1a na1a = { 42 }; // expected-error {{non-aggregate type 'NonAggr1a'}}
+NonAggr1a na1a = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr1a'}}
struct NonAggr1b {
- NonAggr1b(const NonAggr1b &);
+ NonAggr1b(const NonAggr1b &); // expected-note {{candidate constructor}}
int k;
};
-NonAggr1b na1b = { 42 }; // expected-error {{non-aggregate type 'NonAggr1b'}}
+NonAggr1b na1b = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr1b'}}
// no brace-or-equal-initializers for non-static data members, ...
-struct NonAggr2 {
+struct NonAggr2 { // expected-note 3 {{candidate constructor}}
int m = { 123 };
};
-NonAggr2 na2 = { 42 }; // expected-error {{non-aggregate type 'NonAggr2'}}
+NonAggr2 na2 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr2'}}
// no private...
-struct NonAggr3 {
+struct NonAggr3 { // expected-note 3 {{candidate constructor}}
private:
int n;
};
-NonAggr3 na3 = { 42 }; // expected-error {{non-aggregate type 'NonAggr3'}}
+NonAggr3 na3 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr3'}}
// or protected non-static data members, ...
-struct NonAggr4 {
+struct NonAggr4 { // expected-note 3 {{candidate constructor}}
protected:
int n;
};
-NonAggr4 na4 = { 42 }; // expected-error {{non-aggregate type 'NonAggr4'}}
+NonAggr4 na4 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr4'}}
// no base classes, ...
-struct NonAggr5 : Aggr {
+struct NonAggr5 : Aggr { // expected-note 3 {{candidate constructor}}
};
-NonAggr5 na5 = { b }; // expected-error {{non-aggregate type 'NonAggr5'}}
+NonAggr5 na5 = { b }; // expected-error {{no matching constructor for initialization of 'NonAggr5'}}
template<typename...BaseList>
-struct MaybeAggr5a : BaseList... {};
+struct MaybeAggr5a : BaseList... {}; // expected-note {{explicitly marked deleted}}
MaybeAggr5a<> ma5a0 = {}; // ok
-MaybeAggr5a<Aggr> ma5a1 = {}; // expected-error {{non-aggregate type 'MaybeAggr5a<Aggr>'}}
+MaybeAggr5a<Aggr> ma5a1 = {}; // expected-error {{call to deleted constructor of 'MaybeAggr5a<Aggr>'}}
// and no virtual functions.
-struct NonAggr6 {
+struct NonAggr6 { // expected-note 3 {{candidate constructor}}
virtual void f();
int n;
};
-NonAggr6 na6 = { 42 }; // expected-error {{non-aggregate type 'NonAggr6'}}
+NonAggr6 na6 = { 42 }; // expected-error {{no matching constructor for initialization of 'NonAggr6'}}
struct DefaultedAggr {
int n;
Modified: cfe/trunk/test/SemaCXX/aggregate-initialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/aggregate-initialization.cpp?rev=147145&r1=147144&r2=147145&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/aggregate-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/aggregate-initialization.cpp Thu Dec 22 08:44:04 2011
@@ -1,33 +1,33 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// Verify that we can't initialize non-aggregates with an initializer
-// list.
+// Verify that using an initializer list for a non-aggregate looks for
+// constructors..
// Note that due to a (likely) standard bug, this is technically an aggregate,
// but we do not treat it as one.
-struct NonAggr1 {
- NonAggr1(int) { }
+struct NonAggr1 { // expected-note 2 {{candidate constructor}}
+ NonAggr1(int, int) { } // expected-note {{candidate constructor}}
int m;
};
struct Base { };
-struct NonAggr2 : public Base {
+struct NonAggr2 : public Base { // expected-note 3 {{candidate constructor}}
int m;
};
-class NonAggr3 {
+class NonAggr3 { // expected-note 3 {{candidate constructor}}
int m;
};
-struct NonAggr4 {
+struct NonAggr4 { // expected-note 3 {{candidate constructor}}
int m;
virtual void f();
};
-NonAggr1 na1 = { 17 }; // expected-error{{non-aggregate type 'NonAggr1' cannot be initialized with an initializer list}}
-NonAggr2 na2 = { 17 }; // expected-error{{non-aggregate type 'NonAggr2' cannot be initialized with an initializer list}}
-NonAggr3 na3 = { 17 }; // expected-error{{non-aggregate type 'NonAggr3' cannot be initialized with an initializer list}}
-NonAggr4 na4 = { 17 }; // expected-error{{non-aggregate type 'NonAggr4' cannot be initialized with an initializer list}}
+NonAggr1 na1 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr1'}}
+NonAggr2 na2 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr2'}}
+NonAggr3 na3 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr3'}}
+NonAggr4 na4 = { 17 }; // expected-error{{no matching constructor for initialization of 'NonAggr4'}}
// PR5817
typedef int type[][2];
Added: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp?rev=147145&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Thu Dec 22 08:44:04 2011
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+namespace objects {
+
+ struct X1 { X1(int); };
+ struct X2 { explicit X2(int); }; // expected-note 2 {{candidate constructor}}
+
+ template <int N>
+ struct A {
+ A() { static_assert(N == 0, ""); }
+ A(int, double) { static_assert(N == 1, ""); }
+ };
+
+ template <int N>
+ struct E {
+ E(int, int) { static_assert(N == 0, ""); }
+ E(X1, int) { static_assert(N == 1, ""); }
+ };
+
+ void overload_resolution() {
+ { A<0> a{}; }
+ { A<0> a = {}; }
+ { A<1> a{1, 1.0}; }
+ { A<1> a = {1, 1.0}; }
+
+ { E<0> e{1, 2}; }
+ }
+
+ void explicit_implicit() {
+ { X1 x{0}; }
+ { X1 x = {0}; }
+ { X2 x{0}; }
+ { X2 x = {0}; } // expected-error {{no matching constructor}}
+ }
+
+ struct C {
+ C();
+ C(int, double);
+ C(int, int);
+
+ int operator[](C);
+ };
+
+ C function_call() {
+ void takes_C(C);
+ takes_C({1, 1.0});
+
+ //C c;
+ //c[{1, 1.0}]; needs overloading
+
+ return {1, 1.0};
+ }
+
+ void inline_init() {
+ //(void) C{1, 1.0}; FIXME: inline initialization
+ (void) new C{1, 1.0};
+ }
+
+ struct B {
+ B(C, int, C);
+ };
+
+ void nested_init() {
+ //B b{{1, 1.0}, 2, {3, 4}}; needs overloading
+ }
+}
More information about the cfe-commits
mailing list