From: Sebastian Redl Date: Tue, 27 Mar 2012 18:33:03 +0000 (+0000) Subject: Even more careful consideration of C++11 13.3.3.1p4. Fixes PR12241. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f78c0f9aaabf32f5b5f8633b0066e611b24640ee;p=clang Even more careful consideration of C++11 13.3.3.1p4. Fixes PR12241. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153523 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index be0243403b..661f589099 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(); + 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(); - 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) diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp index a14283ce7c..da10189257 100644 --- a/test/SemaCXX/cxx0x-initializer-constructor.cpp +++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp @@ -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 x = - { - { - { - { - {3, 4} - } - } - } - }; + // 5 levels: init list, gen_pair, command_map, init list, command_pair + const std::initializer_list x = {{{{{3, 4}}}}}; + + // 4 levels: init list, gen_pair, command_map via init list, command_pair + const std::initializer_list y = {{{{1, 2}}}}; }