forked from OSchip/llvm-project
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. llvm-svn: 94038
This commit is contained in:
parent
dd969c897e
commit
401982f56c
|
@ -65,6 +65,9 @@ struct CXXBasePathElement {
|
||||||
/// subobject is being used.
|
/// subobject is being used.
|
||||||
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
|
class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> {
|
||||||
public:
|
public:
|
||||||
|
/// \brief The access along this inheritance path.
|
||||||
|
AccessSpecifier Access;
|
||||||
|
|
||||||
/// \brief The set of declarations found inside this base class
|
/// \brief The set of declarations found inside this base class
|
||||||
/// subobject.
|
/// subobject.
|
||||||
DeclContext::lookup_result Decls;
|
DeclContext::lookup_result Decls;
|
||||||
|
@ -131,10 +134,14 @@ class CXXBasePaths {
|
||||||
/// is also recorded.
|
/// is also recorded.
|
||||||
bool DetectVirtual;
|
bool DetectVirtual;
|
||||||
|
|
||||||
/// ScratchPath - A BasePath that is used by Sema::IsDerivedFrom
|
/// ScratchPath - A BasePath that is used by Sema::lookupInBases
|
||||||
/// to help build the set of paths.
|
/// to help build the set of paths.
|
||||||
CXXBasePath ScratchPath;
|
CXXBasePath ScratchPath;
|
||||||
|
|
||||||
|
/// ScratchAccess - A stack of accessibility annotations used by
|
||||||
|
/// Sema::lookupInBases.
|
||||||
|
llvm::SmallVector<AccessSpecifier, 4> ScratchAccess;
|
||||||
|
|
||||||
/// DetectedVirtual - The base class that is virtual.
|
/// DetectedVirtual - The base class that is virtual.
|
||||||
const RecordType *DetectedVirtual;
|
const RecordType *DetectedVirtual;
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ void CXXBasePaths::clear() {
|
||||||
Paths.clear();
|
Paths.clear();
|
||||||
ClassSubobjects.clear();
|
ClassSubobjects.clear();
|
||||||
ScratchPath.clear();
|
ScratchPath.clear();
|
||||||
|
ScratchAccess.clear();
|
||||||
DetectedVirtual = 0;
|
DetectedVirtual = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +190,17 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches,
|
||||||
else
|
else
|
||||||
Element.SubobjectNumber = Subobjects.second;
|
Element.SubobjectNumber = Subobjects.second;
|
||||||
Paths.ScratchPath.push_back(Element);
|
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)) {
|
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
|
// Pop this base specifier off the current path (if we're
|
||||||
// collecting paths).
|
// collecting paths).
|
||||||
if (Paths.isRecordingPaths())
|
if (Paths.isRecordingPaths()) {
|
||||||
Paths.ScratchPath.pop_back();
|
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 we set a virtual earlier, and this isn't a path, forget it again.
|
||||||
if (SetVirtual && !FoundPath) {
|
if (SetVirtual && !FoundPath) {
|
||||||
Paths.DetectedVirtual = 0;
|
Paths.DetectedVirtual = 0;
|
||||||
|
|
|
@ -410,9 +410,16 @@ SourceLocation Decl::getBodyRBrace() const {
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void Decl::CheckAccessDeclContext() const {
|
void Decl::CheckAccessDeclContext() const {
|
||||||
// If the decl is the toplevel translation unit or if we're not in a
|
// Suppress this check if any of the following hold:
|
||||||
// record decl context, we don't need to check anything.
|
// 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) ||
|
if (isa<TranslationUnitDecl>(this) ||
|
||||||
|
isTemplateParameter() ||
|
||||||
|
isa<ParmVarDecl>(this) ||
|
||||||
!isa<CXXRecordDecl>(getDeclContext()))
|
!isa<CXXRecordDecl>(getDeclContext()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -245,10 +245,16 @@ public:
|
||||||
return IDNS;
|
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.
|
/// Does not test the acceptance criteria.
|
||||||
void addDecl(NamedDecl *D) {
|
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;
|
ResultKind = Found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1305,6 +1305,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
||||||
|
|
||||||
// Keep a chain of previous declarations.
|
// Keep a chain of previous declarations.
|
||||||
New->setPreviousDeclaration(Old);
|
New->setPreviousDeclaration(Old);
|
||||||
|
|
||||||
|
// Inherit access appropriately.
|
||||||
|
New->setAccess(Old->getAccess());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MarkLive(CFGBlock *e, llvm::BitVector &live) {
|
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()) {
|
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
|
// An out-of-line member function declaration must also be a
|
||||||
// definition (C++ [dcl.meaning]p1).
|
// definition (C++ [dcl.meaning]p1).
|
||||||
// Note that this is not the case for explicit specializations of
|
// Note that this is not the case for explicit specializations of
|
||||||
|
|
|
@ -445,8 +445,9 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
|
||||||
|
|
||||||
DeclContext::lookup_const_iterator I, E;
|
DeclContext::lookup_const_iterator I, E;
|
||||||
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
|
for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
|
||||||
if (R.isAcceptableDecl(*I)) {
|
NamedDecl *D = *I;
|
||||||
R.addDecl(*I);
|
if (R.isAcceptableDecl(D)) {
|
||||||
|
R.addDecl(D);
|
||||||
Found = true;
|
Found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1047,10 +1048,15 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
|
||||||
// FIXME: support using declarations!
|
// FIXME: support using declarations!
|
||||||
QualType SubobjectType;
|
QualType SubobjectType;
|
||||||
int SubobjectNumber = 0;
|
int SubobjectNumber = 0;
|
||||||
|
AccessSpecifier SubobjectAccess = AS_private;
|
||||||
for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
|
for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
|
||||||
Path != PathEnd; ++Path) {
|
Path != PathEnd; ++Path) {
|
||||||
const CXXBasePathElement &PathElement = Path->back();
|
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.
|
// Determine whether we're looking at a distinct sub-object or not.
|
||||||
if (SubobjectType.isNull()) {
|
if (SubobjectType.isNull()) {
|
||||||
// This is the first subobject we've looked at. Record its type.
|
// 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;
|
DeclContext::lookup_iterator I, E;
|
||||||
for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I)
|
for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I)
|
||||||
R.addDecl(*I);
|
R.addDecl(*I, std::max(SubobjectAccess, (*I)->getAccess()));
|
||||||
R.resolveKind();
|
R.resolveKind();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,6 +150,7 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
|
||||||
Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
|
Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Typedef->setAccess(D->getAccess());
|
||||||
Owner->addDecl(Typedef);
|
Owner->addDecl(Typedef);
|
||||||
|
|
||||||
return Typedef;
|
return Typedef;
|
||||||
|
@ -208,6 +209,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
||||||
if (D->isOutOfLine())
|
if (D->isOutOfLine())
|
||||||
Var->setLexicalDeclContext(D->getLexicalDeclContext());
|
Var->setLexicalDeclContext(D->getLexicalDeclContext());
|
||||||
|
|
||||||
|
Var->setAccess(D->getAccess());
|
||||||
|
|
||||||
// FIXME: In theory, we could have a previous declaration for variables that
|
// FIXME: In theory, we could have a previous declaration for variables that
|
||||||
// are not static data members.
|
// are not static data members.
|
||||||
bool Redeclaration = false;
|
bool Redeclaration = false;
|
||||||
|
@ -375,6 +378,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Field->setImplicit(D->isImplicit());
|
Field->setImplicit(D->isImplicit());
|
||||||
|
Field->setAccess(D->getAccess());
|
||||||
Owner->addDecl(Field);
|
Owner->addDecl(Field);
|
||||||
|
|
||||||
return Field;
|
return Field;
|
||||||
|
@ -559,6 +563,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||||
return Inst;
|
return Inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Inst->setAccess(D->getAccess());
|
||||||
Owner->addDecl(Inst);
|
Owner->addDecl(Inst);
|
||||||
|
|
||||||
// First, we sort the partial specializations by location, so
|
// First, we sort the partial specializations by location, so
|
||||||
|
@ -634,6 +639,8 @@ TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||||
if (!Instantiated)
|
if (!Instantiated)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
Instantiated->setAccess(D->getAccess());
|
||||||
|
|
||||||
// Link the instantiated function template declaration to the function
|
// Link the instantiated function template declaration to the function
|
||||||
// template from which it was instantiated.
|
// template from which it was instantiated.
|
||||||
FunctionTemplateDecl *InstTemplate
|
FunctionTemplateDecl *InstTemplate
|
||||||
|
@ -964,6 +971,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
||||||
if (D->isPure())
|
if (D->isPure())
|
||||||
SemaRef.CheckPureMethod(Method, SourceRange());
|
SemaRef.CheckPureMethod(Method, SourceRange());
|
||||||
|
|
||||||
|
Method->setAccess(D->getAccess());
|
||||||
|
|
||||||
if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
|
if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
|
||||||
!Method->getFriendObjectKind())
|
!Method->getFriendObjectKind())
|
||||||
Owner->addDecl(Method);
|
Owner->addDecl(Method);
|
||||||
|
|
Loading…
Reference in New Issue