Coverage Report

Created: 2022-05-17 06:19

/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
25.1k
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
42
25.1k
  Profile(ID, Parameter, Replacement);
43
25.1k
}
44
45
void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
46
                                           TemplateTemplateParmDecl *parameter,
47
52.0k
                                               TemplateName replacement) {
48
52.0k
  ID.AddPointer(parameter);
49
52.0k
  ID.AddPointer(replacement.getAsVoidPointer());
50
52.0k
}
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
3.18M
TemplateName::TemplateName(void *Ptr) {
66
3.18M
  Storage = StorageType::getFromOpaqueValue(Ptr);
67
3.18M
}
68
69
14.5M
TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
70
TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
71
90.9k
    : Storage(Storage) {}
72
TemplateName::TemplateName(AssumedTemplateStorage *Storage)
73
835
    : Storage(Storage) {}
74
TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
75
26.8k
    : Storage(Storage) {}
76
TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
77
8
    : Storage(Storage) {}
78
219k
TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
79
102k
TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
80
214
TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
81
82
4.24M
bool TemplateName::isNull() const { return Storage.isNull(); }
83
84
41.7M
TemplateName::NameKind TemplateName::getKind() const {
85
41.7M
  if (auto *ND = Storage.dyn_cast<Decl *>()) {
86
41.3M
    if (isa<UsingShadowDecl>(ND))
87
1.24k
      return UsingTemplate;
88
41.3M
    assert(isa<TemplateDecl>(ND));
89
0
    return Template;
90
41.3M
  }
91
92
437k
  if (Storage.is<DependentTemplateName *>())
93
9.65k
    return DependentTemplate;
94
428k
  if (Storage.is<QualifiedTemplateName *>())
95
247k
    return QualifiedTemplate;
96
97
180k
  UncommonTemplateNameStorage *uncommon
98
180k
    = Storage.get<UncommonTemplateNameStorage*>();
99
180k
  if (uncommon->getAsOverloadedStorage())
100
94.2k
    return OverloadedTemplate;
101
86.2k
  if (uncommon->getAsAssumedTemplateName())
102
65
    return AssumedTemplate;
103
86.2k
  if (uncommon->getAsSubstTemplateTemplateParm())
104
86.1k
    return SubstTemplateTemplateParm;
105
22
  return SubstTemplateTemplateParmPack;
106
86.2k
}
107
108
60.6M
TemplateDecl *TemplateName::getAsTemplateDecl() const {
109
60.6M
  if (Decl *TemplateOrUsing = Storage.dyn_cast<Decl *>()) {
110
59.8M
    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(TemplateOrUsing))
111
1.38k
      return cast<TemplateDecl>(USD->getTargetDecl());
112
113
59.8M
    assert(isa<TemplateDecl>(TemplateOrUsing));
114
0
    return cast<TemplateDecl>(TemplateOrUsing);
115
59.8M
  }
116
117
762k
  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
118
626k
    return QTN->getUnderlyingTemplate().getAsTemplateDecl();
119
120
136k
  if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
121
86.1k
    return sub->getReplacement().getAsTemplateDecl();
122
123
50.5k
  if (UsingShadowDecl *USD = getAsUsingShadowDecl())
124
0
    return cast<TemplateDecl>(USD->getTargetDecl());
125
126
50.5k
  return nullptr;
127
50.5k
}
128
129
1.17M
OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
130
1.17M
  if (UncommonTemplateNameStorage *Uncommon =
131
1.17M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
132
94.2k
    return Uncommon->getAsOverloadedStorage();
133
134
1.08M
  return nullptr;
135
1.17M
}
136
137
8.67M
AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
138
8.67M
  if (UncommonTemplateNameStorage *Uncommon =
139
8.67M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
140
23.8k
    return Uncommon->getAsAssumedTemplateName();
141
142
8.64M
  return nullptr;
143
8.67M
}
144
145
SubstTemplateTemplateParmStorage *
146
6.56M
TemplateName::getAsSubstTemplateTemplateParm() const {
147
6.56M
  if (UncommonTemplateNameStorage *uncommon =
148
6.56M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
149
115k
    return uncommon->getAsSubstTemplateTemplateParm();
150
151
6.44M
  return nullptr;
152
6.56M
}
153
154
SubstTemplateTemplateParmPackStorage *
155
3.75M
TemplateName::getAsSubstTemplateTemplateParmPack() const {
156
3.75M
  if (UncommonTemplateNameStorage *Uncommon =
157
3.75M
          Storage.dyn_cast<UncommonTemplateNameStorage *>())
158
250
    return Uncommon->getAsSubstTemplateTemplateParmPack();
159
160
3.75M
  return nullptr;
161
3.75M
}
162
163
20.0M
QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
164
20.0M
  return Storage.dyn_cast<QualifiedTemplateName *>();
165
20.0M
}
166
167
46.4M
DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
168
46.4M
  return Storage.dyn_cast<DependentTemplateName *>();
169
46.4M
}
170
171
50.6k
UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
172
50.6k
  if (Decl *D = Storage.dyn_cast<Decl *>())
173
55
    if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
174
55
      return USD;
175
50.5k
  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
176
1
    return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
177
50.5k
  return nullptr;
178
50.5k
}
179
180
26.8k
TemplateName TemplateName::getNameToSubstitute() const {
181
26.8k
  TemplateDecl *Decl = getAsTemplateDecl();
182
183
  // Substituting a dependent template name: preserve it as written.
184
26.8k
  if (!Decl)
185
463
    return *this;
186
187
  // If we have a template declaration, use the most recent non-friend
188
  // declaration of that template.
189
26.4k
  Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
190
26.4k
  while (Decl->getFriendObjectKind()) {
191
0
    Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
192
0
    assert(Decl && "all declarations of template are friends");
193
0
  }
194
26.4k
  return TemplateName(Decl);
195
26.8k
}
196
197
17.6M
TemplateNameDependence TemplateName::getDependence() const {
198
17.6M
  auto D = TemplateNameDependence::None;
199
17.6M
  switch (getKind()) {
200
199k
  case TemplateName::NameKind::QualifiedTemplate:
201
199k
    D |= toTemplateNameDependence(
202
199k
        getAsQualifiedTemplateName()->getQualifier()->getDependence());
203
199k
    break;
204
1.02k
  case TemplateName::NameKind::DependentTemplate:
205
1.02k
    D |= toTemplateNameDependence(
206
1.02k
        getAsDependentTemplateName()->getQualifier()->getDependence());
207
1.02k
    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
17.4M
  default:
214
17.4M
    break;
215
17.6M
  }
216
17.6M
  if (TemplateDecl *Template = getAsTemplateDecl()) {
217
17.6M
    if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
218
122k
      D |= TemplateNameDependence::DependentInstantiation;
219
122k
      if (TTP->isParameterPack())
220
186
        D |= TemplateNameDependence::UnexpandedPack;
221
122k
    }
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
17.6M
    if (Template->getDeclContext() &&
227
17.6M
        Template->getDeclContext()->isDependentContext())
228
160k
      D |= TemplateNameDependence::DependentInstantiation;
229
17.6M
  } else {
230
1.93k
    D |= TemplateNameDependence::DependentInstantiation;
231
1.93k
  }
232
17.6M
  return D;
233
17.6M
}
234
235
5.65M
bool TemplateName::isDependent() const {
236
5.65M
  return getDependence() & TemplateNameDependence::Dependent;
237
5.65M
}
238
239
0
bool TemplateName::isInstantiationDependent() const {
240
0
  return getDependence() & TemplateNameDependence::Instantiation;
241
0
}
242
243
8.98k
bool TemplateName::containsUnexpandedParameterPack() const {
244
8.98k
  return getDependence() & TemplateNameDependence::UnexpandedPack;
245
8.98k
}
246
247
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
248
195k
                         Qualified Qual) const {
249
195k
  auto Kind = getKind();
250
195k
  TemplateDecl *Template = nullptr;
251
195k
  if (Kind == TemplateName::Template || 
Kind == TemplateName::UsingTemplate323
) {
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
195k
    Template = getAsTemplateDecl();
262
195k
  }
263
264
195k
  if (Template)
265
195k
    if (Policy.CleanUglifiedParameters &&
266
195k
        
isa<TemplateTemplateParmDecl>(Template)129
&&
Template->getIdentifier()2
)
267
2
      OS << Template->getIdentifier()->deuglifiedName();
268
195k
    else if (Qual == Qualified::Fully &&
269
195k
             getDependence() !=
270
1.69k
                 TemplateNameDependenceScope::DependentInstantiation)
271
1.63k
      Template->printQualifiedName(OS, Policy);
272
193k
    else
273
193k
      OS << *Template;
274
286
  else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
275
49
    if (Qual == Qualified::Fully &&
276
49
        getDependence() !=
277
1
            TemplateNameDependenceScope::DependentInstantiation) {
278
1
      QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
279
1
          OS, Policy);
280
1
      return;
281
1
    }
282
48
    if (Qual == Qualified::AsWritten)
283
48
      QTN->getQualifier()->print(OS, Policy);
284
48
    if (QTN->hasTemplateKeyword())
285
19
      OS << "template ";
286
48
    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
195k
}
310
311
const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
312
505
                                             TemplateName N) {
313
505
  std::string NameStr;
314
505
  llvm::raw_string_ostream OS(NameStr);
315
505
  LangOptions LO;
316
505
  LO.CPlusPlus = true;
317
505
  LO.Bool = true;
318
505
  OS << '\'';
319
505
  N.print(OS, PrintingPolicy(LO));
320
505
  OS << '\'';
321
505
  OS.flush();
322
505
  return DB << NameStr;
323
505
}
324
325
82
void TemplateName::dump(raw_ostream &OS) const {
326
82
  LangOptions LO;  // FIXME!
327
82
  LO.CPlusPlus = true;
328
82
  LO.Bool = true;
329
82
  print(OS, PrintingPolicy(LO));
330
82
}
331
332
0
LLVM_DUMP_METHOD void TemplateName::dump() const {
333
0
  dump(llvm::errs());
334
0
}