summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-09-21 21:55:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-09-21 21:55:46 +0000
commit089c31637f86a97a2cc4f309c7d46ebf5f0ddb8c (patch)
treef2ae1df8047a65d0ab7c05a097c1e41fa6041c11 /clang/lib
parent4e9c091dd72b6ec221d71eb928c99f099f5aff41 (diff)
downloadbcm5719-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.cpp35
-rw-r--r--clang/lib/Sema/SemaOverload.cpp11
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp4
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());
}
OpenPOWER on IntegriCloud