diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-24 23:56:31 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-24 23:56:31 +0000 |
commit | ed878af7914df535b32d64f555fa118413186672 (patch) | |
tree | 527d0c3979ed2ec0c8a59064c3502187779002fa /lib/Sema/SemaInit.cpp | |
parent | 5a13d4d2c1e45ab611ca857d923caacfaeb3cd07 (diff) |
Implement C++11 [over.match.copy]p1b2, which allows the use of
explicit conversion functions to initialize the argument to a
copy/move constructor that itself is the subject of direct
initialization. Since we don't have that much context in overload
resolution, we end up threading more flags :(.
Fixes <rdar://problem/10903741> / PR10456.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151409 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index fcc74e7d3f..df0a49b79e 100644 --- a/lib/Sema/SemaInit.cpp +++ b/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(); |