[cfe-commits] r150342 - in /cfe/trunk: include/clang/Sema/Initialization.h lib/Sema/SemaDecl.cpp lib/Sema/SemaInit.cpp test/SemaCXX/cxx0x-initializer-constructor.cpp test/SemaCXX/generalized-initializers.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Feb 12 08:37:24 PST 2012
Author: cornedbee
Date: Sun Feb 12 10:37:24 2012
New Revision: 150342
URL: http://llvm.org/viewvc/llvm-project?rev=150342&view=rev
Log:
Employ DirectList initialized entities to properly sort through some initialization edge cases.
Modified:
cfe/trunk/include/clang/Sema/Initialization.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
cfe/trunk/test/SemaCXX/generalized-initializers.cpp
Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=150342&r1=150341&r2=150342&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Sun Feb 12 10:37:24 2012
@@ -470,9 +470,13 @@
assert(Kind == SIK_Copy && "Only copy initialization has an '='");
return Locations[1];
}
-
+
bool isCopyInit() const { return Kind == SIK_Copy; }
-
+
+ /// \brief Retrieve whether this initialization allows the use of explicit
+ /// constructors.
+ bool AllowExplicit() const { return !isCopyInit(); }
+
/// \brief Retrieve the source range containing the locations of the open
/// and closing parentheses for value and direct initializations.
SourceRange getParenRange() const {
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=150342&r1=150341&r2=150342&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Feb 12 10:37:24 2012
@@ -6143,9 +6143,12 @@
if (!VDecl->isInvalidDecl()) {
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
InitializationKind Kind
- = DirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(),
- Init->getLocStart(),
- Init->getLocEnd())
+ = DirectInit ?
+ CXXDirectInit ? InitializationKind::CreateDirect(VDecl->getLocation(),
+ Init->getLocStart(),
+ Init->getLocEnd())
+ : InitializationKind::CreateDirectList(
+ VDecl->getLocation())
: InitializationKind::CreateCopy(VDecl->getLocation(),
Init->getLocStart());
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=150342&r1=150341&r2=150342&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Sun Feb 12 10:37:24 2012
@@ -2860,9 +2860,7 @@
// 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);
+ bool AllowExplicit = Kind.AllowExplicit();
bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;
// - Otherwise, if T is a class type, constructors are considered. The
@@ -3065,8 +3063,10 @@
if (DestType->isRecordType() && !DestType->isAggregateType()) {
if (S.getLangOptions().CPlusPlus0x) {
Expr *Arg = InitList;
+ // A direct-initializer is not list-syntax, i.e. there's no special
+ // treatment of "A a({1, 2});".
TryConstructorInitialization(S, Entity, Kind, &Arg, 1, DestType,
- Sequence, /*InitListSyntax=*/true);
+ Sequence, Kind.getKind() != InitializationKind::IK_Direct);
} else
Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType);
return;
@@ -3074,7 +3074,7 @@
InitListChecker CheckInitList(S, Entity, InitList,
DestType, /*VerifyOnly=*/true,
- Kind.getKind() != InitializationKind::IK_Direct ||
+ Kind.getKind() != InitializationKind::IK_DirectList ||
!S.getLangOptions().CPlusPlus0x);
if (CheckInitList.HadError()) {
Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed);
@@ -3118,7 +3118,7 @@
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
- bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+ bool AllowExplicit = Kind.AllowExplicit();
const RecordType *T1RecordType = 0;
if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) &&
@@ -3480,7 +3480,7 @@
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
- bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct);
+ bool AllowExplicit = Kind.AllowExplicit();
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1);
@@ -3643,7 +3643,7 @@
// Determine whether we are allowed to call explicit constructors or
// explicit conversion operators.
- bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct;
+ bool AllowExplicit = Kind.AllowExplicit();
if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) {
// The type we're converting to is a class type. Enumerate its constructors
@@ -5028,7 +5028,7 @@
InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty);
InitListChecker PerformInitList(S, IsTemporary ? TempEntity : Entity,
InitList, Ty, /*VerifyOnly=*/false,
- Kind.getKind() != InitializationKind::IK_Direct ||
+ Kind.getKind() != InitializationKind::IK_DirectList ||
!S.getLangOptions().CPlusPlus0x);
if (PerformInitList.HadError())
return ExprError();
@@ -5050,10 +5050,19 @@
}
case SK_ListConstructorCall: {
+ // When an initializer list is passed for a parameter of type "reference
+ // to object", we don't get an EK_Temporary entity, but instead an
+ // EK_Parameter entity with reference type.
+ // FIXME: This is a hack. Why is this necessary here, but not in other
+ // places where implicit temporaries are created?
+ InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
+ Entity.getType().getNonReferenceType());
+ bool UseTemporary = Entity.getType()->isReferenceType();
InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
MultiExprArg Arg(InitList->getInits(), InitList->getNumInits());
- CurInit = PerformConstructorInitialization(S, Entity, Kind,
- move(Arg), *Step,
+ CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity :
+ Entity,
+ Kind, move(Arg), *Step,
ConstructorInitRequiresZeroInit);
break;
}
@@ -5549,7 +5558,7 @@
QualType DestType = Entity.getType();
InitListChecker DiagnoseInitList(S, Entity, InitList,
DestType, /*VerifyOnly=*/false,
- Kind.getKind() != InitializationKind::IK_Direct ||
+ Kind.getKind() != InitializationKind::IK_DirectList ||
!S.getLangOptions().CPlusPlus0x);
assert(DiagnoseInitList.HadError() &&
"Inconsistent init list check result.");
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp?rev=150342&r1=150341&r2=150342&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Sun Feb 12 10:37:24 2012
@@ -146,4 +146,33 @@
static_assert(sizeof(ov2({1})) == sizeof(one), "bad overload"); // list -> int ranks as identity
static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable
}
+
+ struct G { // expected-note 2 {{not viable}}
+ // This is not an initializer-list constructor.
+ template<typename ...T>
+ G(std::initializer_list<int>, T ...); // expected-note {{not viable}}
+ };
+
+ struct H { // expected-note 2 {{not viable}}
+ explicit H(int, int); // expected-note {{not viable}}
+ H(int, void*); // expected-note {{not viable}}
+ };
+
+ void edge_cases() {
+ // invalid (the first phase only considers init-list ctors)
+ // (for the second phase, no constructor is viable)
+ G g1{1, 2, 3}; // expected-error {{no matching constructor}}
+
+ // valid (T deduced to <>).
+ G g2({1, 2, 3});
+
+ // invalid
+ H h1({1, 2}); // expected-error {{no matching constructor}}
+
+ // valid (by copy constructor).
+ H h2({1, nullptr});
+
+ // valid
+ H h3{1, 2};
+ }
}
Modified: cfe/trunk/test/SemaCXX/generalized-initializers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/generalized-initializers.cpp?rev=150342&r1=150341&r2=150342&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/generalized-initializers.cpp (original)
+++ cfe/trunk/test/SemaCXX/generalized-initializers.cpp Sun Feb 12 10:37:24 2012
@@ -49,27 +49,4 @@
// invalid
int const &b({0}); // expected-error {{}}
- struct C { explicit C(int, int); C(int, long); };
-
- // invalid
- C c({1, 2}); // expected-error {{}}
-
- // valid (by copy constructor).
- C d({1, 2L});
-
- // valid
- C e{1, 2};
-
- struct B {
- template<typename ...T>
- B(std::initializer_list<int>, T ...);
- };
-
- // invalid (the first phase only considers init-list ctors)
- // (for the second phase, no constructor is viable)
- B f{1, 2, 3};
-
- // valid (T deduced to <>).
- B g({1, 2, 3});
-
}
More information about the cfe-commits
mailing list