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