blob: 1b477d85a94337fbac54975f7c18835371520c95 [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"
Douglas Gregor14aba762011-02-24 02:36:08 +000017#include "clang/AST/DeclCXX.h"
Douglas Gregord249e1d1f2009-05-29 20:38:28 +000018#include "clang/AST/PrettyPrinter.h"
Douglas Gregore4e5b052009-03-19 00:18:19 +000019#include "clang/AST/Type.h"
Douglas Gregorbad35182009-03-19 03:51:16 +000020#include "llvm/Support/raw_ostream.h"
Douglas Gregorab452ba2009-03-26 23:50:42 +000021#include <cassert>
Douglas Gregorbad35182009-03-19 03:51:16 +000022
Douglas Gregore4e5b052009-03-19 00:18:19 +000023using namespace clang;
24
Douglas Gregorab452ba2009-03-26 23:50:42 +000025NestedNameSpecifier *
Jay Foad4ba2a172011-01-12 09:06:06 +000026NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
Douglas Gregorab452ba2009-03-26 23:50:42 +000027 const NestedNameSpecifier &Mockup) {
28 llvm::FoldingSetNodeID ID;
29 Mockup.Profile(ID);
Douglas Gregore4e5b052009-03-19 00:18:19 +000030
Douglas Gregorab452ba2009-03-26 23:50:42 +000031 void *InsertPos = 0;
Mike Stump1eb44332009-09-09 15:08:12 +000032 NestedNameSpecifier *NNS
Douglas Gregorab452ba2009-03-26 23:50:42 +000033 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
34 if (!NNS) {
Douglas Gregor17343172009-04-01 00:28:59 +000035 NNS = new (Context, 4) NestedNameSpecifier(Mockup);
Douglas Gregorab452ba2009-03-26 23:50:42 +000036 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
37 }
Douglas Gregore4e5b052009-03-19 00:18:19 +000038
Douglas Gregorab452ba2009-03-26 23:50:42 +000039 return NNS;
Douglas Gregore4e5b052009-03-19 00:18:19 +000040}
Douglas Gregorbad35182009-03-19 03:51:16 +000041
Douglas Gregorab452ba2009-03-26 23:50:42 +000042NestedNameSpecifier *
Jay Foad4ba2a172011-01-12 09:06:06 +000043NestedNameSpecifier::Create(const ASTContext &Context,
44 NestedNameSpecifier *Prefix, IdentifierInfo *II) {
Douglas Gregorab452ba2009-03-26 23:50:42 +000045 assert(II && "Identifier cannot be NULL");
Douglas Gregor3b6afbb2009-09-09 00:23:06 +000046 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
Douglas Gregorbad35182009-03-19 03:51:16 +000047
Douglas Gregorab452ba2009-03-26 23:50:42 +000048 NestedNameSpecifier Mockup;
Douglas Gregor17343172009-04-01 00:28:59 +000049 Mockup.Prefix.setPointer(Prefix);
Douglas Gregor14aba762011-02-24 02:36:08 +000050 Mockup.Prefix.setInt(StoredIdentifier);
Douglas Gregor17343172009-04-01 00:28:59 +000051 Mockup.Specifier = II;
Douglas Gregorab452ba2009-03-26 23:50:42 +000052 return FindOrInsert(Context, Mockup);
53}
Douglas Gregorbad35182009-03-19 03:51:16 +000054
Douglas Gregorab452ba2009-03-26 23:50:42 +000055NestedNameSpecifier *
Jay Foad4ba2a172011-01-12 09:06:06 +000056NestedNameSpecifier::Create(const ASTContext &Context,
57 NestedNameSpecifier *Prefix, NamespaceDecl *NS) {
Douglas Gregorab452ba2009-03-26 23:50:42 +000058 assert(NS && "Namespace cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +000059 assert((!Prefix ||
Douglas Gregorab452ba2009-03-26 23:50:42 +000060 (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
61 "Broken nested name specifier");
62 NestedNameSpecifier Mockup;
Douglas Gregor17343172009-04-01 00:28:59 +000063 Mockup.Prefix.setPointer(Prefix);
Douglas Gregor14aba762011-02-24 02:36:08 +000064 Mockup.Prefix.setInt(StoredNamespaceOrAlias);
Douglas Gregor17343172009-04-01 00:28:59 +000065 Mockup.Specifier = NS;
Douglas Gregorab452ba2009-03-26 23:50:42 +000066 return FindOrInsert(Context, Mockup);
67}
68
69NestedNameSpecifier *
Jay Foad4ba2a172011-01-12 09:06:06 +000070NestedNameSpecifier::Create(const ASTContext &Context,
Douglas Gregor14aba762011-02-24 02:36:08 +000071 NestedNameSpecifier *Prefix,
72 NamespaceAliasDecl *Alias) {
73 assert(Alias && "Namespace alias cannot be NULL");
74 assert((!Prefix ||
75 (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) &&
76 "Broken nested name specifier");
77 NestedNameSpecifier Mockup;
78 Mockup.Prefix.setPointer(Prefix);
79 Mockup.Prefix.setInt(StoredNamespaceOrAlias);
80 Mockup.Specifier = Alias;
81 return FindOrInsert(Context, Mockup);
82}
83
84NestedNameSpecifier *
85NestedNameSpecifier::Create(const ASTContext &Context,
Jay Foad4ba2a172011-01-12 09:06:06 +000086 NestedNameSpecifier *Prefix,
John McCallf4c73712011-01-19 06:33:43 +000087 bool Template, const Type *T) {
Douglas Gregorab452ba2009-03-26 23:50:42 +000088 assert(T && "Type cannot be NULL");
89 NestedNameSpecifier Mockup;
Douglas Gregor17343172009-04-01 00:28:59 +000090 Mockup.Prefix.setPointer(Prefix);
Douglas Gregor14aba762011-02-24 02:36:08 +000091 Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
John McCallf4c73712011-01-19 06:33:43 +000092 Mockup.Specifier = const_cast<Type*>(T);
Douglas Gregorab452ba2009-03-26 23:50:42 +000093 return FindOrInsert(Context, Mockup);
94}
Douglas Gregor2700dcd2009-09-02 23:58:38 +000095
96NestedNameSpecifier *
Jay Foad4ba2a172011-01-12 09:06:06 +000097NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
Douglas Gregor2700dcd2009-09-02 23:58:38 +000098 assert(II && "Identifier cannot be NULL");
99 NestedNameSpecifier Mockup;
100 Mockup.Prefix.setPointer(0);
Douglas Gregor14aba762011-02-24 02:36:08 +0000101 Mockup.Prefix.setInt(StoredIdentifier);
Douglas Gregor2700dcd2009-09-02 23:58:38 +0000102 Mockup.Specifier = II;
103 return FindOrInsert(Context, Mockup);
104}
105
Jay Foad4ba2a172011-01-12 09:06:06 +0000106NestedNameSpecifier *
107NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
Douglas Gregorab452ba2009-03-26 23:50:42 +0000108 if (!Context.GlobalNestedNameSpecifier)
Douglas Gregor17343172009-04-01 00:28:59 +0000109 Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier();
Douglas Gregorab452ba2009-03-26 23:50:42 +0000110 return Context.GlobalNestedNameSpecifier;
111}
112
Douglas Gregor14aba762011-02-24 02:36:08 +0000113NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
114 if (Specifier == 0)
115 return Global;
116
117 switch (Prefix.getInt()) {
118 case StoredIdentifier:
119 return Identifier;
120
121 case StoredNamespaceOrAlias:
122 return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace
123 : NamespaceAlias;
124
125 case StoredTypeSpec:
126 return TypeSpec;
127
128 case StoredTypeSpecWithTemplate:
129 return TypeSpecWithTemplate;
130 }
131
132 return Global;
133}
134
135/// \brief Retrieve the namespace stored in this nested name
136/// specifier.
137NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
138 if (Prefix.getInt() == StoredNamespaceOrAlias)
139 return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
140
141 return 0;
142}
143
144/// \brief Retrieve the namespace alias stored in this nested name
145/// specifier.
146NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
147 if (Prefix.getInt() == StoredNamespaceOrAlias)
148 return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
149
150 return 0;
151}
152
153
Douglas Gregorab452ba2009-03-26 23:50:42 +0000154/// \brief Whether this nested name specifier refers to a dependent
155/// type or not.
156bool NestedNameSpecifier::isDependent() const {
157 switch (getKind()) {
158 case Identifier:
159 // Identifier specifiers always represent dependent types
160 return true;
161
162 case Namespace:
Douglas Gregor14aba762011-02-24 02:36:08 +0000163 case NamespaceAlias:
Douglas Gregorab452ba2009-03-26 23:50:42 +0000164 case Global:
165 return false;
166
167 case TypeSpec:
168 case TypeSpecWithTemplate:
169 return getAsType()->isDependentType();
Douglas Gregorbad35182009-03-19 03:51:16 +0000170 }
Douglas Gregorab452ba2009-03-26 23:50:42 +0000171
172 // Necessary to suppress a GCC warning.
173 return false;
174}
175
Douglas Gregord0937222010-12-13 22:49:22 +0000176bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
177 switch (getKind()) {
178 case Identifier:
179 return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
180
181 case Namespace:
Douglas Gregor14aba762011-02-24 02:36:08 +0000182 case NamespaceAlias:
Douglas Gregord0937222010-12-13 22:49:22 +0000183 case Global:
184 return false;
185
186 case TypeSpec:
187 case TypeSpecWithTemplate:
188 return getAsType()->containsUnexpandedParameterPack();
189 }
190
191 // Necessary to suppress a GCC warning.
192 return false;
193}
194
Douglas Gregorab452ba2009-03-26 23:50:42 +0000195/// \brief Print this nested name specifier to the given output
196/// stream.
Mike Stump1eb44332009-09-09 15:08:12 +0000197void
198NestedNameSpecifier::print(llvm::raw_ostream &OS,
Douglas Gregord249e1d1f2009-05-29 20:38:28 +0000199 const PrintingPolicy &Policy) const {
Douglas Gregor17343172009-04-01 00:28:59 +0000200 if (getPrefix())
Douglas Gregord249e1d1f2009-05-29 20:38:28 +0000201 getPrefix()->print(OS, Policy);
Douglas Gregorab452ba2009-03-26 23:50:42 +0000202
203 switch (getKind()) {
204 case Identifier:
205 OS << getAsIdentifier()->getName();
206 break;
207
208 case Namespace:
Douglas Gregor14aba762011-02-24 02:36:08 +0000209 OS << getAsNamespace()->getName();
210 break;
211
212 case NamespaceAlias:
213 OS << getAsNamespaceAlias()->getName();
Douglas Gregorab452ba2009-03-26 23:50:42 +0000214 break;
215
216 case Global:
217 break;
218
219 case TypeSpecWithTemplate:
220 OS << "template ";
221 // Fall through to print the type.
222
223 case TypeSpec: {
224 std::string TypeStr;
John McCallf4c73712011-01-19 06:33:43 +0000225 const Type *T = getAsType();
Douglas Gregorab452ba2009-03-26 23:50:42 +0000226
Douglas Gregord249e1d1f2009-05-29 20:38:28 +0000227 PrintingPolicy InnerPolicy(Policy);
John McCall2191b202009-09-05 06:31:47 +0000228 InnerPolicy.SuppressScope = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000229
Douglas Gregordacd4342009-08-26 00:04:55 +0000230 // Nested-name-specifiers are intended to contain minimally-qualified
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000231 // types. An actual ElaboratedType will not occur, since we'll store
Douglas Gregordacd4342009-08-26 00:04:55 +0000232 // just the type that is referred to in the nested-name-specifier (e.g.,
233 // a TypedefType, TagType, etc.). However, when we are dealing with
Mike Stump1eb44332009-09-09 15:08:12 +0000234 // dependent template-id types (e.g., Outer<T>::template Inner<U>),
Douglas Gregordacd4342009-08-26 00:04:55 +0000235 // the type requires its own nested-name-specifier for uniqueness, so we
236 // suppress that nested-name-specifier during printing.
Abramo Bagnara465d41b2010-05-11 21:36:43 +0000237 assert(!isa<ElaboratedType>(T) &&
238 "Elaborated type in nested-name-specifier");
Douglas Gregordacd4342009-08-26 00:04:55 +0000239 if (const TemplateSpecializationType *SpecType
240 = dyn_cast<TemplateSpecializationType>(T)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000241 // Print the template name without its corresponding
Douglas Gregordacd4342009-08-26 00:04:55 +0000242 // nested-name-specifier.
243 SpecType->getTemplateName().print(OS, InnerPolicy, true);
Mike Stump1eb44332009-09-09 15:08:12 +0000244
Douglas Gregordacd4342009-08-26 00:04:55 +0000245 // Print the template argument list.
246 TypeStr = TemplateSpecializationType::PrintTemplateArgumentList(
Mike Stump1eb44332009-09-09 15:08:12 +0000247 SpecType->getArgs(),
248 SpecType->getNumArgs(),
Douglas Gregordacd4342009-08-26 00:04:55 +0000249 InnerPolicy);
250 } else {
251 // Print the type normally
Douglas Gregorfee8a3c2009-11-10 00:39:07 +0000252 TypeStr = QualType(T, 0).getAsString(InnerPolicy);
Douglas Gregordacd4342009-08-26 00:04:55 +0000253 }
Douglas Gregorab452ba2009-03-26 23:50:42 +0000254 OS << TypeStr;
255 break;
256 }
257 }
258
259 OS << "::";
260}
261
Chris Lattnere4f21422009-06-30 01:26:17 +0000262void NestedNameSpecifier::dump(const LangOptions &LO) {
263 print(llvm::errs(), PrintingPolicy(LO));
Douglas Gregord57959a2009-03-27 23:10:48 +0000264}