Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/AST/TemplateName.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- TemplateName.cpp - C++ Template Name Representation ----------------===//
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 TemplateName interface and subclasses.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/AST/TemplateName.h"
14
#include "clang/AST/Decl.h"
15
#include "clang/AST/DeclBase.h"
16
#include "clang/AST/DeclCXX.h"
17
#include "clang/AST/DeclTemplate.h"
18
#include "clang/AST/DependenceFlags.h"
19
#include "clang/AST/NestedNameSpecifier.h"
20
#include "clang/AST/PrettyPrinter.h"
21
#include "clang/AST/TemplateBase.h"
22
#include "clang/Basic/Diagnostic.h"
23
#include "clang/Basic/LLVM.h"
24
#include "clang/Basic/LangOptions.h"
25
#include "clang/Basic/OperatorKinds.h"
26
#include "llvm/ADT/ArrayRef.h"
27
#include "llvm/ADT/FoldingSet.h"
28
#include "llvm/Support/Casting.h"
29
#include "llvm/Support/Compiler.h"
30
#include "llvm/Support/raw_ostream.h"
31
#include <cassert>
32
#include <optional>
33
#include <string>
34
35
using namespace clang;
36
37
TemplateArgument
38
0
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
39
0
  return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
40
0
}
41
42
TemplateTemplateParmDecl *
43
0
SubstTemplateTemplateParmPackStorage::getParameterPack() const {
44
0
  return cast<TemplateTemplateParmDecl>(
45
0
      getReplacedTemplateParameterList(getAssociatedDecl())
46
0
          ->asArray()[Bits.Index]);
47
0
}
48
49
TemplateTemplateParmDecl *
50
0
SubstTemplateTemplateParmStorage::getParameter() const {
51
0
  return cast<TemplateTemplateParmDecl>(
52
0
      getReplacedTemplateParameterList(getAssociatedDecl())
53
0
          ->asArray()[Bits.Index]);
54
0
}
55
56
0
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
57
0
  Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
58
0
}
59
60
void SubstTemplateTemplateParmStorage::Profile(
61
    llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
62
0
    unsigned Index, std::optional<unsigned> PackIndex) {
63
0
  Replacement.Profile(ID);
64
0
  ID.AddPointer(AssociatedDecl);
65
0
  ID.AddInteger(Index);
66
0
  ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
67
0
}
68
69
SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
70
    ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
71
    bool Final)
72
    : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
73
                                  ArgPack.size()),
74
0
      Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
75
0
  assert(AssociatedDecl != nullptr);
76
0
}
77
78
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
79
0
                                                   ASTContext &Context) {
80
0
  Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
81
0
          getFinal());
82
0
}
83
84
0
Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
85
0
  return AssociatedDeclAndFinal.getPointer();
86
0
}
87
88
0
bool SubstTemplateTemplateParmPackStorage::getFinal() const {
89
0
  return AssociatedDeclAndFinal.getInt();
90
0
}
91
92
void SubstTemplateTemplateParmPackStorage::Profile(
93
    llvm::FoldingSetNodeID &ID, ASTContext &Context,
94
    const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
95
0
    bool Final) {
96
0
  ArgPack.Profile(ID, Context);
97
0
  ID.AddPointer(AssociatedDecl);
98
0
  ID.AddInteger(Index);
99
0
  ID.AddBoolean(Final);
100
0
}
101
102
1
TemplateName::TemplateName(void *Ptr) {
103
1
  Storage = StorageType::getFromOpaqueValue(Ptr);
104
1
}
105
106
0
TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
107
TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
108
0
    : Storage(Storage) {}
109
TemplateName::TemplateName(AssumedTemplateStorage *Storage)
110
3.06k
    : Storage(Storage) {}
111
TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
112
0
    : Storage(Storage) {}
113
TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
114
0
    : Storage(Storage) {}
115
0
TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
116
0
TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
117
0
TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
118
119
0
bool TemplateName::isNull() const { return Storage.isNull(); }
120
121
0
TemplateName::NameKind TemplateName::getKind() const {
122
0
  if (auto *ND = Storage.dyn_cast<Decl *>()) {
123
0
    if (isa<UsingShadowDecl>(ND))
124
0
      return UsingTemplate;
125
0
    assert(isa<TemplateDecl>(ND));
126
0
    return Template;
127
0
  }
128
129
0
  if (Storage.is<DependentTemplateName *>())
130
0
    return DependentTemplate;
131
0
  if (Storage.is<QualifiedTemplateName *>())
132
0
    return QualifiedTemplate;
133
134
0
  UncommonTemplateNameStorage *uncommon
135
0
    = Storage.get<UncommonTemplateNameStorage*>();
136
0
  if (uncommon->getAsOverloadedStorage())
137
0
    return OverloadedTemplate;
138
0
  if (uncommon->getAsAssumedTemplateName())
139
0
    return AssumedTemplate;
140
0
  if (uncommon->getAsSubstTemplateTemplateParm())
141
0
    return SubstTemplateTemplateParm;
142
0
  return SubstTemplateTemplateParmPack;
143
0
}
144
145
0
TemplateDecl *TemplateName::getAsTemplateDecl() const {
146
0
  if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) {
147
0
    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing))
148
0
      return cast<TemplateDecl>(USD->getTargetDecl());
149
150
0
    assert(isa<TemplateDecl>(TemplateOrUsing));
151
0
    return cast<TemplateDecl>(TemplateOrUsing);
152
0
  }
153
154
0
  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
155
0
    return QTN->getUnderlyingTemplate().getAsTemplateDecl();
156
157
0
  if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
158
0
    return sub->getReplacement().getAsTemplateDecl();
159
160
0
  if (UsingShadowDecl *USD = getAsUsingShadowDecl())
161
0
    return cast<TemplateDecl>(USD->getTargetDecl());
162
163
0
  return nullptr;
164
0
}
165
166
0
OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
167
0
  if (UncommonTemplateNameStorage *Uncommon =
168
0
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
169
0
    return Uncommon->getAsOverloadedStorage();
170
171
0
  return nullptr;
172
0
}
173
174
2
AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
175
2
  if (UncommonTemplateNameStorage *Uncommon =
176
2
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
177
2
    return Uncommon->getAsAssumedTemplateName();
178
179
0
  return nullptr;
180
2
}
181
182
SubstTemplateTemplateParmStorage *
183
0
TemplateName::getAsSubstTemplateTemplateParm() const {
184
0
  if (UncommonTemplateNameStorage *uncommon =
185
0
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
186
0
    return uncommon->getAsSubstTemplateTemplateParm();
187
188
0
  return nullptr;
189
0
}
190
191
SubstTemplateTemplateParmPackStorage *
192
0
TemplateName::getAsSubstTemplateTemplateParmPack() const {
193
0
  if (UncommonTemplateNameStorage *Uncommon =
194
0
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
195
0
    return Uncommon->getAsSubstTemplateTemplateParmPack();
196
197
0
  return nullptr;
198
0
}
199
200
0
QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
201
0
  return Storage.dyn_cast<QualifiedTemplateName *>();
202
0
}
203
204
0
DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
205
0
  return Storage.dyn_cast<DependentTemplateName *>();
206
0
}
207
208
0
UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
209
0
  if (Decl *D = Storage.dyn_cast<Decl *>())
210
0
    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
211
0
      return USD;
212
0
  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
213
0
    return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
214
0
  return nullptr;
215
0
}
216
217
0
TemplateName TemplateName::getNameToSubstitute() const {
218
0
  TemplateDecl *Decl = getAsTemplateDecl();
219
220
  // Substituting a dependent template name: preserve it as written.
221
0
  if (!Decl)
222
0
    return *this;
223
224
  // If we have a template declaration, use the most recent non-friend
225
  // declaration of that template.
226
0
  Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
227
0
  while (Decl->getFriendObjectKind()) {
228
0
    Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
229
0
    assert(Decl && "all declarations of template are friends");
230
0
  }
231
0
  return TemplateName(Decl);
232
0
}
233
234
0
TemplateNameDependence TemplateName::getDependence() const {
235
0
  auto D = TemplateNameDependence::None;
236
0
  switch (getKind()) {
237
0
  case TemplateName::NameKind::QualifiedTemplate:
238
0
    D |= toTemplateNameDependence(
239
0
        getAsQualifiedTemplateName()->getQualifier()->getDependence());
240
0
    break;
241
0
  case TemplateName::NameKind::DependentTemplate:
242
0
    D |= toTemplateNameDependence(
243
0
        getAsDependentTemplateName()->getQualifier()->getDependence());
244
0
    break;
245
0
  case TemplateName::NameKind::SubstTemplateTemplateParmPack:
246
0
    D |= TemplateNameDependence::UnexpandedPack;
247
0
    break;
248
0
  case TemplateName::NameKind::OverloadedTemplate:
249
0
    llvm_unreachable("overloaded templates shouldn't survive to here.");
250
0
  default:
251
0
    break;
252
0
  }
253
0
  if (TemplateDecl *Template = getAsTemplateDecl()) {
254
0
    if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
255
0
      D |= TemplateNameDependence::DependentInstantiation;
256
0
      if (TTP->isParameterPack())
257
0
        D |= TemplateNameDependence::UnexpandedPack;
258
0
    }
259
    // FIXME: Hack, getDeclContext() can be null if Template is still
260
    // initializing due to PCH reading, so we check it before using it.
261
    // Should probably modify TemplateSpecializationType to allow constructing
262
    // it without the isDependent() checking.
263
0
    if (Template->getDeclContext() &&
264
0
        Template->getDeclContext()->isDependentContext())
265
0
      D |= TemplateNameDependence::DependentInstantiation;
266
0
  } else {
267
0
    D |= TemplateNameDependence::DependentInstantiation;
268
0
  }
269
0
  return D;
270
0
}
271
272
0
bool TemplateName::isDependent() const {
273
0
  return getDependence() & TemplateNameDependence::Dependent;
274
0
}
275
276
0
bool TemplateName::isInstantiationDependent() const {
277
0
  return getDependence() & TemplateNameDependence::Instantiation;
278
0
}
279
280
0
bool TemplateName::containsUnexpandedParameterPack() const {
281
0
  return getDependence() & TemplateNameDependence::UnexpandedPack;
282
0
}
283
284
0
void TemplateName::Profile(llvm::FoldingSetNodeID &ID) {
285
0
  if (const auto* USD = getAsUsingShadowDecl())
286
0
    ID.AddPointer(USD->getCanonicalDecl());
287
0
  else if (const auto *TD = getAsTemplateDecl())
288
0
    ID.AddPointer(TD->getCanonicalDecl());
289
0
  else
290
0
    ID.AddPointer(Storage.getOpaqueValue());
291
0
}
292
293
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
294
0
                         Qualified Qual) const {
295
0
  auto Kind = getKind();
296
0
  TemplateDecl *Template = nullptr;
297
0
  if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
298
    // After `namespace ns { using std::vector }`, what is the fully-qualified
299
    // name of the UsingTemplateName `vector` within ns?
300
    //
301
    // - ns::vector (the qualified name of the using-shadow decl)
302
    // - std::vector (the qualified name of the underlying template decl)
303
    //
304
    // Similar to the UsingType behavior, using declarations are used to import
305
    // names more often than to export them, thus using the original name is
306
    // most useful in this case.
307
0
    Template = getAsTemplateDecl();
308
0
  }
309
310
0
  if (Template)
311
0
    if (Policy.CleanUglifiedParameters &&
312
0
        isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
313
0
      OS << Template->getIdentifier()->deuglifiedName();
314
0
    else if (Qual == Qualified::Fully &&
315
0
             getDependence() !=
316
0
                 TemplateNameDependenceScope::DependentInstantiation)
317
0
      Template->printQualifiedName(OS, Policy);
318
0
    else
319
0
      OS << *Template;
320
0
  else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
321
0
    if (Qual == Qualified::Fully &&
322
0
        getDependence() !=
323
0
            TemplateNameDependenceScope::DependentInstantiation) {
324
0
      QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
325
0
          OS, Policy);
326
0
      return;
327
0
    }
328
0
    if (Qual == Qualified::AsWritten)
329
0
      QTN->getQualifier()->print(OS, Policy);
330
0
    if (QTN->hasTemplateKeyword())
331
0
      OS << "template ";
332
0
    OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
333
0
  } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
334
0
    if (Qual == Qualified::AsWritten && DTN->getQualifier())
335
0
      DTN->getQualifier()->print(OS, Policy);
336
0
    OS << "template ";
337
338
0
    if (DTN->isIdentifier())
339
0
      OS << DTN->getIdentifier()->getName();
340
0
    else
341
0
      OS << "operator " << getOperatorSpelling(DTN->getOperator());
342
0
  } else if (SubstTemplateTemplateParmStorage *subst
343
0
               = getAsSubstTemplateTemplateParm()) {
344
0
    subst->getReplacement().print(OS, Policy, Qual);
345
0
  } else if (SubstTemplateTemplateParmPackStorage *SubstPack
346
0
                                        = getAsSubstTemplateTemplateParmPack())
347
0
    OS << *SubstPack->getParameterPack();
348
0
  else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
349
0
    Assumed->getDeclName().print(OS, Policy);
350
0
  } else {
351
0
    assert(getKind() == TemplateName::OverloadedTemplate);
352
0
    OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
353
0
    (*OTS->begin())->printName(OS, Policy);
354
0
  }
355
0
}
356
357
const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
358
0
                                             TemplateName N) {
359
0
  std::string NameStr;
360
0
  llvm::raw_string_ostream OS(NameStr);
361
0
  LangOptions LO;
362
0
  LO.CPlusPlus = true;
363
0
  LO.Bool = true;
364
0
  OS << '\'';
365
0
  N.print(OS, PrintingPolicy(LO));
366
0
  OS << '\'';
367
0
  OS.flush();
368
0
  return DB << NameStr;
369
0
}
370
371
0
void TemplateName::dump(raw_ostream &OS) const {
372
0
  LangOptions LO;  // FIXME!
373
0
  LO.CPlusPlus = true;
374
0
  LO.Bool = true;
375
0
  print(OS, PrintingPolicy(LO));
376
0
}
377
378
0
LLVM_DUMP_METHOD void TemplateName::dump() const {
379
0
  dump(llvm::errs());
380
0
}