forked from OSchip/llvm-project
The scope representation can now be either a DeclContext pointer or a
Type pointer. This allows our nested-name-specifiers to retain more information about the actual spelling (e.g., which typedef did the user name, or what exact template arguments were used in the template-id?). It will also allow us to have dependent nested-name-specifiers that don't map to any DeclContext. llvm-svn: 67140
This commit is contained in:
parent
a15ce21135
commit
6bfde496ee
|
@ -1452,6 +1452,21 @@ public:
|
|||
|
||||
bool RequireCompleteDeclContext(const CXXScopeSpec &SS);
|
||||
|
||||
/// \brief Build a scope representation from a declaration context.
|
||||
CXXScopeTy *createScopeRep(DeclContext *DC) {
|
||||
return static_cast<CXXScopeTy *>(DC);
|
||||
}
|
||||
|
||||
/// \brief Build a scope representation from a type.
|
||||
CXXScopeTy *createScopeRep(QualType T);
|
||||
|
||||
DeclContext *getScopeRepAsDeclContext(const CXXScopeSpec &SS);
|
||||
QualType getScopeRepAsType(const CXXScopeSpec &SS);
|
||||
|
||||
/// \brief Determines whether this scope specifier is represented as
|
||||
/// a type.
|
||||
bool isScopeRepType(const CXXScopeSpec &SS);
|
||||
|
||||
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
|
||||
/// global scope ('::').
|
||||
virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
|
||||
|
|
|
@ -17,6 +17,49 @@
|
|||
#include "llvm/ADT/STLExtras.h"
|
||||
using namespace clang;
|
||||
|
||||
/// \brief Retrieve the scope represented by this scope specifier as a
|
||||
/// DeclContext.
|
||||
DeclContext *Sema::getScopeRepAsDeclContext(const CXXScopeSpec &SS) {
|
||||
if (SS.isInvalid() || !SS.getScopeRep())
|
||||
return 0;
|
||||
uintptr_t Rep = reinterpret_cast<uintptr_t>(SS.getScopeRep());
|
||||
if ((Rep & 0x01) == 0)
|
||||
return reinterpret_cast<DeclContext *>(Rep);
|
||||
|
||||
// Retrieve the DeclContext associated with this type.
|
||||
QualType T = QualType(reinterpret_cast<Type *>(Rep & ~0x01), 0);
|
||||
const TagType *TagT = T->getAsTagType();
|
||||
assert(TagT && "No DeclContext from a non-tag type");
|
||||
return TagT->getDecl();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the scope represented by this scope specifier as a
|
||||
/// type.
|
||||
QualType Sema::getScopeRepAsType(const CXXScopeSpec &SS) {
|
||||
if (SS.isInvalid() || !SS.getScopeRep())
|
||||
return QualType();
|
||||
|
||||
uintptr_t Rep = reinterpret_cast<uintptr_t>(SS.getScopeRep());
|
||||
if ((Rep & 0x01) == 0)
|
||||
return QualType();
|
||||
return QualType(reinterpret_cast<Type *>(Rep & ~0x01), 0);
|
||||
}
|
||||
|
||||
Action::CXXScopeTy *Sema::createScopeRep(QualType T) {
|
||||
assert(((reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()) & 0x01) == 0) &&
|
||||
"Scope type with cv-qualifiers");
|
||||
if (T.isNull())
|
||||
return 0;
|
||||
|
||||
return reinterpret_cast<CXXScopeTy *>(
|
||||
reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()) | 0x01);
|
||||
}
|
||||
|
||||
bool Sema::isScopeRepType(const CXXScopeSpec &SS) {
|
||||
uintptr_t Rep = reinterpret_cast<uintptr_t>(SS.getScopeRep());
|
||||
return Rep & 0x01;
|
||||
}
|
||||
|
||||
/// \brief Require that the context specified by SS be complete.
|
||||
///
|
||||
/// If SS refers to a type, this routine checks whether the type is
|
||||
|
@ -30,7 +73,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
|
|||
if (!SS.isSet() || SS.isInvalid())
|
||||
return false;
|
||||
|
||||
DeclContext *DC = static_cast<DeclContext *>(SS.getScopeRep());
|
||||
DeclContext *DC = getScopeRepAsDeclContext(SS);
|
||||
if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
|
||||
// If we're currently defining this type, then lookup into the
|
||||
// type is okay: don't complain that it isn't complete yet.
|
||||
|
@ -52,7 +95,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
|
|||
/// global scope ('::').
|
||||
Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
|
||||
SourceLocation CCLoc) {
|
||||
return cast<DeclContext>(Context.getTranslationUnitDecl());
|
||||
return createScopeRep(Context.getTranslationUnitDecl());
|
||||
}
|
||||
|
||||
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
|
||||
|
@ -70,10 +113,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
|
||||
if (SD) {
|
||||
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
|
||||
if (const RecordType* Record = TD->getUnderlyingType()->getAsRecordType())
|
||||
return cast<DeclContext>(Record->getDecl());
|
||||
if (TD->getUnderlyingType()->isRecordType())
|
||||
return createScopeRep(Context.getTypeDeclType(TD));
|
||||
} else if (isa<NamespaceDecl>(SD) || isa<RecordDecl>(SD)) {
|
||||
return cast<DeclContext>(SD);
|
||||
return createScopeRep(cast<DeclContext>(SD));
|
||||
}
|
||||
|
||||
// FIXME: Template parameters and dependent types.
|
||||
|
@ -109,10 +152,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
|
|||
TypeTy *Ty,
|
||||
SourceRange TypeRange,
|
||||
SourceLocation CCLoc) {
|
||||
QualType Type = QualType::getFromOpaquePtr(Ty);
|
||||
assert(Type->isRecordType() &&
|
||||
"Types in a nested-name-specifier always refer to a record type");
|
||||
return cast<DeclContext>(Type->getAsRecordType()->getDecl());
|
||||
return createScopeRep(QualType::getFromOpaquePtr(Ty));
|
||||
}
|
||||
|
||||
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
|
||||
|
@ -125,7 +165,7 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
|||
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
|
||||
assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
|
||||
PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
|
||||
CurContext = static_cast<DeclContext*>(SS.getScopeRep());
|
||||
CurContext = getScopeRepAsDeclContext(SS);
|
||||
S->setEntity(CurContext);
|
||||
}
|
||||
|
||||
|
@ -136,7 +176,8 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
|||
/// defining scope.
|
||||
void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
|
||||
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
|
||||
assert(S->getEntity() == SS.getScopeRep() && "Context imbalance!");
|
||||
assert(S->getEntity() == getScopeRepAsDeclContext(SS) &&
|
||||
"Context imbalance!");
|
||||
S->setEntity(PreDeclaratorDC);
|
||||
PreDeclaratorDC = 0;
|
||||
|
||||
|
|
|
@ -1257,7 +1257,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
|
|||
DeclSpec::SCS_static,
|
||||
D.getIdentifierLoc());
|
||||
} else { // Something like "int foo::x;"
|
||||
DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
|
||||
DC = getScopeRepAsDeclContext(D.getCXXScopeSpec());
|
||||
// FIXME: RequireCompleteDeclContext(D.getCXXScopeSpec()); ?
|
||||
PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
|
||||
|
||||
|
@ -3020,7 +3020,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
}
|
||||
|
||||
// FIXME: RequireCompleteDeclContext(SS)?
|
||||
DC = static_cast<DeclContext*>(SS.getScopeRep());
|
||||
DC = getScopeRepAsDeclContext(SS);
|
||||
SearchDC = DC;
|
||||
// Look-up name inside 'foo::'.
|
||||
PrevDecl = dyn_cast_or_null<TagDecl>(
|
||||
|
|
|
@ -300,7 +300,7 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
|
|||
const CXXScopeSpec *SS) {
|
||||
CXXRecordDecl *CurDecl;
|
||||
if (SS) {
|
||||
DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
|
||||
DeclContext *DC = getScopeRepAsDeclContext(*SS);
|
||||
CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
|
||||
} else
|
||||
CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
|
||||
|
|
|
@ -727,7 +727,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|||
// implicit member ref, because we want a pointer to the member in general,
|
||||
// not any specific instance's member.
|
||||
if (isAddressOfOperand && SS && !SS->isEmpty() && !HasTrailingLParen) {
|
||||
DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
|
||||
DeclContext *DC = getScopeRepAsDeclContext(*SS);
|
||||
if (D && isa<CXXRecordDecl>(DC)) {
|
||||
QualType DType;
|
||||
if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
|
||||
|
@ -942,7 +942,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
|
|||
// - a nested-name-specifier that contains a class-name that
|
||||
// names a dependent type.
|
||||
else if (SS && !SS->isEmpty()) {
|
||||
for (DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
|
||||
for (DeclContext *DC = getScopeRepAsDeclContext(*SS);
|
||||
DC; DC = DC->getParent()) {
|
||||
// FIXME: could stop early at namespace scope.
|
||||
if (DC->isRecord()) {
|
||||
|
|
|
@ -1039,7 +1039,7 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
|
|||
return LookupResult::CreateLookupResult(Context, 0);
|
||||
|
||||
if (SS->isSet())
|
||||
return LookupQualifiedName(static_cast<DeclContext *>(SS->getScopeRep()),
|
||||
return LookupQualifiedName(getScopeRepAsDeclContext(*SS),
|
||||
Name, NameKind, RedeclarationOnly);
|
||||
}
|
||||
|
||||
|
|
|
@ -399,7 +399,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
|
|||
|
||||
DeclContext *SemanticContext = CurContext;
|
||||
if (SS.isNotEmpty() && !SS.isInvalid()) {
|
||||
SemanticContext = static_cast<DeclContext*>(SS.getScopeRep());
|
||||
SemanticContext = getScopeRepAsDeclContext(SS);
|
||||
|
||||
// FIXME: need to match up several levels of template parameter
|
||||
// lists here.
|
||||
|
|
|
@ -742,8 +742,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
|
|||
}
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
// The scope spec must refer to a class, or be dependent.
|
||||
DeclContext *DC = static_cast<DeclContext*>(
|
||||
DeclType.Mem.Scope().getScopeRep());
|
||||
DeclContext *DC = getScopeRepAsDeclContext(DeclType.Mem.Scope());
|
||||
QualType ClsType;
|
||||
// FIXME: Extend for dependent types when it's actually supported.
|
||||
// See ActOnCXXNestedNameSpecifier.
|
||||
|
|
Loading…
Reference in New Issue