blob: 42f6a133d717423dd2ed4aee9d688f32ec86f3d2 [file] [log] [blame]
Eugene Zelenko21fadad2017-11-21 23:26:08 +00001//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
Douglas Gregor52537682009-03-19 00:18:19 +00002//
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//===----------------------------------------------------------------------===//
Eugene Zelenko21fadad2017-11-21 23:26:08 +000014
Douglas Gregor52537682009-03-19 00:18:19 +000015#include "clang/AST/NestedNameSpecifier.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/Decl.h"
Douglas Gregor7b26ff92011-02-24 02:36:08 +000018#include "clang/AST/DeclCXX.h"
Clement Courbet9d432e02018-12-04 07:59:57 +000019#include "clang/AST/DeclTemplate.h"
Douglas Gregor7de59662009-05-29 20:38:28 +000020#include "clang/AST/PrettyPrinter.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000021#include "clang/AST/TemplateName.h"
Douglas Gregor52537682009-03-19 00:18:19 +000022#include "clang/AST/Type.h"
Douglas Gregor869ad452011-02-24 17:54:50 +000023#include "clang/AST/TypeLoc.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000024#include "clang/Basic/LLVM.h"
25#include "clang/Basic/LangOptions.h"
26#include "clang/Basic/SourceLocation.h"
27#include "llvm/ADT/FoldingSet.h"
28#include "llvm/ADT/SmallVector.h"
29#include "llvm/Support/Casting.h"
30#include "llvm/Support/Compiler.h"
31#include "llvm/Support/ErrorHandling.h"
Douglas Gregor18353912009-03-19 03:51:16 +000032#include "llvm/Support/raw_ostream.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000033#include <algorithm>
Douglas Gregorf21eb492009-03-26 23:50:42 +000034#include <cassert>
Eugene Zelenko21fadad2017-11-21 23:26:08 +000035#include <cstdlib>
36#include <cstring>
Douglas Gregor18353912009-03-19 03:51:16 +000037
Douglas Gregor52537682009-03-19 00:18:19 +000038using namespace clang;
39
Douglas Gregorf21eb492009-03-26 23:50:42 +000040NestedNameSpecifier *
Jay Foad39c79802011-01-12 09:06:06 +000041NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
Douglas Gregorf21eb492009-03-26 23:50:42 +000042 const NestedNameSpecifier &Mockup) {
43 llvm::FoldingSetNodeID ID;
44 Mockup.Profile(ID);
Douglas Gregor52537682009-03-19 00:18:19 +000045
Craig Topper36250ad2014-05-12 05:36:57 +000046 void *InsertPos = nullptr;
Mike Stump11289f42009-09-09 15:08:12 +000047 NestedNameSpecifier *NNS
Douglas Gregorf21eb492009-03-26 23:50:42 +000048 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
49 if (!NNS) {
Benjamin Kramerc3f89252016-10-20 14:27:22 +000050 NNS =
51 new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
Douglas Gregorf21eb492009-03-26 23:50:42 +000052 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
53 }
Douglas Gregor52537682009-03-19 00:18:19 +000054
Douglas Gregorf21eb492009-03-26 23:50:42 +000055 return NNS;
Douglas Gregor52537682009-03-19 00:18:19 +000056}
Douglas Gregor18353912009-03-19 03:51:16 +000057
Douglas Gregorf21eb492009-03-26 23:50:42 +000058NestedNameSpecifier *
Jay Foad39c79802011-01-12 09:06:06 +000059NestedNameSpecifier::Create(const ASTContext &Context,
60 NestedNameSpecifier *Prefix, IdentifierInfo *II) {
Douglas Gregorf21eb492009-03-26 23:50:42 +000061 assert(II && "Identifier cannot be NULL");
Douglas Gregor308047d2009-09-09 00:23:06 +000062 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
Douglas Gregor18353912009-03-19 03:51:16 +000063
Douglas Gregorf21eb492009-03-26 23:50:42 +000064 NestedNameSpecifier Mockup;
Douglas Gregordce2b622009-04-01 00:28:59 +000065 Mockup.Prefix.setPointer(Prefix);
Douglas Gregor7b26ff92011-02-24 02:36:08 +000066 Mockup.Prefix.setInt(StoredIdentifier);
Douglas Gregordce2b622009-04-01 00:28:59 +000067 Mockup.Specifier = II;
Douglas Gregorf21eb492009-03-26 23:50:42 +000068 return FindOrInsert(Context, Mockup);
69}
Douglas Gregor18353912009-03-19 03:51:16 +000070
Douglas Gregorf21eb492009-03-26 23:50:42 +000071NestedNameSpecifier *
Jay Foad39c79802011-01-12 09:06:06 +000072NestedNameSpecifier::Create(const ASTContext &Context,
Dmitri Gribenkoaeeca772013-01-23 17:06:56 +000073 NestedNameSpecifier *Prefix,
74 const NamespaceDecl *NS) {
Douglas Gregorf21eb492009-03-26 23:50:42 +000075 assert(NS && "Namespace cannot be NULL");
Mike Stump11289f42009-09-09 15:08:12 +000076 assert((!Prefix ||
Craig Topper36250ad2014-05-12 05:36:57 +000077 (Prefix->getAsType() == nullptr &&
78 Prefix->getAsIdentifier() == nullptr)) &&
Douglas Gregorf21eb492009-03-26 23:50:42 +000079 "Broken nested name specifier");
80 NestedNameSpecifier Mockup;
Douglas Gregordce2b622009-04-01 00:28:59 +000081 Mockup.Prefix.setPointer(Prefix);
Nikola Smiljanic67860242014-09-26 00:28:20 +000082 Mockup.Prefix.setInt(StoredDecl);
Dmitri Gribenkoaeeca772013-01-23 17:06:56 +000083 Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
Douglas Gregorf21eb492009-03-26 23:50:42 +000084 return FindOrInsert(Context, Mockup);
85}
86
87NestedNameSpecifier *
Jay Foad39c79802011-01-12 09:06:06 +000088NestedNameSpecifier::Create(const ASTContext &Context,
Fangrui Song6907ce22018-07-30 19:24:48 +000089 NestedNameSpecifier *Prefix,
Douglas Gregor7b26ff92011-02-24 02:36:08 +000090 NamespaceAliasDecl *Alias) {
91 assert(Alias && "Namespace alias cannot be NULL");
92 assert((!Prefix ||
Craig Topper36250ad2014-05-12 05:36:57 +000093 (Prefix->getAsType() == nullptr &&
94 Prefix->getAsIdentifier() == nullptr)) &&
Douglas Gregor7b26ff92011-02-24 02:36:08 +000095 "Broken nested name specifier");
96 NestedNameSpecifier Mockup;
97 Mockup.Prefix.setPointer(Prefix);
Nikola Smiljanic67860242014-09-26 00:28:20 +000098 Mockup.Prefix.setInt(StoredDecl);
Douglas Gregor7b26ff92011-02-24 02:36:08 +000099 Mockup.Specifier = Alias;
100 return FindOrInsert(Context, Mockup);
101}
102
103NestedNameSpecifier *
104NestedNameSpecifier::Create(const ASTContext &Context,
Jay Foad39c79802011-01-12 09:06:06 +0000105 NestedNameSpecifier *Prefix,
John McCall424cec92011-01-19 06:33:43 +0000106 bool Template, const Type *T) {
Douglas Gregorf21eb492009-03-26 23:50:42 +0000107 assert(T && "Type cannot be NULL");
108 NestedNameSpecifier Mockup;
Douglas Gregordce2b622009-04-01 00:28:59 +0000109 Mockup.Prefix.setPointer(Prefix);
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000110 Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec);
John McCall424cec92011-01-19 06:33:43 +0000111 Mockup.Specifier = const_cast<Type*>(T);
Douglas Gregorf21eb492009-03-26 23:50:42 +0000112 return FindOrInsert(Context, Mockup);
113}
Douglas Gregor64792e02009-09-02 23:58:38 +0000114
115NestedNameSpecifier *
Jay Foad39c79802011-01-12 09:06:06 +0000116NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
Douglas Gregor64792e02009-09-02 23:58:38 +0000117 assert(II && "Identifier cannot be NULL");
118 NestedNameSpecifier Mockup;
Craig Topper36250ad2014-05-12 05:36:57 +0000119 Mockup.Prefix.setPointer(nullptr);
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000120 Mockup.Prefix.setInt(StoredIdentifier);
Douglas Gregor64792e02009-09-02 23:58:38 +0000121 Mockup.Specifier = II;
122 return FindOrInsert(Context, Mockup);
123}
124
Jay Foad39c79802011-01-12 09:06:06 +0000125NestedNameSpecifier *
126NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
Douglas Gregorf21eb492009-03-26 23:50:42 +0000127 if (!Context.GlobalNestedNameSpecifier)
Richard Smithbeb386a2012-08-15 01:41:43 +0000128 Context.GlobalNestedNameSpecifier =
Benjamin Kramerc3f89252016-10-20 14:27:22 +0000129 new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
Douglas Gregorf21eb492009-03-26 23:50:42 +0000130 return Context.GlobalNestedNameSpecifier;
131}
132
Nikola Smiljanic67860242014-09-26 00:28:20 +0000133NestedNameSpecifier *
134NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
135 CXXRecordDecl *RD) {
136 NestedNameSpecifier Mockup;
137 Mockup.Prefix.setPointer(nullptr);
138 Mockup.Prefix.setInt(StoredDecl);
139 Mockup.Specifier = RD;
140 return FindOrInsert(Context, Mockup);
141}
142
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000143NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
Craig Topper36250ad2014-05-12 05:36:57 +0000144 if (!Specifier)
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000145 return Global;
146
147 switch (Prefix.getInt()) {
148 case StoredIdentifier:
149 return Identifier;
150
Nikola Smiljanic67860242014-09-26 00:28:20 +0000151 case StoredDecl: {
152 NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
153 if (isa<CXXRecordDecl>(ND))
154 return Super;
155 return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias;
156 }
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000157
158 case StoredTypeSpec:
159 return TypeSpec;
160
161 case StoredTypeSpecWithTemplate:
162 return TypeSpecWithTemplate;
163 }
164
David Blaikiee4d798f2012-01-20 21:50:17 +0000165 llvm_unreachable("Invalid NNS Kind!");
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000166}
167
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000168/// Retrieve the namespace stored in this nested name specifier.
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000169NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
Yaron Kerene0bcdd42016-10-08 06:45:10 +0000170 if (Prefix.getInt() == StoredDecl)
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000171 return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
172
Craig Topper36250ad2014-05-12 05:36:57 +0000173 return nullptr;
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000174}
175
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000176/// Retrieve the namespace alias stored in this nested name specifier.
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000177NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
Yaron Kerene0bcdd42016-10-08 06:45:10 +0000178 if (Prefix.getInt() == StoredDecl)
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000179 return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
180
Craig Topper36250ad2014-05-12 05:36:57 +0000181 return nullptr;
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000182}
183
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000184/// Retrieve the record declaration stored in this nested name specifier.
Nikola Smiljanic67860242014-09-26 00:28:20 +0000185CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
Richard Smith5179eb72016-06-28 19:03:57 +0000186 switch (Prefix.getInt()) {
187 case StoredIdentifier:
188 return nullptr;
189
190 case StoredDecl:
Nikola Smiljanic67860242014-09-26 00:28:20 +0000191 return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
192
Richard Smith5179eb72016-06-28 19:03:57 +0000193 case StoredTypeSpec:
194 case StoredTypeSpecWithTemplate:
195 return getAsType()->getAsCXXRecordDecl();
196 }
197
198 llvm_unreachable("Invalid NNS Kind!");
Nikola Smiljanic67860242014-09-26 00:28:20 +0000199}
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000200
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000201/// Whether this nested name specifier refers to a dependent
Douglas Gregorf21eb492009-03-26 23:50:42 +0000202/// type or not.
203bool NestedNameSpecifier::isDependent() const {
204 switch (getKind()) {
205 case Identifier:
206 // Identifier specifiers always represent dependent types
207 return true;
208
209 case Namespace:
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000210 case NamespaceAlias:
Douglas Gregorf21eb492009-03-26 23:50:42 +0000211 case Global:
212 return false;
213
Nikola Smiljanic67860242014-09-26 00:28:20 +0000214 case Super: {
215 CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
216 for (const auto &Base : RD->bases())
217 if (Base.getType()->isDependentType())
218 return true;
219
220 return false;
221 }
222
Douglas Gregorf21eb492009-03-26 23:50:42 +0000223 case TypeSpec:
224 case TypeSpecWithTemplate:
225 return getAsType()->isDependentType();
Douglas Gregor18353912009-03-19 03:51:16 +0000226 }
Douglas Gregorf21eb492009-03-26 23:50:42 +0000227
David Blaikiee4d798f2012-01-20 21:50:17 +0000228 llvm_unreachable("Invalid NNS Kind!");
Douglas Gregorf21eb492009-03-26 23:50:42 +0000229}
230
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000231/// Whether this nested name specifier refers to a dependent
Douglas Gregor678d76c2011-07-01 01:22:09 +0000232/// type or not.
233bool NestedNameSpecifier::isInstantiationDependent() const {
234 switch (getKind()) {
235 case Identifier:
236 // Identifier specifiers always represent dependent types
237 return true;
Fangrui Song6907ce22018-07-30 19:24:48 +0000238
Douglas Gregor678d76c2011-07-01 01:22:09 +0000239 case Namespace:
240 case NamespaceAlias:
241 case Global:
Nikola Smiljanic67860242014-09-26 00:28:20 +0000242 case Super:
Douglas Gregor678d76c2011-07-01 01:22:09 +0000243 return false;
Nikola Smiljanic67860242014-09-26 00:28:20 +0000244
Douglas Gregor678d76c2011-07-01 01:22:09 +0000245 case TypeSpec:
246 case TypeSpecWithTemplate:
247 return getAsType()->isInstantiationDependentType();
248 }
David Blaikiee4d798f2012-01-20 21:50:17 +0000249
250 llvm_unreachable("Invalid NNS Kind!");
Douglas Gregor678d76c2011-07-01 01:22:09 +0000251}
252
Douglas Gregor506bd562010-12-13 22:49:22 +0000253bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
254 switch (getKind()) {
255 case Identifier:
256 return getPrefix() && getPrefix()->containsUnexpandedParameterPack();
257
258 case Namespace:
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000259 case NamespaceAlias:
Douglas Gregor506bd562010-12-13 22:49:22 +0000260 case Global:
Nikola Smiljanic67860242014-09-26 00:28:20 +0000261 case Super:
Douglas Gregor506bd562010-12-13 22:49:22 +0000262 return false;
263
264 case TypeSpec:
265 case TypeSpecWithTemplate:
266 return getAsType()->containsUnexpandedParameterPack();
267 }
268
David Blaikiee4d798f2012-01-20 21:50:17 +0000269 llvm_unreachable("Invalid NNS Kind!");
Douglas Gregor506bd562010-12-13 22:49:22 +0000270}
271
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000272/// Print this nested name specifier to the given output
Douglas Gregorf21eb492009-03-26 23:50:42 +0000273/// stream.
Clement Courbet9d432e02018-12-04 07:59:57 +0000274void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
275 bool ResolveTemplateArguments) const {
Douglas Gregordce2b622009-04-01 00:28:59 +0000276 if (getPrefix())
Douglas Gregor7de59662009-05-29 20:38:28 +0000277 getPrefix()->print(OS, Policy);
Douglas Gregorf21eb492009-03-26 23:50:42 +0000278
279 switch (getKind()) {
280 case Identifier:
281 OS << getAsIdentifier()->getName();
282 break;
283
284 case Namespace:
Douglas Gregor2e10cf92011-11-03 00:16:13 +0000285 if (getAsNamespace()->isAnonymousNamespace())
286 return;
Fangrui Song6907ce22018-07-30 19:24:48 +0000287
Douglas Gregor7b26ff92011-02-24 02:36:08 +0000288 OS << getAsNamespace()->getName();
289 break;
290
291 case NamespaceAlias:
292 OS << getAsNamespaceAlias()->getName();
Douglas Gregorf21eb492009-03-26 23:50:42 +0000293 break;
294
295 case Global:
296 break;
297
Nikola Smiljanic67860242014-09-26 00:28:20 +0000298 case Super:
299 OS << "__super";
300 break;
301
Douglas Gregorf21eb492009-03-26 23:50:42 +0000302 case TypeSpecWithTemplate:
303 OS << "template ";
304 // Fall through to print the type.
Galina Kistanovaf87496d2017-06-03 06:31:42 +0000305 LLVM_FALLTHROUGH;
Douglas Gregorf21eb492009-03-26 23:50:42 +0000306
307 case TypeSpec: {
Clement Courbet9d432e02018-12-04 07:59:57 +0000308 const auto *Record =
309 dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
310 if (ResolveTemplateArguments && Record) {
311 // Print the type trait with resolved template parameters.
312 Record->printName(OS);
313 printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
314 Policy);
315 break;
316 }
John McCall424cec92011-01-19 06:33:43 +0000317 const Type *T = getAsType();
Douglas Gregorf21eb492009-03-26 23:50:42 +0000318
Douglas Gregor7de59662009-05-29 20:38:28 +0000319 PrintingPolicy InnerPolicy(Policy);
John McCallb2e195a2009-09-05 06:31:47 +0000320 InnerPolicy.SuppressScope = true;
Mike Stump11289f42009-09-09 15:08:12 +0000321
Douglas Gregor053f6912009-08-26 00:04:55 +0000322 // Nested-name-specifiers are intended to contain minimally-qualified
Abramo Bagnara6150c882010-05-11 21:36:43 +0000323 // types. An actual ElaboratedType will not occur, since we'll store
Douglas Gregor053f6912009-08-26 00:04:55 +0000324 // just the type that is referred to in the nested-name-specifier (e.g.,
325 // a TypedefType, TagType, etc.). However, when we are dealing with
Mike Stump11289f42009-09-09 15:08:12 +0000326 // dependent template-id types (e.g., Outer<T>::template Inner<U>),
Douglas Gregor053f6912009-08-26 00:04:55 +0000327 // the type requires its own nested-name-specifier for uniqueness, so we
328 // suppress that nested-name-specifier during printing.
Abramo Bagnara6150c882010-05-11 21:36:43 +0000329 assert(!isa<ElaboratedType>(T) &&
330 "Elaborated type in nested-name-specifier");
Douglas Gregor053f6912009-08-26 00:04:55 +0000331 if (const TemplateSpecializationType *SpecType
332 = dyn_cast<TemplateSpecializationType>(T)) {
Mike Stump11289f42009-09-09 15:08:12 +0000333 // Print the template name without its corresponding
Douglas Gregor053f6912009-08-26 00:04:55 +0000334 // nested-name-specifier.
335 SpecType->getTemplateName().print(OS, InnerPolicy, true);
Mike Stump11289f42009-09-09 15:08:12 +0000336
Douglas Gregor053f6912009-08-26 00:04:55 +0000337 // Print the template argument list.
Serge Pavlov03e672c2017-11-28 16:14:14 +0000338 printTemplateArgumentList(OS, SpecType->template_arguments(),
339 InnerPolicy);
Douglas Gregor053f6912009-08-26 00:04:55 +0000340 } else {
341 // Print the type normally
Benjamin Kramer9170e912013-02-22 15:46:01 +0000342 QualType(T, 0).print(OS, InnerPolicy);
Douglas Gregor053f6912009-08-26 00:04:55 +0000343 }
Douglas Gregorf21eb492009-03-26 23:50:42 +0000344 break;
345 }
346 }
347
348 OS << "::";
349}
350
Stephen Kelly07dd5af2018-10-04 19:22:00 +0000351LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
352 dump(llvm::errs(), LO);
Yaron Keren015e6c82015-12-27 14:34:22 +0000353}
354
Stephen Kelly07dd5af2018-10-04 19:22:00 +0000355LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
356
357LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
Yaron Keren015e6c82015-12-27 14:34:22 +0000358 LangOptions LO;
Stephen Kelly07dd5af2018-10-04 19:22:00 +0000359 dump(OS, LO);
360}
361
362LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
363 const LangOptions &LO) const {
364 print(OS, PrintingPolicy(LO));
Douglas Gregor333489b2009-03-27 23:10:48 +0000365}
Douglas Gregor869ad452011-02-24 17:54:50 +0000366
Fangrui Song6907ce22018-07-30 19:24:48 +0000367unsigned
Douglas Gregor869ad452011-02-24 17:54:50 +0000368NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
369 assert(Qualifier && "Expected a non-NULL qualifier");
370
371 // Location of the trailing '::'.
372 unsigned Length = sizeof(unsigned);
373
374 switch (Qualifier->getKind()) {
375 case NestedNameSpecifier::Global:
376 // Nothing more to add.
377 break;
378
379 case NestedNameSpecifier::Identifier:
380 case NestedNameSpecifier::Namespace:
381 case NestedNameSpecifier::NamespaceAlias:
Nikola Smiljanic67860242014-09-26 00:28:20 +0000382 case NestedNameSpecifier::Super:
Douglas Gregor869ad452011-02-24 17:54:50 +0000383 // The location of the identifier or namespace name.
384 Length += sizeof(unsigned);
385 break;
386
387 case NestedNameSpecifier::TypeSpecWithTemplate:
388 case NestedNameSpecifier::TypeSpec:
389 // The "void*" that points at the TypeLoc data.
390 // Note: the 'template' keyword is part of the TypeLoc.
391 Length += sizeof(void *);
392 break;
393 }
394
395 return Length;
396}
397
Fangrui Song6907ce22018-07-30 19:24:48 +0000398unsigned
Douglas Gregor869ad452011-02-24 17:54:50 +0000399NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
400 unsigned Length = 0;
401 for (; Qualifier; Qualifier = Qualifier->getPrefix())
402 Length += getLocalDataLength(Qualifier);
403 return Length;
404}
405
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000406/// Load a (possibly unaligned) source location from a given address
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000407/// and offset.
408static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
409 unsigned Raw;
410 memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
411 return SourceLocation::getFromRawEncoding(Raw);
412}
Fangrui Song6907ce22018-07-30 19:24:48 +0000413
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000414/// Load a (possibly unaligned) pointer from a given address and
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000415/// offset.
416static void *LoadPointer(void *Data, unsigned Offset) {
417 void *Result;
418 memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
419 return Result;
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000420}
Douglas Gregor869ad452011-02-24 17:54:50 +0000421
Douglas Gregora9d87bc2011-02-25 00:36:19 +0000422SourceRange NestedNameSpecifierLoc::getSourceRange() const {
Douglas Gregor12441b32011-02-25 16:33:46 +0000423 if (!Qualifier)
424 return SourceRange();
Fangrui Song6907ce22018-07-30 19:24:48 +0000425
Douglas Gregor869ad452011-02-24 17:54:50 +0000426 NestedNameSpecifierLoc First = *this;
Douglas Gregor12441b32011-02-25 16:33:46 +0000427 while (NestedNameSpecifierLoc Prefix = First.getPrefix())
Douglas Gregor869ad452011-02-24 17:54:50 +0000428 First = Prefix;
Fangrui Song6907ce22018-07-30 19:24:48 +0000429
430 return SourceRange(First.getLocalSourceRange().getBegin(),
Douglas Gregor869ad452011-02-24 17:54:50 +0000431 getLocalSourceRange().getEnd());
432}
433
Douglas Gregora9d87bc2011-02-25 00:36:19 +0000434SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
Douglas Gregor12441b32011-02-25 16:33:46 +0000435 if (!Qualifier)
436 return SourceRange();
Fangrui Song6907ce22018-07-30 19:24:48 +0000437
Douglas Gregor869ad452011-02-24 17:54:50 +0000438 unsigned Offset = getDataLength(Qualifier->getPrefix());
439 switch (Qualifier->getKind()) {
440 case NestedNameSpecifier::Global:
441 return LoadSourceLocation(Data, Offset);
442
443 case NestedNameSpecifier::Identifier:
444 case NestedNameSpecifier::Namespace:
445 case NestedNameSpecifier::NamespaceAlias:
Nikola Smiljanic67860242014-09-26 00:28:20 +0000446 case NestedNameSpecifier::Super:
Douglas Gregor869ad452011-02-24 17:54:50 +0000447 return SourceRange(LoadSourceLocation(Data, Offset),
448 LoadSourceLocation(Data, Offset + sizeof(unsigned)));
449
450 case NestedNameSpecifier::TypeSpecWithTemplate:
451 case NestedNameSpecifier::TypeSpec: {
452 // The "void*" that points at the TypeLoc data.
453 // Note: the 'template' keyword is part of the TypeLoc.
454 void *TypeData = LoadPointer(Data, Offset);
455 TypeLoc TL(Qualifier->getAsType(), TypeData);
456 return SourceRange(TL.getBeginLoc(),
457 LoadSourceLocation(Data, Offset + sizeof(void*)));
458 }
459 }
David Blaikiee4d798f2012-01-20 21:50:17 +0000460
461 llvm_unreachable("Invalid NNS Kind!");
Douglas Gregor869ad452011-02-24 17:54:50 +0000462}
Douglas Gregora9d87bc2011-02-25 00:36:19 +0000463
464TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
Stephen Kelly54272e5b2019-01-07 21:57:30 +0000465 if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
466 Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate)
467 return TypeLoc();
Douglas Gregora9d87bc2011-02-25 00:36:19 +0000468
469 // The "void*" that points at the TypeLoc data.
470 unsigned Offset = getDataLength(Qualifier->getPrefix());
471 void *TypeData = LoadPointer(Data, Offset);
472 return TypeLoc(Qualifier->getAsType(), TypeData);
473}
Douglas Gregor9b272512011-02-28 23:58:31 +0000474
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000475static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
Douglas Gregor9b272512011-02-28 23:58:31 +0000476 unsigned &BufferCapacity) {
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000477 if (Start == End)
478 return;
Chandler Carruthb6708d82015-08-04 03:52:56 +0000479
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000480 if (BufferSize + (End - Start) > BufferCapacity) {
481 // Reallocate the buffer.
482 unsigned NewCapacity = std::max(
483 (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
484 (unsigned)(BufferSize + (End - Start)));
Serge Pavlov52525732018-02-21 02:02:39 +0000485 char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000486 if (BufferCapacity) {
487 memcpy(NewBuffer, Buffer, BufferSize);
488 free(Buffer);
Douglas Gregor9b272512011-02-28 23:58:31 +0000489 }
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000490 Buffer = NewBuffer;
491 BufferCapacity = NewCapacity;
Douglas Gregor9b272512011-02-28 23:58:31 +0000492 }
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000493
494 memcpy(Buffer + BufferSize, Start, End - Start);
495 BufferSize += End-Start;
496}
Fangrui Song6907ce22018-07-30 19:24:48 +0000497
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000498/// Save a source location to the given buffer.
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000499static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
500 unsigned &BufferSize, unsigned &BufferCapacity) {
501 unsigned Raw = Loc.getRawEncoding();
502 Append(reinterpret_cast<char *>(&Raw),
503 reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
504 Buffer, BufferSize, BufferCapacity);
505}
Fangrui Song6907ce22018-07-30 19:24:48 +0000506
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000507/// Save a pointer to the given buffer.
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000508static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
509 unsigned &BufferCapacity) {
510 Append(reinterpret_cast<char *>(&Ptr),
511 reinterpret_cast<char *>(&Ptr) + sizeof(void *),
512 Buffer, BufferSize, BufferCapacity);
Alexander Kornienkoab9db512015-06-22 23:07:51 +0000513}
Douglas Gregor9b272512011-02-28 23:58:31 +0000514
Douglas Gregor9b272512011-02-28 23:58:31 +0000515NestedNameSpecifierLocBuilder::
Fangrui Song6907ce22018-07-30 19:24:48 +0000516NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000517 : Representation(Other.Representation) {
Douglas Gregor9b272512011-02-28 23:58:31 +0000518 if (!Other.Buffer)
519 return;
Fangrui Song6907ce22018-07-30 19:24:48 +0000520
Douglas Gregor9b272512011-02-28 23:58:31 +0000521 if (Other.BufferCapacity == 0) {
522 // Shallow copy is okay.
523 Buffer = Other.Buffer;
524 BufferSize = Other.BufferSize;
525 return;
526 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000527
Douglas Gregor9b272512011-02-28 23:58:31 +0000528 // Deep copy
Serge Pavlov9f81d6a2014-07-16 18:18:13 +0000529 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
530 BufferCapacity);
Douglas Gregor9b272512011-02-28 23:58:31 +0000531}
532
533NestedNameSpecifierLocBuilder &
534NestedNameSpecifierLocBuilder::
535operator=(const NestedNameSpecifierLocBuilder &Other) {
536 Representation = Other.Representation;
Fangrui Song6907ce22018-07-30 19:24:48 +0000537
Douglas Gregor9b272512011-02-28 23:58:31 +0000538 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
539 // Re-use our storage.
540 BufferSize = Other.BufferSize;
541 memcpy(Buffer, Other.Buffer, BufferSize);
542 return *this;
543 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000544
Douglas Gregor9b272512011-02-28 23:58:31 +0000545 // Free our storage, if we have any.
546 if (BufferCapacity) {
547 free(Buffer);
548 BufferCapacity = 0;
549 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000550
Douglas Gregor9b272512011-02-28 23:58:31 +0000551 if (!Other.Buffer) {
552 // Empty.
Craig Topper36250ad2014-05-12 05:36:57 +0000553 Buffer = nullptr;
Douglas Gregor9b272512011-02-28 23:58:31 +0000554 BufferSize = 0;
555 return *this;
556 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000557
Douglas Gregor9b272512011-02-28 23:58:31 +0000558 if (Other.BufferCapacity == 0) {
559 // Shallow copy is okay.
560 Buffer = Other.Buffer;
561 BufferSize = Other.BufferSize;
562 return *this;
563 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000564
Douglas Gregor9b272512011-02-28 23:58:31 +0000565 // Deep copy.
Erik Pilkingtonc5871642018-09-10 21:54:04 +0000566 BufferSize = 0;
Serge Pavlov9f81d6a2014-07-16 18:18:13 +0000567 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
568 BufferCapacity);
Douglas Gregor9b272512011-02-28 23:58:31 +0000569 return *this;
570}
571
Fangrui Song6907ce22018-07-30 19:24:48 +0000572void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
573 SourceLocation TemplateKWLoc,
574 TypeLoc TL,
Douglas Gregor9b272512011-02-28 23:58:31 +0000575 SourceLocation ColonColonLoc) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000576 Representation = NestedNameSpecifier::Create(Context, Representation,
577 TemplateKWLoc.isValid(),
Douglas Gregor9b272512011-02-28 23:58:31 +0000578 TL.getTypePtr());
Fangrui Song6907ce22018-07-30 19:24:48 +0000579
Douglas Gregor9b272512011-02-28 23:58:31 +0000580 // Push source-location info into the buffer.
581 SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
582 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
583}
584
Fangrui Song6907ce22018-07-30 19:24:48 +0000585void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
Douglas Gregor9b272512011-02-28 23:58:31 +0000586 IdentifierInfo *Identifier,
Fangrui Song6907ce22018-07-30 19:24:48 +0000587 SourceLocation IdentifierLoc,
Douglas Gregor9b272512011-02-28 23:58:31 +0000588 SourceLocation ColonColonLoc) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000589 Representation = NestedNameSpecifier::Create(Context, Representation,
Douglas Gregor9b272512011-02-28 23:58:31 +0000590 Identifier);
Fangrui Song6907ce22018-07-30 19:24:48 +0000591
Douglas Gregor9b272512011-02-28 23:58:31 +0000592 // Push source-location info into the buffer.
593 SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
594 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
595}
596
Fangrui Song6907ce22018-07-30 19:24:48 +0000597void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
Douglas Gregor9b272512011-02-28 23:58:31 +0000598 NamespaceDecl *Namespace,
Fangrui Song6907ce22018-07-30 19:24:48 +0000599 SourceLocation NamespaceLoc,
Douglas Gregor9b272512011-02-28 23:58:31 +0000600 SourceLocation ColonColonLoc) {
Fangrui Song6907ce22018-07-30 19:24:48 +0000601 Representation = NestedNameSpecifier::Create(Context, Representation,
Douglas Gregor9b272512011-02-28 23:58:31 +0000602 Namespace);
Fangrui Song6907ce22018-07-30 19:24:48 +0000603
Douglas Gregor9b272512011-02-28 23:58:31 +0000604 // Push source-location info into the buffer.
605 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
606 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
607}
608
609void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
610 NamespaceAliasDecl *Alias,
Fangrui Song6907ce22018-07-30 19:24:48 +0000611 SourceLocation AliasLoc,
Douglas Gregor9b272512011-02-28 23:58:31 +0000612 SourceLocation ColonColonLoc) {
613 Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
Fangrui Song6907ce22018-07-30 19:24:48 +0000614
Douglas Gregor9b272512011-02-28 23:58:31 +0000615 // Push source-location info into the buffer.
616 SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
617 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
618}
619
Fangrui Song6907ce22018-07-30 19:24:48 +0000620void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
Douglas Gregor9b272512011-02-28 23:58:31 +0000621 SourceLocation ColonColonLoc) {
622 assert(!Representation && "Already have a nested-name-specifier!?");
623 Representation = NestedNameSpecifier::GlobalSpecifier(Context);
Fangrui Song6907ce22018-07-30 19:24:48 +0000624
Douglas Gregor9b272512011-02-28 23:58:31 +0000625 // Push source-location info into the buffer.
626 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
627}
628
Nikola Smiljanic67860242014-09-26 00:28:20 +0000629void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
630 CXXRecordDecl *RD,
631 SourceLocation SuperLoc,
632 SourceLocation ColonColonLoc) {
633 Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
634
635 // Push source-location info into the buffer.
636 SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
637 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
638}
639
Fangrui Song6907ce22018-07-30 19:24:48 +0000640void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
641 NestedNameSpecifier *Qualifier,
Douglas Gregor9b272512011-02-28 23:58:31 +0000642 SourceRange R) {
643 Representation = Qualifier;
Fangrui Song6907ce22018-07-30 19:24:48 +0000644
645 // Construct bogus (but well-formed) source information for the
Douglas Gregor9b272512011-02-28 23:58:31 +0000646 // nested-name-specifier.
647 BufferSize = 0;
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000648 SmallVector<NestedNameSpecifier *, 4> Stack;
Douglas Gregor9b272512011-02-28 23:58:31 +0000649 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
650 Stack.push_back(NNS);
651 while (!Stack.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000652 NestedNameSpecifier *NNS = Stack.pop_back_val();
Douglas Gregor9b272512011-02-28 23:58:31 +0000653 switch (NNS->getKind()) {
654 case NestedNameSpecifier::Identifier:
655 case NestedNameSpecifier::Namespace:
656 case NestedNameSpecifier::NamespaceAlias:
657 SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
658 break;
Fangrui Song6907ce22018-07-30 19:24:48 +0000659
Douglas Gregor9b272512011-02-28 23:58:31 +0000660 case NestedNameSpecifier::TypeSpec:
661 case NestedNameSpecifier::TypeSpecWithTemplate: {
662 TypeSourceInfo *TSInfo
663 = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
664 R.getBegin());
Fangrui Song6907ce22018-07-30 19:24:48 +0000665 SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
Douglas Gregor9b272512011-02-28 23:58:31 +0000666 BufferCapacity);
667 break;
668 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000669
Douglas Gregor9b272512011-02-28 23:58:31 +0000670 case NestedNameSpecifier::Global:
Nikola Smiljanic67860242014-09-26 00:28:20 +0000671 case NestedNameSpecifier::Super:
Douglas Gregor9b272512011-02-28 23:58:31 +0000672 break;
673 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000674
Douglas Gregor9b272512011-02-28 23:58:31 +0000675 // Save the location of the '::'.
Fangrui Song6907ce22018-07-30 19:24:48 +0000676 SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(),
Douglas Gregor9b272512011-02-28 23:58:31 +0000677 Buffer, BufferSize, BufferCapacity);
678 }
679}
680
681void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
682 if (BufferCapacity)
683 free(Buffer);
684
685 if (!Other) {
Craig Topper36250ad2014-05-12 05:36:57 +0000686 Representation = nullptr;
Douglas Gregor9b272512011-02-28 23:58:31 +0000687 BufferSize = 0;
688 return;
689 }
Fangrui Song6907ce22018-07-30 19:24:48 +0000690
691 // Rather than copying the data (which is wasteful), "adopt" the
Douglas Gregor9b272512011-02-28 23:58:31 +0000692 // pointer (which points into the ASTContext) but set the capacity to zero to
693 // indicate that we don't own it.
694 Representation = Other.getNestedNameSpecifier();
695 Buffer = static_cast<char *>(Other.getOpaqueData());
696 BufferSize = Other.getDataLength();
697 BufferCapacity = 0;
698}
699
Fangrui Song6907ce22018-07-30 19:24:48 +0000700NestedNameSpecifierLoc
Douglas Gregor9b272512011-02-28 23:58:31 +0000701NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
702 if (!Representation)
703 return NestedNameSpecifierLoc();
Fangrui Song6907ce22018-07-30 19:24:48 +0000704
Douglas Gregor9b272512011-02-28 23:58:31 +0000705 // If we adopted our data pointer from elsewhere in the AST context, there's
706 // no need to copy the memory.
707 if (BufferCapacity == 0)
708 return NestedNameSpecifierLoc(Representation, Buffer);
Fangrui Song6907ce22018-07-30 19:24:48 +0000709
Douglas Gregor9b272512011-02-28 23:58:31 +0000710 // FIXME: After copying the source-location information, should we free
711 // our (temporary) buffer and adopt the ASTContext-allocated memory?
712 // Doing so would optimize repeated calls to getWithLocInContext().
Benjamin Kramerc3f89252016-10-20 14:27:22 +0000713 void *Mem = Context.Allocate(BufferSize, alignof(void *));
Douglas Gregor9b272512011-02-28 23:58:31 +0000714 memcpy(Mem, Buffer, BufferSize);
715 return NestedNameSpecifierLoc(Representation, Mem);
716}