diff options
author | John McCall <rjmccall@apple.com> | 2010-01-20 21:53:11 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-01-20 21:53:11 +0000 |
commit | 46460a68f6508775e98c19b4bb8454bb471aac24 (patch) | |
tree | d1149be909b4f69e69a2d06d67538462ba88282e /lib | |
parent | 78205d4bada39d95097e766af9eb30cdd0159461 (diff) | |
download | clang-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.cpp | 20 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/Lookup.h | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 9 |
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); |