diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-07-18 14:32:15 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2009-07-18 14:32:15 +0000 |
commit | 726212f41bac77dc7f3352bc7047615fa0cd9e58 (patch) | |
tree | 8ee07375e36b17ddfa5c75f87cc21ff1a7f7d70f /lib/Sema/SemaAccess.cpp | |
parent | 089962112ebbb730dfe18c104566bcf9810b341e (diff) |
Enhance testing of overriding exception specs for inaccessible base exceptions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76317 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaAccess.cpp')
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 73 |
1 files changed, 43 insertions, 30 deletions
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index bae69ac6dc..31d8a3f5ab 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -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; } |