forked from OSchip/llvm-project
Access control for implicit destructor calls. Diagnostic could be orders of
magnitude clearer. llvm-svn: 95078
This commit is contained in:
parent
49786a6c31
commit
6781b05a92
clang
|
@ -2417,6 +2417,7 @@ public:
|
|||
AccessSpecifier Access);
|
||||
bool CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D,
|
||||
AccessSpecifier Access);
|
||||
bool CheckDestructorAccess(SourceLocation Loc, QualType T);
|
||||
bool CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr,
|
||||
NamedDecl *D, AccessSpecifier Access);
|
||||
bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access);
|
||||
|
|
|
@ -306,6 +306,31 @@ bool Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Sema::CheckDestructorAccess(SourceLocation Loc,
|
||||
QualType T) {
|
||||
if (!getLangOptions().AccessControl)
|
||||
return false;
|
||||
|
||||
const RecordType *Record = T->getAs<RecordType>();
|
||||
if (!Record)
|
||||
return false;
|
||||
|
||||
CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Record->getDecl());
|
||||
CXXDestructorDecl *Dtor = NamingClass->getDestructor(Context);
|
||||
|
||||
AccessSpecifier Access = Dtor->getAccess();
|
||||
if (Access == AS_public)
|
||||
return false;
|
||||
|
||||
LookupResult R(*this, Dtor->getDeclName(), Loc, LookupOrdinaryName);
|
||||
R.suppressDiagnostics();
|
||||
|
||||
R.setNamingClass(NamingClass);
|
||||
return CheckAccess(R, Dtor, Access);
|
||||
|
||||
// FIXME: protected check
|
||||
}
|
||||
|
||||
/// Checks access to a constructor.
|
||||
bool Sema::CheckConstructorAccess(SourceLocation UseLoc,
|
||||
CXXConstructorDecl *Constructor,
|
||||
|
|
|
@ -2637,6 +2637,9 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) {
|
|||
Diag(Param->getLocation(), diag::err_array_star_in_function_definition);
|
||||
}
|
||||
}
|
||||
|
||||
if (getLangOptions().AccessControl)
|
||||
CheckDestructorAccess(Param->getLocation(), Param->getType());
|
||||
}
|
||||
|
||||
return HasInvalidParm;
|
||||
|
|
|
@ -3985,10 +3985,11 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD,
|
|||
void Sema::FinalizeVarWithDestructor(VarDecl *VD, QualType DeclInitType) {
|
||||
CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(
|
||||
DeclInitType->getAs<RecordType>()->getDecl());
|
||||
if (!ClassDecl->hasTrivialDestructor())
|
||||
if (CXXDestructorDecl *Destructor =
|
||||
const_cast<CXXDestructorDecl*>(ClassDecl->getDestructor(Context)))
|
||||
MarkDeclarationReferenced(VD->getLocation(), Destructor);
|
||||
if (!ClassDecl->hasTrivialDestructor()) {
|
||||
CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context);
|
||||
MarkDeclarationReferenced(VD->getLocation(), Destructor);
|
||||
CheckDestructorAccess(VD->getLocation(), VD->getType());
|
||||
}
|
||||
}
|
||||
|
||||
/// AddCXXDirectInitializerToDecl - This action is called immediately after
|
||||
|
|
|
@ -83,3 +83,32 @@ namespace test1 {
|
|||
ca(priv); // expected-error {{access to private member}}
|
||||
}
|
||||
}
|
||||
|
||||
// Implicit constructor calls.
|
||||
namespace test2 {
|
||||
class A {
|
||||
private:
|
||||
A(); // expected-note {{declared private here}}
|
||||
|
||||
static A foo;
|
||||
};
|
||||
|
||||
A a; // expected-error {{access to private member}}
|
||||
A A::foo; // okay
|
||||
}
|
||||
|
||||
// Implicit destructor calls.
|
||||
namespace test3 {
|
||||
class A{
|
||||
private:
|
||||
~A(); // expected-note 3 {{declared private here}}
|
||||
static A foo;
|
||||
};
|
||||
|
||||
A a; // expected-error {{access to private member}}
|
||||
A A::foo;
|
||||
|
||||
void foo(A param) { // expected-error {{access to private member}}
|
||||
A local; // expected-error {{access to private member}}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue