]> granicus.if.org Git - clang/commitdiff
The scope representation can now be either a DeclContext pointer or a
authorDouglas Gregor <dgregor@apple.com>
Wed, 18 Mar 2009 00:36:05 +0000 (00:36 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 18 Mar 2009 00:36:05 +0000 (00:36 +0000)
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

lib/Sema/Sema.h
lib/Sema/SemaCXXScopeSpec.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaLookup.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaType.cpp

index fae0fa680c382d7a3f7bcf1f2d73e49a5f2e6063..38541ef96ecd6b0e869a7dfd7d279bfa6c2a3b08 100644 (file)
@@ -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,
index 7773d288ae54d092757611343f6f56ad2e665ebf..e30ec2adcf275bb7225df2ce7dd4cbbfc42a69c5 100644 (file)
 #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;
 
index 0b7c33ff98713117519e3e1d78f9792365bc8c10..c3dfd19be4b84fe152e6ba4910f3ec8514d931c2 100644 (file)
@@ -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>(
index acf82245424fcb4552cb4cf2e6023812955dffa7..3307dd0cc45d32f47fb757810aa67657784a404a 100644 (file)
@@ -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);
index 0893bc7fb323eb006e4e9db63022932e4e7452a3..1e184d0349b97e6b74ae6beccc2cd89df8a3aca3 100644 (file)
@@ -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()) {
index 57683b30ecd02746ba8e9739ed567655743c3163..d6c36d44a9db3bf0d0ab810d28a31414953cf459 100644 (file)
@@ -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);
   }
 
index fd1eaf0ace62a9d81a67336b50505f8aba26177a..6277d9e51227ee3a5bb23326ebd9b7e38c4f1878 100644 (file)
@@ -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.
index ac0e1e1f73c53fe04ba43e67b23e8d4d038159d9..c52f64055b85c0ee0166f0a4e07a55e2f3e4cc75 100644 (file)
@@ -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.