diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 44 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 14 |
4 files changed, 52 insertions, 18 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6d2f3b252b1..a2180be53c4 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9032,7 +9032,8 @@ bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, - ASTOwningVector<Expr*> &ConvertedArgs) { + ASTOwningVector<Expr*> &ConvertedArgs, + bool AllowExplicit) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); Expr **Args = (Expr **)ArgsPtr.get(); @@ -9053,7 +9054,7 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, SmallVector<Expr *, 8> AllArgs; bool Invalid = GatherArgumentsForCall(Loc, Constructor, Proto, 0, Args, NumArgs, AllArgs, - CallType); + CallType, AllowExplicit); ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size()); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index fcb2d410cb2..2868b822e6d 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3248,7 +3248,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, unsigned FirstProtoArg, Expr **Args, unsigned NumArgs, SmallVector<Expr *, 8> &AllArgs, - VariadicCallType CallType) { + VariadicCallType CallType, + bool AllowExplicit) { unsigned NumArgsInProto = Proto->getNumArgs(); unsigned NumArgsToCheck = NumArgs; bool Invalid = false; @@ -3288,7 +3289,9 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, Proto->isArgConsumed(i)); ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), - Owned(Arg)); + Owned(Arg), + /*TopLevelOfInitList=*/false, + AllowExplicit); if (ArgE.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index fcc74e7d3fb..df0a49b79e8 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2827,10 +2827,22 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet, SuppressUserConversions); - else + else { + // C++ [over.match.copy]p1: + // - When initializing a temporary to be bound to the first parameter + // of a constructor that takes a reference to possibly cv-qualified + // T as its first argument, called with a single argument in the + // context of direct-initialization, explicit conversion functions + // are also considered. + bool AllowExplicitConv = AllowExplicit && !CopyInitializing && + NumArgs == 1 && + Constructor->isCopyOrMoveConstructor(); S.AddOverloadCandidate(Constructor, FoundDecl, Args, NumArgs, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, + /*PartialOverloading=*/false, + /*AllowExplicit=*/AllowExplicitConv); + } } } @@ -3122,8 +3134,8 @@ static void TryListInitialization(Sema &S, static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, - Expr *Initializer, - bool AllowRValues, + Expr *Initializer, + bool AllowRValues, InitializationSequence &Sequence) { QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); @@ -3151,7 +3163,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. bool AllowExplicit = Kind.AllowExplicit(); - + bool AllowExplicitConvs = Kind.allowExplicitConversionFunctions(); + const RecordType *T1RecordType = 0; if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) && !S.RequireCompleteType(Kind.getLocation(), T1, 0)) { @@ -3220,7 +3233,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // FIXME: Do we need to make sure that we only consider conversion // candidates with reference-compatible results? That might be needed to // break recursion. - if ((AllowExplicit || !Conv->isExplicit()) && + if ((AllowExplicitConvs || !Conv->isExplicit()) && (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), @@ -4636,10 +4649,21 @@ PerformConstructorInitialization(Sema &S, ExprResult CurInit = S.Owned((Expr *)0); + // C++ [over.match.copy]p1: + // - When initializing a temporary to be bound to the first parameter + // of a constructor that takes a reference to possibly cv-qualified + // T as its first argument, called with a single argument in the + // context of direct-initialization, explicit conversion functions + // are also considered. + bool AllowExplicitConv = Kind.AllowExplicit() && !Kind.isCopyInit() && + Args.size() == 1 && + Constructor->isCopyOrMoveConstructor(); + // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, move(Args), - Loc, ConstructorArgs)) + Loc, ConstructorArgs, + AllowExplicitConv)) return ExprError(); @@ -6097,7 +6121,8 @@ ExprResult Sema::PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, - bool TopLevelOfInitList) { + bool TopLevelOfInitList, + bool AllowExplicit) { if (Init.isInvalid()) return ExprError(); @@ -6108,7 +6133,8 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, EqualLoc = InitE->getLocStart(); InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), - EqualLoc); + EqualLoc, + AllowExplicit); InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); Init.release(); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 2b567b39842..c7f33943437 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -4213,7 +4213,8 @@ static ImplicitConversionSequence TryCopyInitialization(Sema &S, Expr *From, QualType ToType, bool SuppressUserConversions, bool InOverloadResolution, - bool AllowObjCWritebackConversion); + bool AllowObjCWritebackConversion, + bool AllowExplicit = false); /// TryListConversion - Try to copy-initialize a value of type ToType from the /// initializer list From. @@ -4413,7 +4414,8 @@ static ImplicitConversionSequence TryCopyInitialization(Sema &S, Expr *From, QualType ToType, bool SuppressUserConversions, bool InOverloadResolution, - bool AllowObjCWritebackConversion) { + bool AllowObjCWritebackConversion, + bool AllowExplicit) { if (InitListExpr *FromInitList = dyn_cast<InitListExpr>(From)) return TryListConversion(S, FromInitList, ToType, SuppressUserConversions, InOverloadResolution,AllowObjCWritebackConversion); @@ -4422,7 +4424,7 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType, return TryReferenceInit(S, From, ToType, /*FIXME:*/From->getLocStart(), SuppressUserConversions, - /*AllowExplicit=*/false); + AllowExplicit); return TryImplicitConversion(S, From, ToType, SuppressUserConversions, @@ -5103,7 +5105,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, - bool PartialOverloading) { + bool PartialOverloading, + bool AllowExplicit) { const FunctionProtoType* Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -5204,7 +5207,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, SuppressUserConversions, /*InOverloadResolution=*/true, /*AllowObjCWritebackConversion=*/ - getLangOptions().ObjCAutoRefCount); + getLangOptions().ObjCAutoRefCount, + AllowExplicit); if (Candidate.Conversions[ArgIdx].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; |