diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-10-14 18:03:49 +0000 |
commit | 4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch) | |
tree | 137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Sema/SemaAccess.cpp | |
parent | 5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff) |
Notes
Diffstat (limited to 'lib/Sema/SemaAccess.cpp')
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 89 |
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; } |