TemplateBase.cpp revision 218893
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>
27218893Sdim#include <iomanip>
28218893Sdim#include <sstream>
29198893Srdivacky
30198893Srdivackyusing namespace clang;
31198893Srdivacky
32218893Sdim/// \brief Print a template integral argument value.
33218893Sdim///
34218893Sdim/// \param TemplArg the TemplateArgument instance to print.
35218893Sdim///
36218893Sdim/// \param Out the raw_ostream instance to use for printing.
37218893Sdimstatic void printIntegral(const TemplateArgument &TemplArg,
38218893Sdim                          llvm::raw_ostream &Out) {
39218893Sdim  const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
40218893Sdim  const llvm::APSInt *Val = TemplArg.getAsIntegral();
41218893Sdim
42218893Sdim  if (T->isBooleanType()) {
43218893Sdim    Out << (Val->getBoolValue() ? "true" : "false");
44218893Sdim  } else if (T->isCharType()) {
45218893Sdim    char Ch = Val->getSExtValue();
46218893Sdim    if (std::isprint(Ch)) {
47218893Sdim      Out << "'";
48218893Sdim      if (Ch == '\'' || Ch == '\\')
49218893Sdim        Out << '\\';
50218893Sdim      Out << Ch << "'";
51218893Sdim    } else {
52218893Sdim      std::ostringstream Str;
53218893Sdim      Str << std::setw(2) << std::setfill('0') << std::hex << (int)Ch;
54218893Sdim      Out << "'\\x" << Str.str() << "'";
55218893Sdim    }
56218893Sdim  } else {
57218893Sdim    Out << Val->toString(10);
58218893Sdim  }
59218893Sdim}
60218893Sdim
61198893Srdivacky//===----------------------------------------------------------------------===//
62198893Srdivacky// TemplateArgument Implementation
63198893Srdivacky//===----------------------------------------------------------------------===//
64198893Srdivacky
65218893SdimTemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
66218893Sdim                                                  const TemplateArgument *Args,
67218893Sdim                                                  unsigned NumArgs) {
68218893Sdim  if (NumArgs == 0)
69218893Sdim    return TemplateArgument(0, 0);
70218893Sdim
71218893Sdim  TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
72218893Sdim  std::copy(Args, Args + NumArgs, Storage);
73218893Sdim  return TemplateArgument(Storage, NumArgs);
74218893Sdim}
75198893Srdivacky
76218893Sdimbool TemplateArgument::isDependent() const {
77218893Sdim  switch (getKind()) {
78218893Sdim  case Null:
79218893Sdim    assert(false && "Should not have a NULL template argument");
80218893Sdim    return false;
81218893Sdim
82218893Sdim  case Type:
83218893Sdim    return getAsType()->isDependentType();
84218893Sdim
85218893Sdim  case Template:
86218893Sdim    return getAsTemplate().isDependent();
87218893Sdim
88218893Sdim  case TemplateExpansion:
89218893Sdim    return true;
90218893Sdim
91218893Sdim  case Declaration:
92218893Sdim    if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
93218893Sdim      return DC->isDependentContext();
94218893Sdim    return getAsDecl()->getDeclContext()->isDependentContext();
95218893Sdim
96218893Sdim  case Integral:
97218893Sdim    // Never dependent
98218893Sdim    return false;
99218893Sdim
100218893Sdim  case Expression:
101218893Sdim    return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
102218893Sdim
103218893Sdim  case Pack:
104218893Sdim    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
105218893Sdim      if (P->isDependent())
106218893Sdim        return true;
107218893Sdim    }
108218893Sdim
109218893Sdim    return false;
110198893Srdivacky  }
111198893Srdivacky
112218893Sdim  return false;
113198893Srdivacky}
114198893Srdivacky
115218893Sdimbool TemplateArgument::isPackExpansion() const {
116218893Sdim  switch (getKind()) {
117218893Sdim  case Null:
118218893Sdim  case Declaration:
119218893Sdim  case Integral:
120218893Sdim  case Pack:
121218893Sdim  case Template:
122218893Sdim    return false;
123218893Sdim
124218893Sdim  case TemplateExpansion:
125218893Sdim    return true;
126218893Sdim
127218893Sdim  case Type:
128218893Sdim    return isa<PackExpansionType>(getAsType());
129218893Sdim
130218893Sdim  case Expression:
131218893Sdim    return isa<PackExpansionExpr>(getAsExpr());
132218893Sdim  }
133218893Sdim
134218893Sdim  return false;
135218893Sdim}
136218893Sdim
137218893Sdimbool TemplateArgument::containsUnexpandedParameterPack() const {
138218893Sdim  switch (getKind()) {
139218893Sdim  case Null:
140218893Sdim  case Declaration:
141218893Sdim  case Integral:
142218893Sdim  case TemplateExpansion:
143218893Sdim    break;
144218893Sdim
145218893Sdim  case Type:
146218893Sdim    if (getAsType()->containsUnexpandedParameterPack())
147218893Sdim      return true;
148218893Sdim    break;
149218893Sdim
150218893Sdim  case Template:
151218893Sdim    if (getAsTemplate().containsUnexpandedParameterPack())
152218893Sdim      return true;
153218893Sdim    break;
154218893Sdim
155218893Sdim  case Expression:
156218893Sdim    if (getAsExpr()->containsUnexpandedParameterPack())
157218893Sdim      return true;
158218893Sdim    break;
159218893Sdim
160218893Sdim  case Pack:
161218893Sdim    for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
162218893Sdim      if (P->containsUnexpandedParameterPack())
163218893Sdim        return true;
164218893Sdim
165218893Sdim    break;
166218893Sdim  }
167218893Sdim
168218893Sdim  return false;
169218893Sdim}
170218893Sdim
171218893Sdimllvm::Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
172218893Sdim  assert(Kind == TemplateExpansion);
173218893Sdim  if (TemplateArg.NumExpansions)
174218893Sdim    return TemplateArg.NumExpansions - 1;
175218893Sdim
176218893Sdim  return llvm::Optional<unsigned>();
177218893Sdim}
178218893Sdim
179198893Srdivackyvoid TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
180218893Sdim                               const ASTContext &Context) const {
181198893Srdivacky  ID.AddInteger(Kind);
182198893Srdivacky  switch (Kind) {
183198893Srdivacky  case Null:
184198893Srdivacky    break;
185198893Srdivacky
186198893Srdivacky  case Type:
187198893Srdivacky    getAsType().Profile(ID);
188198893Srdivacky    break;
189198893Srdivacky
190198893Srdivacky  case Declaration:
191198893Srdivacky    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
192198893Srdivacky    break;
193198893Srdivacky
194199482Srdivacky  case Template:
195218893Sdim  case TemplateExpansion: {
196218893Sdim    TemplateName Template = getAsTemplateOrTemplatePattern();
197199990Srdivacky    if (TemplateTemplateParmDecl *TTP
198199990Srdivacky          = dyn_cast_or_null<TemplateTemplateParmDecl>(
199218893Sdim                                                Template.getAsTemplateDecl())) {
200199990Srdivacky      ID.AddBoolean(true);
201199990Srdivacky      ID.AddInteger(TTP->getDepth());
202199990Srdivacky      ID.AddInteger(TTP->getPosition());
203218893Sdim      ID.AddBoolean(TTP->isParameterPack());
204199990Srdivacky    } else {
205199990Srdivacky      ID.AddBoolean(false);
206218893Sdim      ID.AddPointer(Context.getCanonicalTemplateName(Template)
207218893Sdim                                                          .getAsVoidPointer());
208199990Srdivacky    }
209199482Srdivacky    break;
210218893Sdim  }
211199482Srdivacky
212198893Srdivacky  case Integral:
213198893Srdivacky    getAsIntegral()->Profile(ID);
214198893Srdivacky    getIntegralType().Profile(ID);
215198893Srdivacky    break;
216198893Srdivacky
217198893Srdivacky  case Expression:
218198893Srdivacky    getAsExpr()->Profile(ID, Context, true);
219198893Srdivacky    break;
220198893Srdivacky
221198893Srdivacky  case Pack:
222198893Srdivacky    ID.AddInteger(Args.NumArgs);
223198893Srdivacky    for (unsigned I = 0; I != Args.NumArgs; ++I)
224198893Srdivacky      Args.Args[I].Profile(ID, Context);
225198893Srdivacky  }
226198893Srdivacky}
227198893Srdivacky
228210299Sedbool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
229210299Sed  if (getKind() != Other.getKind()) return false;
230210299Sed
231210299Sed  switch (getKind()) {
232210299Sed  case Null:
233210299Sed  case Type:
234210299Sed  case Declaration:
235218893Sdim  case Expression:
236210299Sed  case Template:
237218893Sdim  case TemplateExpansion:
238210299Sed    return TypeOrValue == Other.TypeOrValue;
239210299Sed
240210299Sed  case Integral:
241210299Sed    return getIntegralType() == Other.getIntegralType() &&
242210299Sed           *getAsIntegral() == *Other.getAsIntegral();
243210299Sed
244210299Sed  case Pack:
245210299Sed    if (Args.NumArgs != Other.Args.NumArgs) return false;
246210299Sed    for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
247210299Sed      if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
248210299Sed        return false;
249210299Sed    return true;
250210299Sed  }
251210299Sed
252210299Sed  // Suppress warnings.
253210299Sed  return false;
254210299Sed}
255210299Sed
256218893SdimTemplateArgument TemplateArgument::getPackExpansionPattern() const {
257218893Sdim  assert(isPackExpansion());
258218893Sdim
259218893Sdim  switch (getKind()) {
260218893Sdim  case Type:
261218893Sdim    return getAsType()->getAs<PackExpansionType>()->getPattern();
262218893Sdim
263218893Sdim  case Expression:
264218893Sdim    return cast<PackExpansionExpr>(getAsExpr())->getPattern();
265218893Sdim
266218893Sdim  case TemplateExpansion:
267218893Sdim    return TemplateArgument(getAsTemplateOrTemplatePattern());
268218893Sdim
269218893Sdim  case Declaration:
270218893Sdim  case Integral:
271218893Sdim  case Pack:
272218893Sdim  case Null:
273218893Sdim  case Template:
274218893Sdim    return TemplateArgument();
275218893Sdim  }
276218893Sdim
277218893Sdim  return TemplateArgument();
278218893Sdim}
279218893Sdim
280218893Sdimvoid TemplateArgument::print(const PrintingPolicy &Policy,
281218893Sdim                             llvm::raw_ostream &Out) const {
282218893Sdim  switch (getKind()) {
283218893Sdim  case Null:
284218893Sdim    Out << "<no value>";
285218893Sdim    break;
286218893Sdim
287218893Sdim  case Type: {
288218893Sdim    std::string TypeStr;
289218893Sdim    getAsType().getAsStringInternal(TypeStr, Policy);
290218893Sdim    Out << TypeStr;
291218893Sdim    break;
292218893Sdim  }
293218893Sdim
294218893Sdim  case Declaration: {
295218893Sdim    bool Unnamed = true;
296218893Sdim    if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getAsDecl())) {
297218893Sdim      if (ND->getDeclName()) {
298218893Sdim        Unnamed = false;
299218893Sdim        Out << ND->getNameAsString();
300218893Sdim      }
301218893Sdim    }
302218893Sdim
303218893Sdim    if (Unnamed) {
304218893Sdim      Out << "<anonymous>";
305218893Sdim    }
306218893Sdim    break;
307218893Sdim  }
308218893Sdim
309218893Sdim  case Template:
310218893Sdim    getAsTemplate().print(Out, Policy);
311218893Sdim    break;
312218893Sdim
313218893Sdim  case TemplateExpansion:
314218893Sdim    getAsTemplateOrTemplatePattern().print(Out, Policy);
315218893Sdim    Out << "...";
316218893Sdim    break;
317218893Sdim
318218893Sdim  case Integral: {
319218893Sdim    printIntegral(*this, Out);
320218893Sdim    break;
321218893Sdim  }
322218893Sdim
323218893Sdim  case Expression:
324218893Sdim    getAsExpr()->printPretty(Out, 0, Policy);
325218893Sdim    break;
326218893Sdim
327218893Sdim  case Pack:
328218893Sdim    Out << "<";
329218893Sdim    bool First = true;
330218893Sdim    for (TemplateArgument::pack_iterator P = pack_begin(), PEnd = pack_end();
331218893Sdim         P != PEnd; ++P) {
332218893Sdim      if (First)
333218893Sdim        First = false;
334218893Sdim      else
335218893Sdim        Out << ", ";
336218893Sdim
337218893Sdim      P->print(Policy, Out);
338218893Sdim    }
339218893Sdim    Out << ">";
340218893Sdim    break;
341218893Sdim  }
342218893Sdim}
343218893Sdim
344198893Srdivacky//===----------------------------------------------------------------------===//
345198893Srdivacky// TemplateArgumentLoc Implementation
346198893Srdivacky//===----------------------------------------------------------------------===//
347198893Srdivacky
348218893SdimTemplateArgumentLocInfo::TemplateArgumentLocInfo() {
349218893Sdim  memset(this, 0, sizeof(TemplateArgumentLocInfo));
350218893Sdim}
351218893Sdim
352198893SrdivackySourceRange TemplateArgumentLoc::getSourceRange() const {
353198893Srdivacky  switch (Argument.getKind()) {
354198893Srdivacky  case TemplateArgument::Expression:
355198893Srdivacky    return getSourceExpression()->getSourceRange();
356212904Sdim
357198893Srdivacky  case TemplateArgument::Declaration:
358198893Srdivacky    return getSourceDeclExpression()->getSourceRange();
359212904Sdim
360198893Srdivacky  case TemplateArgument::Type:
361212904Sdim    if (TypeSourceInfo *TSI = getTypeSourceInfo())
362212904Sdim      return TSI->getTypeLoc().getSourceRange();
363212904Sdim    else
364212904Sdim      return SourceRange();
365212904Sdim
366199482Srdivacky  case TemplateArgument::Template:
367199482Srdivacky    if (getTemplateQualifierRange().isValid())
368218893Sdim      return SourceRange(getTemplateQualifierRange().getBegin(),
369199482Srdivacky                         getTemplateNameLoc());
370199482Srdivacky    return SourceRange(getTemplateNameLoc());
371212904Sdim
372218893Sdim  case TemplateArgument::TemplateExpansion:
373218893Sdim    if (getTemplateQualifierRange().isValid())
374218893Sdim      return SourceRange(getTemplateQualifierRange().getBegin(),
375218893Sdim                         getTemplateEllipsisLoc());
376218893Sdim    return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
377218893Sdim
378198893Srdivacky  case TemplateArgument::Integral:
379198893Srdivacky  case TemplateArgument::Pack:
380198893Srdivacky  case TemplateArgument::Null:
381198893Srdivacky    return SourceRange();
382198893Srdivacky  }
383198893Srdivacky
384198893Srdivacky  // Silence bonus gcc warning.
385198893Srdivacky  return SourceRange();
386198893Srdivacky}
387208600Srdivacky
388218893SdimTemplateArgumentLoc
389218893SdimTemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis,
390218893Sdim                                       llvm::Optional<unsigned> &NumExpansions,
391218893Sdim                                             ASTContext &Context) const {
392218893Sdim  assert(Argument.isPackExpansion());
393218893Sdim
394218893Sdim  switch (Argument.getKind()) {
395218893Sdim  case TemplateArgument::Type: {
396218893Sdim    // FIXME: We shouldn't ever have to worry about missing
397218893Sdim    // type-source info!
398218893Sdim    TypeSourceInfo *ExpansionTSInfo = getTypeSourceInfo();
399218893Sdim    if (!ExpansionTSInfo)
400218893Sdim      ExpansionTSInfo = Context.getTrivialTypeSourceInfo(
401218893Sdim                                                     getArgument().getAsType(),
402218893Sdim                                                         Ellipsis);
403218893Sdim    PackExpansionTypeLoc Expansion
404218893Sdim      = cast<PackExpansionTypeLoc>(ExpansionTSInfo->getTypeLoc());
405218893Sdim    Ellipsis = Expansion.getEllipsisLoc();
406218893Sdim
407218893Sdim    TypeLoc Pattern = Expansion.getPatternLoc();
408218893Sdim    NumExpansions = Expansion.getTypePtr()->getNumExpansions();
409218893Sdim
410218893Sdim    // FIXME: This is horrible. We know where the source location data is for
411218893Sdim    // the pattern, and we have the pattern's type, but we are forced to copy
412218893Sdim    // them into an ASTContext because TypeSourceInfo bundles them together
413218893Sdim    // and TemplateArgumentLoc traffics in TypeSourceInfo pointers.
414218893Sdim    TypeSourceInfo *PatternTSInfo
415218893Sdim      = Context.CreateTypeSourceInfo(Pattern.getType(),
416218893Sdim                                     Pattern.getFullDataSize());
417218893Sdim    memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(),
418218893Sdim           Pattern.getOpaqueData(), Pattern.getFullDataSize());
419218893Sdim    return TemplateArgumentLoc(TemplateArgument(Pattern.getType()),
420218893Sdim                               PatternTSInfo);
421218893Sdim  }
422218893Sdim
423218893Sdim  case TemplateArgument::Expression: {
424218893Sdim    PackExpansionExpr *Expansion
425218893Sdim      = cast<PackExpansionExpr>(Argument.getAsExpr());
426218893Sdim    Expr *Pattern = Expansion->getPattern();
427218893Sdim    Ellipsis = Expansion->getEllipsisLoc();
428218893Sdim    NumExpansions = Expansion->getNumExpansions();
429218893Sdim    return TemplateArgumentLoc(Pattern, Pattern);
430218893Sdim  }
431218893Sdim
432218893Sdim  case TemplateArgument::TemplateExpansion:
433218893Sdim    Ellipsis = getTemplateEllipsisLoc();
434218893Sdim    NumExpansions = Argument.getNumTemplateExpansions();
435218893Sdim    return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
436218893Sdim                               getTemplateQualifierRange(),
437218893Sdim                               getTemplateNameLoc());
438218893Sdim
439218893Sdim  case TemplateArgument::Declaration:
440218893Sdim  case TemplateArgument::Template:
441218893Sdim  case TemplateArgument::Integral:
442218893Sdim  case TemplateArgument::Pack:
443218893Sdim  case TemplateArgument::Null:
444218893Sdim    return TemplateArgumentLoc();
445218893Sdim  }
446218893Sdim
447218893Sdim  return TemplateArgumentLoc();
448218893Sdim}
449218893Sdim
450208600Srdivackyconst DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
451208600Srdivacky                                           const TemplateArgument &Arg) {
452208600Srdivacky  switch (Arg.getKind()) {
453208600Srdivacky  case TemplateArgument::Null:
454212904Sdim    // This is bad, but not as bad as crashing because of argument
455212904Sdim    // count mismatches.
456212904Sdim    return DB << "(null template argument)";
457208600Srdivacky
458208600Srdivacky  case TemplateArgument::Type:
459208600Srdivacky    return DB << Arg.getAsType();
460208600Srdivacky
461208600Srdivacky  case TemplateArgument::Declaration:
462208600Srdivacky    return DB << Arg.getAsDecl();
463208600Srdivacky
464208600Srdivacky  case TemplateArgument::Integral:
465208600Srdivacky    return DB << Arg.getAsIntegral()->toString(10);
466208600Srdivacky
467208600Srdivacky  case TemplateArgument::Template:
468208600Srdivacky    return DB << Arg.getAsTemplate();
469218893Sdim
470218893Sdim  case TemplateArgument::TemplateExpansion:
471218893Sdim    return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
472218893Sdim
473208600Srdivacky  case TemplateArgument::Expression: {
474208600Srdivacky    // This shouldn't actually ever happen, so it's okay that we're
475208600Srdivacky    // regurgitating an expression here.
476208600Srdivacky    // FIXME: We're guessing at LangOptions!
477208600Srdivacky    llvm::SmallString<32> Str;
478208600Srdivacky    llvm::raw_svector_ostream OS(Str);
479208600Srdivacky    LangOptions LangOpts;
480208600Srdivacky    LangOpts.CPlusPlus = true;
481208600Srdivacky    PrintingPolicy Policy(LangOpts);
482208600Srdivacky    Arg.getAsExpr()->printPretty(OS, 0, Policy);
483208600Srdivacky    return DB << OS.str();
484208600Srdivacky  }
485208600Srdivacky
486218893Sdim  case TemplateArgument::Pack: {
487218893Sdim    // FIXME: We're guessing at LangOptions!
488218893Sdim    llvm::SmallString<32> Str;
489218893Sdim    llvm::raw_svector_ostream OS(Str);
490218893Sdim    LangOptions LangOpts;
491218893Sdim    LangOpts.CPlusPlus = true;
492218893Sdim    PrintingPolicy Policy(LangOpts);
493218893Sdim    Arg.print(Policy, OS);
494218893Sdim    return DB << OS.str();
495208600Srdivacky  }
496218893Sdim  }
497208600Srdivacky
498208600Srdivacky  return DB;
499208600Srdivacky}
500