//===--------------------------------------------------------------------===//
// 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,
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");
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;
}