diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-01-08 21:45:44 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2017-01-08 21:45:44 +0000 |
commit | f9c59b71220ce1b740a85a1b4b6d962fae60c3c1 (patch) | |
tree | 426db2785b30debb374c1df554cf853ab5022f6d /clang/lib/Sema/SemaOverload.cpp | |
parent | f51ba1e3da910efab70a90697c2913dd7a32374e (diff) | |
download | bcm5719-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.cpp | 31 |
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; |