summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaAccess.cpp
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
commit4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch)
tree137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Sema/SemaAccess.cpp
parent5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff)
Notes
Diffstat (limited to 'lib/Sema/SemaAccess.cpp')
-rw-r--r--lib/Sema/SemaAccess.cpp89
1 files changed, 51 insertions, 38 deletions
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index bae69ac6dc74a..21f83a560d7c4 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -11,15 +11,16 @@
//
//===----------------------------------------------------------------------===//
-#include "SemaInherit.h"
#include "Sema.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/CXXInheritance.h"
+#include "clang/AST/DeclCXX.h"
using namespace clang;
/// SetMemberAccessSpecifier - Set the access specifier of a member.
/// Returns true on error (when the previous member decl access specifier
/// is different from the new member decl access specifier).
-bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
+bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
NamedDecl *PrevMemberDecl,
AccessSpecifier LexicalAS) {
if (!PrevMemberDecl) {
@@ -27,52 +28,49 @@ bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
MemberDecl->setAccess(LexicalAS);
return false;
}
-
+
// C++ [class.access.spec]p3: When a member is redeclared its access
// specifier must be same as its initial declaration.
if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) {
- Diag(MemberDecl->getLocation(),
- diag::err_class_redeclared_with_different_access)
+ Diag(MemberDecl->getLocation(),
+ diag::err_class_redeclared_with_different_access)
<< MemberDecl << LexicalAS;
Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration)
<< PrevMemberDecl << PrevMemberDecl->getAccess();
return true;
}
-
+
MemberDecl->setAccess(PrevMemberDecl->getAccess());
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, CXXBasePaths &Paths, bool NoPrivileges) {
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");
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 (CXXBasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end();
Path != PathsEnd; ++Path) {
-
+
bool FoundInaccessibleBase = false;
-
- for (BasePath::const_iterator Element = Path->begin(),
+
+ for (CXXBasePath::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) {
- Diag(AccessLoc, InaccessibleBaseID)
+ 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,
+ CXXBasePaths &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;
}