From db05cd37a1e75fbdb9775f1b152e6546b94634e8 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 12 Dec 2013 03:40:18 +0000 Subject: [PATCH] PR17602: check accessibility when performing an implicit derived-to-base conversion on the LHS of a .* or ->*. Slightly improve diagnostics in case of an ambiguous base class. llvm-svn: 197125 --- clang/lib/Sema/SemaExprCXX.cpp | 19 ++++++++++--------- clang/test/SemaCXX/member-pointer.cpp | 8 ++++++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 3c9724d0be18..04871d367e8a 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4136,22 +4136,23 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS, OpSpelling, (int)isIndirect)) { return QualType(); } - CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, - /*DetectVirtual=*/false); - // FIXME: Would it be useful to print full ambiguity paths, or is that - // overkill? - if (!IsDerivedFrom(LHSType, Class, Paths) || - Paths.isAmbiguous(Context.getCanonicalType(Class))) { + + if (!IsDerivedFrom(LHSType, Class)) { Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling << (int)isIndirect << LHS.get()->getType(); return QualType(); } + + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(LHSType, Class, Loc, + SourceRange(LHS.get()->getLocStart(), + RHS.get()->getLocEnd()), + &BasePath)) + return QualType(); + // Cast LHS to type of use. QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind(); - - CXXCastPath BasePath; - BuildBasePathArray(Paths, BasePath); LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK, &BasePath); } diff --git a/clang/test/SemaCXX/member-pointer.cpp b/clang/test/SemaCXX/member-pointer.cpp index 4e8b4a813ba7..82873d9c7dae 100644 --- a/clang/test/SemaCXX/member-pointer.cpp +++ b/clang/test/SemaCXX/member-pointer.cpp @@ -7,6 +7,7 @@ struct D : A {}; struct E : A {}; struct F : D, E {}; struct G : virtual D {}; +class H : A {}; // expected-note 2{{implicitly declared private here}} int A::*pdi1; int (::A::*pdi2); @@ -115,8 +116,11 @@ void h() { (void)(d.*pai); (void)(pd->*pai); F f, *ptrf = &f; - (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'F'}} - (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'F *'}} + (void)(f.*pai); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A'}} + (void)(ptrf->*pai); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A'}} + H h, *ptrh = &h; + (void)(h.*pai); // expected-error {{cannot cast 'H' to its private base class 'A'}} + (void)(ptrh->*pai); // expected-error {{cannot cast 'H' to its private base class 'A'}} (void)(hm.*i); // expected-error {{pointer-to-member}} (void)(phm->*i); // expected-error {{pointer-to-member}}