aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-26 23:50:42 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-26 23:50:42 +0000
commitab452ba8323d1985e08bade2bced588cddf2cc28 (patch)
tree5434985218412826cd26ffd2f8d87857109eb50b
parent5bf17cd277db2a253f6012968471064c4f4537a3 (diff)
Revamp our representation of C++ nested-name-specifiers. We now have a
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
-rw-r--r--include/clang/AST/ASTContext.h12
-rw-r--r--include/clang/AST/ExprCXX.h67
-rw-r--r--include/clang/AST/NestedNameSpecifier.h194
-rw-r--r--include/clang/AST/Type.h37
-rw-r--r--lib/AST/ASTContext.cpp29
-rw-r--r--lib/AST/ExprCXX.cpp48
-rw-r--r--lib/AST/NestedNameSpecifier.cpp165
-rw-r--r--lib/AST/StmtPrinter.cpp4
-rw-r--r--lib/AST/Type.cpp24
-rw-r--r--lib/AST/TypeSerialization.cpp2
-rw-r--r--lib/Sema/Sema.h10
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp87
-rw-r--r--lib/Sema/SemaDeclCXX.cpp13
-rw-r--r--lib/Sema/SemaExpr.cpp31
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp73
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp14
-rw-r--r--lib/Sema/SemaType.cpp8
17 files changed, 470 insertions, 348 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 36bf12b787..3cf48b4994 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -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
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 1292eaf2d2..366f860c50 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -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());
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index a371e89638..a740efbe09 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -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);
};
}
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 3453cb09df..e37b186871 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -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;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index c656d966db..84976a0294 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -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);
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 5a9de19254..c2fcc5f9ee 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -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
//===----------------------------------------------------------------------===//
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
index ea4b506e64..62e972efd5 100644
--- a/lib/AST/NestedNameSpecifier.cpp
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -16,46 +16,137 @@
#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);
}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 60300ba04e..bd5e22491e 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -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();
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 19a3f14423..103c0a9134 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -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;
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 6f93a1859f..4490847a56 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -421,9 +421,7 @@ CreateImpl(ASTCon