aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-19 00:18:19 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-19 00:18:19 +0000
commite4e5b054b4917f0ee493bb2fda5b1ec749bfb9a1 (patch)
treede98baadcf679cb6d084a3efd3ffd6b8e30f2009 /lib/AST
parent72374594c5d9ade02451bc85cf9dfa5b0ea106e7 (diff)
Introduce a representation for types that we referred to via a
qualified name, e.g., foo::x so that we retain the nested-name-specifier as written in the source code and can reproduce that qualified name when printing the types back (e.g., in diagnostics). This is PR3493, which won't be complete until finished the other tasks mentioned near the end of this commit. The parser's representation of nested-name-specifiers, CXXScopeSpec, is now a bit fatter, because it needs to contain the scopes that precede each '::' and keep track of whether the global scoping operator '::' was at the beginning. For example, we need to keep track of the leading '::', 'foo', and 'bar' in ::foo::bar::x The Action's CXXScopeTy * is no longer a DeclContext *. It's now the opaque version of the new NestedNameSpecifier, which contains a single component of a nested-name-specifier (either a DeclContext * or a Type *, bitmangled). The new sugar type QualifiedNameType composes a sequence of NestedNameSpecifiers with a representation of the type we're actually referring to. At present, we only build QualifiedNameType nodes within Sema::getTypeName. This will be extended to other type-constructing actions (e.g., ActOnClassTemplateId). Also on the way: QualifiedDeclRefExprs will also store a sequence of NestedNameSpecifiers, so that we can print out the property nested-name-specifier. I expect to also use this for handling dependent names like Fibonacci<I - 1>::value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67265 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTContext.cpp23
-rw-r--r--lib/AST/CMakeLists.txt1
-rw-r--r--lib/AST/NestedNameSpecifier.cpp34
-rw-r--r--lib/AST/Type.cpp63
-rw-r--r--lib/AST/TypeSerialization.cpp15
5 files changed, 135 insertions, 1 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index c318107dab..c5441dd304 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1375,6 +1375,29 @@ ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
return QualType(Spec, 0);
}
+QualType
+ASTContext::getQualifiedNameType(const NestedNameSpecifier *Components,
+ unsigned NumComponents,
+ QualType NamedType) {
+ llvm::FoldingSetNodeID ID;
+ QualifiedNameType::Profile(ID, Components, NumComponents, NamedType);
+
+ void *InsertPos = 0;
+ QualifiedNameType *T
+ = QualifiedNameTypes.FindNodeOrInsertPos(ID, InsertPos);
+ if (T)
+ return QualType(T, 0);
+
+ void *Mem = Allocate((sizeof(QualifiedNameType) +
+ sizeof(NestedNameSpecifier) * NumComponents),
+ 8);
+ T = new (Mem) QualifiedNameType(Components, NumComponents, NamedType,
+ getCanonicalType(NamedType));
+ Types.push_back(T);
+ QualifiedNameTypes.InsertNode(T, InsertPos);
+ return QualType(T, 0);
+}
+
/// CmpProtocolNames - Comparison predicate for sorting protocols
/// alphabetically.
static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 48b1971112..5ea7a47fd6 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -18,6 +18,7 @@ add_clang_library(clangAST
Expr.cpp
ExprCXX.cpp
InheritViz.cpp
+ NestedNameSpecifier.cpp
ParentMap.cpp
Stmt.cpp
StmtDumper.cpp
diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp
new file mode 100644
index 0000000000..318c05fe7c
--- /dev/null
+++ b/lib/AST/NestedNameSpecifier.cpp
@@ -0,0 +1,34 @@
+//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the NestedNameSpecifier class, which represents
+// a C++ nested-name-specifier.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Type.h"
+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();
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index bb3df0882f..b066802c67 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -96,6 +96,8 @@ QualType Type::getDesugaredType() const {
if (const ClassTemplateSpecializationType *Spec
= dyn_cast<ClassTemplateSpecializationType>(this))
return Spec->getCanonicalTypeInternal().getDesugaredType();
+ if (const QualifiedNameType *QualName = dyn_cast<QualifiedNameType>(this))
+ return QualName->getNamedType().getDesugaredType();
// FIXME: remove this cast.
return QualType(const_cast<Type*>(this), 0);
@@ -1045,6 +1047,28 @@ 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
//===----------------------------------------------------------------------===//
@@ -1411,6 +1435,38 @@ getAsStringInternal(std::string &InnerString) const {
InnerString = SpecString + ' ' + InnerString;
}
+void QualifiedNameType::getAsStringInternal(std::string &InnerString) const {
+ std::string MyString;
+
+ for (iterator Comp = begin(), CompEnd = end(); Comp != CompEnd; ++Comp) {
+ if (Type *T = Comp->getAsType()) {
+ std::string TypeStr;
+ if (const TagType *TagT = dyn_cast<TagType>(T))
+ TagT->getAsStringInternal(TypeStr, true);
+ else
+ T->getAsStringInternal(TypeStr);
+
+ MyString += TypeStr;
+ } else if (NamedDecl *NamedDC
+ = dyn_cast_or_null<NamedDecl>(Comp->getAsDeclContext()))
+ MyString += NamedDC->getNameAsString();
+ MyString += "::";
+ }
+
+ std::string TypeStr;
+ if (const TagType *TagT = dyn_cast<TagType>(NamedType.getTypePtr())) {
+ // Suppress printing of 'enum', 'struct', 'union', or 'class'.
+ TagT->getAsStringInternal(TypeStr, true);
+ } else
+ NamedType.getAsStringInternal(TypeStr);
+
+ MyString += TypeStr;
+ if (InnerString.empty())
+ InnerString.swap(MyString);
+ else
+ InnerString = MyString + ' ' + InnerString;
+}
+
void ObjCInterfaceType::getAsStringInternal(std::string &InnerString) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
@@ -1451,10 +1507,15 @@ void ObjCQualifiedIdType::getAsStringInternal(std::string &InnerString) const {
}
void TagType::getAsStringInternal(std::string &InnerString) const {
+ getAsStringInternal(InnerString, false);
+}
+
+void TagType::getAsStringInternal(std::string &InnerString,
+ bool SuppressTagKind) const {
if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'.
InnerString = ' ' + InnerString;
- const char *Kind = getDecl()->getKindName();
+ const char *Kind = SuppressTagKind? 0 : getDecl()->getKindName();
const char *ID;
if (const IdentifierInfo *II = getDecl()->getIdentifier())
ID = II->getName();
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 8498e0123e..6f93a1859f 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -418,6 +418,21 @@ 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*
+QualifiedNameType::CreateImpl(ASTContext& Context, llvm::Deserializer& D) {
+ // FIXME: Implement de-serialization
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
// VariableArrayType
//===----------------------------------------------------------------------===//