TemplateBase.cpp revision 221345
1198893Srdivacky//===--- TemplateBase.cpp - Common template AST class implementation ------===//
2198893Srdivacky//
3198893Srdivacky//                     The LLVM Compiler Infrastructure
4198893Srdivacky//
5198893Srdivacky// This file is distributed under the University of Illinois Open Source
6198893Srdivacky// License. See LICENSE.TXT for details.
7198893Srdivacky//
8198893Srdivacky//===----------------------------------------------------------------------===//
9198893Srdivacky//
10198893Srdivacky// This file implements common classes used throughout C++ template
11198893Srdivacky// representations.
12198893Srdivacky//
13198893Srdivacky//===----------------------------------------------------------------------===//
14198893Srdivacky
15198893Srdivacky#include "clang/AST/TemplateBase.h"
16218893Sdim#include "clang/AST/ASTContext.h"
17198893Srdivacky#include "clang/AST/DeclBase.h"
18199990Srdivacky#include "clang/AST/DeclTemplate.h"
19198893Srdivacky#include "clang/AST/Expr.h"
20218893Sdim#include "clang/AST/ExprCXX.h"
21218893Sdim#include "clang/AST/Type.h"
22198893Srdivacky#include "clang/AST/TypeLoc.h"
23208600Srdivacky#include "clang/Basic/Diagnostic.h"
24218893Sdim#include "llvm/ADT/FoldingSet.h"
25218893Sdim#include <algorithm>
26218893Sdim#include <cctype>
27198893Srdivacky
28198893Srdivackyusing namespace clang;
29198893Srdivacky
30218893Sdim/// \brief Print a template integral argument value.
31218893Sdim///
32218893Sdim/// \param TemplArg the TemplateArgument instance to print.
33218893Sdim///
34218893Sdim/// \param Out the raw_ostream instance to use for printing.
35218893Sdimstatic void printIntegral(const TemplateArgument &TemplArg,
36218893Sdim                          llvm::raw_ostream &Out) {
37218893Sdim  const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
38218893Sdim  const llvm::APSInt *Val = TemplArg.getAsIntegral();
39218893Sdim
40218893Sdim  if (T->isBooleanType()) {
41218893Sdim    Out << (Val->getBoolValue() ? "true" : "false");
42218893Sdim  } else if (T->isCharType()) {
43219077Sdim    const unsigned char Ch = Val->getZExtValue();
44219077Sdim    const std::string Str(1, Ch);
45219077Sdim    Out << ((Ch == '\'') ? "'\\" : "'");
46219077Sdim    Out.write_escaped(Str, /*UseHexEscapes=*/ true);
47219077Sdim    Out << "'";
48218893Sdim  } else {
49218893Sdim    Out << Val->toString(10);
50218893Sdim  }
51218893Sdim}
52218893Sdim
53198893Srdivacky//===----------------------------------------------------------------------===//
54198893Srdivacky// TemplateArgument Implementation
55198893Srdivacky//===----------------------------------------------------------------------===//
56198893Srdivacky
57218893SdimTemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
58218893Sdim                                                  const TemplateArgument *Args,
59218893Sdim                                                  unsigned NumArgs) {
60218893Sdim  if (NumArgs == 0)
61218893Sdim    return TemplateArgument(0, 0);
62218893Sdim
63218893Sdim  TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
64218893Sdim  std::copy(Args, Args + NumArgs, Storage);
65218893Sdim  return TemplateArgument(Storage, NumArgs);
66218893Sdim}
67198893Srdivacky
68218893Sdimbool TemplateArgument::isDependent() const {
69218893Sdim  switch (getKind()) {
70218893Sdim  case Null:
71218893Sdim    assert(false && "Should not have a NULL template argument");
72218893Sdim    return false;
73218893Sdim
74218893Sdim  case Type:
75218893Sdim    return getAsType()->isDependentType();
76218893Sdim
77218893Sdim  case Template:
78218893Sdim    return getAsTemplate().isDependent();
79218893Sdim
80218893Sdim  case TemplateExpansion:
81218893Sdim    return true;
82218893Sdim
83218893Sdim  case Declaration:
84218893Sdim    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
85218893Sdim      return DC->isDependentContext();
86218893Sdim    return getAsDecl()->getDeclContext()->isDependentContext();
87218893Sdim
88218893Sdim  case Integral:
89218893Sdim    // Never dependent
90218893Sdim    return false;
91218893Sdim
92218893Sdim  case Expression:
93218893Sdim    return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
94218893Sdim
95218893Sdim  case Pack:
96218893Sdim    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
97218893Sdim      if (P->isDependent())
98218893Sdim        return true;
99218893Sdim    }
100218893Sdim
101218893Sdim    return false;
102198893Srdivacky  }
103198893Srdivacky
104218893Sdim  return false;
105198893Srdivacky}
106198893Srdivacky
107218893Sdimbool TemplateArgument::isPackExpansion() const {
108218893Sdim  switch (getKind()) {
109218893Sdim  case Null:
110218893Sdim  case Declaration:
111218893Sdim  case Integral:
112218893Sdim  case Pack:
113218893Sdim  case Template:
114218893Sdim    return false;
115218893Sdim
116218893Sdim  case TemplateExpansion:
117218893Sdim    return true;
118218893Sdim
119218893Sdim  case Type:
120218893Sdim    return isa<PackExpansionType>(getAsType());
121218893Sdim
122218893Sdim  case Expression:
123218893Sdim    return isa<PackExpansionExpr>(getAsExpr());
124218893Sdim  }
125218893Sdim
126218893Sdim  return false;
127218893Sdim}
128218893Sdim
129218893Sdimbool TemplateArgument::containsUnexpandedParameterPack() const {
130218893Sdim  switch (getKind()) {
131218893Sdim  case Null:
132218893Sdim  case Declaration:
133218893Sdim  case Integral:
134218893Sdim  case TemplateExpansion:
135218893Sdim    break;
136218893Sdim
137218893Sdim  case Type:
138218893Sdim    if (getAsType()->containsUnexpandedParameterPack())
139218893Sdim      return true;
140218893Sdim    break;
141218893Sdim
142218893Sdim  case Template:
143218893Sdim    if (getAsTemplate().containsUnexpandedParameterPack())
144218893Sdim      return true;
145218893Sdim    break;
146218893Sdim
147218893Sdim  case Expression:
148218893Sdim    if (getAsExpr()->containsUnexpandedParameterPack())
149218893Sdim      return true;
150218893Sdim    break;
151218893Sdim
152218893Sdim  case Pack:
153218893Sdim    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
154218893Sdim      if (P->containsUnexpandedParameterPack())
155218893Sdim        return true;
156218893Sdim
157218893Sdim    break;
158218893Sdim  }
159218893Sdim
160218893Sdim  return false;
161218893Sdim}
162218893Sdim
163218893Sdimllvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
164218893Sdim  assert(Kind == TemplateExpansion);
165218893Sdim  if (TemplateArg.NumExpansions)
166218893Sdim    return TemplateArg.NumExpansions - 1;
167218893Sdim
168218893Sdim  return llvm::Optional<unsigned>();
169218893Sdim}
170218893Sdim
171198893Srdivackyvoid TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
172218893Sdim                               const ASTContext &Context) const {
173198893Srdivacky  ID.AddInteger(Kind);
174198893Srdivacky  switch (Kind) {
175198893Srdivacky  case Null:
176198893Srdivacky    break;
177198893Srdivacky
178198893Srdivacky  case Type:
179198893Srdivacky    getAsType().Profile(ID);
180198893Srdivacky    break;
181198893Srdivacky
182198893Srdivacky  case Declaration:
183198893Srdivacky    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
184198893Srdivacky    break;
185198893Srdivacky
186199482Srdivacky  case Template:
187218893Sdim  case TemplateExpansion: {
188218893Sdim    TemplateName Template = getAsTemplateOrTemplatePattern();
189199990Srdivacky    if (TemplateTemplateParmDecl *TTP
190199990Srdivacky          = dyn_cast_or_null<TemplateTemplateParmDecl>(
191218893Sdim                                                Template.getAsTemplateDecl())) {
192199990Srdivacky      ID.AddBoolean(true);
193199990Srdivacky      ID.AddInteger(TTP->getDepth());
194199990Srdivacky      ID.AddInteger(TTP->getPosition());
195218893Sdim      ID.AddBoolean(TTP->isParameterPack());
196199990Srdivacky    } else {
197199990Srdivacky      ID.AddBoolean(false);
198218893Sdim      ID.AddPointer(Context.getCanonicalTemplateName(Template)
199218893Sdim                                                          .getAsVoidPointer());
200199990Srdivacky    }
201199482Srdivacky    break;
202218893Sdim  }
203199482Srdivacky
204198893Srdivacky  case Integral:
205198893Srdivacky    getAsIntegral()->Profile(ID);
206198893Srdivacky    getIntegralType().Profile(ID);
207198893Srdivacky    break;
208198893Srdivacky
209198893Srdivacky  case Expression:
210198893Srdivacky    getAsExpr()->Profile(ID, Context, true);
211198893Srdivacky    break;
212198893Srdivacky
213198893Srdivacky  case Pack:
214198893Srdivacky    ID.AddInteger(Args.NumArgs);
215198893Srdivacky    for (unsigned I = 0; I != Args.NumArgs; ++I)
216198893Srdivacky      Args.Args[I].Profile(ID, Context);
217198893Srdivacky  }
218198893Srdivacky}
219198893Srdivacky
220210299Sedbool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
221210299Sed  if (getKind() != Other.getKind()) return false;
222210299Sed
223210299Sed  switch (getKind()) {
224210299Sed  case Null:
225210299Sed  case Type:
226210299Sed  case Declaration:
227218893Sdim  case Expression:
228210299Sed  case Template:
229218893Sdim  case TemplateExpansion:
230210299Sed    return TypeOrValue == Other.TypeOrValue;
231210299Sed
232210299Sed  case Integral:
233210299Sed    return getIntegralType() == Other.getIntegralType() &&
234210299Sed           *getAsIntegral() == *Other.getAsIntegral();
235210299Sed
236210299Sed  case Pack:
237210299Sed    if (Args.NumArgs != Other.Args.NumArgs) return false;
238210299Sed    for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
239210299Sed      if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
240210299Sed        return false;
241210299Sed    return true;
242210299Sed  }
243210299Sed
244210299Sed  // Suppress warnings.
245210299Sed  return false;
246210299Sed}
247210299Sed
248218893SdimTemplateArgument TemplateArgument::getPackExpansionPattern() const {
249218893Sdim  assert(isPackExpansion());
250218893Sdim
251218893Sdim  switch (getKind()) {
252218893Sdim  case Type:
253218893Sdim    return getAsType()->getAs<PackExpansionType>()->getPattern();
254218893Sdim
255218893Sdim  case Expression:
256218893Sdim    return cast<PackExpansionExpr>(getAsExpr())->getPattern();
257218893Sdim
258218893Sdim  case TemplateExpansion:
259218893Sdim    return TemplateArgument(getAsTemplateOrTemplatePattern());
260218893Sdim
261218893Sdim  case Declaration:
262218893Sdim  case Integral:
263218893Sdim  case Pack:
264218893Sdim  case Null:
265218893Sdim  case Template:
266218893Sdim    return TemplateArgument();
267218893Sdim  }
268218893Sdim
269218893Sdim  return TemplateArgument();
270218893Sdim}
271218893Sdim
272218893Sdimvoid TemplateArgument::print(const PrintingPolicy &Policy,
273218893Sdim                             llvm::raw_ostream &Out) const {
274218893Sdim  switch (getKind()) {
275218893Sdim  case Null:
276218893Sdim    Out << "<no value>";
277218893Sdim    break;
278218893Sdim
279218893Sdim  case Type: {
280218893Sdim    std::string TypeStr;
281218893Sdim    getAsType().getAsStringInternal(TypeStr, Policy);
282218893Sdim    Out << TypeStr;
283218893Sdim    break;
284218893Sdim  }
285218893Sdim
286218893Sdim  case Declaration: {
287218893Sdim    bool Unnamed = true;
288218893Sdim    if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
289218893Sdim      if (ND->getDeclName()) {
290218893Sdim        Unnamed = false;
291218893Sdim        Out << ND->getNameAsString();
292218893Sdim      }
293218893Sdim    }
294218893Sdim
295218893Sdim    if (Unnamed) {
296218893Sdim      Out << "<anonymous>";
297218893Sdim    }
298218893Sdim    break;
299218893Sdim  }
300218893Sdim
301218893Sdim  case Template:
302218893Sdim    getAsTemplate().print(Out, Policy);
303218893Sdim    break;
304218893Sdim
305218893Sdim  case TemplateExpansion:
306218893Sdim    getAsTemplateOrTemplatePattern().print(Out, Policy);
307218893Sdim    Out << "...";
308218893Sdim    break;
309218893Sdim
310218893Sdim  case Integral: {
311218893Sdim    printIntegral(*this, Out);
312218893Sdim    break;
313218893Sdim  }
314218893Sdim
315218893Sdim  case Expression:
316218893Sdim    getAsExpr()->printPretty(Out, 0, Policy);
317218893Sdim    break;
318218893Sdim
319218893Sdim  case Pack:
320218893Sdim    Out << "<";
321218893Sdim    bool First = true;
322218893Sdim    for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
323218893Sdim         P != PEnd; ++P) {
324218893Sdim      if (First)
325218893Sdim        First = false;
326218893Sdim      else
327218893Sdim        Out << ", ";
328218893Sdim
329218893Sdim      P->print(Policy, Out);
330218893Sdim    }
331218893Sdim    Out << ">";
332218893Sdim    break;
333218893Sdim  }
334218893Sdim}
335218893Sdim
336198893Srdivacky//===----------------------------------------------------------------------===//
337198893Srdivacky// TemplateArgumentLoc Implementation
338198893Srdivacky//===----------------------------------------------------------------------===//
339198893Srdivacky
340218893SdimTemplateArgumentLocInfo::TemplateArgumentLocInfo() {
341221345Sdim  memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
342218893Sdim}
343218893Sdim
344198893SrdivackySourceRange TemplateArgumentLoc::getSourceRange() const {
345198893Srdivacky  switch (Argument.getKind()) {
346198893Srdivacky  case TemplateArgument::Expression:
347198893Srdivacky    return getSourceExpression()->getSourceRange();
348212904Sdim
349198893Srdivacky  case TemplateArgument::Declaration:
350198893Srdivacky    return getSourceDeclExpression()->getSourceRange();
351212904Sdim
352198893Srdivacky  case TemplateArgument::Type:
353212904Sdim    if (TypeSourceInfo *TSI = getTypeSourceInfo())
354212904Sdim      return TSI->getTypeLoc().getSourceRange();
355212904Sdim    else
356212904Sdim      return SourceRange();
357212904Sdim
358199482Srdivacky  case TemplateArgument::Template:
359221345Sdim    if (getTemplateQualifierLoc())
360221345Sdim      return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
361199482Srdivacky                         getTemplateNameLoc());
362199482Srdivacky    return SourceRange(getTemplateNameLoc());
363212904Sdim
364218893Sdim  case TemplateArgument::TemplateExpansion:
365221345Sdim    if (getTemplateQualifierLoc())
366221345Sdim      return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
367218893Sdim                         getTemplateEllipsisLoc());
368218893Sdim    return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
369218893Sdim
370198893Srdivacky  case TemplateArgument::Integral:
371198893Srdivacky  case TemplateArgument::Pack:
372198893Srdivacky  case TemplateArgument::Null:
373198893Srdivacky    return SourceRange();
374198893Srdivacky  }
375198893Srdivacky
376198893Srdivacky  // Silence bonus gcc warning.
377198893Srdivacky  return SourceRange();
378198893Srdivacky}
379208600Srdivacky
380218893SdimTemplateArgumentLoc
381218893SdimTemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
382218893Sdim                                       llvm::Optional<unsigned> &NumExpansions,
383218893Sdim                                             ASTContext &Context) const {
384218893Sdim  assert(Argument.isPackExpansion());
385218893Sdim
386218893Sdim  switch (Argument.getKind()) {
387218893Sdim  case TemplateArgument::Type: {
388218893Sdim    // FIXME: We shouldn't ever have to worry about missing
389218893Sdim    // type-source info!
390218893Sdim    TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
391218893Sdim    if (!ExpansionTSInfo)
392218893Sdim      ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
393218893Sdim                                                     getArgument().getAsType(),
394218893Sdim                                                         Ellipsis);
395218893Sdim    PackExpansionTypeLoc Expansion
396218893Sdim      = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
397218893Sdim    Ellipsis = Expansion.getEllipsisLoc();
398218893Sdim
399218893Sdim    TypeLoc Pattern = Expansion.getPatternLoc();
400218893Sdim    NumExpansions = Expansion.getTypePtr()->getNumExpansions();
401218893Sdim
402218893Sdim    // FIXME: This is horrible. We know where the source location data is for
403218893Sdim    // the pattern, and we have the pattern's type, but we are forced to copy
404218893Sdim    // them into an ASTContext because TypeSourceInfo bundles them together
405218893Sdim    // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
406218893Sdim    TypeSourceInfo *PatternTSInfo
407218893Sdim      = Context.CreateTypeSourceInfo(Pattern.getType(),
408218893Sdim                                     Pattern.getFullDataSize());
409218893Sdim    memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
410218893Sdim           Pattern.getOpaqueData(), Pattern.getFullDataSize());
411218893Sdim    return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
412218893Sdim                               PatternTSInfo);
413218893Sdim  }
414218893Sdim
415218893Sdim  case TemplateArgument::Expression: {
416218893Sdim    PackExpansionExpr *Expansion
417218893Sdim      = cast<PackExpansionExpr>(Argument.getAsExpr());
418218893Sdim    Expr *Pattern = Expansion->getPattern();
419218893Sdim    Ellipsis = Expansion->getEllipsisLoc();
420218893Sdim    NumExpansions = Expansion->getNumExpansions();
421218893Sdim    return TemplateArgumentLoc(Pattern, Pattern);
422218893Sdim  }
423218893Sdim
424218893Sdim  case TemplateArgument::TemplateExpansion:
425218893Sdim    Ellipsis = getTemplateEllipsisLoc();
426218893Sdim    NumExpansions = Argument.getNumTemplateExpansions();
427218893Sdim    return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
428221345Sdim                               getTemplateQualifierLoc(),
429218893Sdim                               getTemplateNameLoc());
430218893Sdim
431218893Sdim  case TemplateArgument::Declaration:
432218893Sdim  case TemplateArgument::Template:
433218893Sdim  case TemplateArgument::Integral:
434218893Sdim  case TemplateArgument::Pack:
435218893Sdim  case TemplateArgument::Null:
436218893Sdim    return TemplateArgumentLoc();
437218893Sdim  }
438218893Sdim
439218893Sdim  return TemplateArgumentLoc();
440218893Sdim}
441218893Sdim
442208600Srdivackyconst DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
443208600Srdivacky                                           const TemplateArgument &Arg) {
444208600Srdivacky  switch (Arg.getKind()) {
445208600Srdivacky  case TemplateArgument::Null:
446212904Sdim    // This is bad, but not as bad as crashing because of argument
447212904Sdim    // count mismatches.
448212904Sdim    return DB << "(null template argument)";
449208600Srdivacky
450208600Srdivacky  case TemplateArgument::Type:
451208600Srdivacky    return DB << Arg.getAsType();
452208600Srdivacky
453208600Srdivacky  case TemplateArgument::Declaration:
454208600Srdivacky    return DB << Arg.getAsDecl();
455208600Srdivacky
456208600Srdivacky  case TemplateArgument::Integral:
457208600Srdivacky    return DB << Arg.getAsIntegral()->toString(10);
458208600Srdivacky
459208600Srdivacky  case TemplateArgument::Template:
460208600Srdivacky    return DB << Arg.getAsTemplate();
461218893Sdim
462218893Sdim  case TemplateArgument::TemplateExpansion:
463218893Sdim    return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
464218893Sdim
465208600Srdivacky  case TemplateArgument::Expression: {
466208600Srdivacky    // This shouldn't actually ever happen, so it's okay that we're
467208600Srdivacky    // regurgitating an expression here.
468208600Srdivacky    // FIXME: We're guessing at LangOptions!
469208600Srdivacky    llvm::SmallString<32> Str;
470208600Srdivacky    llvm::raw_svector_ostream OS(Str);
471208600Srdivacky    LangOptions LangOpts;
472208600Srdivacky    LangOpts.CPlusPlus = true;
473208600Srdivacky    PrintingPolicy Policy(LangOpts);
474208600Srdivacky    Arg.getAsExpr()->printPretty(OS, 0, Policy);
475208600Srdivacky    return DB << OS.str();
476208600Srdivacky  }
477208600Srdivacky
478218893Sdim  case TemplateArgument::Pack: {
479218893Sdim    // FIXME: We're guessing at LangOptions!
480218893Sdim    llvm::SmallString<32> Str;
481218893Sdim    llvm::raw_svector_ostream OS(Str);
482218893Sdim    LangOptions LangOpts;
483218893Sdim    LangOpts.CPlusPlus = true;
484218893Sdim    PrintingPolicy Policy(LangOpts);
485218893Sdim    Arg.print(Policy, OS);
486218893Sdim    return DB << OS.str();
487208600Srdivacky  }
488218893Sdim  }
489208600Srdivacky
490208600Srdivacky  return DB;
491208600Srdivacky}
492