[cfe-commits] r150408 - in /cfe/trunk: lib/Sema/SemaCast.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/cxx0x-initializer-aggregates.cpp test/SemaCXX/cxx0x-initializer-constructor.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Mon Feb 13 11:55:44 PST 2012


Author: cornedbee
Date: Mon Feb 13 13:55:43 2012
New Revision: 150408

URL: http://llvm.org/viewvc/llvm-project?rev=150408&view=rev
Log:
Don't route explicit construction via list-initialization through the functional cast code path. It sometimes does the wrong thing, produces horrible error messages, and is just unnecessary.

Modified:
    cfe/trunk/lib/Sema/SemaCast.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp

Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=150408&r1=150407&r2=150408&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Mon Feb 13 13:55:43 2012
@@ -301,7 +301,8 @@
 /// diagnostics were emitted.
 static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
                                       SourceRange range, Expr *src,
-                                      QualType destType) {
+                                      QualType destType,
+                                      bool listInitialization) {
   switch (CT) {
   // These cast kinds don't consider user-defined conversions.
   case CT_Const:
@@ -320,13 +321,12 @@
   if (!destType->isRecordType() && !srcType->isRecordType())
     return false;
 
-  bool initList = isa<InitListExpr>(src);
   InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
   InitializationKind initKind
     = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(),
-                                                              range, initList)
+                                                      range, listInitialization)
     : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range,
-                                                                      initList)
+                                                             listInitialization)
     : InitializationKind::CreateCast(/*type range?*/ range);
   InitializationSequence sequence(S, entity, initKind, &src, 1);
 
@@ -376,14 +376,16 @@
 
 /// Diagnose a failed cast.
 static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
-                            SourceRange opRange, Expr *src, QualType destType) {
+                            SourceRange opRange, Expr *src, QualType destType,
+                            bool listInitialization) {
   if (src->getType() == S.Context.BoundMemberTy) {
     (void) S.CheckPlaceholderExpr(src); // will always fail
     return;
   }
 
   if (msg == diag::err_bad_cxx_cast_generic &&
-      tryDiagnoseOverloadedCast(S, castType, opRange, src, destType))
+      tryDiagnoseOverloadedCast(S, castType, opRange, src, destType,
+                                listInitialization))
     return;
 
   S.Diag(opRange.getBegin(), msg) << castType
@@ -705,7 +707,8 @@
       Self.NoteAllOverloadCandidates(SrcExpr.get());
 
     } else {
-      diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType);
+      diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
+                      DestType, /*listInitialization=*/false);
     }
   } else if (tcr == TC_Success && Self.getLangOptions().ObjCAutoRefCount) {
     checkObjCARCConversion(Sema::CCK_OtherCast);
@@ -763,7 +766,8 @@
         << oe->getQualifierLoc().getSourceRange();
       Self.NoteAllOverloadCandidates(SrcExpr.get());
     } else {
-      diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType);
+      diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType,
+                      /*listInitialization=*/false);
     }
   } else if (tcr == TC_Success) {
     if (Kind == CK_BitCast)
@@ -1867,7 +1871,7 @@
 
     } else {
       diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
-                      OpRange, SrcExpr.get(), DestType);
+                      OpRange, SrcExpr.get(), DestType, ListInitialization);
     }
   } else if (Kind == CK_BitCast) {
     checkCastAlign();
@@ -2090,14 +2094,12 @@
                                             SourceLocation LPLoc,
                                             Expr *CastExpr,
                                             SourceLocation RPLoc) {
-  bool ListInitialization = LPLoc.isInvalid();
-  assert((!ListInitialization || isa<InitListExpr>(CastExpr)) &&
-         "List initialization must have initializer list as expression.");
+  assert(LPLoc.isValid() && "List-initialization shouldn't get here.");
   CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
   Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
   Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
 
-  Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true, ListInitialization);
+  Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false);
   if (Op.SrcExpr.isInvalid())
     return ExprError();
 

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=150408&r1=150407&r2=150408&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Feb 13 13:55:43 2012
@@ -802,7 +802,7 @@
   // If the expression list is a single expression, the type conversion
   // expression is equivalent (in definedness, and if defined in meaning) to the
   // corresponding cast expression.
-  if (NumExprs == 1) {
+  if (NumExprs == 1 && !ListInitialization) {
     Expr *Arg = Exprs[0];
     exprs.release();
     return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
@@ -810,13 +810,28 @@
 
   InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
   InitializationKind Kind
-    = NumExprs ? InitializationKind::CreateDirect(TyBeginLoc,
-                                                  LParenLoc, RParenLoc)
+    = NumExprs ? ListInitialization
+                    ? InitializationKind::CreateDirectList(TyBeginLoc)
+                    : InitializationKind::CreateDirect(TyBeginLoc,
+                                                       LParenLoc, RParenLoc)
                : InitializationKind::CreateValue(TyBeginLoc,
                                                  LParenLoc, RParenLoc);
   InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs);
   ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs));
 
+  if (!Result.isInvalid() && ListInitialization &&
+      isa<InitListExpr>(Result.get())) {
+    // If the list-initialization doesn't involve a constructor call, we'll get
+    // the initializer-list (with corrected type) back, but that's not what we
+    // want, since it will be treated as an initializer list in further
+    // processing. Explicitly insert a cast here.
+    InitListExpr *List = cast<InitListExpr>(Result.take());
+    Result = Owned(CXXFunctionalCastExpr::Create(Context, List->getType(),
+                                    Expr::getValueKindForType(TInfo->getType()),
+                                                 TInfo, TyBeginLoc, CK_NoOp,
+                                                 List, /*Path=*/0, RParenLoc));
+  }
+
   // FIXME: Improve AST representation?
   return move(Result);
 }

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp?rev=150408&r1=150407&r2=150408&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-aggregates.cpp Mon Feb 13 13:55:43 2012
@@ -34,6 +34,13 @@
     new S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
   }
 
+  void bracing_construct() {
+    (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, { {7, 8} } }; // completely braced
+    (void) S{ 1, 2, 3, 4, 5, 6 }; // expected-error 5 {{cannot omit braces}}
+    (void) S{ {1, 2}, {3, 4}, {5, 6}, { {7, 8} } }; // expected-error 2 {{cannot omit braces}}
+    (void) S{ {1, 2}, {3, 4}, { {5}, {6} }, {7, 8} }; // expected-error {{cannot omit braces}}
+  }
+
   struct String {
     String(const char*);
   };

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=150408&r1=150407&r2=150408&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-constructor.cpp Mon Feb 13 13:55:43 2012
@@ -147,32 +147,43 @@
     static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable
   }
 
-  struct G { // expected-note 2 {{not viable}}
+  struct G { // expected-note 6 {{not viable}}
     // This is not an initializer-list constructor.
     template<typename ...T>
-    G(std::initializer_list<int>, T ...);  // expected-note {{not viable}}
+    G(std::initializer_list<int>, T ...);  // expected-note 3 {{not viable}}
   };
 
-  struct H { // expected-note 2 {{not viable}}
-    explicit H(int, int); // expected-note {{not viable}}
-    H(int, void*); // expected-note {{not viable}}
+  struct H { // expected-note 6 {{not viable}}
+    explicit H(int, int); // expected-note 3 {{not viable}}
+    H(int, void*); // expected-note 3 {{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}}
+    (void) new G{1, 2, 3}; // expected-error {{no matching constructor}}
+    (void) G{1, 2, 3} // expected-error {{no matching constructor}}
 
     // valid (T deduced to <>).
     G g2({1, 2, 3});
+    (void) new G({1, 2, 3});
+    (void) G({1, 2, 3});
 
     // invalid
     H h1({1, 2}); // expected-error {{no matching constructor}}
+    (void) new H({1, 2}); // expected-error {{no matching constructor}}
+    // FIXME: Bad diagnostic, mentions void type instead of init list.
+    (void) H({1, 2}); // expected-error {{no matching conversion}}
 
     // valid (by copy constructor).
     H h2({1, nullptr});
+    (void) new H({1, nullptr});
+    (void) H({1, nullptr});
 
     // valid
     H h3{1, 2};
+    (void) new H{1, 2};
+    (void) H{1, 2};
   }
 }





More information about the cfe-commits mailing list