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