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