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