blob: ead788507743389e2f51a3744b8aec2d88751922 [file] [log] [blame]
John McCall275c10a2009-10-29 07:48:15 +00001//===--- 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 "llvm/ADT/FoldingSet.h"
16#include "clang/AST/TemplateBase.h"
17#include "clang/AST/DeclBase.h"
Douglas Gregor74295b32009-11-23 12:52:47 +000018#include "clang/AST/DeclTemplate.h"
John McCall275c10a2009-10-29 07:48:15 +000019#include "clang/AST/Expr.h"
John McCall833ca992009-10-29 08:12:44 +000020#include "clang/AST/TypeLoc.h"
Douglas Gregora9333192010-05-08 17:41:32 +000021#include "clang/Basic/Diagnostic.h"
John McCall275c10a2009-10-29 07:48:15 +000022
23using namespace clang;
24
25//===----------------------------------------------------------------------===//
26// TemplateArgument Implementation
27//===----------------------------------------------------------------------===//
28
Douglas Gregorbebbe0d2010-12-15 01:34:56 +000029bool TemplateArgument::isDependent() const {
30 switch (getKind()) {
31 case Null:
32 assert(false && "Should not have a NULL template argument");
33 return false;
34
35 case Type:
36 return getAsType()->isDependentType();
37
38 case Template:
39 return getAsTemplate().isDependent();
40
41 case Declaration:
42 if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
43 return DC->isDependentContext();
44 return getAsDecl()->getDeclContext()->isDependentContext();
45
46 case Integral:
47 // Never dependent
48 return false;
49
50 case Expression:
51 return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent());
52
53 case Pack:
54 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P) {
55 if (P->isDependent())
56 return true;
57 }
58
59 return false;
60 }
61
62 return false;
63}
64
Douglas Gregord0937222010-12-13 22:49:22 +000065bool TemplateArgument::containsUnexpandedParameterPack() const {
66 switch (getKind()) {
67 case Null:
68 case Declaration:
69 case Integral:
70 break;
71
72 case Type:
73 if (getAsType()->containsUnexpandedParameterPack())
74 return true;
75 break;
76
77 case Template:
78 if (getAsTemplate().containsUnexpandedParameterPack())
79 return true;
80 break;
81
82 case Expression:
83 if (getAsExpr()->containsUnexpandedParameterPack())
84 return true;
85 break;
86
87 case Pack:
88 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
89 if (P->containsUnexpandedParameterPack())
90 return true;
91
92 break;
93 }
94
95 return false;
96}
97
John McCall275c10a2009-10-29 07:48:15 +000098void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
99 ASTContext &Context) const {
100 ID.AddInteger(Kind);
101 switch (Kind) {
102 case Null:
103 break;
104
105 case Type:
106 getAsType().Profile(ID);
107 break;
108
109 case Declaration:
110 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
111 break;
112
Douglas Gregor788cd062009-11-11 01:00:40 +0000113 case Template:
Douglas Gregor74295b32009-11-23 12:52:47 +0000114 if (TemplateTemplateParmDecl *TTP
115 = dyn_cast_or_null<TemplateTemplateParmDecl>(
116 getAsTemplate().getAsTemplateDecl())) {
117 ID.AddBoolean(true);
118 ID.AddInteger(TTP->getDepth());
119 ID.AddInteger(TTP->getPosition());
120 } else {
121 ID.AddBoolean(false);
122 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
123 .getAsVoidPointer());
124 }
Douglas Gregor788cd062009-11-11 01:00:40 +0000125 break;
126
John McCall275c10a2009-10-29 07:48:15 +0000127 case Integral:
128 getAsIntegral()->Profile(ID);
129 getIntegralType().Profile(ID);
130 break;
131
132 case Expression:
133 getAsExpr()->Profile(ID, Context, true);
134 break;
135
136 case Pack:
137 ID.AddInteger(Args.NumArgs);
138 for (unsigned I = 0; I != Args.NumArgs; ++I)
139 Args.Args[I].Profile(ID, Context);
140 }
141}
John McCall833ca992009-10-29 08:12:44 +0000142
John McCall33500952010-06-11 00:33:02 +0000143bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
144 if (getKind() != Other.getKind()) return false;
145
146 switch (getKind()) {
147 case Null:
148 case Type:
149 case Declaration:
150 case Template:
151 case Expression:
152 return TypeOrValue == Other.TypeOrValue;
153
154 case Integral:
155 return getIntegralType() == Other.getIntegralType() &&
156 *getAsIntegral() == *Other.getAsIntegral();
157
158 case Pack:
159 if (Args.NumArgs != Other.Args.NumArgs) return false;
160 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
161 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
162 return false;
163 return true;
164 }
165
166 // Suppress warnings.
167 return false;
168}
169
John McCall833ca992009-10-29 08:12:44 +0000170//===----------------------------------------------------------------------===//
171// TemplateArgumentLoc Implementation
172//===----------------------------------------------------------------------===//
173
John McCall828bff22009-10-29 18:45:58 +0000174SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000175 switch (Argument.getKind()) {
176 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000177 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000178
John McCall833ca992009-10-29 08:12:44 +0000179 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000180 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000181
John McCall828bff22009-10-29 18:45:58 +0000182 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000183 if (TypeSourceInfo *TSI = getTypeSourceInfo())
184 return TSI->getTypeLoc().getSourceRange();
185 else
186 return SourceRange();
187
Douglas Gregor788cd062009-11-11 01:00:40 +0000188 case TemplateArgument::Template:
189 if (getTemplateQualifierRange().isValid())
190 return SourceRange(getTemplateQualifierRange().getBegin(),
191 getTemplateNameLoc());
192 return SourceRange(getTemplateNameLoc());
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000193
John McCall833ca992009-10-29 08:12:44 +0000194 case TemplateArgument::Integral:
195 case TemplateArgument::Pack:
196 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000197 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000198 }
199
200 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000201 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000202}
Douglas Gregora9333192010-05-08 17:41:32 +0000203
204const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
205 const TemplateArgument &Arg) {
206 switch (Arg.getKind()) {
207 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000208 // This is bad, but not as bad as crashing because of argument
209 // count mismatches.
210 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000211
212 case TemplateArgument::Type:
213 return DB << Arg.getAsType();
214
215 case TemplateArgument::Declaration:
216 return DB << Arg.getAsDecl();
217
218 case TemplateArgument::Integral:
219 return DB << Arg.getAsIntegral()->toString(10);
220
221 case TemplateArgument::Template:
222 return DB << Arg.getAsTemplate();
223
224 case TemplateArgument::Expression: {
225 // This shouldn't actually ever happen, so it's okay that we're
226 // regurgitating an expression here.
227 // FIXME: We're guessing at LangOptions!
228 llvm::SmallString<32> Str;
229 llvm::raw_svector_ostream OS(Str);
230 LangOptions LangOpts;
231 LangOpts.CPlusPlus = true;
232 PrintingPolicy Policy(LangOpts);
233 Arg.getAsExpr()->printPretty(OS, 0, Policy);
234 return DB << OS.str();
235 }
236
237 case TemplateArgument::Pack:
238 // FIXME: Format arguments in a list!
239 return DB << "<parameter pack>";
240 }
241
242 return DB;
243}