]> granicus.if.org Git - clang/commitdiff
Revamp our representation of C++ nested-name-specifiers. We now have a
authorDouglas Gregor <dgregor@apple.com>
Thu, 26 Mar 2009 23:50:42 +0000 (23:50 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 26 Mar 2009 23:50:42 +0000 (23:50 +0000)
uniqued representation that should both save some memory and make it
far easier to properly build canonical types for types involving
dependent nested-name-specifiers, e.g., "typename T::Nested::type".

This approach will greatly simplify the representation of
CXXScopeSpec. That'll be next.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67799 91177308-0d34-0410-b5e6-96231b3b80d8

17 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/ExprCXX.h
include/clang/AST/NestedNameSpecifier.h
include/clang/AST/Type.h
lib/AST/ASTContext.cpp
lib/AST/ExprCXX.cpp
lib/AST/NestedNameSpecifier.cpp
lib/AST/StmtPrinter.cpp
lib/AST/Type.cpp
lib/AST/TypeSerialization.cpp
lib/Sema/Sema.h
lib/Sema/SemaCXXScopeSpec.cpp
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateExpr.cpp
lib/Sema/SemaType.cpp

index 36bf12b787baf83fd0eb3ab4163d4a50458f0018..3cf48b4994c357eedb8aa93a5ebe4e82c38963bb 100644 (file)
@@ -18,6 +18,7 @@
 #include "clang/Basic/LangOptions.h"
 #include "clang/AST/Builtins.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMap.h"
@@ -74,6 +75,14 @@ class ASTContext {
   llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;
   llvm::FoldingSet<ObjCQualifiedInterfaceType> ObjCQualifiedInterfaceTypes;
   llvm::FoldingSet<ObjCQualifiedIdType> ObjCQualifiedIdTypes;
+
+  /// \brief The set of nested name specifiers.
+  ///
+  /// This set is managed by the NestedNameSpecifier class.
+  llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers;
+  NestedNameSpecifier *GlobalNestedNameSpecifier;
+  friend class NestedNameSpecifier;
+
   /// ASTRecordLayouts - A cache mapping from RecordDecls to ASTRecordLayouts.
   ///  This is lazily created.  This is intentionally not serialized.
   llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts;
@@ -284,8 +293,7 @@ public:
                                               unsigned NumArgs,
                                               QualType Canon = QualType());
 
-  QualType getQualifiedNameType(const NestedNameSpecifier *Components,
-                                unsigned NumComponents,
+  QualType getQualifiedNameType(NestedNameSpecifier *NNS,
                                 QualType NamedType);
 
   /// getObjCQualifiedInterfaceType - Return a 
index 1292eaf2d282120691d2411ec8b792a3fac64fba..366f860c50f0f00d302ce7ef16428fb66808f4f4 100644 (file)
@@ -856,34 +856,22 @@ class QualifiedDeclRefExpr : public DeclRefExpr {
   /// nested-name-specifier.
   SourceRange QualifierRange;
 
-  /// The number of components in the complete nested-name-specifier.
-  unsigned NumComponents;
-
-  QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, 
-                       bool VD, SourceRange R,
-                       const NestedNameSpecifier *Components,
-                       unsigned NumComponents);
+  /// \brief The nested-name-specifier that qualifies this declaration
+  /// name.
+  NestedNameSpecifier *NNS;
 
 public:
-  static QualifiedDeclRefExpr *Create(ASTContext &Context, NamedDecl *d, 
-                                      QualType t, SourceLocation l, bool TD, 
-                                      bool VD, SourceRange R,
-                                      const NestedNameSpecifier *Components,
-                                      unsigned NumComponents);
+  QualifiedDeclRefExpr(NamedDecl *d, QualType t, SourceLocation l, bool TD, 
+                       bool VD, SourceRange R, NestedNameSpecifier *NNS)
+    : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), 
+      QualifierRange(R), NNS(NNS) { }
 
   /// \brief Retrieve the source range of the nested-name-specifier.
   SourceRange getQualifierRange() const { return QualifierRange; }
 
-  // Iteration over of the parts of the nested-name-specifier.
-  typedef const NestedNameSpecifier * iterator;
-
-  iterator begin() const { 
-    return reinterpret_cast<const NestedNameSpecifier *>(this + 1); 
-  }
-
-  iterator end() const { return begin() + NumComponents; }
-
-  unsigned size() const { return NumComponents; }
+  /// \brief Retrieve the nested-name-specifier that qualifies this
+  /// declaration.
+  NestedNameSpecifier *getQualifier() const { return NNS; }
 
   virtual SourceRange getSourceRange() const { 
     return SourceRange(QualifierRange.getBegin(), getLocation()); 
@@ -908,7 +896,10 @@ public:
 /// the qualification (e.g., X<T>::) refers to a dependent type. In
 /// this case, X<T>::value cannot resolve to a declaration because the
 /// declaration will differ from on instantiation of X<T> to the
-/// next. Therefore, UnresolvedDeclRefExpr keeps track of the qualifier (X<T>::) and the name of the entity being referenced ("value"). Such expressions will instantiate to QualifiedDeclRefExprs.
+/// next. Therefore, UnresolvedDeclRefExpr keeps track of the
+/// qualifier (X<T>::) and the name of the entity being referenced
+/// ("value"). Such expressions will instantiate to
+/// QualifiedDeclRefExprs.
 class UnresolvedDeclRefExpr : public Expr {
   /// The name of the entity we will be referencing.
   DeclarationName Name;
@@ -920,18 +911,15 @@ class UnresolvedDeclRefExpr : public Expr {
   /// nested-name-specifier.
   SourceRange QualifierRange;
 
-  /// The number of components in the complete nested-name-specifier.
-  unsigned NumComponents;
-
-  UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
-                        SourceRange R, const NestedNameSpecifier *Components,
-                        unsigned NumComponents);
+  /// \brief The nested-name-specifier that qualifies this unresolved
+  /// declaration name.
+  NestedNameSpecifier *NNS;
 
 public:
-  static UnresolvedDeclRefExpr *Create(ASTContext &Context, DeclarationName N,
-                                       SourceLocation L, SourceRange R,
-                                       const NestedNameSpecifier *Components,
-                                       unsigned NumComponents);
+  UnresolvedDeclRefExpr(DeclarationName N, QualType T, SourceLocation L,
+                        SourceRange R, NestedNameSpecifier *NNS)
+    : Expr(UnresolvedDeclRefExprClass, T, true, true), 
+      Name(N), Loc(L), QualifierRange(R), NNS(NNS) { }
 
   /// \brief Retrieve the name that this expression refers to.
   DeclarationName getDeclName() const { return Name; }
@@ -942,16 +930,9 @@ public:
   /// \brief Retrieve the source range of the nested-name-specifier.
   SourceRange getQualifierRange() const { return QualifierRange; }
 
-  // Iteration over of the parts of the nested-name-specifier.
-  typedef const NestedNameSpecifier * iterator;
-
-  iterator begin() const { 
-    return reinterpret_cast<const NestedNameSpecifier *>(this + 1); 
-  }
-
-  iterator end() const { return begin() + NumComponents; }
-
-  unsigned size() const { return NumComponents; }
+  /// \brief Retrieve the nested-name-specifier that qualifies this
+  /// declaration.
+  NestedNameSpecifier *getQualifier() const { return NNS; }
 
   virtual SourceRange getSourceRange() const { 
     return SourceRange(QualifierRange.getBegin(), getLocation()); 
index a371e896381a71d56be5e4617ed1ff3e06c12b23..a740efbe09c01ba9d201b9b40a5ea33ff0f76ca4 100644 (file)
@@ -14,8 +14,8 @@
 #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
 #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
 
-#include "llvm/Support/DataTypes.h"
-#include <cassert>
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/PointerIntPair.h"
 
 namespace llvm {
   class raw_ostream;
@@ -24,93 +24,151 @@ namespace llvm {
 namespace clang {
 
 class ASTContext;
-class DeclContext;
+class DeclContext; // FIXME: die die die
+class NamespaceDecl;
+class IdentifierInfo;
 class Type;
 
-/// \brief Represents a single component in a C++ nested-name-specifier.
+/// \brief Represents a C++ nested name specifier, such as
+/// "::std::vector<int>::".
 ///
-/// C++ nested-name-specifiers are the prefixes to qualified
-/// namespaces. For example, "foo::" in "foo::x" is a
-/// nested-name-specifier. Multiple nested-name-specifiers can be
-/// strung together to build qualified names, e.g., "foo::bar::" in
-/// "foo::bar::x". Each NestedNameSpecifier class contains one of the
-/// terms, e.g., "foo::" or "bar::", which may be represented either
-/// as a type or as a DeclContext.
-class NestedNameSpecifier {
-  /// \brief A DeclContext or Type pointer, depending on whether the
-  /// low bit is set.
-  uintptr_t Data;
+/// C++ nested name specifiers are the prefixes to qualified
+/// namespaces. For example, "foo::" in "foo::x" is a nested name
+/// specifier. Nested name specifiers are made up of a sequence of
+/// specifiers, each of which can be a namespace, type, identifier
+/// (for dependent names), or the global specifier ('::', must be the
+/// first specifier).
+class NestedNameSpecifier : public llvm::FoldingSetNode {
+  /// \brief The nested name specifier that precedes this nested name
+  /// specifier.
+  NestedNameSpecifier *Prefix;
+
+  /// \brief The last component in the nested name specifier, which
+  /// can be an identifier, a declaration, or a type.
+  ///
+  /// When the pointer is NULL, this specifier represents the global
+  /// specifier '::'. Otherwise, the pointer is one of
+  /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
+  /// specifier. The integer stores one ofthe first four values of
+  /// type SpecifierKind.
+  llvm::PointerIntPair<void*, 2> Specifier;
 
 public:
-  NestedNameSpecifier() : Data(0) { }
-
-  /// \brief Construct a nested name specifier that refers to a type.
-  NestedNameSpecifier(const Type *T) { 
-    Data = reinterpret_cast<uintptr_t>(T);
-    assert((Data & 0x01) == 0 && "cv-qualified type in nested-name-specifier");
-    Data |= 0x01;
+  /// \brief The kind of specifier that completes this nested name
+  /// specifier.
+  enum SpecifierKind {
+    /// \brief An identifier, stored as an IdentifierInfo*.
+    Identifier = 0,
+    /// \brief A namespace, stored as a Namespace*.
+    Namespace = 1,
+    /// \brief A type, stored as a Type*.
+    TypeSpec = 2,
+    /// \brief A type that was preceded by the 'template' keyword,
+    /// stored as a Type*.
+    TypeSpecWithTemplate = 3,
+    /// \brief The global specifier '::'. There is no stored value.
+    Global = 4
+  };
+
+private:
+  /// \brief Builds the global specifier.
+  NestedNameSpecifier() : Prefix(0), Specifier(0, 0) { }
+
+  /// \brief Copy constructor used internally to clone nested name
+  /// specifiers.
+  NestedNameSpecifier(const NestedNameSpecifier &Other) 
+    : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), 
+      Specifier(Other.Specifier) {
   }
 
-  /// \brief Construct nested name specifier that refers to a
-  /// DeclContext.
-  NestedNameSpecifier(const DeclContext *DC) {
-    Data = reinterpret_cast<uintptr_t>(DC);
-    assert((Data & 0x01) == 0 && "Badly aligned DeclContext pointer");
-  }
+  NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement
 
-  /// \brief Determines whether this nested-name-specifier refers to a
-  /// type. Otherwise, it refers to a DeclContext.
-  bool isType() const { return Data & 0x01; }
+  /// \brief Either find or insert the given nested name specifier
+  /// mockup in the given context.
+  static NestedNameSpecifier *FindOrInsert(ASTContext &Context, const NestedNameSpecifier &Mockup);
 
-  /// \brief Compute the declaration context to which this
-  /// nested-name-specifier refers.
+public:
+  /// \brief Builds a specifier combining a prefix and an identifier.
   ///
-  /// This routine computes the declaration context referenced by this
-  /// nested-name-specifier. The nested-name-specifier may store
-  /// either a DeclContext (the trivial case) or a non-dependent type
-  /// (which will have an associated DeclContext). It is an error to
-  /// invoke this routine when the nested-name-specifier refers to a
-  /// dependent type.
+  /// The prefix must be dependent, since nested name specifiers
+  /// referencing an identifier are only permitted when the identifier
+  /// cannot be resolved.
+  static NestedNameSpecifier *Create(ASTContext &Context, 
+                                     NestedNameSpecifier *Prefix, 
+                                     IdentifierInfo *II);
+
+  /// \brief Builds a nested name specifier that names a namespace.
+  static NestedNameSpecifier *Create(ASTContext &Context, 
+                                     NestedNameSpecifier *Prefix, 
+                                     NamespaceDecl *NS);
+
+  /// \brief Builds a nested name specifier that names a type.
+  static NestedNameSpecifier *Create(ASTContext &Context, 
+                                     NestedNameSpecifier *Prefix, 
+                                     bool Template, Type *T);
+
+  /// \brief Returns the nested name specifier representing the global
+  /// scope.
+  static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
+
+  /// \brief Return the prefix of this nested name specifier.
   ///
-  /// \returns The stored DeclContext, if the nested-name-specifier
-  /// stores a DeclContext. If the nested-name-specifier stores a
-  /// non-dependent type, returns the DeclContext associated with that
-  /// type.
-  DeclContext *computeDeclContext(ASTContext &Context) const;
+  /// The prefix contains all of the parts of the nested name
+  /// specifier that preced this current specifier. For example, for a
+  /// nested name specifier that represents "foo::bar::", the current
+  /// specifier will contain "bar::" and the prefix will contain
+  /// "foo::".
+  NestedNameSpecifier *getPrefix() const { return Prefix; }
+
+  /// \brief Determine what kind of nested name specifier is stored.
+  SpecifierKind getKind() const { 
+    if (Specifier.getPointer() == 0)
+      return Global;
+    return (SpecifierKind)Specifier.getInt(); 
+  }
 
-  /// \brief Retrieve the nested-name-specifier as a type. 
-  ///
-  /// \returns The stored type. If the nested-name-specifier does not
-  /// store a type, returns NULL.
-  Type *getAsType() const {
-    if (Data & 0x01)
-      return reinterpret_cast<Type *>(Data & ~0x01);
+  /// \brief Retrieve the identifier stored in this nested name
+  /// specifier.
+  IdentifierInfo *getAsIdentifier() const {
+    if (Specifier.getInt() == Identifier)
+      return (IdentifierInfo *)Specifier.getPointer();
 
     return 0;
   }
+  
+  /// \brief Retrieve the namespace stored in this nested name
+  /// specifier.
+  NamespaceDecl *getAsNamespace() const {
+    if (Specifier.getInt() == Namespace)
+      return (NamespaceDecl *)Specifier.getPointer();
 
-  /// \brief Retrieves the nested-name-specifier as a DeclContext.
-  ///
-  /// \returns The stored DeclContext. If the nested-name-specifier
-  /// does not store a DeclContext, returns NULL.
-  DeclContext *getAsDeclContext() const {
-    if (Data & 0x01)
-      return 0;
-    return reinterpret_cast<DeclContext *>(Data);
+    return 0;
   }
 
-  /// \brief Retrieve nested name specifier as an opaque pointer.
-  void *getAsOpaquePtr() const { return reinterpret_cast<void *>(Data); }
+  /// \brief Retrieve the type stored in this nested name specifier.
+  Type *getAsType() const {
+    if (Specifier.getInt() == TypeSpec || 
+        Specifier.getInt() == TypeSpecWithTemplate)
+      return (Type *)Specifier.getPointer();
+
+    return 0;
+  }
+
+  /// \brief Whether this nested name specifier refers to a dependent
+  /// type or not.
+  bool isDependent() const;
+
+  /// \brief Print this nested name specifier to the given output
+  /// stream.
+  void Print(llvm::raw_ostream &OS) const;
 
-  /// \brief Reconstruct a nested name specifier from an opaque pointer.
-  static NestedNameSpecifier getFromOpaquePtr(void *Ptr) {
-    NestedNameSpecifier NS;
-    NS.Data = reinterpret_cast<uintptr_t>(Ptr);
-    return NS;
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddPointer(Prefix);
+    ID.AddPointer(Specifier.getPointer());
+    ID.AddInteger(Specifier.getInt());
   }
 
-  static void Print(llvm::raw_ostream &OS, const NestedNameSpecifier *First,
-                    const NestedNameSpecifier *Last);
+  void Destroy(ASTContext &Context);
 };
 
 }
index 3453cb09dfc09b301360656a5bf203b0b1e39993..e37b1868717bafdcefcfcb85c6bd335a472d299f 100644 (file)
@@ -1564,32 +1564,22 @@ protected:
 /// This type is used to keep track of a type name as written in the
 /// source code, including any nested-name-specifiers.
 class QualifiedNameType : public Type, public llvm::FoldingSetNode {
-  /// \brief The number of components in the qualified name, not
-  /// counting the final type.
-  unsigned NumComponents;
+  /// \brief The nested name specifier containing the qualifier.
+  NestedNameSpecifier *NNS;
 
   /// \brief The type that this qualified name refers to.
   QualType NamedType;
 
-  QualifiedNameType(const NestedNameSpecifier *Components,
-                    unsigned NumComponents, QualType NamedType,
-                    QualType CanonType);
+  QualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType,
+                    QualType CanonType)
+    : Type(QualifiedName, CanonType, NamedType->isDependentType()),
+      NNS(NNS), NamedType(NamedType) { }
 
   friend class ASTContext;  // ASTContext creates these
 
 public:
-  typedef const NestedNameSpecifier * iterator;
-
-  iterator begin() const { return getComponents(); }
-  iterator end() const { return getComponents() + getNumComponents(); }
-
-  /// \brief Retrieve the array of nested-name-specifier components.
-  const NestedNameSpecifier *getComponents() const { 
-    return reinterpret_cast<const NestedNameSpecifier *>(this + 1);
-  }
-
-  /// \brief Retrieve the number of nested-name-specifier components.
-  unsigned getNumComponents() const { return NumComponents; }
+  /// \brief Retrieve the qualification on this type.
+  NestedNameSpecifier *getQualifier() const { return NNS; }
 
   /// \brief Retrieve the type named by the qualified-id.
   QualType getNamedType() const { return NamedType; }
@@ -1597,13 +1587,14 @@ public:
   virtual void getAsStringInternal(std::string &InnerString) const;
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getComponents(), NumComponents, NamedType);
+    Profile(ID, NNS, NamedType);
   }
 
-  static void Profile(llvm::FoldingSetNodeID &ID, 
-                      const NestedNameSpecifier *Components,
-                      unsigned NumComponents, 
-                      QualType NamedType);
+  static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
+                      QualType NamedType) {
+    ID.AddPointer(NNS);
+    NamedType.Profile(ID);
+  }
 
   static bool classof(const Type *T) { 
     return T->getTypeClass() == QualifiedName; 
index c656d966db3a16a2dc4697bb19800f6b8d55bc9c..84976a029449d8c0a732104772c6f960cd55036c 100644 (file)
@@ -33,9 +33,9 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
                        TargetInfo &t,
                        IdentifierTable &idents, SelectorTable &sels,
                        bool FreeMem, unsigned size_reserve) : 
-  CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0),
-  SourceMgr(SM), LangOpts(LOpts), FreeMemory(FreeMem), Target(t), 
-  Idents(idents), Selectors(sels)
+  GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), 
+  ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), 
+  FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels)
 {  
   if (size_reserve > 0) Types.reserve(size_reserve);    
   InitBuiltinTypes();
@@ -77,7 +77,18 @@ ASTContext::~ASTContext() {
     }
   }
 
+  // Destroy nested-name-specifiers.
+  for (llvm::FoldingSet<NestedNameSpecifier>::iterator 
+         NNS = NestedNameSpecifiers.begin(),
+         NNSEnd = NestedNameSpecifiers.end(); 
+       NNS != NNSEnd; ++NNS)
+    NNS->Destroy(*this);
+
+  if (GlobalNestedNameSpecifier)
+    GlobalNestedNameSpecifier->Destroy(*this);
+
   TUDecl->Destroy(*this);
+
 }
 
 void ASTContext::PrintStats() const {
@@ -1376,11 +1387,10 @@ ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
 }
 
 QualType 
-ASTContext::getQualifiedNameType(const NestedNameSpecifier *Components,
-                                 unsigned NumComponents,
+ASTContext::getQualifiedNameType(NestedNameSpecifier *NNS,
                                  QualType NamedType) {
   llvm::FoldingSetNodeID ID;
-  QualifiedNameType::Profile(ID, Components, NumComponents, NamedType);
+  QualifiedNameType::Profile(ID, NNS, NamedType);
 
   void *InsertPos = 0;
   QualifiedNameType *T 
@@ -1388,11 +1398,8 @@ ASTContext::getQualifiedNameType(const NestedNameSpecifier *Components,
   if (T)
     return QualType(T, 0);
 
-  void *Mem = Allocate((sizeof(QualifiedNameType) +
-                        sizeof(NestedNameSpecifier) * NumComponents), 
-                       8);
-  T = new (Mem) QualifiedNameType(Components, NumComponents, NamedType,
-                                  getCanonicalType(NamedType));
+  T = new (*this) QualifiedNameType(NNS, NamedType, 
+                                    getCanonicalType(NamedType));
   Types.push_back(T);
   QualifiedNameTypes.InsertNode(T, InsertPos);
   return QualType(T, 0);
index 5a9de19254d3be63974c5bb83e29d66911284259..c2fcc5f9ee4cbd75eb6509cf2a7cd9b7f40ced7f 100644 (file)
@@ -24,54 +24,6 @@ void CXXConditionDeclExpr::Destroy(ASTContext& C) {
   C.Deallocate(this);
 }
 
-QualifiedDeclRefExpr::QualifiedDeclRefExpr(NamedDecl *d, QualType t, 
-                                           SourceLocation l, bool TD, 
-                                           bool VD, SourceRange R,
-                                       const NestedNameSpecifier *Components,
-                                           unsigned NumComponents)
-  : DeclRefExpr(QualifiedDeclRefExprClass, d, t, l, TD, VD), 
-    QualifierRange(R), NumComponents(NumComponents) {
-  NestedNameSpecifier *Data 
-    = reinterpret_cast<NestedNameSpecifier *>(this + 1);
-  for (unsigned I = 0; I < NumComponents; ++I)
-    Data[I] = Components[I];
-}
-
-QualifiedDeclRefExpr *
-QualifiedDeclRefExpr::Create(ASTContext &Context, NamedDecl *d, QualType t, 
-                             SourceLocation l, bool TD, 
-                             bool VD, SourceRange R,
-                             const NestedNameSpecifier *Components,
-                             unsigned NumComponents) {
-  void *Mem = Context.Allocate((sizeof(QualifiedDeclRefExpr) +
-                                sizeof(NestedNameSpecifier) * NumComponents));
-  return new (Mem) QualifiedDeclRefExpr(d, t, l, TD, VD, R, Components, 
-                                        NumComponents);
-}
-
-UnresolvedDeclRefExpr::UnresolvedDeclRefExpr(DeclarationName N, QualType T,
-                                             SourceLocation L, SourceRange R,
-                                       const NestedNameSpecifier *Components,
-                                             unsigned NumComponents)
-  : Expr(UnresolvedDeclRefExprClass, T, true, true), 
-    Name(N), Loc(L), QualifierRange(R), NumComponents(NumComponents) {
-  NestedNameSpecifier *Data 
-    = reinterpret_cast<NestedNameSpecifier *>(this + 1);
-  for (unsigned I = 0; I < NumComponents; ++I)
-    Data[I] = Components[I];
-}
-
-UnresolvedDeclRefExpr *
-UnresolvedDeclRefExpr::Create(ASTContext &Context, DeclarationName N,
-                              SourceLocation L, SourceRange R,
-                              const NestedNameSpecifier *Components,
-                              unsigned NumComponents) {
-  void *Mem = Context.Allocate((sizeof(UnresolvedDeclRefExpr) +
-                                sizeof(NestedNameSpecifier) * NumComponents));
-  return new (Mem) UnresolvedDeclRefExpr(N, Context.DependentTy, L, R, 
-                                         Components, NumComponents);
-}
-
 //===----------------------------------------------------------------------===//
 //  Child Iterators for iterating over subexpressions/substatements
 //===----------------------------------------------------------------------===//
index ea4b506e6405cc79c9886398af3217c5035c322c..62e972efd5704a26ba416a97e86c80c821c148b4 100644 (file)
 #include "clang/AST/Decl.h"
 #include "clang/AST/Type.h"
 #include "llvm/Support/raw_ostream.h"
+#include <cassert>
 
 using namespace clang;
 
-DeclContext *
-NestedNameSpecifier::computeDeclContext(ASTContext &Context) const {
-  // The simple case: we're storing a DeclContext
-  if ((Data & 0x01) == 0)
-    return reinterpret_cast<DeclContext *>(Data);
-
-  Type *T = getAsType();
-  if (!T)
-    return 0;
-
-  // Retrieve the DeclContext associated with this type.
-  const TagType *TagT = T->getAsTagType();
-  assert(TagT && "No DeclContext from a non-tag type");
-  return TagT->getDecl();
-}
-
-void NestedNameSpecifier::Print(llvm::raw_ostream &OS, 
-                                const NestedNameSpecifier *First,
-                                const NestedNameSpecifier *Last) {
-  for (; First != Last; ++First) {
-    if (Type *T = First->getAsType()) {
-      std::string TypeStr;
-
-      // If this is a qualified name type, suppress the qualification:
-      // it's part of our nested-name-specifier sequence anyway.
-      if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
-        T = QualT->getNamedType().getTypePtr();
-
-      if (const TagType *TagT = dyn_cast<TagType>(T))
-        TagT->getAsStringInternal(TypeStr, true);
-      else
-        T->getAsStringInternal(TypeStr);
-      OS << TypeStr;
-    } else if (NamedDecl *NamedDC 
-                 = dyn_cast_or_null<NamedDecl>(First->getAsDeclContext()))
-      OS << NamedDC->getNameAsString();
+NestedNameSpecifier *
+NestedNameSpecifier::FindOrInsert(ASTContext &Context, 
+                                  const NestedNameSpecifier &Mockup) {
+  llvm::FoldingSetNodeID ID;
+  Mockup.Profile(ID);
+
+  void *InsertPos = 0;
+  NestedNameSpecifier *NNS 
+    = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
+  if (!NNS) {
+    NNS = new (Context) NestedNameSpecifier(Mockup);
+    Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
+  }
+
+  return NNS;
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 
+                            IdentifierInfo *II) {
+  assert(II && "Identifier cannot be NULL");
+  assert(Prefix && Prefix->isDependent() && "Prefix must be dependent");
+
+  NestedNameSpecifier Mockup;
+  Mockup.Prefix = Prefix;
+  Mockup.Specifier.setPointer(II);
+  Mockup.Specifier.setInt(Identifier);
+  return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 
+                            NamespaceDecl *NS) {
+  assert(NS && "Namespace cannot be NULL");
+  assert((!Prefix || 
+          (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
+         "Broken nested name specifier");
+  NestedNameSpecifier Mockup;
+  Mockup.Prefix = Prefix;
+  Mockup.Specifier.setPointer(NS);
+  Mockup.Specifier.setInt(Namespace);
+  return FindOrInsert(Context, Mockup);
+}
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
+                            bool Template, Type *T) {
+  assert(T && "Type cannot be NULL");
+  NestedNameSpecifier Mockup;
+  Mockup.Prefix = Prefix;
+  Mockup.Specifier.setPointer(T);
+  Mockup.Specifier.setInt(Template? TypeSpecWithTemplate : TypeSpec);
+  return FindOrInsert(Context, Mockup);
+}
   
-    OS <<  "::";
+NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) {
+  if (!Context.GlobalNestedNameSpecifier)
+    Context.GlobalNestedNameSpecifier = new (Context) NestedNameSpecifier();
+  return Context.GlobalNestedNameSpecifier;
+}
+
+/// \brief Whether this nested name specifier refers to a dependent
+/// type or not.
+bool NestedNameSpecifier::isDependent() const {
+  switch (getKind()) {
+  case Identifier:
+    // Identifier specifiers always represent dependent types
+    return true;
+
+  case Namespace:
+  case Global:
+    return false;
+
+  case TypeSpec:
+  case TypeSpecWithTemplate:
+    return getAsType()->isDependentType();
   }
+
+  // Necessary to suppress a GCC warning.
+  return false;
+}
+
+/// \brief Print this nested name specifier to the given output
+/// stream.
+void NestedNameSpecifier::Print(llvm::raw_ostream &OS) const {
+  if (Prefix)
+    Prefix->Print(OS);
+
+  switch (getKind()) {
+  case Identifier:
+    OS << getAsIdentifier()->getName();
+    break;
+
+  case Namespace:
+    OS << getAsNamespace()->getIdentifier()->getName();
+    break;
+
+  case Global:
+    break;
+
+  case TypeSpecWithTemplate:
+    OS << "template ";
+    // Fall through to print the type.
+
+  case TypeSpec: {
+    std::string TypeStr;
+    Type *T = getAsType();
+
+    // If this is a qualified name type, suppress the qualification:
+    // it's part of our nested-name-specifier sequence anyway.  FIXME:
+    // We should be able to assert that this doesn't happen.
+    if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
+      T = QualT->getNamedType().getTypePtr();
+    
+    if (const TagType *TagT = dyn_cast<TagType>(T))
+      TagT->getAsStringInternal(TypeStr, true);
+    else
+      T->getAsStringInternal(TypeStr);
+    OS << TypeStr;
+    break;
+  }
+  }
+
+  OS << "::";
+}
+
+void NestedNameSpecifier::Destroy(ASTContext &Context) {
+  this->~NestedNameSpecifier();
+  Context.Deallocate((void *)this);
 }
index 60300ba04ead12b34fdcbb715ffa7bae5d452142..bd5e22491e6551bd344b7a82b5513f123689de4f 100644 (file)
@@ -533,12 +533,12 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
 void StmtPrinter::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *Node) {  
   NamedDecl *D = Node->getDecl();
 
-  NestedNameSpecifier::Print(OS, Node->begin(), Node->end());
+  Node->getQualifier()->Print(OS);
   OS << D->getNameAsString();
 }
 
 void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) {  
-  NestedNameSpecifier::Print(OS, Node->begin(), Node->end());
+  Node->getQualifier()->Print(OS);
   OS << Node->getDeclName().getAsString();
 }
 
index 19a3f144234a20d31ca5c97983f619054b4a448d..103c0a91345dc0993a3f0dc59aa14aaf5fb38e82 100644 (file)
@@ -1047,28 +1047,6 @@ ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
     Args[Idx].Profile(ID);
 }
 
-QualifiedNameType::QualifiedNameType(const NestedNameSpecifier *Components,
-                                     unsigned NumComponents, 
-                                     QualType NamedType,
-                                     QualType CanonType)
-  : Type(QualifiedName, CanonType, NamedType->isDependentType()),
-    NumComponents(NumComponents), NamedType(NamedType) {
-  NestedNameSpecifier *InitComponents 
-    = reinterpret_cast<NestedNameSpecifier *>(this + 1);
-  for (unsigned I = 0; I < NumComponents; ++I)
-    new (InitComponents + I) NestedNameSpecifier(Components[I]);
-}
-
-void QualifiedNameType::Profile(llvm::FoldingSetNodeID &ID, 
-                                const NestedNameSpecifier *Components,
-                                unsigned NumComponents, 
-                                QualType NamedType) {
-  ID.AddInteger(NumComponents);
-  for (unsigned I = 0; I < NumComponents; ++I)
-    ID.AddPointer(Components[I].getAsOpaquePtr());
-  NamedType.Profile(ID);
-}
-
 //===----------------------------------------------------------------------===//
 // Type Printing
 //===----------------------------------------------------------------------===//
@@ -1440,7 +1418,7 @@ void QualifiedNameType::getAsStringInternal(std::string &InnerString) const {
 
   {
     llvm::raw_string_ostream OS(MyString);
-    NestedNameSpecifier::Print(OS, begin(), end());
+    NNS->Print(OS);
   }
   
   std::string TypeStr;
index 6f93a1859fe462f39e15a0a7c8e2befac3943cf2..4490847a56212239fcf7fd09a78ad088969853a4 100644 (file)
@@ -421,9 +421,7 @@ CreateImpl(ASTContext& Context, Deserializer& D) {
 // QualifiedNameType
 //===----------------------------------------------------------------------===//
 void QualifiedNameType::EmitImpl(llvm::Serializer& S) const {
-  S.EmitInt(NumComponents);
   // FIXME: Serialize the actual components
-  S.Emit(NamedType);
 }
 
 Type* 
index 9d71cf322983bda0779c860a96a55f6872a17588..8c8cae2c8c18a7f343d7a26609968d2483595cd8 100644 (file)
@@ -1940,11 +1940,11 @@ public:
                            ClassTemplateSpecializationDecl *ClassTemplateSpec,
                            bool ExplicitInstantiation);
 
-  CXXScopeSpec InstantiateScopeSpecifier(const NestedNameSpecifier *Components,
-                                         unsigned NumComponents,
-                                         SourceRange Range,
-                                         const TemplateArgument *TemplateArgs,
-                                         unsigned NumTemplateArgs);
+  NestedNameSpecifier *
+  InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                 SourceRange Range,
+                                 const TemplateArgument *TemplateArgs,
+                                 unsigned NumTemplateArgs);
 
   // Simple function for cloning expressions.
   template<typename T> 
index 9e1196143b6af53a32913c4b00d0b19d79366e9e..ca864a2a2ef0ff9af6721a356777f6cb07a33539 100644 (file)
@@ -24,24 +24,41 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS) {
   if (!SS.isSet() || SS.isInvalid())
     return 0;
 
-  NestedNameSpecifier NNS
-    = NestedNameSpecifier::getFromOpaquePtr(SS.getCurrentScopeRep());
-  return NNS.computeDeclContext(Context);
+  NestedNameSpecifier *NNS 
+    = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
+  if (NNS->isDependent())
+    return 0;
+
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    assert(false && "Dependent nested-name-specifier has no DeclContext");
+    break;
+
+  case NestedNameSpecifier::Namespace:
+    return NNS->getAsNamespace();
+
+  case NestedNameSpecifier::TypeSpec:
+  case NestedNameSpecifier::TypeSpecWithTemplate: {
+    const TagType *Tag = NNS->getAsType()->getAsTagType();
+    assert(Tag && "Non-tag type in nested-name-specifier");
+    return Tag->getDecl();
+  } break;
+
+  case NestedNameSpecifier::Global:
+    return Context.getTranslationUnitDecl();
+  }
+
+  // Required to silence a GCC warning.
+  return 0;
 }
 
 bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
   if (!SS.isSet() || SS.isInvalid())
     return false;
 
-  NestedNameSpecifier NNS
-    = NestedNameSpecifier::getFromOpaquePtr(SS.getCurrentScopeRep());
-
-  if (Type *T = NNS.getAsType())
-    return T->isDependentType();
-
-  // FIXME: What about the injected-class-name of a class template? It
-  // is dependent, but we represent it as a declaration.
-  return false;
+  NestedNameSpecifier *NNS 
+    = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
+  return NNS->isDependent();
 }
 
 /// \brief Require that the context specified by SS be complete.
@@ -79,7 +96,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
 /// global scope ('::').
 Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
                                                      SourceLocation CCLoc) {
-  return NestedNameSpecifier(Context.getTranslationUnitDecl()).getAsOpaquePtr();
+  return NestedNameSpecifier::GlobalSpecifier(Context);
 }
 
 /// ActOnCXXNestedNameSpecifier - Called during parsing of a
@@ -93,20 +110,38 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
                                                     SourceLocation IdLoc,
                                                     SourceLocation CCLoc,
                                                     IdentifierInfo &II) {
+  NestedNameSpecifier *Prefix 
+    = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
+
+  // If the prefix is already dependent, there is no name lookup to
+  // perform. Just build the resulting nested-name-specifier.
+  if (Prefix && Prefix->isDependent())
+    return NestedNameSpecifier::Create(Context, Prefix, &II);
+
   NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName);
 
   if (SD) {
-    if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
-      if (TD->getUnderlyingType()->isRecordType())
-        return NestedNameSpecifier(Context.getTypeDeclType(TD).getTypePtr())
-                .getAsOpaquePtr();
-    } else if (isa<NamespaceDecl>(SD) || isa<RecordDecl>(SD)) {
-      return NestedNameSpecifier(cast<DeclContext>(SD)).getAsOpaquePtr();
+    if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD))
+      return NestedNameSpecifier::Create(Context, Prefix, Namespace);
+
+    if (TypeDecl *Type = dyn_cast<TypeDecl>(SD)) {
+      // Determine whether we have a class (or, in C++0x, an enum) or
+      // a typedef thereof. If so, build the nested-name-specifier.
+      QualType T;
+      if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
+        if (TD->getUnderlyingType()->isRecordType() ||
+            (getLangOptions().CPlusPlus0x && 
+             TD->getUnderlyingType()->isEnumeralType()))
+          T = Context.getTypeDeclType(TD);
+      } else if (isa<RecordDecl>(Type) || 
+                 (getLangOptions().CPlusPlus0x && isa<EnumDecl>(Type)))
+        T = Context.getTypeDeclType(Type);
+
+      if (!T.isNull())
+        return NestedNameSpecifier::Create(Context, Prefix, false, 
+                                           T.getTypePtr());
     }
 
-    // FIXME: Template parameters and dependent types.
-    // FIXME: C++0x scoped enums
-
     // Fall through to produce an error: we found something that isn't
     // a class or a namespace.
   }
@@ -137,8 +172,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
                                                     TypeTy *Ty,
                                                     SourceRange TypeRange,
                                                     SourceLocation CCLoc) {
-  return NestedNameSpecifier(QualType::getFromOpaquePtr(Ty).getTypePtr())
-           .getAsOpaquePtr();
+  NestedNameSpecifier *Prefix 
+    = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
+  return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
+                                QualType::getFromOpaquePtr(Ty).getTypePtr());
 }
 
 /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
@@ -152,6 +189,7 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
   assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
   PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
   CurContext = computeDeclContext(SS);
+  assert(CurContext && "No context?");
   S->setEntity(CurContext);
 }
 
@@ -170,4 +208,5 @@ void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
   while (!S->getEntity() && S->getParent())
     S = S->getParent();
   CurContext = static_cast<DeclContext*>(S->getEntity());
+  assert(CurContext && "No context?");
 }
index cb44cfc186a3c39e0d04f5c79f8e0dc09883d1df..bb306e4a0f110efe0489f3e541499d71415f7998 100644 (file)
@@ -1159,9 +1159,13 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
 /// Method declaration as if we had just parsed the qualified method
 /// name. However, it should not bring the parameters into scope;
 /// that will be performed by ActOnDelayedCXXMethodParameter.
-void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *Method) {
+void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclTy *MethodD) {
   CXXScopeSpec SS;
-  SS.setScopeRep(((FunctionDecl*)Method)->getDeclContext());
+  FunctionDecl *Method = (FunctionDecl*)MethodD;
+  QualType ClassTy 
+    = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+  SS.setScopeRep(
+    NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
   ActOnCXXEnterDeclaratorScope(S, SS);
 }
 
@@ -1192,7 +1196,10 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclTy *ParamD) {
 void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclTy *MethodD) {
   FunctionDecl *Method = (FunctionDecl*)MethodD;
   CXXScopeSpec SS;
-  SS.setScopeRep(Method->getDeclContext());
+  QualType ClassTy 
+    = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));
+  SS.setScopeRep(
+    NestedNameSpecifier::Create(Context, 0, false, ClassTy.getTypePtr()));
   ActOnCXXExitDeclaratorScope(S, SS);
 
   // Now that we have our default arguments, check the constructor
index c46bde00ffcaa5eafea8741e647eed3eee0d6651..288b6171918afd8861aa7de5e9a4eb3d110e7254 100644 (file)
@@ -440,13 +440,9 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
                        bool TypeDependent, bool ValueDependent,
                        const CXXScopeSpec *SS) {
   if (SS && !SS->isEmpty()) {
-    llvm::SmallVector<NestedNameSpecifier, 16> Specs;
-    for (CXXScopeSpec::iterator Spec = SS->begin(), SpecEnd = SS->end();
-         Spec != SpecEnd; ++Spec)
-      Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec));
-    return QualifiedDeclRefExpr::Create(Context, D, Ty, Loc, TypeDependent, 
-                                        ValueDependent, SS->getRange(),
-                                        &Specs[0], Specs.size());
+    return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, 
+                                              ValueDependent, SS->getRange(),
+                  static_cast<NestedNameSpecifier *>(SS->getCurrentScopeRep()));
   } else
     return new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
 }
@@ -619,13 +615,9 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
   //     -- a nested-name-specifier that contains a class-name that
   //        names a dependent type.
   if (SS && isDependentScopeSpecifier(*SS)) {
-    llvm::SmallVector<NestedNameSpecifier, 16> Specs;
-    for (CXXScopeSpec::iterator Spec = SS->begin(), SpecEnd = SS->end();
-         Spec != SpecEnd; ++Spec)
-      Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec));
-    return Owned(UnresolvedDeclRefExpr::Create(Context, Name, Loc,
-                                               SS->getRange(), &Specs[0],
-                                               Specs.size()));
+    return Owned(new (Context) UnresolvedDeclRefExpr(Name, Context.DependentTy,
+                                                     Loc, SS->getRange(), 
+                static_cast<NestedNameSpecifier *>(SS->getCurrentScopeRep())));
   }
 
   LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName,
@@ -2302,12 +2294,11 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
       Expr *NewFn = 0;
       if (QualifiedDeclRefExpr *QDRExpr
             = dyn_cast_or_null<QualifiedDeclRefExpr>(DRExpr))
-        NewFn = QualifiedDeclRefExpr::Create(Context, FDecl, FDecl->getType(),
-                                             QDRExpr->getLocation(),
-                                             false, false,
-                                             QDRExpr->getQualifierRange(),
-                                             QDRExpr->begin(), 
-                                             QDRExpr->size());
+        NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(),
+                                                   QDRExpr->getLocation(),
+                                                   false, false,
+                                                 QDRExpr->getQualifierRange(),
+                                                   QDRExpr->getQualifier());
       else
         NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(),
                                           Fn->getSourceRange().getBegin());
index f6e36bf77914718b12957916b73e7ccbba5d85f6..52f87b93f7622decc0d9e6978597c83fb29dbbe9 100644 (file)
@@ -768,33 +768,52 @@ Sema::InstantiateClassTemplateSpecialization(
                           ClassTemplateSpec->getNumTemplateArgs());
 }
 
-/// \brief Instantiate a sequence of nested-name-specifiers into a
-/// scope specifier.
-CXXScopeSpec 
-Sema::InstantiateScopeSpecifier(const NestedNameSpecifier *Components,
-                                unsigned NumComponents,
-                                SourceRange Range,
-                                const TemplateArgument *TemplateArgs,
-                                unsigned NumTemplateArgs) {
-  CXXScopeSpec SS;
-  for (unsigned Comp = 0; Comp < NumComponents; ++Comp) {
-    if (Type *T = Components[Comp].getAsType()) {
-      QualType NewT = InstantiateType(QualType(T, 0), TemplateArgs, 
-                                      NumTemplateArgs, Range.getBegin(),
-                                      DeclarationName());
-      if (NewT.isNull())
-        return SS;
-      NestedNameSpecifier NNS(NewT.getTypePtr());
-      SS.addScopeRep(NNS.getAsOpaquePtr());
-    } else {
-      DeclContext *DC = Components[Comp].getAsDeclContext();
-      // FIXME: injected-class-name might be dependent, and therefore
-      // would need instantiation.
-      NestedNameSpecifier NNS(DC);
-      SS.addScopeRep(NNS.getAsOpaquePtr());
-    }
+/// \brief Instantiate a nested-name-specifier.
+NestedNameSpecifier *
+Sema::InstantiateNestedNameSpecifier(NestedNameSpecifier *NNS,
+                                     SourceRange Range,
+                                     const TemplateArgument *TemplateArgs,
+                                     unsigned NumTemplateArgs) {
+  // Instantiate the prefix of this nested name specifier.
+  NestedNameSpecifier *Prefix = NNS->getPrefix();
+  if (Prefix) {
+    Prefix = InstantiateNestedNameSpecifier(Prefix, Range, TemplateArgs,
+                                            NumTemplateArgs);
+    if (!Prefix)
+      return 0;
+  }
+
+  switch (NNS->getKind()) {
+  case NestedNameSpecifier::Identifier:
+    // FIXME: Implement this lookup!
+    assert(false && "Cannot instantiate this nested-name-specifier");
+    break;
+
+  case NestedNameSpecifier::Namespace:
+  case NestedNameSpecifier::Global:
+    return NNS;
+    
+  case NestedNameSpecifier::TypeSpecWithTemplate:
+  case NestedNameSpecifier::TypeSpec: {
+    QualType T = QualType(NNS->getAsType(), 0);
+    if (!T->isDependentType())
+      return NNS;
+
+    T = InstantiateType(T, TemplateArgs, NumTemplateArgs, Range.getBegin(),
+                        DeclarationName());
+    if (T.isNull())
+      return 0;
+
+    // Note that T.getTypePtr(), below, strips cv-qualifiers. This is
+    // perfectly reasonable, since cv-qualified types in
+    // nested-name-specifiers don't matter.
+    // FIXME: we need to perform more checking on this type.
+    return NestedNameSpecifier::Create(Context, Prefix, 
+                 NNS->getKind() == NestedNameSpecifier::TypeSpecWithTemplate,
+                                       T.getTypePtr());
+  }
   }
 
-  SS.setRange(Range);
-  return SS;
+  // Required to silence GCC warning.
+  return 0;
 }
index 780afd4468b3a5451223ac4ab4b971658b4cc07b..5476ad3502b74c7f66f2297622dbf69ae65ee75f 100644 (file)
@@ -321,13 +321,17 @@ TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
 
 Sema::OwningExprResult 
 TemplateExprInstantiator::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) {
-  CXXScopeSpec SS = SemaRef.InstantiateScopeSpecifier(E->begin(), E->size(),
-                                                      E->getQualifierRange(),
-                                                      TemplateArgs,
-                                                      NumTemplateArgs);
-  if (SS.isInvalid() || SS.isEmpty())
+  NestedNameSpecifier *NNS 
+    = SemaRef.InstantiateNestedNameSpecifier(E->getQualifier(), 
+                                             E->getQualifierRange(),
+                                             TemplateArgs, NumTemplateArgs);
+  if (!NNS)
     return SemaRef.ExprError();
 
+  CXXScopeSpec SS;
+  SS.setRange(E->getQualifierRange());
+  SS.setScopeRep(NNS);
+
   // FIXME: We're passing in a NULL scope, because
   // ActOnDeclarationNameExpr doesn't actually use the scope when we
   // give it a non-empty scope specifier. Investigate whether it would
index 4b2565795a97c52abe7ea84f7ae830a2857ed80e..0780ad8f4ad619b677cfb12490692252b0b1ab2a 100644 (file)
@@ -1101,9 +1101,7 @@ QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) {
   if (!SS.isSet() || SS.isInvalid() || T.isNull())
     return T;
   
-  llvm::SmallVector<NestedNameSpecifier, 4> Specs;
-  for (CXXScopeSpec::iterator Spec = SS.begin(), SpecEnd = SS.end();
-       Spec != SpecEnd; ++Spec)
-    Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec));
-  return Context.getQualifiedNameType(&Specs[0], Specs.size(), T);
+  NestedNameSpecifier *NNS
+    = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
+  return Context.getQualifiedNameType(NNS, T);
 }