blob: ef2deea8c8429ed3a422ec9a1f1218b8017054fa [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 Gregord0937222010-12-13 22:49:22 +000029bool TemplateArgument::containsUnexpandedParameterPack() const {
30 switch (getKind()) {
31 case Null:
32 case Declaration:
33 case Integral:
34 break;
35
36 case Type:
37 if (getAsType()->containsUnexpandedParameterPack())
38 return true;
39 break;
40
41 case Template:
42 if (getAsTemplate().containsUnexpandedParameterPack())
43 return true;
44 break;
45
46 case Expression:
47 if (getAsExpr()->containsUnexpandedParameterPack())
48 return true;
49 break;
50
51 case Pack:
52 for (pack_iterator P = pack_begin(), PEnd = pack_end(); P != PEnd; ++P)
53 if (P->containsUnexpandedParameterPack())
54 return true;
55
56 break;
57 }
58
59 return false;
60}
61
John McCall275c10a2009-10-29 07:48:15 +000062void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
63 ASTContext &Context) const {
64 ID.AddInteger(Kind);
65 switch (Kind) {
66 case Null:
67 break;
68
69 case Type:
70 getAsType().Profile(ID);
71 break;
72
73 case Declaration:
74 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
75 break;
76
Douglas Gregor788cd062009-11-11 01:00:40 +000077 case Template:
Douglas Gregor74295b32009-11-23 12:52:47 +000078 if (TemplateTemplateParmDecl *TTP
79 = dyn_cast_or_null<TemplateTemplateParmDecl>(
80 getAsTemplate().getAsTemplateDecl())) {
81 ID.AddBoolean(true);
82 ID.AddInteger(TTP->getDepth());
83 ID.AddInteger(TTP->getPosition());
84 } else {
85 ID.AddBoolean(false);
86 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
87 .getAsVoidPointer());
88 }
Douglas Gregor788cd062009-11-11 01:00:40 +000089 break;
90
John McCall275c10a2009-10-29 07:48:15 +000091 case Integral:
92 getAsIntegral()->Profile(ID);
93 getIntegralType().Profile(ID);
94 break;
95
96 case Expression:
97 getAsExpr()->Profile(ID, Context, true);
98 break;
99
100 case Pack:
101 ID.AddInteger(Args.NumArgs);
102 for (unsigned I = 0; I != Args.NumArgs; ++I)
103 Args.Args[I].Profile(ID, Context);
104 }
105}
John McCall833ca992009-10-29 08:12:44 +0000106
John McCall33500952010-06-11 00:33:02 +0000107bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
108 if (getKind() != Other.getKind()) return false;
109
110 switch (getKind()) {
111 case Null:
112 case Type:
113 case Declaration:
114 case Template:
115 case Expression:
116 return TypeOrValue == Other.TypeOrValue;
117
118 case Integral:
119 return getIntegralType() == Other.getIntegralType() &&
120 *getAsIntegral() == *Other.getAsIntegral();
121
122 case Pack:
123 if (Args.NumArgs != Other.Args.NumArgs) return false;
124 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
125 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
126 return false;
127 return true;
128 }
129
130 // Suppress warnings.
131 return false;
132}
133
John McCall833ca992009-10-29 08:12:44 +0000134//===----------------------------------------------------------------------===//
135// TemplateArgumentLoc Implementation
136//===----------------------------------------------------------------------===//
137
John McCall828bff22009-10-29 18:45:58 +0000138SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000139 switch (Argument.getKind()) {
140 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000141 return getSourceExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000142
John McCall833ca992009-10-29 08:12:44 +0000143 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000144 return getSourceDeclExpression()->getSourceRange();
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000145
John McCall828bff22009-10-29 18:45:58 +0000146 case TemplateArgument::Type:
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000147 if (TypeSourceInfo *TSI = getTypeSourceInfo())
148 return TSI->getTypeLoc().getSourceRange();
149 else
150 return SourceRange();
151
Douglas Gregor788cd062009-11-11 01:00:40 +0000152 case TemplateArgument::Template:
153 if (getTemplateQualifierRange().isValid())
154 return SourceRange(getTemplateQualifierRange().getBegin(),
155 getTemplateNameLoc());
156 return SourceRange(getTemplateNameLoc());
Zhanyong Wanf38ef0c2010-09-03 23:50:56 +0000157
John McCall833ca992009-10-29 08:12:44 +0000158 case TemplateArgument::Integral:
159 case TemplateArgument::Pack:
160 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000161 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000162 }
163
164 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000165 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000166}
Douglas Gregora9333192010-05-08 17:41:32 +0000167
168const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
169 const TemplateArgument &Arg) {
170 switch (Arg.getKind()) {
171 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000172 // This is bad, but not as bad as crashing because of argument
173 // count mismatches.
174 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000175
176 case TemplateArgument::Type:
177 return DB << Arg.getAsType();
178
179 case TemplateArgument::Declaration:
180 return DB << Arg.getAsDecl();
181
182 case TemplateArgument::Integral:
183 return DB << Arg.getAsIntegral()->toString(10);
184
185 case TemplateArgument::Template:
186 return DB << Arg.getAsTemplate();
187
188 case TemplateArgument::Expression: {
189 // This shouldn't actually ever happen, so it's okay that we're
190 // regurgitating an expression here.
191 // FIXME: We're guessing at LangOptions!
192 llvm::SmallString<32> Str;
193 llvm::raw_svector_ostream OS(Str);
194 LangOptions LangOpts;
195 LangOpts.CPlusPlus = true;
196 PrintingPolicy Policy(LangOpts);
197 Arg.getAsExpr()->printPretty(OS, 0, Policy);
198 return DB << OS.str();
199 }
200
201 case TemplateArgument::Pack:
202 // FIXME: Format arguments in a list!
203 return DB << "<parameter pack>";
204 }
205
206 return DB;
207}