]> granicus.if.org Git - clang/commitdiff
PR17602: check accessibility when performing an implicit derived-to-base
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 12 Dec 2013 03:40:18 +0000 (03:40 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 12 Dec 2013 03:40:18 +0000 (03:40 +0000)
conversion on the LHS of a .* or ->*. Slightly improve diagnostics in case
of an ambiguous base class.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@197125 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/member-pointer.cpp

index 3c9724d0be18b7e4a4e54b0d5a266ca00c1cab86..04871d367e8a89a4ce65bde5071a71c65395c974 100644 (file)
@@ -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);
   }
index 4e8b4a813ba73538db69e27e44d437bedecaabb3..82873d9c7daed59f32487f16542765ab2bc5512f 100644 (file)
@@ -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}}