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