r228276 - PR22465: when performing list-initialization for a class type C, if we see an

Richard Smith richard-llvm at metafoo.co.uk
Wed Feb 4 23:02:11 PST 2015


Author: rsmith
Date: Thu Feb  5 01:02:11 2015
New Revision: 228276

URL: http://llvm.org/viewvc/llvm-project?rev=228276&view=rev
Log:
PR22465: when performing list-initialization for a class type C, if we see an
initializer of the form {x}, where x is of type C or a type derived from C,
perform *non-list* initialization of the entity from x, but create a
CXXConstructExpr that knows that we used list-initialization syntax.

Plus some fixes to ensure we mangle correctly in this and related cases.

Modified:
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/CXX/drs/dr14xx.cpp
    cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=228276&r1=228275&r2=228276&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Thu Feb  5 01:02:11 2015
@@ -2864,7 +2864,7 @@ recurse:
 
   case Expr::CXXConstructExprClass: {
     const auto *CE = cast<CXXConstructExpr>(E);
-    if (!CE->isListInitialization()) {
+    if (!CE->isListInitialization() || CE->isStdInitListInitialization()) {
       assert(
           CE->getNumArgs() >= 1 &&
           (CE->getNumArgs() == 1 || isa<CXXDefaultArgExpr>(CE->getArg(1))) &&
@@ -2890,8 +2890,18 @@ recurse:
     mangleType(CE->getType());
     if (!List && N != 1)
       Out << '_';
-    for (auto *E : CE->arguments())
-      mangleExpression(E);
+    if (CE->isStdInitListInitialization()) {
+      // We implicitly created a std::initializer_list<T> for the first argument
+      // of a constructor of type U in an expression of the form U{a, b, c}.
+      // Strip all the semantic gunk off the initializer list.
+      auto *SILE =
+          cast<CXXStdInitializerListExpr>(CE->getArg(0)->IgnoreImplicit());
+      auto *ILE = cast<InitListExpr>(SILE->getSubExpr()->IgnoreImplicit());
+      mangleInitListElements(ILE);
+    } else {
+      for (auto *E : CE->arguments())
+        mangleExpression(E);
+    }
     if (List || N != 1)
       Out << 'E';
     break;

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=228276&r1=228275&r2=228276&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Thu Feb  5 01:02:11 2015
@@ -1694,7 +1694,9 @@ void StmtPrinter::VisitCXXBindTemporaryE
 
 void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) {
   Node->getType().print(OS, Policy);
-  if (Node->isListInitialization())
+  if (Node->isStdInitListInitialization())
+    /* Nothing to do; braces are part of creating the std::initializer_list. */;
+  else if (Node->isListInitialization())
     OS << "{";
   else
     OS << "(";
@@ -1707,7 +1709,9 @@ void StmtPrinter::VisitCXXTemporaryObjec
       OS << ", ";
     PrintExpr(*Arg);
   }
-  if (Node->isListInitialization())
+  if (Node->isStdInitListInitialization())
+    /* See above. */;
+  else if (Node->isListInitialization())
     OS << "}";
   else
     OS << ")";
@@ -1876,7 +1880,7 @@ void StmtPrinter::VisitCXXPseudoDestruct
 }
 
 void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) {
-  if (E->isListInitialization())
+  if (E->isListInitialization() && !E->isStdInitListInitialization())
     OS << "{";
 
   for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) {
@@ -1889,7 +1893,7 @@ void StmtPrinter::VisitCXXConstructExpr(
     PrintExpr(E->getArg(i));
   }
 
-  if (E->isListInitialization())
+  if (E->isListInitialization() && !E->isStdInitListInitialization())
     OS << "}";
 }
 

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=228276&r1=228275&r2=228276&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Feb  5 01:02:11 2015
@@ -3174,16 +3174,19 @@ ResolveConstructorOverload(Sema &S, Sour
 /// \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 InitListSyntax is true, this is list-initialization of a non-aggregate
-/// class type.
+/// \param InitListSyntax Is this list-initialization?
+/// \param IsInitListCopy Is this non-list-initialization resulting from a
+///                       list-initialization from {x} where x is the same
+///                       type as the entity?
 static void TryConstructorInitialization(Sema &S,
                                          const InitializedEntity &Entity,
                                          const InitializationKind &Kind,
                                          MultiExprArg Args, QualType DestType,
                                          InitializationSequence &Sequence,
-                                         bool InitListSyntax = false) {
-  assert((!InitListSyntax || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
-         "InitListSyntax must come with a single initializer list argument.");
+                                         bool IsListInit = false,
+                                         bool IsInitListCopy = false) {
+  assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
+         "IsListInit must come with a single initializer list argument.");
 
   // The type we're constructing needs to be complete.
   if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) {
@@ -3202,7 +3205,7 @@ static void TryConstructorInitialization
 
   // Determine whether we are allowed to call explicit constructors or
   // explicit conversion operators.
-  bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax;
+  bool AllowExplicit = Kind.AllowExplicit() || IsListInit;
   bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;
 
   //   - Otherwise, if T is a class type, constructors are considered. The
@@ -3227,7 +3230,7 @@ static void TryConstructorInitialization
   //   - Initially, the candidate functions are the initializer-list
   //     constructors of the class T and the argument list consists of the
   //     initializer list as a single argument.
-  if (InitListSyntax) {
+  if (IsListInit) {
     InitListExpr *ILE = cast<InitListExpr>(Args[0]);
     AsInitializerList = true;
 
@@ -3256,7 +3259,7 @@ static void TryConstructorInitialization
                                         /*OnlyListConstructors=*/false);
   }
   if (Result) {
-    Sequence.SetOverloadFailure(InitListSyntax ?
+    Sequence.SetOverloadFailure(IsListInit ?
                       InitializationSequence::FK_ListConstructorOverloadFailed :
                       InitializationSequence::FK_ConstructorOverloadFailed,
                                 Result);
@@ -3278,7 +3281,7 @@ static void TryConstructorInitialization
   //   In copy-list-initialization, if an explicit constructor is chosen, the
   //   initializer is ill-formed.
   CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
-  if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
+  if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
     Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
     return;
   }
@@ -3286,10 +3289,9 @@ static void TryConstructorInitialization
   // Add the constructor initialization step. Any cv-qualification conversion is
   // subsumed by the initialization.
   bool HadMultipleCandidates = (CandidateSet.size() > 1);
-  Sequence.AddConstructorInitializationStep(CtorDecl,
-                                            Best->FoundDecl.getAccess(),
-                                            DestType, HadMultipleCandidates,
-                                            InitListSyntax, AsInitializerList);
+  Sequence.AddConstructorInitializationStep(
+      CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates,
+      IsListInit | IsInitListCopy, AsInitializerList);
 }
 
 static bool
@@ -3445,9 +3447,10 @@ static void TryListInitialization(Sema &
       QualType InitType = InitList->getInit(0)->getType();
       if (S.Context.hasSameUnqualifiedType(InitType, DestType) ||
           S.IsDerivedFrom(InitType, DestType)) {
-        Expr *InitListAsExpr = InitList;
-        TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType,
-                                     Sequence, /*InitListSyntax*/true);
+        Expr *InitAsExpr = InitList->getInit(0);
+        TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType,
+                                     Sequence, /*InitListSyntax*/ false,
+                                     /*IsInitListCopy*/ true);
         return;
       }
     }

Modified: cfe/trunk/test/CXX/drs/dr14xx.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr14xx.cpp?rev=228276&r1=228275&r2=228276&view=diff
==============================================================================
--- cfe/trunk/test/CXX/drs/dr14xx.cpp (original)
+++ cfe/trunk/test/CXX/drs/dr14xx.cpp Thu Feb  5 01:02:11 2015
@@ -314,6 +314,16 @@ namespace dr1467 {  // dr1467: 3.7 c++11
       NonAggregate z{{x}};
     }
   } // nonaggregate
+
+  namespace SelfInitIsNotListInit {
+    struct S {
+      S();
+      explicit S(S &);
+      S(const S &);
+    };
+    S s1;
+    S s2 = {s1}; // ok, not list-initialization so we pick the non-explicit constructor
+  }
 } // dr1467
 
 namespace dr1490 {  // dr1490: 3.7 c++11

Modified: cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp?rev=228276&r1=228275&r2=228276&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-exprs.cpp Thu Feb  5 01:02:11 2015
@@ -298,6 +298,8 @@ namespace test7 {
   struct B { B(int, int); } extern b;
   struct C { C(B); };
   struct D { D(C); };
+  struct E { E(std::initializer_list<int>); };
+  struct F { F(E); };
 
   template<class T> decltype(A{1,2},T()) fA1(T t) {}
   template<class T> decltype(A({1,2}),T()) fA2(T t) {}
@@ -307,6 +309,10 @@ namespace test7 {
   template<class T> decltype(C({1,2}),T()) fC2(T t) {}
   template<class T> decltype(D{b},T()) fD1(T t) {}
   template<class T> decltype(D(b),T()) fD2(T t) {}
+  template<class T> decltype(E{1,2},T()) fE1(T t) {}
+  template<class T> decltype(E({1,2}),T()) fE2(T t) {}
+  template<class T> decltype(F{{1,2}},T()) fF1(T t) {}
+  template<class T> decltype(F({1,2}),T()) fF2(T t) {}
 
   int main() {
     fA1(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fA1IiEEDTcmtlNS_1AELi1ELi2EEcvT__EES2_
@@ -317,5 +323,9 @@ namespace test7 {
     fC2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fC2IiEEDTcmcvNS_1CEilLi1ELi2EEcvT__EES2_
     fD1(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bEEEcvT__EES2_
     fD2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fD2IiEEDTcmcvNS_1DEL_ZNS_1bEEcvT__EES2_
+    fE1(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fE1IiEEDTcmtlNS_1EELi1ELi2EEcvT__EES2_
+    fE2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fE2IiEEDTcmcvNS_1EEilLi1ELi2EEcvT__EES2_
+    fF1(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fF1IiEEDTcmtlNS_1FEilLi1ELi2EEEcvT__EES2_
+    fF2(1); // CHECK-LABEL: define {{.*}} @_ZN5test73fF2IiEEDTcmcvNS_1FEilLi1ELi2EEcvT__EES2_
   }
 }





More information about the cfe-commits mailing list