Coverage Report

Created: 2020-02-25 14:32

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/NestedNameSpecifier.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
//  This file defines the NestedNameSpecifier class, which represents
10
//  a C++ nested-name-specifier.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/NestedNameSpecifier.h"
15
#include "clang/AST/ASTContext.h"
16
#include "clang/AST/Decl.h"
17
#include "clang/AST/DeclCXX.h"
18
#include "clang/AST/DeclTemplate.h"
19
#include "clang/AST/PrettyPrinter.h"
20
#include "clang/AST/TemplateName.h"
21
#include "clang/AST/Type.h"
22
#include "clang/AST/TypeLoc.h"
23
#include "clang/Basic/LLVM.h"
24
#include "clang/Basic/LangOptions.h"
25
#include "clang/Basic/SourceLocation.h"
26
#include "llvm/ADT/FoldingSet.h"
27
#include "llvm/ADT/SmallVector.h"
28
#include "llvm/Support/Casting.h"
29
#include "llvm/Support/Compiler.h"
30
#include "llvm/Support/ErrorHandling.h"
31
#include "llvm/Support/raw_ostream.h"
32
#include <algorithm>
33
#include <cassert>
34
#include <cstdlib>
35
#include <cstring>
36
37
using namespace clang;
38
39
NestedNameSpecifier *
40
NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
41
11.5M
                                  const NestedNameSpecifier &Mockup) {
42
11.5M
  llvm::FoldingSetNodeID ID;
43
11.5M
  Mockup.Profile(ID);
44
11.5M
45
11.5M
  void *InsertPos = nullptr;
46
11.5M
  NestedNameSpecifier *NNS
47
11.5M
    = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
48
11.5M
  if (!NNS) {
49
4.85M
    NNS =
50
4.85M
        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
51
4.85M
    Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos);
52
4.85M
  }
53
11.5M
54
11.5M
  return NNS;
55
11.5M
}
56
57
NestedNameSpecifier *
58
NestedNameSpecifier::Create(const ASTContext &Context,
59
110k
                            NestedNameSpecifier *Prefix, IdentifierInfo *II) {
60
110k
  assert(II && "Identifier cannot be NULL");
61
110k
  assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
62
110k
63
110k
  NestedNameSpecifier Mockup;
64
110k
  Mockup.Prefix.setPointer(Prefix);
65
110k
  Mockup.Prefix.setInt(StoredIdentifier);
66
110k
  Mockup.Specifier = II;
67
110k
  return FindOrInsert(Context, Mockup);
68
110k
}
69
70
NestedNameSpecifier *
71
NestedNameSpecifier::Create(const ASTContext &Context,
72
                            NestedNameSpecifier *Prefix,
73
1.46M
                            const NamespaceDecl *NS) {
74
1.46M
  assert(NS && "Namespace cannot be NULL");
75
1.46M
  assert((!Prefix ||
76
1.46M
          (Prefix->getAsType() == nullptr &&
77
1.46M
           Prefix->getAsIdentifier() == nullptr)) &&
78
1.46M
         "Broken nested name specifier");
79
1.46M
  NestedNameSpecifier Mockup;
80
1.46M
  Mockup.Prefix.setPointer(Prefix);
81
1.46M
  Mockup.Prefix.setInt(StoredDecl);
82
1.46M
  Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
83
1.46M
  return FindOrInsert(Context, Mockup);
84
1.46M
}
85
86
NestedNameSpecifier *
87
NestedNameSpecifier::Create(const ASTContext &Context,
88
                            NestedNameSpecifier *Prefix,
89
223
                            NamespaceAliasDecl *Alias) {
90
223
  assert(Alias && "Namespace alias cannot be NULL");
91
223
  assert((!Prefix ||
92
223
          (Prefix->getAsType() == nullptr &&
93
223
           Prefix->getAsIdentifier() == nullptr)) &&
94
223
         "Broken nested name specifier");
95
223
  NestedNameSpecifier Mockup;
96
223
  Mockup.Prefix.setPointer(Prefix);
97
223
  Mockup.Prefix.setInt(StoredDecl);
98
223
  Mockup.Specifier = Alias;
99
223
  return FindOrInsert(Context, Mockup);
100
223
}
101
102
NestedNameSpecifier *
103
NestedNameSpecifier::Create(const ASTContext &Context,
104
                            NestedNameSpecifier *Prefix,
105
9.96M
                            bool Template, const Type *T) {
106
9.96M
  assert(T && "Type cannot be NULL");
107
9.96M
  NestedNameSpecifier Mockup;
108
9.96M
  Mockup.Prefix.setPointer(Prefix);
109
9.96M
  Mockup.Prefix.setInt(Template? 
StoredTypeSpecWithTemplate2.35k
:
StoredTypeSpec9.96M
);
110
9.96M
  Mockup.Specifier = const_cast<Type*>(T);
111
9.96M
  return FindOrInsert(Context, Mockup);
112
9.96M
}
113
114
NestedNameSpecifier *
115
0
NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) {
116
0
  assert(II && "Identifier cannot be NULL");
117
0
  NestedNameSpecifier Mockup;
118
0
  Mockup.Prefix.setPointer(nullptr);
119
0
  Mockup.Prefix.setInt(StoredIdentifier);
120
0
  Mockup.Specifier = II;
121
0
  return FindOrInsert(Context, Mockup);
122
0
}
123
124
NestedNameSpecifier *
125
217k
NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
126
217k
  if (!Context.GlobalNestedNameSpecifier)
127
2.77k
    Context.GlobalNestedNameSpecifier =
128
2.77k
        new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
129
217k
  return Context.GlobalNestedNameSpecifier;
130
217k
}
131
132
NestedNameSpecifier *
133
NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
134
58
                                    CXXRecordDecl *RD) {
135
58
  NestedNameSpecifier Mockup;
136
58
  Mockup.Prefix.setPointer(nullptr);
137
58
  Mockup.Prefix.setInt(StoredDecl);
138
58
  Mockup.Specifier = RD;
139
58
  return FindOrInsert(Context, Mockup);
140
58
}
141
142
144M
NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
143
144M
  if (!Specifier)
144
5.94M
    return Global;
145
138M
146
138M
  switch (Prefix.getInt()) {
147
371k
  case StoredIdentifier:
148
371k
    return Identifier;
149
0
150
30.3M
  case StoredDecl: {
151
30.3M
    NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
152
30.3M
    if (isa<CXXRecordDecl>(ND))
153
1.50k
      return Super;
154
30.3M
    return isa<NamespaceDecl>(ND) ? 
Namespace30.3M
:
NamespaceAlias6.22k
;
155
30.3M
  }
156
30.3M
157
107M
  case StoredTypeSpec:
158
107M
    return TypeSpec;
159
30.3M
160
30.3M
  case StoredTypeSpecWithTemplate:
161
22.6k
    return TypeSpecWithTemplate;
162
0
  }
163
0
164
0
  llvm_unreachable("Invalid NNS Kind!");
165
0
}
166
167
/// Retrieve the namespace stored in this nested name specifier.
168
2.63M
NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
169
2.63M
  if (Prefix.getInt() == StoredDecl)
170
2.63M
    return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier));
171
596
172
596
  return nullptr;
173
596
}
174
175
/// Retrieve the namespace alias stored in this nested name specifier.
176
1.33k
NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
177
1.33k
  if (Prefix.getInt() == StoredDecl)
178
784
    return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier));
179
554
180
554
  return nullptr;
181
554
}
182
183
/// Retrieve the record declaration stored in this nested name specifier.
184
79.6k
CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
185
79.6k
  switch (Prefix.getInt()) {
186
0
  case StoredIdentifier:
187
0
    return nullptr;
188
0
189
119
  case StoredDecl:
190
119
    return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier));
191
0
192
79.4k
  case StoredTypeSpec:
193
79.4k
  case StoredTypeSpecWithTemplate:
194
79.4k
    return getAsType()->getAsCXXRecordDecl();
195
0
  }
196
0
197
0
  llvm_unreachable("Invalid NNS Kind!");
198
0
}
199
200
/// Whether this nested name specifier refers to a dependent
201
/// type or not.
202
20.4M
bool NestedNameSpecifier::isDependent() const {
203
20.4M
  switch (getKind()) {
204
121k
  case Identifier:
205
121k
    // Identifier specifiers always represent dependent types
206
121k
    return true;
207
0
208
3.19M
  case Namespace:
209
3.19M
  case NamespaceAlias:
210
3.19M
  case Global:
211
3.19M
    return false;
212
3.19M
213
3.19M
  case Super: {
214
278
    CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
215
278
    for (const auto &Base : RD->bases())
216
283
      if (Base.getType()->isDependentType())
217
170
        return true;
218
278
219
278
    
return false108
;
220
278
  }
221
278
222
17.1M
  case TypeSpec:
223
17.1M
  case TypeSpecWithTemplate:
224
17.1M
    return getAsType()->isDependentType();
225
0
  }
226
0
227
0
  llvm_unreachable("Invalid NNS Kind!");
228
0
}
229
230
/// Whether this nested name specifier refers to a dependent
231
/// type or not.
232
3.43M
bool NestedNameSpecifier::isInstantiationDependent() const {
233
3.43M
  switch (getKind()) {
234
8.80k
  case Identifier:
235
8.80k
    // Identifier specifiers always represent dependent types
236
8.80k
    return true;
237
0
238
707k
  case Namespace:
239
707k
  case NamespaceAlias:
240
707k
  case Global:
241
707k
  case Super:
242
707k
    return false;
243
707k
244
2.72M
  case TypeSpec:
245
2.72M
  case TypeSpecWithTemplate:
246
2.72M
    return getAsType()->isInstantiationDependentType();
247
0
  }
248
0
249
0
  llvm_unreachable("Invalid NNS Kind!");
250
0
}
251
252
5.35M
bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
253
5.35M
  switch (getKind()) {
254
16.4k
  case Identifier:
255
16.4k
    return getPrefix() && 
getPrefix()->containsUnexpandedParameterPack()16.3k
;
256
0
257
826k
  case Namespace:
258
826k
  case NamespaceAlias:
259
826k
  case Global:
260
826k
  case Super:
261
826k
    return false;
262
826k
263
4.50M
  case TypeSpec:
264
4.50M
  case TypeSpecWithTemplate:
265
4.50M
    return getAsType()->containsUnexpandedParameterPack();
266
0
  }
267
0
268
0
  llvm_unreachable("Invalid NNS Kind!");
269
0
}
270
271
/// Print this nested name specifier to the given output
272
/// stream.
273
void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
274
105k
                                bool ResolveTemplateArguments) const {
275
105k
  if (getPrefix())
276
26.4k
    getPrefix()->print(OS, Policy);
277
105k
278
105k
  switch (getKind()) {
279
17
  case Identifier:
280
17
    OS << getAsIdentifier()->getName();
281
17
    break;
282
0
283
28.4k
  case Namespace:
284
28.4k
    if (getAsNamespace()->isAnonymousNamespace())
285
0
      return;
286
28.4k
287
28.4k
    OS << getAsNamespace()->getName();
288
28.4k
    break;
289
28.4k
290
28.4k
  case NamespaceAlias:
291
16
    OS << getAsNamespaceAlias()->getName();
292
16
    break;
293
28.4k
294
28.4k
  case Global:
295
374
    break;
296
28.4k
297
28.4k
  case Super:
298
16
    OS << "__super";
299
16
    break;
300
28.4k
301
28.4k
  case TypeSpecWithTemplate:
302
0
    OS << "template ";
303
0
    // Fall through to print the type.
304
0
    LLVM_FALLTHROUGH;
305
0
306
76.3k
  case TypeSpec: {
307
76.3k
    const auto *Record =
308
76.3k
            dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl());
309
76.3k
    if (ResolveTemplateArguments && 
Record70.8k
) {
310
70.8k
        // Print the type trait with resolved template parameters.
311
70.8k
        Record->printName(OS);
312
70.8k
        printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(),
313
70.8k
                                  Policy);
314
70.8k
        break;
315
70.8k
    }
316
5.58k
    const Type *T = getAsType();
317
5.58k
318
5.58k
    PrintingPolicy InnerPolicy(Policy);
319
5.58k
    InnerPolicy.SuppressScope = true;
320
5.58k
321
5.58k
    // Nested-name-specifiers are intended to contain minimally-qualified
322
5.58k
    // types. An actual ElaboratedType will not occur, since we'll store
323
5.58k
    // just the type that is referred to in the nested-name-specifier (e.g.,
324
5.58k
    // a TypedefType, TagType, etc.). However, when we are dealing with
325
5.58k
    // dependent template-id types (e.g., Outer<T>::template Inner<U>),
326
5.58k
    // the type requires its own nested-name-specifier for uniqueness, so we
327
5.58k
    // suppress that nested-name-specifier during printing.
328
5.58k
    assert(!isa<ElaboratedType>(T) &&
329
5.58k
           "Elaborated type in nested-name-specifier");
330
5.58k
    if (const TemplateSpecializationType *SpecType
331
2.51k
          = dyn_cast<TemplateSpecializationType>(T)) {
332
2.51k
      // Print the template name without its corresponding
333
2.51k
      // nested-name-specifier.
334
2.51k
      SpecType->getTemplateName().print(OS, InnerPolicy, true);
335
2.51k
336
2.51k
      // Print the template argument list.
337
2.51k
      printTemplateArgumentList(OS, SpecType->template_arguments(),
338
2.51k
                                InnerPolicy);
339
3.07k
    } else {
340
3.07k
      // Print the type normally
341
3.07k
      QualType(T, 0).print(OS, InnerPolicy);
342
3.07k
    }
343
5.58k
    break;
344
5.58k
  }
345
105k
  }
346
105k
347
105k
  OS << "::";
348
105k
}
349
350
0
LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
351
0
  dump(llvm::errs(), LO);
352
0
}
353
354
0
LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); }
355
356
0
LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
357
0
  LangOptions LO;
358
0
  dump(OS, LO);
359
0
}
360
361
LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
362
0
                                                const LangOptions &LO) const {
363
0
  print(OS, PrintingPolicy(LO));
364
0
}
365
366
unsigned
367
19.1M
NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
368
19.1M
  assert(Qualifier && "Expected a non-NULL qualifier");
369
19.1M
370
19.1M
  // Location of the trailing '::'.
371
19.1M
  unsigned Length = sizeof(unsigned);
372
19.1M
373
19.1M
  switch (Qualifier->getKind()) {
374
210k
  case NestedNameSpecifier::Global:
375
210k
    // Nothing more to add.
376
210k
    break;
377
0
378
9.21M
  case NestedNameSpecifier::Identifier:
379
9.21M
  case NestedNameSpecifier::Namespace:
380
9.21M
  case NestedNameSpecifier::NamespaceAlias:
381
9.21M
  case NestedNameSpecifier::Super:
382
9.21M
    // The location of the identifier or namespace name.
383
9.21M
    Length += sizeof(unsigned);
384
9.21M
    break;
385
9.21M
386
9.76M
  case NestedNameSpecifier::TypeSpecWithTemplate:
387
9.76M
  case NestedNameSpecifier::TypeSpec:
388
9.76M
    // The "void*" that points at the TypeLoc data.
389
9.76M
    // Note: the 'template' keyword is part of the TypeLoc.
390
9.76M
    Length += sizeof(void *);
391
9.76M
    break;
392
19.1M
  }
393
19.1M
394
19.1M
  return Length;
395
19.1M
}
396
397
unsigned
398
89.3M
NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
399
89.3M
  unsigned Length = 0;
400
108M
  for (; Qualifier; 
Qualifier = Qualifier->getPrefix()19.1M
)
401
19.1M
    Length += getLocalDataLength(Qualifier);
402
89.3M
  return Length;
403
89.3M
}
404
405
/// Load a (possibly unaligned) source location from a given address
406
/// and offset.
407
89.2M
static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
408
89.2M
  unsigned Raw;
409
89.2M
  memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned));
410
89.2M
  return SourceLocation::getFromRawEncoding(Raw);
411
89.2M
}
412
413
/// Load a (possibly unaligned) pointer from a given address and
414
/// offset.
415
60.2M
static void *LoadPointer(void *Data, unsigned Offset) {
416
60.2M
  void *Result;
417
60.2M
  memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*));
418
60.2M
  return Result;
419
60.2M
}
420
421
34.1M
SourceRange NestedNameSpecifierLoc::getSourceRange() const {
422
34.1M
  if (!Qualifier)
423
152k
    return SourceRange();
424
33.9M
425
33.9M
  NestedNameSpecifierLoc First = *this;
426
40.0M
  while (NestedNameSpecifierLoc Prefix = First.getPrefix())
427
6.13M
    First = Prefix;
428
33.9M
429
33.9M
  return SourceRange(First.getLocalSourceRange().getBegin(),
430
33.9M
                     getLocalSourceRange().getEnd());
431
33.9M
}
432
433
74.5M
SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
434
74.5M
  if (!Qualifier)
435
0
    return SourceRange();
436
74.5M
437
74.5M
  unsigned Offset = getDataLength(Qualifier->getPrefix());
438
74.5M
  switch (Qualifier->getKind()) {
439
3.65M
  case NestedNameSpecifier::Global:
440
3.65M
    return LoadSourceLocation(Data, Offset);
441
0
442
14.7M
  case NestedNameSpecifier::Identifier:
443
14.7M
  case NestedNameSpecifier::Namespace:
444
14.7M
  case NestedNameSpecifier::NamespaceAlias:
445
14.7M
  case NestedNameSpecifier::Super:
446
14.7M
    return SourceRange(LoadSourceLocation(Data, Offset),
447
14.7M
                       LoadSourceLocation(Data, Offset + sizeof(unsigned)));
448
14.7M
449
56.0M
  case NestedNameSpecifier::TypeSpecWithTemplate:
450
56.0M
  case NestedNameSpecifier::TypeSpec: {
451
56.0M
    // The "void*" that points at the TypeLoc data.
452
56.0M
    // Note: the 'template' keyword is part of the TypeLoc.
453
56.0M
    void *TypeData = LoadPointer(Data, Offset);
454
56.0M
    TypeLoc TL(Qualifier->getAsType(), TypeData);
455
56.0M
    return SourceRange(TL.getBeginLoc(),
456
56.0M
                       LoadSourceLocation(Data, Offset + sizeof(void*)));
457
0
  }
458
0
  }
459
0
460
0
  llvm_unreachable("Invalid NNS Kind!");
461
0
}
462
463
4.14M
TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
464
4.14M
  if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec &&
465
4.14M
      
Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate2.17k
)
466
0
    return TypeLoc();
467
4.14M
468
4.14M
  // The "void*" that points at the TypeLoc data.
469
4.14M
  unsigned Offset = getDataLength(Qualifier->getPrefix());
470
4.14M
  void *TypeData = LoadPointer(Data, Offset);
471
4.14M
  return TypeLoc(Qualifier->getAsType(), TypeData);
472
4.14M
}
473
474
static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
475
13.6M
                   unsigned &BufferCapacity) {
476
13.6M
  if (Start == End)
477
12
    return;
478
13.6M
479
13.6M
  if (BufferSize + (End - Start) > BufferCapacity) {
480
6.53M
    // Reallocate the buffer.
481
6.53M
    unsigned NewCapacity = std::max(
482
6.53M
        (unsigned)(BufferCapacity ? 
BufferCapacity * 2263k
:
sizeof(void *) * 26.27M
),
483
6.53M
        (unsigned)(BufferSize + (End - Start)));
484
6.53M
    char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity));
485
6.53M
    if (Buffer) {
486
263k
      memcpy(NewBuffer, Buffer, BufferSize);
487
263k
      if (BufferCapacity)
488
263k
        free(Buffer);
489
263k
    }
490
6.53M
    Buffer = NewBuffer;
491
6.53M
    BufferCapacity = NewCapacity;
492
6.53M
  }
493
13.6M
  assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");
494
13.6M
  memcpy(Buffer + BufferSize, Start, End - Start);
495
13.6M
  BufferSize += End - Start;
496
13.6M
}
497
498
/// Save a source location to the given buffer.
499
static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
500
8.15M
                               unsigned &BufferSize, unsigned &BufferCapacity) {
501
8.15M
  unsigned Raw = Loc.getRawEncoding();
502
8.15M
  Append(reinterpret_cast<char *>(&Raw),
503
8.15M
         reinterpret_cast<char *>(&Raw) + sizeof(unsigned),
504
8.15M
         Buffer, BufferSize, BufferCapacity);
505
8.15M
}
506
507
/// Save a pointer to the given buffer.
508
static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
509
5.23M
                        unsigned &BufferCapacity) {
510
5.23M
  Append(reinterpret_cast<char *>(&Ptr),
511
5.23M
         reinterpret_cast<char *>(&Ptr) + sizeof(void *),
512
5.23M
         Buffer, BufferSize, BufferCapacity);
513
5.23M
}
514
515
NestedNameSpecifierLocBuilder::
516
NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
517
8.81M
    : Representation(Other.Representation) {
518
8.81M
  if (!Other.Buffer)
519
8.77M
    return;
520
37.4k
521
37.4k
  if (Other.BufferCapacity == 0) {
522
28.8k
    // Shallow copy is okay.
523
28.8k
    Buffer = Other.Buffer;
524
28.8k
    BufferSize = Other.BufferSize;
525
28.8k
    return;
526
28.8k
  }
527
8.60k
528
8.60k
  // Deep copy
529
8.60k
  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
530
8.60k
         BufferCapacity);
531
8.60k
}
532
533
NestedNameSpecifierLocBuilder &
534
NestedNameSpecifierLocBuilder::
535
1.61M
operator=(const NestedNameSpecifierLocBuilder &Other) {
536
1.61M
  Representation = Other.Representation;
537
1.61M
538
1.61M
  if (Buffer && 
Other.Buffer35
&&
BufferCapacity >= Other.BufferSize35
) {
539
22
    // Re-use our storage.
540
22
    BufferSize = Other.BufferSize;
541
22
    memcpy(Buffer, Other.Buffer, BufferSize);
542
22
    return *this;
543
22
  }
544
1.61M
545
1.61M
  // Free our storage, if we have any.
546
1.61M
  if (BufferCapacity) {
547
0
    free(Buffer);
548
0
    BufferCapacity = 0;
549
0
  }
550
1.61M
551
1.61M
  if (!Other.Buffer) {
552
1.27M
    // Empty.
553
1.27M
    Buffer = nullptr;
554
1.27M
    BufferSize = 0;
555
1.27M
    return *this;
556
1.27M
  }
557
345k
558
345k
  if (Other.BufferCapacity == 0) {
559
132k
    // Shallow copy is okay.
560
132k
    Buffer = Other.Buffer;
561
132k
    BufferSize = Other.BufferSize;
562
132k
    return *this;
563
132k
  }
564
212k
565
212k
  // Deep copy.
566
212k
  BufferSize = 0;
567
212k
  Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize,
568
212k
         BufferCapacity);
569
212k
  return *this;
570
212k
}
571
572
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
573
                                           SourceLocation TemplateKWLoc,
574
                                           TypeLoc TL,
575
4.90M
                                           SourceLocation ColonColonLoc) {
576
4.90M
  Representation = NestedNameSpecifier::Create(Context, Representation,
577
4.90M
                                               TemplateKWLoc.isValid(),
578
4.90M
                                               TL.getTypePtr());
579
4.90M
580
4.90M
  // Push source-location info into the buffer.
581
4.90M
  SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
582
4.90M
  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
583
4.90M
}
584
585
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
586
                                           IdentifierInfo *Identifier,
587
                                           SourceLocation IdentifierLoc,
588
17.8k
                                           SourceLocation ColonColonLoc) {
589
17.8k
  Representation = NestedNameSpecifier::Create(Context, Representation,
590
17.8k
                                               Identifier);
591
17.8k
592
17.8k
  // Push source-location info into the buffer.
593
17.8k
  SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity);
594
17.8k
  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
595
17.8k
}
596
597
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
598
                                           NamespaceDecl *Namespace,
599
                                           SourceLocation NamespaceLoc,
600
1.33M
                                           SourceLocation ColonColonLoc) {
601
1.33M
  Representation = NestedNameSpecifier::Create(Context, Representation,
602
1.33M
                                               Namespace);
603
1.33M
604
1.33M
  // Push source-location info into the buffer.
605
1.33M
  SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity);
606
1.33M
  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
607
1.33M
}
608
609
void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
610
                                           NamespaceAliasDecl *Alias,
611
                                           SourceLocation AliasLoc,
612
219
                                           SourceLocation ColonColonLoc) {
613
219
  Representation = NestedNameSpecifier::Create(Context, Representation, Alias);
614
219
615
219
  // Push source-location info into the buffer.
616
219
  SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity);
617
219
  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
618
219
}
619
620
void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
621
211k
                                               SourceLocation ColonColonLoc) {
622
211k
  assert(!Representation && "Already have a nested-name-specifier!?");
623
211k
  Representation = NestedNameSpecifier::GlobalSpecifier(Context);
624
211k
625
211k
  // Push source-location info into the buffer.
626
211k
  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
627
211k
}
628
629
void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
630
                                              CXXRecordDecl *RD,
631
                                              SourceLocation SuperLoc,
632
58
                                              SourceLocation ColonColonLoc) {
633
58
  Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
634
58
635
58
  // Push source-location info into the buffer.
636
58
  SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity);
637
58
  SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity);
638
58
}
639
640
void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
641
                                                NestedNameSpecifier *Qualifier,
642
327k
                                                SourceRange R) {
643
327k
  Representation = Qualifier;
644
327k
645
327k
  // Construct bogus (but well-formed) source information for the
646
327k
  // nested-name-specifier.
647
327k
  BufferSize = 0;
648
327k
  SmallVector<NestedNameSpecifier *, 4> Stack;
649
654k
  for (NestedNameSpecifier *NNS = Qualifier; NNS; 
NNS = NNS->getPrefix()326k
)
650
326k
    Stack.push_back(NNS);
651
654k
  while (!Stack.empty()) {
652
326k
    NestedNameSpecifier *NNS = Stack.pop_back_val();
653
326k
    switch (NNS->getKind()) {
654
3.90k
      case NestedNameSpecifier::Identifier:
655
3.90k
      case NestedNameSpecifier::Namespace:
656
3.90k
      case NestedNameSpecifier::NamespaceAlias:
657
3.90k
        SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity);
658
3.90k
        break;
659
3.90k
660
322k
      case NestedNameSpecifier::TypeSpec:
661
322k
      case NestedNameSpecifier::TypeSpecWithTemplate: {
662
322k
        TypeSourceInfo *TSInfo
663
322k
        = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0),
664
322k
                                           R.getBegin());
665
322k
        SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
666
322k
                    BufferCapacity);
667
322k
        break;
668
322k
      }
669
322k
670
322k
      case NestedNameSpecifier::Global:
671
33
      case NestedNameSpecifier::Super:
672
33
        break;
673
326k
    }
674
326k
675
326k
    // Save the location of the '::'.
676
326k
    SaveSourceLocation(Stack.empty()? 
R.getEnd()324k
:
R.getBegin()2.51k
,
677
326k
                       Buffer, BufferSize, BufferCapacity);
678
326k
  }
679
327k
}
680
681
7.90M
void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
682
7.90M
  if (BufferCapacity)
683
161k
    free(Buffer);
684
7.90M
685
7.90M
  if (!Other) {
686
0
    Representation = nullptr;
687
0
    BufferSize = 0;
688
0
    return;
689
0
  }
690
7.90M
691
7.90M
  // Rather than copying the data (which is wasteful), "adopt" the
692
7.90M
  // pointer (which points into the ASTContext) but set the capacity to zero to
693
7.90M
  // indicate that we don't own it.
694
7.90M
  Representation = Other.getNestedNameSpecifier();
695
7.90M
  Buffer = static_cast<char *>(Other.getOpaqueData());
696
7.90M
  BufferSize = Other.getDataLength();
697
7.90M
  BufferCapacity = 0;
698
7.90M
}
699
700
NestedNameSpecifierLoc
701
7.55M
NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
702
7.55M
  if (!Representation)
703
150k
    return NestedNameSpecifierLoc();
704
7.40M
705
7.40M
  // If we adopted our data pointer from elsewhere in the AST context, there's
706
7.40M
  // no need to copy the memory.
707
7.40M
  if (BufferCapacity == 0)
708
2.95M
    return NestedNameSpecifierLoc(Representation, Buffer);
709
4.44M
710
4.44M
  // FIXME: After copying the source-location information, should we free
711
4.44M
  // our (temporary) buffer and adopt the ASTContext-allocated memory?
712
4.44M
  // Doing so would optimize repeated calls to getWithLocInContext().
713
4.44M
  void *Mem = Context.Allocate(BufferSize, alignof(void *));
714
4.44M
  memcpy(Mem, Buffer, BufferSize);
715
4.44M
  return NestedNameSpecifierLoc(Representation, Mem);
716
4.44M
}