forked from OSchip/llvm-project
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
This commit is contained in:
parent
4b739894f0
commit
db05cd37a1
|
@ -4136,22 +4136,23 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
|
||||||
OpSpelling, (int)isIndirect)) {
|
OpSpelling, (int)isIndirect)) {
|
||||||
return QualType();
|
return QualType();
|
||||||
}
|
}
|
||||||
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
|
||||||
/*DetectVirtual=*/false);
|
if (!IsDerivedFrom(LHSType, Class)) {
|
||||||
// FIXME: Would it be useful to print full ambiguity paths, or is that
|
|
||||||
// overkill?
|
|
||||||
if (!IsDerivedFrom(LHSType, Class, Paths) ||
|
|
||||||
Paths.isAmbiguous(Context.getCanonicalType(Class))) {
|
|
||||||
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
|
Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling
|
||||||
<< (int)isIndirect << LHS.get()->getType();
|
<< (int)isIndirect << LHS.get()->getType();
|
||||||
return QualType();
|
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.
|
// Cast LHS to type of use.
|
||||||
QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
|
QualType UseType = isIndirect ? Context.getPointerType(Class) : Class;
|
||||||
ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();
|
ExprValueKind VK = isIndirect ? VK_RValue : LHS.get()->getValueKind();
|
||||||
|
|
||||||
CXXCastPath BasePath;
|
|
||||||
BuildBasePathArray(Paths, BasePath);
|
|
||||||
LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK,
|
LHS = ImpCastExprToType(LHS.take(), UseType, CK_DerivedToBase, VK,
|
||||||
&BasePath);
|
&BasePath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ struct D : A {};
|
||||||
struct E : A {};
|
struct E : A {};
|
||||||
struct F : D, E {};
|
struct F : D, E {};
|
||||||
struct G : virtual D {};
|
struct G : virtual D {};
|
||||||
|
class H : A {}; // expected-note 2{{implicitly declared private here}}
|
||||||
|
|
||||||
int A::*pdi1;
|
int A::*pdi1;
|
||||||
int (::A::*pdi2);
|
int (::A::*pdi2);
|
||||||
|
@ -115,8 +116,11 @@ void h() {
|
||||||
(void)(d.*pai);
|
(void)(d.*pai);
|
||||||
(void)(pd->*pai);
|
(void)(pd->*pai);
|
||||||
F f, *ptrf = &f;
|
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)(f.*pai); // expected-error {{ambiguous conversion from derived class 'F' to base class 'A'}}
|
||||||
(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)(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)(hm.*i); // expected-error {{pointer-to-member}}
|
||||||
(void)(phm->*i); // expected-error {{pointer-to-member}}
|
(void)(phm->*i); // expected-error {{pointer-to-member}}
|
||||||
|
|
Loading…
Reference in New Issue