зеркало из https://github.com/microsoft/clang-1.git
Introduce ScopedDecl::getLexicalDeclContext() which is different from ScopedDecl::getDeclContext() when there are nested-names.
e.g.: namespace A { void f(); // SemanticDC (getDeclContext) == LexicalDC (getLexicalDeclContext) == 'namespace A' } void A::f(); // SemanticDC == namespace 'A' // LexicalDC == global namespace git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58948 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
0f84a23cc5
Коммит
5239304ff7
|
@ -92,16 +92,72 @@ class ScopedDecl : public NamedDecl {
|
|||
///
|
||||
ScopedDecl *Next;
|
||||
|
||||
DeclContext *DeclCtx;
|
||||
/// DeclCtx - Holds either a DeclContext* or a MultipleDC*.
|
||||
/// For declarations that don't contain C++ scope specifiers, it contains
|
||||
/// the DeclContext where the ScopedDecl was declared.
|
||||
/// For declarations with C++ scope specifiers, it contains a MultipleDC*
|
||||
/// with the context where it semantically belongs (SemanticDC) and the
|
||||
/// context where it was lexically declared (LexicalDC).
|
||||
/// e.g.:
|
||||
///
|
||||
/// namespace A {
|
||||
/// void f(); // SemanticDC == LexicalDC == 'namespace A'
|
||||
/// }
|
||||
/// void A::f(); // SemanticDC == namespace 'A'
|
||||
/// // LexicalDC == global namespace
|
||||
uintptr_t DeclCtx;
|
||||
|
||||
struct MultipleDC {
|
||||
DeclContext *SemanticDC;
|
||||
DeclContext *LexicalDC;
|
||||
};
|
||||
|
||||
inline bool isInSemaDC() const { return (DeclCtx & 0x1) == 0; }
|
||||
inline bool isOutOfSemaDC() const { return (DeclCtx & 0x1) != 0; }
|
||||
inline MultipleDC *getMultipleDC() const {
|
||||
return reinterpret_cast<MultipleDC*>(DeclCtx & ~0x1);
|
||||
}
|
||||
|
||||
protected:
|
||||
ScopedDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||
IdentifierInfo *Id, ScopedDecl *PrevDecl)
|
||||
: NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0), DeclCtx(DC) {}
|
||||
: NamedDecl(DK, L, Id), NextDeclarator(PrevDecl), Next(0),
|
||||
DeclCtx(reinterpret_cast<uintptr_t>(DC)) {}
|
||||
|
||||
virtual ~ScopedDecl();
|
||||
|
||||
public:
|
||||
const DeclContext *getDeclContext() const { return DeclCtx; }
|
||||
DeclContext *getDeclContext() { return DeclCtx; }
|
||||
const DeclContext *getDeclContext() const {
|
||||
if (isInSemaDC())
|
||||
return reinterpret_cast<DeclContext*>(DeclCtx);
|
||||
return getMultipleDC()->SemanticDC;
|
||||
}
|
||||
DeclContext *getDeclContext() {
|
||||
return const_cast<DeclContext*>(
|
||||
const_cast<const ScopedDecl*>(this)->getDeclContext());
|
||||
}
|
||||
|
||||
/// getLexicalDeclContext - The declaration context where this ScopedDecl was
|
||||
/// lexically declared (LexicalDC). May be different from
|
||||
/// getDeclContext() (SemanticDC).
|
||||
/// e.g.:
|
||||
///
|
||||
/// namespace A {
|
||||
/// void f(); // SemanticDC == LexicalDC == 'namespace A'
|
||||
/// }
|
||||
/// void A::f(); // SemanticDC == namespace 'A'
|
||||
/// // LexicalDC == global namespace
|
||||
const DeclContext *getLexicalDeclContext() const {
|
||||
if (isInSemaDC())
|
||||
return reinterpret_cast<DeclContext*>(DeclCtx);
|
||||
return getMultipleDC()->LexicalDC;
|
||||
}
|
||||
DeclContext *getLexicalDeclContext() {
|
||||
return const_cast<DeclContext*>(
|
||||
const_cast<const ScopedDecl*>(this)->getLexicalDeclContext());
|
||||
}
|
||||
|
||||
void setLexicalDeclContext(DeclContext *DC);
|
||||
|
||||
ScopedDecl *getNext() const { return Next; }
|
||||
void setNext(ScopedDecl *N) { Next = N; }
|
||||
|
|
|
@ -391,14 +391,12 @@ protected:
|
|||
/// CXXMethodDecl - Represents a static or instance method of a
|
||||
/// struct/union/class.
|
||||
class CXXMethodDecl : public FunctionDecl {
|
||||
bool IsInlineDef : 1;
|
||||
|
||||
protected:
|
||||
CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L,
|
||||
IdentifierInfo *Id, QualType T,
|
||||
bool isStatic, bool isInline, ScopedDecl *PrevDecl)
|
||||
: FunctionDecl(DK, RD, L, Id, T, (isStatic ? Static : None),
|
||||
isInline, PrevDecl), IsInlineDef(false) {}
|
||||
isInline, PrevDecl) {}
|
||||
|
||||
public:
|
||||
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
|
||||
|
@ -409,9 +407,9 @@ public:
|
|||
bool isStatic() const { return getStorageClass() == Static; }
|
||||
bool isInstance() const { return !isStatic(); }
|
||||
|
||||
bool isOutOfLineDefinition() const { return !isInlineDefinition(); }
|
||||
bool isInlineDefinition() const { return IsInlineDef; }
|
||||
void setInlineDefinition(bool flag) { IsInlineDef = flag; }
|
||||
bool isOutOfLineDefinition() const {
|
||||
return getLexicalDeclContext() != getDeclContext();
|
||||
}
|
||||
|
||||
void setAccess(AccessSpecifier AS) { Access = AS; }
|
||||
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
|
||||
|
|
|
@ -139,6 +139,29 @@ const char *NamedDecl::getName() const {
|
|||
return "";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ScopedDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
void ScopedDecl::setLexicalDeclContext(DeclContext *DC) {
|
||||
if (DC == getLexicalDeclContext())
|
||||
return;
|
||||
|
||||
if (isInSemaDC()) {
|
||||
MultipleDC *MDC = new MultipleDC();
|
||||
MDC->SemanticDC = getDeclContext();
|
||||
MDC->LexicalDC = DC;
|
||||
DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
|
||||
} else {
|
||||
getMultipleDC()->LexicalDC = DC;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedDecl::~ScopedDecl() {
|
||||
if (isOutOfSemaDC())
|
||||
delete getMultipleDC();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FunctionDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -145,15 +145,31 @@ void ScopedDecl::EmitInRec(Serializer& S) const {
|
|||
NamedDecl::EmitInRec(S);
|
||||
S.EmitPtr(getNext()); // From ScopedDecl.
|
||||
S.EmitPtr(cast_or_null<Decl>(getDeclContext())); // From ScopedDecl.
|
||||
S.EmitPtr(cast_or_null<Decl>(getLexicalDeclContext())); // From ScopedDecl.
|
||||
}
|
||||
|
||||
void ScopedDecl::ReadInRec(Deserializer& D, ASTContext& C) {
|
||||
NamedDecl::ReadInRec(D, C);
|
||||
D.ReadPtr(Next); // From ScopedDecl.
|
||||
|
||||
assert(DeclCtx == 0); // Allow back-patching. Observe that we register
|
||||
D.ReadPtr(DeclCtx); // the variable of the *object* for back-patching.
|
||||
// Its actual value will get filled in later.
|
||||
|
||||
assert(DeclCtx == 0);
|
||||
|
||||
const SerializedPtrID &SemaDCPtrID = D.ReadPtrID();
|
||||
const SerializedPtrID &LexicalDCPtrID = D.ReadPtrID();
|
||||
|
||||
if (SemaDCPtrID == LexicalDCPtrID) {
|
||||
// Allow back-patching. Observe that we register the variable of the
|
||||
// *object* for back-patching. Its actual value will get filled in later.
|
||||
D.ReadUIntPtr(DeclCtx, SemaDCPtrID);
|
||||
}
|
||||
else {
|
||||
MultipleDC *MDC = new MultipleDC();
|
||||
DeclCtx = reinterpret_cast<uintptr_t>(MDC) | 0x1;
|
||||
// Allow back-patching. Observe that we register the variable of the
|
||||
// *object* for back-patching. Its actual value will get filled in later.
|
||||
D.ReadUIntPtr(reinterpret_cast<uintptr_t&>(MDC->SemanticDC), SemaDCPtrID);
|
||||
D.ReadUIntPtr(reinterpret_cast<uintptr_t&>(MDC->LexicalDC), LexicalDCPtrID);
|
||||
}
|
||||
}
|
||||
|
||||
//===------------------------------------------------------------===//
|
||||
|
|
|
@ -109,10 +109,6 @@ public:
|
|||
/// CurContext - This is the current declaration context of parsing.
|
||||
DeclContext *CurContext;
|
||||
|
||||
/// LexicalFileContext - The current lexical file declaration context,
|
||||
/// the translation unit or a namespace.
|
||||
DeclContext *LexicalFileContext;
|
||||
|
||||
/// PreDeclaratorDC - Keeps the declaration context before switching to the
|
||||
/// context of a declarator's nested-name-specifier.
|
||||
DeclContext *PreDeclaratorDC;
|
||||
|
|
|
@ -53,8 +53,8 @@ std::string Sema::getTypeAsString(TypeTy *Type) {
|
|||
DeclContext *Sema::getContainingDC(DeclContext *DC) {
|
||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) {
|
||||
// A C++ out-of-line method will return to the file declaration context.
|
||||
if (!MD->isInlineDefinition())
|
||||
return LexicalFileContext;
|
||||
if (MD->isOutOfLineDefinition())
|
||||
return MD->getLexicalDeclContext();
|
||||
|
||||
// A C++ inline method is parsed *after* the topmost class it was declared in
|
||||
// is fully parsed (it's "complete").
|
||||
|
@ -70,25 +70,24 @@ DeclContext *Sema::getContainingDC(DeclContext *DC) {
|
|||
return DC;
|
||||
}
|
||||
|
||||
if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))
|
||||
return LexicalFileContext;
|
||||
if (isa<ObjCMethodDecl>(DC))
|
||||
return Context.getTranslationUnitDecl();
|
||||
|
||||
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(DC))
|
||||
return SD->getLexicalDeclContext();
|
||||
|
||||
return DC->getParent();
|
||||
}
|
||||
|
||||
void Sema::PushDeclContext(DeclContext *DC) {
|
||||
assert(getContainingDC(DC) == CurContext &&
|
||||
"The next DeclContext should be directly contained in the current one.");
|
||||
"The next DeclContext should be lexically contained in the current one.");
|
||||
CurContext = DC;
|
||||
if (CurContext->isFileContext())
|
||||
LexicalFileContext = CurContext;
|
||||
}
|
||||
|
||||
void Sema::PopDeclContext() {
|
||||
assert(CurContext && "DeclContext imbalance!");
|
||||
CurContext = getContainingDC(CurContext);
|
||||
if (CurContext->isFileContext())
|
||||
LexicalFileContext = CurContext;
|
||||
}
|
||||
|
||||
/// Add this decl to the scope shadowed decl chains.
|
||||
|
@ -1147,6 +1146,10 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
|||
New = NewVD;
|
||||
}
|
||||
|
||||
// Set the lexical context. If the declarator has a C++ scope specifier, the
|
||||
// lexical context will be different from the semantic context.
|
||||
New->setLexicalDeclContext(CurContext);
|
||||
|
||||
// If this has an identifier, add it to the scope stack.
|
||||
if (II)
|
||||
PushOnScopeChains(New, S);
|
||||
|
@ -2004,10 +2007,6 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) {
|
|||
Diag(Definition->getLocation(), diag::err_previous_definition);
|
||||
}
|
||||
|
||||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD))
|
||||
if (isa<CXXRecordDecl>(CurContext))
|
||||
MD->setInlineDefinition(true);
|
||||
|
||||
PushDeclContext(FD);
|
||||
|
||||
// Check the validity of our function parameters
|
||||
|
@ -2267,6 +2266,11 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
|
|||
|
||||
if (Attr)
|
||||
ProcessDeclAttributeList(New, Attr);
|
||||
|
||||
// Set the lexical context. If the tag has a C++ scope specifier, the
|
||||
// lexical context will be different from the semantic context.
|
||||
New->setLexicalDeclContext(CurContext);
|
||||
|
||||
return New;
|
||||
}
|
||||
|
||||
|
@ -2421,6 +2425,10 @@ Sema::DeclTy *Sema::ActOnTagStruct(Scope *S, TagDecl::TagKind Kind, TagKind TK,
|
|||
if (Attr)
|
||||
ProcessDeclAttributeList(New, Attr);
|
||||
|
||||
// Set the lexical context. If the tag has a C++ scope specifier, the
|
||||
// lexical context will be different from the semantic context.
|
||||
New->setLexicalDeclContext(CurContext);
|
||||
|
||||
return New;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,15 @@ struct A::C c2;
|
|||
struct S : public A::C {};
|
||||
struct A::undef; // expected-error {{'undef' does not name a tag member in the specified scope}}
|
||||
|
||||
namespace A2 {
|
||||
typedef int INT;
|
||||
struct RC;
|
||||
}
|
||||
|
||||
struct A2::RC {
|
||||
INT x;
|
||||
};
|
||||
|
||||
void f3() {
|
||||
N::x = 0; // expected-error {{use of undeclared identifier 'N'}}
|
||||
int N;
|
||||
|
|
Загрузка…
Ссылка в новой задаче