TemplateBase.cpp revision 210299
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 "llvm/ADT/FoldingSet.h"
16198893Srdivacky#include "clang/AST/TemplateBase.h"
17198893Srdivacky#include "clang/AST/DeclBase.h"
18199990Srdivacky#include "clang/AST/DeclTemplate.h"
19198893Srdivacky#include "clang/AST/Expr.h"
20198893Srdivacky#include "clang/AST/TypeLoc.h"
21208600Srdivacky#include "clang/Basic/Diagnostic.h"
22198893Srdivacky
23198893Srdivackyusing namespace clang;
24198893Srdivacky
25198893Srdivacky//===----------------------------------------------------------------------===//
26198893Srdivacky// TemplateArgument Implementation
27198893Srdivacky//===----------------------------------------------------------------------===//
28198893Srdivacky
29198893Srdivacky/// \brief Construct a template argument pack.
30198893Srdivackyvoid TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
31198893Srdivacky                                       bool CopyArgs) {
32198893Srdivacky  assert(isNull() && "Must call setArgumentPack on a null argument");
33198893Srdivacky
34198893Srdivacky  Kind = Pack;
35198893Srdivacky  Args.NumArgs = NumArgs;
36198893Srdivacky  Args.CopyArgs = CopyArgs;
37198893Srdivacky  if (!Args.CopyArgs) {
38198893Srdivacky    Args.Args = args;
39198893Srdivacky    return;
40198893Srdivacky  }
41198893Srdivacky
42198893Srdivacky  // FIXME: Allocate in ASTContext
43198893Srdivacky  Args.Args = new TemplateArgument[NumArgs];
44198893Srdivacky  for (unsigned I = 0; I != Args.NumArgs; ++I)
45198893Srdivacky    Args.Args[I] = args[I];
46198893Srdivacky}
47198893Srdivacky
48198893Srdivackyvoid TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
49198893Srdivacky                               ASTContext &Context) const {
50198893Srdivacky  ID.AddInteger(Kind);
51198893Srdivacky  switch (Kind) {
52198893Srdivacky  case Null:
53198893Srdivacky    break;
54198893Srdivacky
55198893Srdivacky  case Type:
56198893Srdivacky    getAsType().Profile(ID);
57198893Srdivacky    break;
58198893Srdivacky
59198893Srdivacky  case Declaration:
60198893Srdivacky    ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
61198893Srdivacky    break;
62198893Srdivacky
63199482Srdivacky  case Template:
64199990Srdivacky    if (TemplateTemplateParmDecl *TTP
65199990Srdivacky          = dyn_cast_or_null<TemplateTemplateParmDecl>(
66199990Srdivacky                                       getAsTemplate().getAsTemplateDecl())) {
67199990Srdivacky      ID.AddBoolean(true);
68199990Srdivacky      ID.AddInteger(TTP->getDepth());
69199990Srdivacky      ID.AddInteger(TTP->getPosition());
70199990Srdivacky    } else {
71199990Srdivacky      ID.AddBoolean(false);
72199990Srdivacky      ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
73199990Srdivacky                      .getAsVoidPointer());
74199990Srdivacky    }
75199482Srdivacky    break;
76199482Srdivacky
77198893Srdivacky  case Integral:
78198893Srdivacky    getAsIntegral()->Profile(ID);
79198893Srdivacky    getIntegralType().Profile(ID);
80198893Srdivacky    break;
81198893Srdivacky
82198893Srdivacky  case Expression:
83198893Srdivacky    getAsExpr()->Profile(ID, Context, true);
84198893Srdivacky    break;
85198893Srdivacky
86198893Srdivacky  case Pack:
87198893Srdivacky    ID.AddInteger(Args.NumArgs);
88198893Srdivacky    for (unsigned I = 0; I != Args.NumArgs; ++I)
89198893Srdivacky      Args.Args[I].Profile(ID, Context);
90198893Srdivacky  }
91198893Srdivacky}
92198893Srdivacky
93210299Sedbool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
94210299Sed  if (getKind() != Other.getKind()) return false;
95210299Sed
96210299Sed  switch (getKind()) {
97210299Sed  case Null:
98210299Sed  case Type:
99210299Sed  case Declaration:
100210299Sed  case Template:
101210299Sed  case Expression:
102210299Sed    return TypeOrValue == Other.TypeOrValue;
103210299Sed
104210299Sed  case Integral:
105210299Sed    return getIntegralType() == Other.getIntegralType() &&
106210299Sed           *getAsIntegral() == *Other.getAsIntegral();
107210299Sed
108210299Sed  case Pack:
109210299Sed    if (Args.NumArgs != Other.Args.NumArgs) return false;
110210299Sed    for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
111210299Sed      if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
112210299Sed        return false;
113210299Sed    return true;
114210299Sed  }
115210299Sed
116210299Sed  // Suppress warnings.
117210299Sed  return false;
118210299Sed}
119210299Sed
120198893Srdivacky//===----------------------------------------------------------------------===//
121198893Srdivacky// TemplateArgumentLoc Implementation
122198893Srdivacky//===----------------------------------------------------------------------===//
123198893Srdivacky
124198893SrdivackySourceRange TemplateArgumentLoc::getSourceRange() const {
125198893Srdivacky  switch (Argument.getKind()) {
126198893Srdivacky  case TemplateArgument::Expression:
127198893Srdivacky    return getSourceExpression()->getSourceRange();
128199482Srdivacky
129198893Srdivacky  case TemplateArgument::Declaration:
130198893Srdivacky    return getSourceDeclExpression()->getSourceRange();
131199482Srdivacky
132198893Srdivacky  case TemplateArgument::Type:
133208600Srdivacky    return getTypeSourceInfo()->getTypeLoc().getSourceRange();
134199482Srdivacky
135199482Srdivacky  case TemplateArgument::Template:
136199482Srdivacky    if (getTemplateQualifierRange().isValid())
137199482Srdivacky      return SourceRange(getTemplateQualifierRange().getBegin(),
138199482Srdivacky                         getTemplateNameLoc());
139199482Srdivacky    return SourceRange(getTemplateNameLoc());
140199482Srdivacky
141198893Srdivacky  case TemplateArgument::Integral:
142198893Srdivacky  case TemplateArgument::Pack:
143198893Srdivacky  case TemplateArgument::Null:
144198893Srdivacky    return SourceRange();
145198893Srdivacky  }
146198893Srdivacky
147198893Srdivacky  // Silence bonus gcc warning.
148198893Srdivacky  return SourceRange();
149198893Srdivacky}
150208600Srdivacky
151208600Srdivackyconst DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
152208600Srdivacky                                           const TemplateArgument &Arg) {
153208600Srdivacky  switch (Arg.getKind()) {
154208600Srdivacky  case TemplateArgument::Null:
155208600Srdivacky    return DB;
156208600Srdivacky
157208600Srdivacky  case TemplateArgument::Type:
158208600Srdivacky    return DB << Arg.getAsType();
159208600Srdivacky
160208600Srdivacky  case TemplateArgument::Declaration:
161208600Srdivacky    return DB << Arg.getAsDecl();
162208600Srdivacky
163208600Srdivacky  case TemplateArgument::Integral:
164208600Srdivacky    return DB << Arg.getAsIntegral()->toString(10);
165208600Srdivacky
166208600Srdivacky  case TemplateArgument::Template:
167208600Srdivacky    return DB << Arg.getAsTemplate();
168208600Srdivacky
169208600Srdivacky  case TemplateArgument::Expression: {
170208600Srdivacky    // This shouldn't actually ever happen, so it's okay that we're
171208600Srdivacky    // regurgitating an expression here.
172208600Srdivacky    // FIXME: We're guessing at LangOptions!
173208600Srdivacky    llvm::SmallString<32> Str;
174208600Srdivacky    llvm::raw_svector_ostream OS(Str);
175208600Srdivacky    LangOptions LangOpts;
176208600Srdivacky    LangOpts.CPlusPlus = true;
177208600Srdivacky    PrintingPolicy Policy(LangOpts);
178208600Srdivacky    Arg.getAsExpr()->printPretty(OS, 0, Policy);
179208600Srdivacky    return DB << OS.str();
180208600Srdivacky  }
181208600Srdivacky
182208600Srdivacky  case TemplateArgument::Pack:
183208600Srdivacky    // FIXME: Format arguments in a list!
184208600Srdivacky    return DB << "<parameter pack>";
185208600Srdivacky  }
186208600Srdivacky
187208600Srdivacky  return DB;
188208600Srdivacky}
189