[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