Even more careful consideration of C++11 13.3.3.1p4. Fixes PR12241.

llvm-svn: 153523
This commit is contained in:
Sebastian Redl 2012-03-27 18:33:03 +00:00
parent 41ab2899b2
commit e541716286
2 changed files with 27 additions and 22 deletions

View File

@ -2758,6 +2758,19 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType,
return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,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 static OverloadingResult
IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
CXXRecordDecl *To, CXXRecordDecl *To,
@ -2784,15 +2797,19 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
S.isInitListConstructor(Constructor) && S.isInitListConstructor(Constructor) &&
(AllowExplicit || !Constructor->isExplicit()); (AllowExplicit || !Constructor->isExplicit());
if (Usable) { if (Usable) {
// If the first argument is (a reference to) the target type,
// suppress conversions.
bool SuppressUserConversions =
isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
if (ConstructorTmpl) if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ 0, /*ExplicitArgs*/ 0,
From, CandidateSet, From, CandidateSet,
/*SuppressUserConversions=*/true); SuppressUserConversions);
else else
S.AddOverloadCandidate(Constructor, FoundDecl, S.AddOverloadCandidate(Constructor, FoundDecl,
From, CandidateSet, From, CandidateSet,
/*SuppressUserConversions=*/true); SuppressUserConversions);
} }
} }
@ -2918,15 +2935,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
if (NumArgs == 1) { if (NumArgs == 1) {
// If the first argument is (a reference to) the target type, // If the first argument is (a reference to) the target type,
// suppress conversions. // suppress conversions.
const FunctionProtoType *CtorType = SuppressUserConversions = isFirstArgumentCompatibleWithType(
Constructor->getType()->getAs<FunctionProtoType>(); S.Context, Constructor, ToType);
if (CtorType->getNumArgs() > 0) {
QualType FirstArg = CtorType->getArgType(0);
if (S.Context.hasSameUnqualifiedType(ToType,
FirstArg.getNonReferenceType())) {
SuppressUserConversions = true;
}
}
} }
} }
if (ConstructorTmpl) if (ConstructorTmpl)

View File

@ -237,7 +237,7 @@ namespace PR12167 {
bool s = f(string<1>()); bool s = f(string<1>());
} }
namespace PR12257 { namespace PR12257_PR12241 {
struct command_pair struct command_pair
{ {
command_pair(int, int); command_pair(int, int);
@ -253,14 +253,9 @@ namespace PR12257 {
generator_pair(const command_map); generator_pair(const command_map);
}; };
const std::initializer_list<generator_pair> x = // 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}}}};
{3, 4}
}
}
}
};
} }