Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/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 <string>
33
34
using namespace clang;
35
36
TemplateArgument
37
9
SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
38
9
  return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
39
9
}
40
41
27.4k
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
42
27.4k
  Profile(ID, Parameter, Replacement);
43
27.4k
}
44
45
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
46
                                           TemplateTemplateParmDecl *parameter,
47
56.5k
                                               TemplateName replacement) {
48
56.5k
  ID.AddPointer(parameter);
49
56.5k
  ID.AddPointer(replacement.getAsVoidPointer());
50
56.5k
}
51
52
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
53
0
                                                   ASTContext &Context) {
54
0
  Profile(ID, Context, Parameter, getArgumentPack());
55
0
}
56
57
void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
58
                                                   ASTContext &Context,
59
                                           TemplateTemplateParmDecl *Parameter,
60
8
                                             const TemplateArgument &ArgPack) {
61
8
  ID.AddPointer(Parameter);
62
8
  ArgPack.Profile(ID, Context);
63
8
}
64
65
4.17M
TemplateName::TemplateName(void *Ptr) {
66
4.17M
  Storage = StorageType::getFromOpaqueValue(Ptr);
67
4.17M
}
68
69
17.2M
TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
70
TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
71
140k
    : Storage(Storage) {}
72
TemplateName::TemplateName(AssumedTemplateStorage *Storage)
73
828
    : Storage(Storage) {}
74
TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
75
29.0k
    : Storage(Storage) {}
76
TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
77
8
    : Storage(Storage) {}
78
296k
TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
79
82.5k
TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
80
219
TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
81
82
5.23M
bool TemplateName::isNull() const { return Storage.isNull(); }
83
84
49.7M
TemplateName::NameKind TemplateName::getKind() const {
85
49.7M
  if (auto *ND = Storage.dyn_cast<Decl *>()) {
86
49.2M
    if (isa<UsingShadowDecl>(ND))
87
1.25k
      return UsingTemplate;
88
49.2M
    assert(isa<TemplateDecl>(ND));
89
0
    return Template;
90
49.2M
  }
91
92
572k
  if (Storage.is<DependentTemplateName *>())
93
12.4k
    return DependentTemplate;
94
560k
  if (Storage.is<QualifiedTemplateName *>())
95
321k
    return QualifiedTemplate;
96
97
238k
  UncommonTemplateNameStorage *uncommon
98
238k
    = Storage.get<UncommonTemplateNameStorage*>();
99
238k
  if (uncommon->getAsOverloadedStorage())
100
143k
    return OverloadedTemplate;
101
94.8k
  if (uncommon->getAsAssumedTemplateName())
102
67
    return AssumedTemplate;
103
94.8k
  if (uncommon->getAsSubstTemplateTemplateParm())
104
94.8k
    return SubstTemplateTemplateParm;
105
22
  return SubstTemplateTemplateParmPack;
106
94.8k
}
107
108
73.5M
TemplateDecl *TemplateName::getAsTemplateDecl() const {
109
73.5M
  if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) {
110
72.6M
    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing))
111
1.38k
      return cast<TemplateDecl>(USD->getTargetDecl());
112
113
72.6M
    assert(isa<TemplateDecl>(TemplateOrUsing));
114
0
    return cast<TemplateDecl>(TemplateOrUsing);
115
72.6M
  }
116
117
891k
  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
118
739k
    return QTN->getUnderlyingTemplate().getAsTemplateDecl();
119
120
151k
  if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
121
93.9k
    return sub->getReplacement().getAsTemplateDecl();
122
123
57.4k
  if (UsingShadowDecl *USD = getAsUsingShadowDecl())
124
0
    return cast<TemplateDecl>(USD->getTargetDecl());
125
126
57.4k
  return nullptr;
127
57.4k
}
128
129
1.60M
OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
130
1.60M
  if (UncommonTemplateNameStorage *Uncommon =
131
1.60M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
132
143k
    return Uncommon->getAsOverloadedStorage();
133
134
1.46M
  return nullptr;
135
1.60M
}
136
137
11.1M
AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
138
11.1M
  if (UncommonTemplateNameStorage *Uncommon =
139
11.1M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
140
24.3k
    return Uncommon->getAsAssumedTemplateName();
141
142
11.1M
  return nullptr;
143
11.1M
}
144
145
SubstTemplateTemplateParmStorage *
146
8.31M
TemplateName::getAsSubstTemplateTemplateParm() const {
147
8.31M
  if (UncommonTemplateNameStorage *uncommon =
148
8.31M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
149
128k
    return uncommon->getAsSubstTemplateTemplateParm();
150
151
8.18M
  return nullptr;
152
8.31M
}
153
154
SubstTemplateTemplateParmPackStorage *
155
4.59M
TemplateName::getAsSubstTemplateTemplateParmPack() const {
156
4.59M
  if (UncommonTemplateNameStorage *Uncommon =
157
4.59M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
158
250
    return Uncommon->getAsSubstTemplateTemplateParmPack();
159
160
4.59M
  return nullptr;
161
4.59M
}
162
163
24.5M
QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
164
24.5M
  return Storage.dyn_cast<QualifiedTemplateName *>();
165
24.5M
}
166
167
57.2M
DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
168
57.2M
  return Storage.dyn_cast<DependentTemplateName *>();
169
57.2M
}
170
171
57.5k
UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
172
57.5k
  if (Decl *D = Storage.dyn_cast<Decl *>())
173
60
    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
174
60
      return USD;
175
57.4k
  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
176
1
    return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
177
57.4k
  return nullptr;
178
57.4k
}
179
180
28.9k
TemplateName TemplateName::getNameToSubstitute() const {
181
28.9k
  TemplateDecl *Decl = getAsTemplateDecl();
182
183
  // Substituting a dependent template name: preserve it as written.
184
28.9k
  if (!Decl)
185
483
    return *this;
186
187
  // If we have a template declaration, use the most recent non-friend
188
  // declaration of that template.
189
28.4k
  Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
190
28.4k
  while (Decl->getFriendObjectKind()) {
191
0
    Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
192
0
    assert(Decl && "all declarations of template are friends");
193
0
  }
194
28.4k
  return TemplateName(Decl);
195
28.9k
}
196
197
21.5M
TemplateNameDependence TemplateName::getDependence() const {
198
21.5M
  auto D = TemplateNameDependence::None;
199
21.5M
  switch (getKind()) {
200
221k
  case TemplateName::NameKind::QualifiedTemplate:
201
221k
    D |= toTemplateNameDependence(
202
221k
        getAsQualifiedTemplateName()->getQualifier()->getDependence());
203
221k
    break;
204
1.13k
  case TemplateName::NameKind::DependentTemplate:
205
1.13k
    D |= toTemplateNameDependence(
206
1.13k
        getAsDependentTemplateName()->getQualifier()->getDependence());
207
1.13k
    break;
208
8
  case TemplateName::NameKind::SubstTemplateTemplateParmPack:
209
8
    D |= TemplateNameDependence::UnexpandedPack;
210
8
    break;
211
0
  case TemplateName::NameKind::OverloadedTemplate:
212
0
    llvm_unreachable("overloaded templates shouldn't survive to here.");
213
21.3M
  default:
214
21.3M
    break;
215
21.5M
  }
216
21.5M
  if (TemplateDecl *Template = getAsTemplateDecl()) {
217
21.5M
    if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
218
135k
      D |= TemplateNameDependence::DependentInstantiation;
219
135k
      if (TTP->isParameterPack())
220
186
        D |= TemplateNameDependence::UnexpandedPack;
221
135k
    }
222
    // FIXME: Hack, getDeclContext() can be null if Template is still
223
    // initializing due to PCH reading, so we check it before using it.
224
    // Should probably modify TemplateSpecializationType to allow constructing
225
    // it without the isDependent() checking.
226
21.5M
    if (Template->getDeclContext() &&
227
21.5M
        Template->getDeclContext()->isDependentContext())
228
234k
      D |= TemplateNameDependence::DependentInstantiation;
229
21.5M
  } else {
230
2.08k
    D |= TemplateNameDependence::DependentInstantiation;
231
2.08k
  }
232
21.5M
  return D;
233
21.5M
}
234
235
7.21M
bool TemplateName::isDependent() const {
236
7.21M
  return getDependence() & TemplateNameDependence::Dependent;
237
7.21M
}
238
239
0
bool TemplateName::isInstantiationDependent() const {
240
0
  return getDependence() & TemplateNameDependence::Instantiation;
241
0
}
242
243
9.39k
bool TemplateName::containsUnexpandedParameterPack() const {
244
9.39k
  return getDependence() & TemplateNameDependence::UnexpandedPack;
245
9.39k
}
246
247
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
248
209k
                         Qualified Qual) const {
249
209k
  auto Kind = getKind();
250
209k
  TemplateDecl *Template = nullptr;
251
209k
  if (Kind == TemplateName::Template || 
Kind == TemplateName::UsingTemplate324
) {
252
    // After `namespace ns { using std::vector }`, what is the fully-qualified
253
    // name of the UsingTemplateName `vector` within ns?
254
    //
255
    // - ns::vector (the qualified name of the using-shadow decl)
256
    // - std::vector (the qualified name of the underlying template decl)
257
    //
258
    // Similar to the UsingType behavior, using declarations are used to import
259
    // names more often than to export them, thus using the original name is
260
    // most useful in this case.
261
209k
    Template = getAsTemplateDecl();
262
209k
  }
263
264
209k
  if (Template)
265
209k
    if (Policy.CleanUglifiedParameters &&
266
209k
        
isa<TemplateTemplateParmDecl>(Template)129
&&
Template->getIdentifier()2
)
267
2
      OS << Template->getIdentifier()->deuglifiedName();
268
209k
    else if (Qual == Qualified::Fully &&
269
209k
             getDependence() !=
270
1.69k
                 TemplateNameDependenceScope::DependentInstantiation)
271
1.63k
      Template->printQualifiedName(OS, Policy);
272
207k
    else
273
207k
      OS << *Template;
274
287
  else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
275
50
    if (Qual == Qualified::Fully &&
276
50
        getDependence() !=
277
1
            TemplateNameDependenceScope::DependentInstantiation) {
278
1
      QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
279
1
          OS, Policy);
280
1
      return;
281
1
    }
282
49
    if (Qual == Qualified::AsWritten)
283
49
      QTN->getQualifier()->print(OS, Policy);
284
49
    if (QTN->hasTemplateKeyword())
285
19
      OS << "template ";
286
49
    OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
287
237
  } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
288
12
    if (Qual == Qualified::AsWritten && DTN->getQualifier())
289
12
      DTN->getQualifier()->print(OS, Policy);
290
12
    OS << "template ";
291
292
12
    if (DTN->isIdentifier())
293
0
      OS << DTN->getIdentifier()->getName();
294
12
    else
295
12
      OS << "operator " << getOperatorSpelling(DTN->getOperator());
296
225
  } else if (SubstTemplateTemplateParmStorage *subst
297
225
               = getAsSubstTemplateTemplateParm()) {
298
222
    subst->getReplacement().print(OS, Policy, Qual);
299
222
  } else 
if (SubstTemplateTemplateParmPackStorage *3
SubstPack3
300
3
                                        = getAsSubstTemplateTemplateParmPack())
301
0
    OS << *SubstPack->getParameterPack();
302
3
  else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
303
0
    Assumed->getDeclName().print(OS, Policy);
304
3
  } else {
305
3
    assert(getKind() == TemplateName::OverloadedTemplate);
306
0
    OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
307
3
    (*OTS->begin())->printName(OS);
308
3
  }
309
209k
}
310
311
const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
312
563
                                             TemplateName N) {
313
563
  std::string NameStr;
314
563
  llvm::raw_string_ostream OS(NameStr);
315
563
  LangOptions LO;
316
563
  LO.CPlusPlus = true;
317
563
  LO.Bool = true;
318
563
  OS << '\'';
319
563
  N.print(OS, PrintingPolicy(LO));
320
563
  OS << '\'';
321
563
  OS.flush();
322
563
  return DB << NameStr;
323
563
}
324
325
102
void TemplateName::dump(raw_ostream &OS) const {
326
102
  LangOptions LO;  // FIXME!
327
102
  LO.CPlusPlus = true;
328
102
  LO.Bool = true;
329
102
  print(OS, PrintingPolicy(LO));
330
102
}
331
332
0
LLVM_DUMP_METHOD void TemplateName::dump() const {
333
0
  dump(llvm::errs());
334
0
}