summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2017-01-08 21:45:44 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2017-01-08 21:45:44 +0000
commitf9c59b71220ce1b740a85a1b4b6d962fae60c3c1 (patch)
tree426db2785b30debb374c1df554cf853ab5022f6d /clang/lib/Sema/SemaOverload.cpp
parentf51ba1e3da910efab70a90697c2913dd7a32374e (diff)
downloadbcm5719-llvm-f9c59b71220ce1b740a85a1b4b6d962fae60c3c1.tar.gz
bcm5719-llvm-f9c59b71220ce1b740a85a1b4b6d962fae60c3c1.zip
PR30305: Implement proposed DR resolution to prevent slicing via inherited constructor.
The rule we use is that a construction of a class type T from an argument of type U cannot use an inherited constructor if U is the same as T or is derived from T (or if the initialization would first convert it to such a type). This (approximately) matches the rule in use by GCC, and matches the current proposed DR resolution. llvm-svn: 291403
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
-rw-r--r--clang/lib/Sema/SemaOverload.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 33574b9aec3..15503036532 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -5971,6 +5971,31 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
}
}
+ // C++ [over.best.ics]p4+: (proposed DR resolution)
+ // If the target is the first parameter of an inherited constructor when
+ // constructing an object of type C with an argument list that has exactly
+ // one expression, an implicit conversion sequence cannot be formed if C is
+ // reference-related to the type that the argument would have after the
+ // application of the user-defined conversion (if any) and before the final
+ // standard conversion sequence.
+ auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl.getDecl());
+ if (Shadow && Args.size() == 1 && !isa<InitListExpr>(Args.front())) {
+ bool DerivedToBase, ObjCConversion, ObjCLifetimeConversion;
+ QualType ConvertedArgumentType = Args.front()->getType();
+ if (Candidate.Conversions[0].isUserDefined())
+ ConvertedArgumentType =
+ Candidate.Conversions[0].UserDefined.After.getFromType();
+ if (CompareReferenceRelationship(Args.front()->getLocStart(),
+ Context.getRecordType(Shadow->getParent()),
+ ConvertedArgumentType, DerivedToBase,
+ ObjCConversion,
+ ObjCLifetimeConversion) >= Ref_Related) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_inhctor_slice;
+ return;
+ }
+ }
+
if (EnableIfAttr *FailedAttr = CheckEnableIf(Function, Args)) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_enable_if;
@@ -9927,6 +9952,12 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_ext_disabled:
return DiagnoseOpenCLExtensionDisabled(S, Cand);
+ case ovl_fail_inhctor_slice:
+ S.Diag(Fn->getLocation(),
+ diag::note_ovl_candidate_inherited_constructor_slice);
+ MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl);
+ return;
+
case ovl_fail_addr_not_available: {
bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function);
(void)Available;
OpenPOWER on IntegriCloud