blob: 351aebe3f834b904da4208ed04446c46e9c92bda [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
John McCall275c10a2009-10-29 07:48:15 +000029/// \brief Construct a template argument pack.
30void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
31 bool CopyArgs) {
32 assert(isNull() && "Must call setArgumentPack on a null argument");
33
34 Kind = Pack;
35 Args.NumArgs = NumArgs;
36 Args.CopyArgs = CopyArgs;
37 if (!Args.CopyArgs) {
38 Args.Args = args;
39 return;
40 }
41
42 // FIXME: Allocate in ASTContext
43 Args.Args = new TemplateArgument[NumArgs];
44 for (unsigned I = 0; I != Args.NumArgs; ++I)
45 Args.Args[I] = args[I];
46}
47
48void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
49 ASTContext &Context) const {
50 ID.AddInteger(Kind);
51 switch (Kind) {
52 case Null:
53 break;
54
55 case Type:
56 getAsType().Profile(ID);
57 break;
58
59 case Declaration:
60 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
61 break;
62
Douglas Gregor788cd062009-11-11 01:00:40 +000063 case Template:
Douglas Gregor74295b32009-11-23 12:52:47 +000064 if (TemplateTemplateParmDecl *TTP
65 = dyn_cast_or_null<TemplateTemplateParmDecl>(
66 getAsTemplate().getAsTemplateDecl())) {
67 ID.AddBoolean(true);
68 ID.AddInteger(TTP->getDepth());
69 ID.AddInteger(TTP->getPosition());
70 } else {
71 ID.AddBoolean(false);
72 ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
73 .getAsVoidPointer());
74 }
Douglas Gregor788cd062009-11-11 01:00:40 +000075 break;
76
John McCall275c10a2009-10-29 07:48:15 +000077 case Integral:
78 getAsIntegral()->Profile(ID);
79 getIntegralType().Profile(ID);
80 break;
81
82 case Expression:
83 getAsExpr()->Profile(ID, Context, true);
84 break;
85
86 case Pack:
87 ID.AddInteger(Args.NumArgs);
88 for (unsigned I = 0; I != Args.NumArgs; ++I)
89 Args.Args[I].Profile(ID, Context);
90 }
91}
John McCall833ca992009-10-29 08:12:44 +000092
John McCall33500952010-06-11 00:33:02 +000093bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
94 if (getKind() != Other.getKind()) return false;
95
96 switch (getKind()) {
97 case Null:
98 case Type:
99 case Declaration:
100 case Template:
101 case Expression:
102 return TypeOrValue == Other.TypeOrValue;
103
104 case Integral:
105 return getIntegralType() == Other.getIntegralType() &&
106 *getAsIntegral() == *Other.getAsIntegral();
107
108 case Pack:
109 if (Args.NumArgs != Other.Args.NumArgs) return false;
110 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
111 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
112 return false;
113 return true;
114 }
115
116 // Suppress warnings.
117 return false;
118}
119
John McCall833ca992009-10-29 08:12:44 +0000120//===----------------------------------------------------------------------===//
121// TemplateArgumentLoc Implementation
122//===----------------------------------------------------------------------===//
123
John McCall828bff22009-10-29 18:45:58 +0000124SourceRange TemplateArgumentLoc::getSourceRange() const {
John McCall833ca992009-10-29 08:12:44 +0000125 switch (Argument.getKind()) {
126 case TemplateArgument::Expression:
John McCall828bff22009-10-29 18:45:58 +0000127 return getSourceExpression()->getSourceRange();
Douglas Gregor788cd062009-11-11 01:00:40 +0000128
John McCall833ca992009-10-29 08:12:44 +0000129 case TemplateArgument::Declaration:
John McCall828bff22009-10-29 18:45:58 +0000130 return getSourceDeclExpression()->getSourceRange();
Douglas Gregor788cd062009-11-11 01:00:40 +0000131
John McCall828bff22009-10-29 18:45:58 +0000132 case TemplateArgument::Type:
Abramo Bagnarabd054db2010-05-20 10:00:11 +0000133 return getTypeSourceInfo()->getTypeLoc().getSourceRange();
Douglas Gregor788cd062009-11-11 01:00:40 +0000134
135 case TemplateArgument::Template:
136 if (getTemplateQualifierRange().isValid())
137 return SourceRange(getTemplateQualifierRange().getBegin(),
138 getTemplateNameLoc());
139 return SourceRange(getTemplateNameLoc());
140
John McCall833ca992009-10-29 08:12:44 +0000141 case TemplateArgument::Integral:
142 case TemplateArgument::Pack:
143 case TemplateArgument::Null:
John McCall828bff22009-10-29 18:45:58 +0000144 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000145 }
146
147 // Silence bonus gcc warning.
John McCall828bff22009-10-29 18:45:58 +0000148 return SourceRange();
John McCall833ca992009-10-29 08:12:44 +0000149}
Douglas Gregora9333192010-05-08 17:41:32 +0000150
151const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
152 const TemplateArgument &Arg) {
153 switch (Arg.getKind()) {
154 case TemplateArgument::Null:
John McCall67c4a0c2010-08-05 04:58:04 +0000155 // This is bad, but not as bad as crashing because of argument
156 // count mismatches.
157 return DB << "(null template argument)";
Douglas Gregora9333192010-05-08 17:41:32 +0000158
159 case TemplateArgument::Type:
160 return DB << Arg.getAsType();
161
162 case TemplateArgument::Declaration:
163 return DB << Arg.getAsDecl();
164
165 case TemplateArgument::Integral:
166 return DB << Arg.getAsIntegral()->toString(10);
167
168 case TemplateArgument::Template:
169 return DB << Arg.getAsTemplate();
170
171 case TemplateArgument::Expression: {
172 // This shouldn't actually ever happen, so it's okay that we're
173 // regurgitating an expression here.
174 // FIXME: We're guessing at LangOptions!
175 llvm::SmallString<32> Str;
176 llvm::raw_svector_ostream OS(Str);
177 LangOptions LangOpts;
178 LangOpts.CPlusPlus = true;
179 PrintingPolicy Policy(LangOpts);
180 Arg.getAsExpr()->printPretty(OS, 0, Policy);
181 return DB << OS.str();
182 }
183
184 case TemplateArgument::Pack:
185 // FIXME: Format arguments in a list!
186 return DB << "<parameter pack>";
187 }
188
189 return DB;
190}