summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-01-20 21:53:11 +0000
committerJohn McCall <rjmccall@apple.com>2010-01-20 21:53:11 +0000
commit46460a68f6508775e98c19b4bb8454bb471aac24 (patch)
treed1149be909b4f69e69a2d06d67538462ba88282e /lib
parent78205d4bada39d95097e766af9eb30cdd0159461 (diff)
downloadclang-46460a68f6508775e98c19b4bb8454bb471aac24.tar.gz
First pass at collecting access-specifier information along inheritance paths.
Triggers lots of assertions about missing access information; fix them. Will actually consume this information soon. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94038 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/CXXInheritance.cpp20
-rw-r--r--lib/AST/DeclBase.cpp11
-rw-r--r--lib/Sema/Lookup.h10
-rw-r--r--lib/Sema/SemaDecl.cpp7
-rw-r--r--lib/Sema/SemaLookup.cpp12
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp9
6 files changed, 60 insertions, 9 deletions
diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 92a58b76d8..d575ccd982 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -61,6 +61,7 @@ void CXXBasePaths::clear() {
Paths.clear();
ClassSubobjects.clear();
ScratchPath.clear();
+ ScratchAccess.clear();
DetectedVirtual = 0;
}
@@ -145,7 +146,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
void *UserData,
CXXBasePaths &Paths) const {
bool FoundPath = false;
-
+
ASTContext &Context = getASTContext();
for (base_class_const_iterator BaseSpec = bases_begin(),
BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) {
@@ -189,6 +190,17 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
else
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());
}
if (BaseMatches(BaseSpec, Paths.ScratchPath, UserData)) {
@@ -223,8 +235,12 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
// Pop this base specifier off the current path (if we're
// collecting paths).
- if (Paths.isRecordingPaths())
+ 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.
if (SetVirtual && !FoundPath) {
Paths.DetectedVirtual = 0;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 76ff83448a..95b749bfbb 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -410,9 +410,16 @@ SourceLocation Decl::getBodyRBrace() const {
#ifndef NDEBUG
void Decl::CheckAccessDeclContext() const {
- // If the decl is the toplevel translation unit or if we're not in a
- // record decl context, we don't need to check anything.
+ // Suppress this check if any of the following hold:
+ // 1. this is the translation unit (and thus has no parent)
+ // 2. this is a template parameter (and thus doesn't belong to its context)
+ // 3. this is a ParmVarDecl (which can be in a record context during
+ // the brief period between its creation and the creation of the
+ // FunctionDecl)
+ // 4. the context is not a record
if (isa<TranslationUnitDecl>(this) ||
+ isTemplateParameter() ||
+ isa<ParmVarDecl>(this) ||
!isa<CXXRecordDecl>(getDeclContext()))
return;
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index 33d1106559..274a3dabbf 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -245,10 +245,16 @@ public:
return IDNS;
}
- /// \brief Add a declaration to these results with no access bits.
+ /// \brief Add a declaration to these results with its natural access.
/// Does not test the acceptance criteria.
void addDecl(NamedDecl *D) {
- Decls.addDecl(D);
+ addDecl(D, D->getAccess());
+ }
+
+ /// \brief Add a declaration to these results with the given access.
+ /// Does not test the acceptance criteria.
+ void addDecl(NamedDecl *D, AccessSpecifier AS) {
+ Decls.addDecl(D, AS);
ResultKind = Found;
}
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1e46787d8f..7e86120b16 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1305,6 +1305,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
// Keep a chain of previous declarations.
New->setPreviousDeclaration(Old);
+
+ // Inherit access appropriately.
+ New->setAccess(Old->getAccess());
}
static void MarkLive(CFGBlock *e, llvm::BitVector &live) {
@@ -3361,6 +3364,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
+ // Fake up an access specifier if it's supposed to be a class member.
+ if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
+ NewFD->setAccess(AS_public);
+
// An out-of-line member function declaration must also be a
// definition (C++ [dcl.meaning]p1).
// Note that this is not the case for explicit specializations of
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index da7626780c..ddce4a4c23 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -445,8 +445,9 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
DeclContext::lookup_const_iterator I, E;
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
- if (R.isAcceptableDecl(*I)) {
- R.addDecl(*I);
+ NamedDecl *D = *I;
+ if (R.isAcceptableDecl(D)) {
+ R.addDecl(D);
Found = true;
}
}
@@ -1047,10 +1048,15 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
// FIXME: support using declarations!
QualType SubobjectType;
int SubobjectNumber = 0;
+ AccessSpecifier SubobjectAccess = AS_private;
for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
Path != PathEnd; ++Path) {
const CXXBasePathElement &PathElement = Path->back();
+ // Pick the best (i.e. most permissive i.e. numerically lowest) access
+ // across all paths.
+ SubobjectAccess = std::min(SubobjectAccess, Path->Access);
+
// Determine whether we're looking at a distinct sub-object or not.
if (SubobjectType.isNull()) {
// This is the first subobject we've looked at. Record its type.
@@ -1106,7 +1112,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
DeclContext::lookup_iterator I, E;
for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I)
- R.addDecl(*I);
+ R.addDecl(*I, std::max(SubobjectAccess, (*I)->getAccess()));
R.resolveKind();
return true;
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e3a180a578..c3768b3a7c 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -150,6 +150,7 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
}
+ Typedef->setAccess(D->getAccess());
Owner->addDecl(Typedef);
return Typedef;
@@ -208,6 +209,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
if (D->isOutOfLine())
Var->setLexicalDeclContext(D->getLexicalDeclContext());
+ Var->setAccess(D->getAccess());
+
// FIXME: In theory, we could have a previous declaration for variables that
// are not static data members.
bool Redeclaration = false;
@@ -375,6 +378,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
}
Field->setImplicit(D->isImplicit());
+ Field->setAccess(D->getAccess());
Owner->addDecl(Field);
return Field;
@@ -559,6 +563,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
return Inst;
}
+ Inst->setAccess(D->getAccess());
Owner->addDecl(Inst);
// First, we sort the partial specializations by location, so
@@ -634,6 +639,8 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (!Instantiated)
return 0;
+ Instantiated->setAccess(D->getAccess());
+
// Link the instantiated function template declaration to the function
// template from which it was instantiated.
FunctionTemplateDecl *InstTemplate
@@ -964,6 +971,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
if (D->isPure())
SemaRef.CheckPureMethod(Method, SourceRange());
+ Method->setAccess(D->getAccess());
+
if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
!Method->getFriendObjectKind())
Owner->addDecl(Method);