diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-18 00:36:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-18 00:36:05 +0000 |
commit | ca5e77fefc4ac06aa787d7e777957ba6b7a03c60 (patch) | |
tree | 35cb4eff8700973df2001b3bdb242054a57a1e0d | |
parent | d46f0acef540c3030f7b40525fb732fc343dcfad (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67140 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 15 | ||||
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 63 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 3 |
8 files changed, 75 insertions, 20 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index fae0fa680c..38541ef96e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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, diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 7773d288ae..e30ec2adcf 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -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; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0b7c33ff98..c3dfd19be4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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>( diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index acf8224542..3307dd0cc4 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 0893bc7fb3..1e184d0349 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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()) { diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 57683b30ec..d6c36d44a9 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -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); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index fd1eaf0ace..6277d9e512 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index ac0e1e1f73..c52f64055b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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. |