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 /lib/Sema/SemaCXXScopeSpec.cpp | |
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
Diffstat (limited to 'lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 63 |
1 files changed, 52 insertions, 11 deletions
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; |