1//===- TemplateBase.cpp - Common template AST class implementation --------===//
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 implements common classes used throughout C++ template
10// representations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/TemplateBase.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/AST/DependenceFlags.h"
20#include "clang/AST/Expr.h"
21#include "clang/AST/ExprCXX.h"
22#include "clang/AST/PrettyPrinter.h"
23#include "clang/AST/TemplateName.h"
24#include "clang/AST/Type.h"
25#include "clang/AST/TypeLoc.h"
26#include "clang/Basic/Diagnostic.h"
27#include "clang/Basic/LLVM.h"
28#include "clang/Basic/LangOptions.h"
29#include "clang/Basic/SourceLocation.h"
30#include "llvm/ADT/APSInt.h"
31#include "llvm/ADT/FoldingSet.h"
32#include "llvm/ADT/None.h"
33#include "llvm/ADT/SmallString.h"
34#include "llvm/ADT/StringRef.h"
35#include "llvm/Support/Casting.h"
36#include "llvm/Support/Compiler.h"
37#include "llvm/Support/ErrorHandling.h"
38#include "llvm/Support/raw_ostream.h"
39#include <cassert>
40#include <cstddef>
41#include <cstdint>
42#include <cstring>
43
44using namespace clang;
45
46/// Print a template integral argument value.
47///
48/// \param TemplArg the TemplateArgument instance to print.
49///
50/// \param Out the raw_ostream instance to use for printing.
51///
52/// \param Policy the printing policy for EnumConstantDecl printing.
53static void printIntegral(const TemplateArgument &TemplArg,
54                          raw_ostream &Out, const PrintingPolicy& Policy) {
55  const Type *T = TemplArg.getIntegralType().getTypePtr();
56  const llvm::APSInt &Val = TemplArg.getAsIntegral();
57
58  if (const EnumType *ET = T->getAs<EnumType>()) {
59    for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
60      // In Sema::CheckTemplateArugment, enum template arguments value are
61      // extended to the size of the integer underlying the enum type.  This
62      // may create a size difference between the enum value and template
63      // argument value, requiring isSameValue here instead of operator==.
64      if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
65        ECD->printQualifiedName(Out, Policy);
66        return;
67      }
68    }
69  }
70
71  if (T->isBooleanType() && !Policy.MSVCFormatting) {
72    Out << (Val.getBoolValue() ? "true" : "false");
73  } else if (T->isCharType()) {
74    const char Ch = Val.getZExtValue();
75    Out << ((Ch == '\'') ? "'\\" : "'");
76    Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
77    Out << "'";
78  } else {
79    Out << Val;
80  }
81}
82
83//===----------------------------------------------------------------------===//
84// TemplateArgument Implementation
85//===----------------------------------------------------------------------===//
86
87TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
88                                   QualType Type) {
89  Integer.Kind = Integral;
90  // Copy the APSInt value into our decomposed form.
91  Integer.BitWidth = Value.getBitWidth();
92  Integer.IsUnsigned = Value.isUnsigned();
93  // If the value is large, we have to get additional memory from the ASTContext
94  unsigned NumWords = Value.getNumWords();
95  if (NumWords > 1) {
96    void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
97    std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
98    Integer.pVal = static_cast<uint64_t *>(Mem);
99  } else {
100    Integer.VAL = Value.getZExtValue();
101  }
102
103  Integer.Type = Type.getAsOpaquePtr();
104}
105
106TemplateArgument
107TemplateArgument::CreatePackCopy(ASTContext &Context,
108                                 ArrayRef<TemplateArgument> Args) {
109  if (Args.empty())
110    return getEmptyPack();
111
112  return TemplateArgument(Args.copy(Context));
113}
114
115TemplateArgumentDependence TemplateArgument::getDependence() const {
116  auto Deps = TemplateArgumentDependence::None;
117  switch (getKind()) {
118  case Null:
119    llvm_unreachable("Should not have a NULL template argument");
120
121  case Type:
122    Deps = toTemplateArgumentDependence(getAsType()->getDependence());
123    if (isa<PackExpansionType>(getAsType()))
124      Deps |= TemplateArgumentDependence::Dependent;
125    return Deps;
126
127  case Template:
128    return toTemplateArgumentDependence(getAsTemplate().getDependence());
129
130  case TemplateExpansion:
131    return TemplateArgumentDependence::Dependent |
132           TemplateArgumentDependence::Instantiation;
133
134  case Declaration: {
135    auto *DC = dyn_cast<DeclContext>(getAsDecl());
136    if (!DC)
137      DC = getAsDecl()->getDeclContext();
138    if (DC->isDependentContext())
139      Deps = TemplateArgumentDependence::Dependent |
140             TemplateArgumentDependence::Instantiation;
141    return Deps;
142  }
143
144  case NullPtr:
145  case Integral:
146    return TemplateArgumentDependence::None;
147
148  case Expression:
149    Deps = toTemplateArgumentDependence(getAsExpr()->getDependence());
150    if (isa<PackExpansionExpr>(getAsExpr()))
151      Deps |= TemplateArgumentDependence::Dependent |
152              TemplateArgumentDependence::Instantiation;
153    return Deps;
154
155  case Pack:
156    for (const auto &P : pack_elements())
157      Deps |= P.getDependence();
158    return Deps;
159  }
160  llvm_unreachable("unhandled ArgKind");
161}
162
163bool TemplateArgument::isDependent() const {
164  return getDependence() & TemplateArgumentDependence::Dependent;
165}
166
167bool TemplateArgument::isInstantiationDependent() const {
168  return getDependence() & TemplateArgumentDependence::Instantiation;
169}
170
171bool TemplateArgument::isPackExpansion() const {
172  switch (getKind()) {
173  case Null:
174  case Declaration:
175  case Integral:
176  case Pack:
177  case Template:
178  case NullPtr:
179    return false;
180
181  case TemplateExpansion:
182    return true;
183
184  case Type:
185    return isa<PackExpansionType>(getAsType());
186
187  case Expression:
188    return isa<PackExpansionExpr>(getAsExpr());
189  }
190
191  llvm_unreachable("Invalid TemplateArgument Kind!");
192}
193
194bool TemplateArgument::containsUnexpandedParameterPack() const {
195  return getDependence() & TemplateArgumentDependence::UnexpandedPack;
196}
197
198Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
199  assert(getKind() == TemplateExpansion);
200  if (TemplateArg.NumExpansions)
201    return TemplateArg.NumExpansions - 1;
202
203  return None;
204}
205
206QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
207  switch (getKind()) {
208  case TemplateArgument::Null:
209  case TemplateArgument::Type:
210  case TemplateArgument::Template:
211  case TemplateArgument::TemplateExpansion:
212  case TemplateArgument::Pack:
213    return QualType();
214
215  case TemplateArgument::Integral:
216    return getIntegralType();
217
218  case TemplateArgument::Expression:
219    return getAsExpr()->getType();
220
221  case TemplateArgument::Declaration:
222    return getParamTypeForDecl();
223
224  case TemplateArgument::NullPtr:
225    return getNullPtrType();
226  }
227
228  llvm_unreachable("Invalid TemplateArgument Kind!");
229}
230
231void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
232                               const ASTContext &Context) const {
233  ID.AddInteger(getKind());
234  switch (getKind()) {
235  case Null:
236    break;
237
238  case Type:
239    getAsType().Profile(ID);
240    break;
241
242  case NullPtr:
243    getNullPtrType().Profile(ID);
244    break;
245
246  case Declaration:
247    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
248    break;
249
250  case Template:
251  case TemplateExpansion: {
252    TemplateName Template = getAsTemplateOrTemplatePattern();
253    if (TemplateTemplateParmDecl *TTP
254          = dyn_cast_or_null<TemplateTemplateParmDecl>(
255                                                Template.getAsTemplateDecl())) {
256      ID.AddBoolean(true);
257      ID.AddInteger(TTP->getDepth());
258      ID.AddInteger(TTP->getPosition());
259      ID.AddBoolean(TTP->isParameterPack());
260    } else {
261      ID.AddBoolean(false);
262      ID.AddPointer(Context.getCanonicalTemplateName(Template)
263                                                          .getAsVoidPointer());
264    }
265    break;
266  }
267
268  case Integral:
269    getAsIntegral().Profile(ID);
270    getIntegralType().Profile(ID);
271    break;
272
273  case Expression:
274    getAsExpr()->Profile(ID, Context, true);
275    break;
276
277  case Pack:
278    ID.AddInteger(Args.NumArgs);
279    for (unsigned I = 0; I != Args.NumArgs; ++I)
280      Args.Args[I].Profile(ID, Context);
281  }
282}
283
284bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
285  if (getKind() != Other.getKind()) return false;
286
287  switch (getKind()) {
288  case Null:
289  case Type:
290  case Expression:
291  case Template:
292  case TemplateExpansion:
293  case NullPtr:
294    return TypeOrValue.V == Other.TypeOrValue.V;
295
296  case Declaration:
297    return getAsDecl() == Other.getAsDecl();
298
299  case Integral:
300    return getIntegralType() == Other.getIntegralType() &&
301           getAsIntegral() == Other.getAsIntegral();
302
303  case Pack:
304    if (Args.NumArgs != Other.Args.NumArgs) return false;
305    for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
306      if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
307        return false;
308    return true;
309  }
310
311  llvm_unreachable("Invalid TemplateArgument Kind!");
312}
313
314TemplateArgument TemplateArgument::getPackExpansionPattern() const {
315  assert(isPackExpansion());
316
317  switch (getKind()) {
318  case Type:
319    return getAsType()->castAs<PackExpansionType>()->getPattern();
320
321  case Expression:
322    return cast<PackExpansionExpr>(getAsExpr())->getPattern();
323
324  case TemplateExpansion:
325    return TemplateArgument(getAsTemplateOrTemplatePattern());
326
327  case Declaration:
328  case Integral:
329  case Pack:
330  case Null:
331  case Template:
332  case NullPtr:
333    return TemplateArgument();
334  }
335
336  llvm_unreachable("Invalid TemplateArgument Kind!");
337}
338
339void TemplateArgument::print(const PrintingPolicy &Policy,
340                             raw_ostream &Out) const {
341  switch (getKind()) {
342  case Null:
343    Out << "(no value)";
344    break;
345
346  case Type: {
347    PrintingPolicy SubPolicy(Policy);
348    SubPolicy.SuppressStrongLifetime = true;
349    getAsType().print(Out, SubPolicy);
350    break;
351  }
352
353  case Declaration: {
354    NamedDecl *ND = getAsDecl();
355    if (!getParamTypeForDecl()->isReferenceType())
356      Out << '&';
357    ND->printQualifiedName(Out);
358    break;
359  }
360
361  case NullPtr:
362    Out << "nullptr";
363    break;
364
365  case Template:
366    getAsTemplate().print(Out, Policy);
367    break;
368
369  case TemplateExpansion:
370    getAsTemplateOrTemplatePattern().print(Out, Policy);
371    Out << "...";
372    break;
373
374  case Integral:
375    printIntegral(*this, Out, Policy);
376    break;
377
378  case Expression:
379    getAsExpr()->printPretty(Out, nullptr, Policy);
380    break;
381
382  case Pack:
383    Out << "<";
384    bool First = true;
385    for (const auto &P : pack_elements()) {
386      if (First)
387        First = false;
388      else
389        Out << ", ";
390
391      P.print(Policy, Out);
392    }
393    Out << ">";
394    break;
395  }
396}
397
398void TemplateArgument::dump(raw_ostream &Out) const {
399  LangOptions LO; // FIXME! see also TemplateName::dump().
400  LO.CPlusPlus = true;
401  LO.Bool = true;
402  print(PrintingPolicy(LO), Out);
403}
404
405LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }
406
407//===----------------------------------------------------------------------===//
408// TemplateArgumentLoc Implementation
409//===----------------------------------------------------------------------===//
410
411SourceRange TemplateArgumentLoc::getSourceRange() const {
412  switch (Argument.getKind()) {
413  case TemplateArgument::Expression:
414    return getSourceExpression()->getSourceRange();
415
416  case TemplateArgument::Declaration:
417    return getSourceDeclExpression()->getSourceRange();
418
419  case TemplateArgument::NullPtr:
420    return getSourceNullPtrExpression()->getSourceRange();
421
422  case TemplateArgument::Type:
423    if (TypeSourceInfo *TSI = getTypeSourceInfo())
424      return TSI->getTypeLoc().getSourceRange();
425    else
426      return SourceRange();
427
428  case TemplateArgument::Template:
429    if (getTemplateQualifierLoc())
430      return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
431                         getTemplateNameLoc());
432    return SourceRange(getTemplateNameLoc());
433
434  case TemplateArgument::TemplateExpansion:
435    if (getTemplateQualifierLoc())
436      return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
437                         getTemplateEllipsisLoc());
438    return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
439
440  case TemplateArgument::Integral:
441    return getSourceIntegralExpression()->getSourceRange();
442
443  case TemplateArgument::Pack:
444  case TemplateArgument::Null:
445    return SourceRange();
446  }
447
448  llvm_unreachable("Invalid TemplateArgument Kind!");
449}
450
451const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
452                                           const TemplateArgument &Arg) {
453  switch (Arg.getKind()) {
454  case TemplateArgument::Null:
455    // This is bad, but not as bad as crashing because of argument
456    // count mismatches.
457    return DB << "(null template argument)";
458
459  case TemplateArgument::Type:
460    return DB << Arg.getAsType();
461
462  case TemplateArgument::Declaration:
463    return DB << Arg.getAsDecl();
464
465  case TemplateArgument::NullPtr:
466    return DB << "nullptr";
467
468  case TemplateArgument::Integral:
469    return DB << Arg.getAsIntegral().toString(10);
470
471  case TemplateArgument::Template:
472    return DB << Arg.getAsTemplate();
473
474  case TemplateArgument::TemplateExpansion:
475    return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
476
477  case TemplateArgument::Expression: {
478    // This shouldn't actually ever happen, so it's okay that we're
479    // regurgitating an expression here.
480    // FIXME: We're guessing at LangOptions!
481    SmallString<32> Str;
482    llvm::raw_svector_ostream OS(Str);
483    LangOptions LangOpts;
484    LangOpts.CPlusPlus = true;
485    PrintingPolicy Policy(LangOpts);
486    Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
487    return DB << OS.str();
488  }
489
490  case TemplateArgument::Pack: {
491    // FIXME: We're guessing at LangOptions!
492    SmallString<32> Str;
493    llvm::raw_svector_ostream OS(Str);
494    LangOptions LangOpts;
495    LangOpts.CPlusPlus = true;
496    PrintingPolicy Policy(LangOpts);
497    Arg.print(Policy, OS);
498    return DB << OS.str();
499  }
500  }
501
502  llvm_unreachable("Invalid TemplateArgument Kind!");
503}
504
505const ASTTemplateArgumentListInfo *
506ASTTemplateArgumentListInfo::Create(const ASTContext &C,
507                                    const TemplateArgumentListInfo &List) {
508  std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
509  void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
510  return new (Mem) ASTTemplateArgumentListInfo(List);
511}
512
513ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
514    const TemplateArgumentListInfo &Info) {
515  LAngleLoc = Info.getLAngleLoc();
516  RAngleLoc = Info.getRAngleLoc();
517  NumTemplateArgs = Info.size();
518
519  TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
520  for (unsigned i = 0; i != NumTemplateArgs; ++i)
521    new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
522}
523
524void ASTTemplateKWAndArgsInfo::initializeFrom(
525    SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
526    TemplateArgumentLoc *OutArgArray) {
527  this->TemplateKWLoc = TemplateKWLoc;
528  LAngleLoc = Info.getLAngleLoc();
529  RAngleLoc = Info.getRAngleLoc();
530  NumTemplateArgs = Info.size();
531
532  for (unsigned i = 0; i != NumTemplateArgs; ++i)
533    new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
534}
535
536void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
537  assert(TemplateKWLoc.isValid());
538  LAngleLoc = SourceLocation();
539  RAngleLoc = SourceLocation();
540  this->TemplateKWLoc = TemplateKWLoc;
541  NumTemplateArgs = 0;
542}
543
544void ASTTemplateKWAndArgsInfo::initializeFrom(
545    SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
546    TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
547  this->TemplateKWLoc = TemplateKWLoc;
548  LAngleLoc = Info.getLAngleLoc();
549  RAngleLoc = Info.getRAngleLoc();
550  NumTemplateArgs = Info.size();
551
552  for (unsigned i = 0; i != NumTemplateArgs; ++i) {
553    Deps |= Info[i].getArgument().getDependence();
554
555    new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
556  }
557}
558
559void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
560                                        TemplateArgumentListInfo &Info) const {
561  Info.setLAngleLoc(LAngleLoc);
562  Info.setRAngleLoc(RAngleLoc);
563  for (unsigned I = 0; I != NumTemplateArgs; ++I)
564    Info.addArgument(ArgArray[I]);
565}
566