summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/CXXInheritance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/CXXInheritance.cpp')
-rw-r--r--clang/lib/AST/CXXInheritance.cpp42
1 files changed, 28 insertions, 14 deletions
diff --git a/clang/lib/AST/CXXInheritance.cpp b/clang/lib/AST/CXXInheritance.cpp
index d575ccd9826..72083286926 100644
--- a/clang/lib/AST/CXXInheritance.cpp
+++ b/clang/lib/AST/CXXInheritance.cpp
@@ -61,7 +61,6 @@ void CXXBasePaths::clear() {
Paths.clear();
ClassSubobjects.clear();
ScratchPath.clear();
- ScratchAccess.clear();
DetectedVirtual = 0;
}
@@ -147,6 +146,10 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
CXXBasePaths &Paths) const {
bool FoundPath = false;
+ // The access of the path down to this record.
+ AccessSpecifier AccessToHere = Paths.ScratchPath.Access;
+ bool IsFirstStep = Paths.ScratchPath.empty();
+
ASTContext &Context = getASTContext();
for (base_class_const_iterator BaseSpec = bases_begin(),
BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) {
@@ -191,20 +194,30 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
Element.SubobjectNumber = Subobjects.second;
Paths.ScratchPath.push_back(Element);
- // C++0x [class.access.base]p1 (paraphrased):
- // The access of a member of a base class is the less permissive
- // of its access within the base class and the access of the base
- // class within the derived class.
- // We're just calculating the access along the path, so we ignore
- // the access specifiers of whatever decls we've found.
- AccessSpecifier PathAccess = Paths.ScratchPath.Access;
- Paths.ScratchAccess.push_back(PathAccess);
- Paths.ScratchPath.Access
- = std::max(PathAccess, BaseSpec->getAccessSpecifier());
+ // Calculate the "top-down" access to this base class.
+ // The spec actually describes this bottom-up, but top-down is
+ // equivalent because the definition works out as follows:
+ // 1. Write down the access along each step in the inheritance
+ // chain, followed by the access of the decl itself.
+ // For example, in
+ // class A { public: int foo; };
+ // class B : protected A {};
+ // class C : public B {};
+ // class D : private C {};
+ // we would write:
+ // private public protected public
+ // 2. If 'private' appears anywhere except far-left, access is denied.
+ // 3. Otherwise, overall access is determined by the most restrictive
+ // access in the sequence.
+ if (IsFirstStep)
+ Paths.ScratchPath.Access = BaseSpec->getAccessSpecifier();
+ else
+ Paths.ScratchPath.Access
+ = MergeAccess(AccessToHere, BaseSpec->getAccessSpecifier());
}
if (BaseMatches(BaseSpec, Paths.ScratchPath, UserData)) {
- // We've found a path that terminates that this base.
+ // We've found a path that terminates at this base.
FoundPath = true;
if (Paths.isRecordingPaths()) {
// We have a path. Make a copy of it before moving on.
@@ -237,8 +250,6 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
// collecting paths).
if (Paths.isRecordingPaths()) {
Paths.ScratchPath.pop_back();
- Paths.ScratchPath.Access = Paths.ScratchAccess.back();
- Paths.ScratchAccess.pop_back();
}
// If we set a virtual earlier, and this isn't a path, forget it again.
@@ -246,6 +257,9 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
Paths.DetectedVirtual = 0;
}
}
+
+ // Reset the scratch path access.
+ Paths.ScratchPath.Access = AccessToHere;
return FoundPath;
}
OpenPOWER on IntegriCloud