]> granicus.if.org Git - clang/commitdiff
Even more careful consideration of C++11 13.3.3.1p4. Fixes PR12241.
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 27 Mar 2012 18:33:03 +0000 (18:33 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 27 Mar 2012 18:33:03 +0000 (18:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153523 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaOverload.cpp
test/SemaCXX/cxx0x-initializer-constructor.cpp

index be0243403b5e623fc3971e2c003f34e9a9fc7d27..661f589099ea9398e69d65fc466528018be717c7 100644 (file)
@@ -2758,6 +2758,19 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
   return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
 }
 
+static bool isFirstArgumentCompatibleWithType(ASTContext &Context,
+                                              CXXConstructorDecl *Constructor,
+                                              QualType Type) {
+  const FunctionProtoType *CtorType =
+      Constructor->getType()->getAs<FunctionProtoType>();
+  if (CtorType->getNumArgs() > 0) {
+    QualType FirstArg = CtorType->getArgType(0);
+    if (Context.hasSameUnqualifiedType(Type, FirstArg.getNonReferenceType()))
+      return true;
+  }
+  return false;
+}
+
 static OverloadingResult
 IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
                                        CXXRecordDecl *To,
@@ -2784,15 +2797,19 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
                   S.isInitListConstructor(Constructor) &&
                   (AllowExplicit || !Constructor->isExplicit());
     if (Usable) {
+      // If the first argument is (a reference to) the target type,
+      // suppress conversions.
+      bool SuppressUserConversions =
+          isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
       if (ConstructorTmpl)
         S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
                                        /*ExplicitArgs*/ 0,
                                        From, CandidateSet,
-                                       /*SuppressUserConversions=*/true);
+                                       SuppressUserConversions);
       else
         S.AddOverloadCandidate(Constructor, FoundDecl,
                                From, CandidateSet,
-                               /*SuppressUserConversions=*/true);
+                               SuppressUserConversions);
     }
   }
 
@@ -2918,15 +2935,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
             if (NumArgs == 1) {
               // If the first argument is (a reference to) the target type,
               // suppress conversions.
-              const FunctionProtoType *CtorType =
-                  Constructor->getType()->getAs<FunctionProtoType>();
-              if (CtorType->getNumArgs() > 0) {
-                QualType FirstArg = CtorType->getArgType(0);
-                if (S.Context.hasSameUnqualifiedType(ToType,
-                                              FirstArg.getNonReferenceType())) {
-                  SuppressUserConversions = true;
-                }
-              }
+              SuppressUserConversions = isFirstArgumentCompatibleWithType(
+                                                S.Context, Constructor, ToType);
             }
           }
           if (ConstructorTmpl)
index a14283ce7c003388de547e7e1f407f91bf84efde..da10189257797374bc85ea8d79b0323f95097f2f 100644 (file)
@@ -237,7 +237,7 @@ namespace PR12167 {
   bool s = f(string<1>());
 }
 
-namespace PR12257 {
+namespace PR12257_PR12241 {
   struct command_pair
   {
     command_pair(int, int);
@@ -253,14 +253,9 @@ namespace PR12257 {
     generator_pair(const command_map);
   };
 
-  const std::initializer_list<generator_pair> x =
-  {
-    {
-      {
-        {
-          {3, 4}
-        }
-      }
-    }
-  };
+  // 5 levels: init list, gen_pair, command_map, init list, command_pair
+  const std::initializer_list<generator_pair> x = {{{{{3, 4}}}}};
+
+  // 4 levels: init list, gen_pair, command_map via init list, command_pair
+  const std::initializer_list<generator_pair> y = {{{{1, 2}}}};
 }