diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-09-21 21:55:46 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-09-21 21:55:46 +0000 |
| commit | 089c31637f86a97a2cc4f309c7d46ebf5f0ddb8c (patch) | |
| tree | f2ae1df8047a65d0ab7c05a097c1e41fa6041c11 /clang/lib | |
| parent | 4e9c091dd72b6ec221d71eb928c99f099f5aff41 (diff) | |
| download | bcm5719-llvm-089c31637f86a97a2cc4f309c7d46ebf5f0ddb8c.tar.gz bcm5719-llvm-089c31637f86a97a2cc4f309c7d46ebf5f0ddb8c.zip | |
PR17295: Do not allow explicit conversion functions to be used in cases where
an additional conversion (other than a qualification conversion) would be
required after the explicit conversion.
Conversely, do allow explicit conversion functions to be used when initializing
a temporary for a reference binding in direct-list-initialization.
llvm-svn: 191150
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 35 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 |
3 files changed, 49 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1c33c329c71..afd9393123e 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3346,6 +3346,33 @@ static void TryListInitialization(Sema &S, return; } } + if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && + InitList->getNumInits() == 1 && + InitList->getInit(0)->getType()->isRecordType()) { + // - Otherwise, if the initializer list has a single element of type E + // [...references are handled above...], the object or reference is + // initialized from that element; if a narrowing conversion is required + // to convert the element to T, the program is ill-formed. + // + // Per core-24034, this is direct-initialization if we were performing + // direct-list-initialization and copy-initialization otherwise. + // We can't use InitListChecker for this, because it always performs + // copy-initialization. This only matters if we might use an 'explicit' + // conversion operator, so we only need to handle the cases where the source + // is of record type. + InitializationKind SubKind = + Kind.getKind() == InitializationKind::IK_DirectList + ? InitializationKind::CreateDirect(Kind.getLocation(), + InitList->getLBraceLoc(), + InitList->getRBraceLoc()) + : Kind; + Expr *SubInit[1] = { InitList->getInit(0) }; + Sequence.InitializeFrom(S, Entity, SubKind, SubInit, + /*TopLevelOfInitList*/true); + if (Sequence) + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); + return; + } InitListChecker CheckInitList(S, Entity, InitList, DestType, /*VerifyOnly=*/true); @@ -4366,6 +4393,14 @@ InitializationSequence::InitializationSequence(Sema &S, MultiExprArg Args, bool TopLevelOfInitList) : FailedCandidateSet(Kind.getLocation()) { + InitializeFrom(S, Entity, Kind, Args, TopLevelOfInitList); +} + +void InitializationSequence::InitializeFrom(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + bool TopLevelOfInitList) { ASTContext &Context = S.Context; // Eliminate non-overload placeholder types in the arguments. We diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 800f9832498..df18752bfa8 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5829,6 +5829,17 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, ConvType = Conversion->getConversionType().getNonReferenceType(); } + // Per C++ [over.match.conv]p1, [over.match.ref]p1, an explicit conversion + // operator is only a candidate if its return type is the target type or + // can be converted to the target type with a qualification conversion. + bool ObjCLifetimeConversion; + QualType ToNonRefType = ToType.getNonReferenceType(); + if (Conversion->isExplicit() && + !Context.hasSameUnqualifiedType(ConvType, ToNonRefType) && + !IsQualificationConversion(ConvType, ToNonRefType, /*CStyle*/false, + ObjCLifetimeConversion)) + return; + // Overload resolution is always an unevaluated context. EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e03e8c55c9a..d712cec2204 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3372,7 +3372,9 @@ void Sema::BuildVariableInstantiation( OldVar->isPreviousDeclInSameBlockScope()); NewVar->setAccess(OldVar->getAccess()); - if (!OldVar->isStaticDataMember()) { + // For local variables, inherit the 'used' and 'referenced' flags from the + // primary template. + if (OldVar->getLexicalDeclContext()->isFunctionOrMethod()) { NewVar->setIsUsed(OldVar->isUsed(false)); NewVar->setReferenced(OldVar->isReferenced()); } |

