From 0b83b08fa41977cce765d5ea3e37843dea2d6fcc Mon Sep 17 00:00:00 2001 From: dim Date: Tue, 7 Mar 2017 21:44:05 +0000 Subject: Pull in r291403 from upstream clang trunk (by Richard Smith): 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. Pull in r291955 from upstream clang trunk (by Richard Smith): PR31606: Generalize our tentative DR resolution for inheriting copy/move constructors to better match the pre-P0136R1 behavior. Together, these fix an issue with C++ using declarations sometimes enabling illegal implicit casts. Direct commit to stable/11, since head already has clang 4.0.0, which includes this change. Reported by: kami PR: 215969 --- contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'contrib/llvm/tools/clang/lib/Sema') diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 40d6e91..f148c2d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -5783,6 +5783,28 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Candidate.FailureKind = ovl_fail_illegal_constructor; return; } + + // C++ [over.match.funcs]p8: (proposed DR resolution) + // A constructor inherited from class type C that has a first parameter + // of type "reference to P" (including such a constructor instantiated + // from a template) is excluded from the set of candidate functions when + // constructing an object of type cv D if the argument list has exactly + // one argument and D is reference-related to P and P is reference-related + // to C. + auto *Shadow = dyn_cast(FoundDecl.getDecl()); + if (Shadow && Args.size() == 1 && Constructor->getNumParams() >= 1 && + Constructor->getParamDecl(0)->getType()->isReferenceType()) { + QualType P = Constructor->getParamDecl(0)->getType()->getPointeeType(); + QualType C = Context.getRecordType(Constructor->getParent()); + QualType D = Context.getRecordType(Shadow->getParent()); + SourceLocation Loc = Args.front()->getExprLoc(); + if ((Context.hasSameUnqualifiedType(P, C) || IsDerivedFrom(Loc, P, C)) && + (Context.hasSameUnqualifiedType(D, P) || IsDerivedFrom(Loc, D, P))) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_inhctor_slice; + return; + } + } } unsigned NumParams = Proto->getNumParams(); @@ -9750,6 +9772,17 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, case ovl_fail_enable_if: return DiagnoseFailedEnableIfAttr(S, Cand); + case ovl_fail_inhctor_slice: + // It's generally not interesting to note copy/move constructors here. + if (cast(Fn)->isCopyOrMoveConstructor()) + return; + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_inherited_constructor_slice) + << (Fn->getPrimaryTemplate() ? 1 : 0) + << Fn->getParamDecl(0)->getType()->isRValueReferenceType(); + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); + return; + case ovl_fail_addr_not_available: { bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function); (void)Available; -- cgit v1.1