forked from OSchip/llvm-project
Enhance testing of overriding exception specs for inaccessible base exceptions.
llvm-svn: 76317
This commit is contained in:
parent
0ef680bcbd
commit
e644e19671
|
@ -1989,17 +1989,21 @@ public:
|
|||
//===--------------------------------------------------------------------===//
|
||||
// C++ Access Control
|
||||
//
|
||||
|
||||
|
||||
bool SetMemberAccessSpecifier(NamedDecl *MemberDecl,
|
||||
NamedDecl *PrevMemberDecl,
|
||||
AccessSpecifier LexicalAS);
|
||||
|
||||
bool CheckBaseClassAccess(QualType Derived, QualType Base,
|
||||
|
||||
const CXXBaseSpecifier *FindInaccessibleBase(QualType Derived, QualType Base,
|
||||
BasePaths &Paths,
|
||||
bool NoPrivileges = false);
|
||||
|
||||
bool CheckBaseClassAccess(QualType Derived, QualType Base,
|
||||
unsigned InaccessibleBaseID,
|
||||
BasePaths& Paths, SourceLocation AccessLoc,
|
||||
DeclarationName Name);
|
||||
|
||||
|
||||
|
||||
|
||||
enum AbstractDiagSelID {
|
||||
AbstractNone = -1,
|
||||
AbstractReturnType,
|
||||
|
|
|
@ -43,36 +43,34 @@ bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
|
|||
return false;
|
||||
}
|
||||
|
||||
/// CheckBaseClassAccess - Check that a derived class can access its base class
|
||||
/// and report an error if it can't. [class.access.base]
|
||||
bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
|
||||
unsigned InaccessibleBaseID,
|
||||
BasePaths& Paths, SourceLocation AccessLoc,
|
||||
DeclarationName Name) {
|
||||
/// Find a class on the derivation path between Derived and Base that is
|
||||
/// inaccessible. If @p NoPrivileges is true, special access rights (members
|
||||
/// and friends) are not considered.
|
||||
const CXXBaseSpecifier *Sema::FindInaccessibleBase(
|
||||
QualType Derived, QualType Base, BasePaths &Paths, bool NoPrivileges)
|
||||
{
|
||||
Base = Context.getCanonicalType(Base).getUnqualifiedType();
|
||||
assert(!Paths.isAmbiguous(Base) &&
|
||||
"Can't check base class access if set of paths is ambiguous");
|
||||
assert(Paths.isRecordingPaths() &&
|
||||
"Can't check base class access without recorded paths");
|
||||
|
||||
if (!getLangOptions().AccessControl)
|
||||
return false;
|
||||
|
||||
const CXXBaseSpecifier *InacessibleBase = 0;
|
||||
|
||||
const CXXRecordDecl* CurrentClassDecl = 0;
|
||||
|
||||
const CXXBaseSpecifier *InaccessibleBase = 0;
|
||||
|
||||
const CXXRecordDecl *CurrentClassDecl = 0;
|
||||
if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(getCurFunctionDecl()))
|
||||
CurrentClassDecl = MD->getParent();
|
||||
|
||||
for (BasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end();
|
||||
for (BasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end();
|
||||
Path != PathsEnd; ++Path) {
|
||||
|
||||
|
||||
bool FoundInaccessibleBase = false;
|
||||
|
||||
for (BasePath::const_iterator Element = Path->begin(),
|
||||
|
||||
for (BasePath::const_iterator Element = Path->begin(),
|
||||
ElementEnd = Path->end(); Element != ElementEnd; ++Element) {
|
||||
const CXXBaseSpecifier *Base = Element->Base;
|
||||
|
||||
|
||||
switch (Base->getAccessSpecifier()) {
|
||||
default:
|
||||
assert(0 && "invalid access specifier");
|
||||
|
@ -81,44 +79,59 @@ bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
|
|||
break;
|
||||
case AS_private:
|
||||
// FIXME: Check if the current function/class is a friend.
|
||||
if (CurrentClassDecl != Element->Class)
|
||||
if (NoPrivileges || CurrentClassDecl != Element->Class)
|
||||
FoundInaccessibleBase = true;
|
||||
break;
|
||||
case AS_protected:
|
||||
case AS_protected:
|
||||
// FIXME: Implement
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (FoundInaccessibleBase) {
|
||||
InacessibleBase = Base;
|
||||
InaccessibleBase = Base;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!FoundInaccessibleBase) {
|
||||
// We found a path to the base, our work here is done.
|
||||
InacessibleBase = 0;
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (InacessibleBase) {
|
||||
assert(InaccessibleBase && "no path found, but no inaccessible base");
|
||||
return InaccessibleBase;
|
||||
}
|
||||
|
||||
/// CheckBaseClassAccess - Check that a derived class can access its base class
|
||||
/// and report an error if it can't. [class.access.base]
|
||||
bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base,
|
||||
unsigned InaccessibleBaseID,
|
||||
BasePaths &Paths, SourceLocation AccessLoc,
|
||||
DeclarationName Name) {
|
||||
|
||||
if (!getLangOptions().AccessControl)
|
||||
return false;
|
||||
const CXXBaseSpecifier *InaccessibleBase = FindInaccessibleBase(
|
||||
Derived, Base, Paths);
|
||||
|
||||
if (InaccessibleBase) {
|
||||
Diag(AccessLoc, InaccessibleBaseID)
|
||||
<< Derived << Base << Name;
|
||||
|
||||
AccessSpecifier AS = InacessibleBase->getAccessSpecifierAsWritten();
|
||||
|
||||
AccessSpecifier AS = InaccessibleBase->getAccessSpecifierAsWritten();
|
||||
|
||||
// If there's no written access specifier, then the inheritance specifier
|
||||
// is implicitly private.
|
||||
if (AS == AS_none)
|
||||
Diag(InacessibleBase->getSourceRange().getBegin(),
|
||||
Diag(InaccessibleBase->getSourceRange().getBegin(),
|
||||
diag::note_inheritance_implicitly_private_here);
|
||||
else
|
||||
Diag(InacessibleBase->getSourceRange().getBegin(),
|
||||
Diag(InaccessibleBase->getSourceRange().getBegin(),
|
||||
diag::note_inheritance_specifier_here) << AS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1294,7 +1294,7 @@ bool Sema::CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID,
|
|||
bool SubIsClass = CanonicalSubT->isRecordType();
|
||||
CanonicalSubT.setCVRQualifiers(0);
|
||||
|
||||
BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false,
|
||||
BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
||||
/*DetectVirtual=*/false);
|
||||
|
||||
bool Contained = false;
|
||||
|
@ -1332,7 +1332,8 @@ bool Sema::CheckExceptionSpecSubset(unsigned DiagID, unsigned NoteID,
|
|||
if (Paths.isAmbiguous(CanonicalSuperT))
|
||||
continue;
|
||||
|
||||
// FIXME: Check base access. Don't forget to enable path recording.
|
||||
if (FindInaccessibleBase(CanonicalSubT, CanonicalSuperT, Paths, true))
|
||||
continue;
|
||||
|
||||
Contained = true;
|
||||
break;
|
||||
|
|
|
@ -78,6 +78,10 @@ struct D : B1, B2
|
|||
{
|
||||
};
|
||||
|
||||
struct P : private A
|
||||
{
|
||||
};
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual void f1() throw();
|
||||
|
@ -94,6 +98,7 @@ struct Base
|
|||
virtual void g2() throw(int); // expected-note {{overridden virtual function is here}}
|
||||
virtual void g3() throw(A); // expected-note {{overridden virtual function is here}}
|
||||
virtual void g4() throw(B1); // expected-note {{overridden virtual function is here}}
|
||||
virtual void g5() throw(A); // expected-note {{overridden virtual function is here}}
|
||||
};
|
||||
struct Derived : Base
|
||||
{
|
||||
|
@ -111,4 +116,5 @@ struct Derived : Base
|
|||
virtual void g2(); // expected-error {{exception specification of overriding function is more lax}}
|
||||
virtual void g3() throw(D); // expected-error {{exception specification of overriding function is more lax}}
|
||||
virtual void g4() throw(A); // expected-error {{exception specification of overriding function is more lax}}
|
||||
virtual void g5() throw(P); // expected-error {{exception specification of overriding function is more lax}}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue