blob: c94a4da7b610c5addbc6bbbb34196d384fe24f41 [file] [log] [blame]
Douglas Gregore4e5b052009-03-19 00:18:19 +00001//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the NestedNameSpecifier class, which represents
11// a C++ nested-name-specifier.
12//
13//===----------------------------------------------------------------------===//
14#include "clang/AST/NestedNameSpecifier.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/Type.h"
Douglas Gregorbad35182009-03-19 03:51:16 +000018#include "llvm/Support/raw_ostream.h"
Douglas Gregorab452ba2009-03-26 23:50:42 +000019#include <cassert>
Douglas Gregorbad35182009-03-19 03:51:16 +000020
Douglas Gregore4e5b052009-03-19 00:18:19 +000021using namespace clang;
22
Douglas Gregorab452ba2009-03-26 23:50:42 +000023NestedNameSpecifier *
24NestedNameSpecifier::FindOrInsert(ASTContext &Context,
25 const NestedNameSpecifier &Mockup) {
26 llvm::FoldingSetNodeID ID;
27 Mockup.Profile(ID);
Douglas Gregore4e5b052009-03-19 00:18:19 +000028
Douglas Gregorab452ba2009-03-26 23:50:42 +000029 void *InsertPos = 0;
30 NestedNameSpecifier *NNS
31 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
32 if (!NNS) {
Douglas Gregor17343172009-04-01 00:28:59 +000033 NNS = new (Context, 4) NestedNameSpecifier(Mockup);
Douglas Gregorab452ba2009-03-26 23:50:42 +000034 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
35 }
Douglas Gregore4e5b052009-03-19 00:18:19 +000036
Douglas Gregorab452ba2009-03-26 23:50:42 +000037 return NNS;
Douglas Gregore4e5b052009-03-19 00:18:19 +000038}
Douglas Gregorbad35182009-03-19 03:51:16 +000039
Douglas Gregorab452ba2009-03-26 23:50:42 +000040NestedNameSpecifier *
41NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
42 IdentifierInfo *II) {
43 assert(II && "Identifier cannot be NULL");
44 assert(Prefix && Prefix->isDependent() && "Prefix must be dependent");
Douglas Gregorbad35182009-03-19 03:51:16 +000045
Douglas Gregorab452ba2009-03-26 23:50:42 +000046 NestedNameSpecifier Mockup;
Douglas Gregor17343172009-04-01 00:28:59 +000047 Mockup.Prefix.setPointer(Prefix);
48 Mockup.Prefix.setInt(Identifier);
49 Mockup.Specifier = II;
Douglas Gregorab452ba2009-03-26 23:50:42 +000050 return FindOrInsert(Context, Mockup);
51}
Douglas Gregorbad35182009-03-19 03:51:16 +000052
Douglas Gregorab452ba2009-03-26 23:50:42 +000053NestedNameSpecifier *
54NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
55 NamespaceDecl *NS) {
56 assert(NS && "Namespace cannot be NULL");
57 assert((!Prefix ||
58 (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
59 "Broken nested name specifier");
60 NestedNameSpecifier Mockup;
Douglas Gregor17343172009-04-01 00:28:59 +000061 Mockup.Prefix.setPointer(Prefix);
62 Mockup.Prefix.setInt(Namespace);
63 Mockup.Specifier = NS;
Douglas Gregorab452ba2009-03-26 23:50:42 +000064 return FindOrInsert(Context, Mockup);
65}
66
67NestedNameSpecifier *
68NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix,
69 bool Template, Type *T) {
70 assert(T && "Type cannot be NULL");
71 NestedNameSpecifier Mockup;
Douglas Gregor17343172009-04-01 00:28:59 +000072 Mockup.Prefix.setPointer(Prefix);
73 Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec);
74 Mockup.Specifier = T;
Douglas Gregorab452ba2009-03-26 23:50:42 +000075 return FindOrInsert(Context, Mockup);
76}
Douglas Gregorbad35182009-03-19 03:51:16 +000077
Douglas Gregorab452ba2009-03-26 23:50:42 +000078NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) {
79 if (!Context.GlobalNestedNameSpecifier)
Douglas Gregor17343172009-04-01 00:28:59 +000080 Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier();
Douglas Gregorab452ba2009-03-26 23:50:42 +000081 return Context.GlobalNestedNameSpecifier;
82}
83
84/// \brief Whether this nested name specifier refers to a dependent
85/// type or not.
86bool NestedNameSpecifier::isDependent() const {
87 switch (getKind()) {
88 case Identifier:
89 // Identifier specifiers always represent dependent types
90 return true;
91
92 case Namespace:
93 case Global:
94 return false;
95
96 case TypeSpec:
97 case TypeSpecWithTemplate:
98 return getAsType()->isDependentType();
Douglas Gregorbad35182009-03-19 03:51:16 +000099 }
Douglas Gregorab452ba2009-03-26 23:50:42 +0000100
101 // Necessary to suppress a GCC warning.
102 return false;
103}
104
105/// \brief Print this nested name specifier to the given output
106/// stream.
Douglas Gregor9bde7732009-03-31 20:22:05 +0000107void NestedNameSpecifier::print(llvm::raw_ostream &OS) const {
Douglas Gregor17343172009-04-01 00:28:59 +0000108 if (getPrefix())
109 getPrefix()->print(OS);
Douglas Gregorab452ba2009-03-26 23:50:42 +0000110
111 switch (getKind()) {
112 case Identifier:
113 OS << getAsIdentifier()->getName();
114 break;
115
116 case Namespace:
117 OS << getAsNamespace()->getIdentifier()->getName();
118 break;
119
120 case Global:
121 break;
122
123 case TypeSpecWithTemplate:
124 OS << "template ";
125 // Fall through to print the type.
126
127 case TypeSpec: {
128 std::string TypeStr;
129 Type *T = getAsType();
130
131 // If this is a qualified name type, suppress the qualification:
132 // it's part of our nested-name-specifier sequence anyway. FIXME:
133 // We should be able to assert that this doesn't happen.
134 if (const QualifiedNameType *QualT = dyn_cast<QualifiedNameType>(T))
135 T = QualT->getNamedType().getTypePtr();
136
137 if (const TagType *TagT = dyn_cast<TagType>(T))
138 TagT->getAsStringInternal(TypeStr, true);
139 else
140 T->getAsStringInternal(TypeStr);
141 OS << TypeStr;
142 break;
143 }
144 }
145
146 OS << "::";
147}
148
149void NestedNameSpecifier::Destroy(ASTContext &Context) {
150 this->~NestedNameSpecifier();
151 Context.Deallocate((void *)this);
Douglas Gregorbad35182009-03-19 03:51:16 +0000152}
Douglas Gregord57959a2009-03-27 23:10:48 +0000153
Douglas Gregor9bde7732009-03-31 20:22:05 +0000154void NestedNameSpecifier::dump() {
155 print(llvm::errs());
Douglas Gregord57959a2009-03-27 23:10:48 +0000156}