blob: fe779ebd80de1eae9c86576e9bb3fe0b2959861a [file] [log] [blame]
Douglas Gregor0b9247f2009-06-04 00:03:07 +00001//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/
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// This file implements C++ template argument deduction.
10//
11//===----------------------------------------------------------------------===/
12
13#include "Sema.h"
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/DeclTemplate.h"
16#include "clang/AST/StmtVisitor.h"
17#include "clang/AST/Expr.h"
18#include "clang/AST/ExprCXX.h"
19#include "clang/Parse/DeclSpec.h"
20#include "llvm/Support/Compiler.h"
21using namespace clang;
22
Douglas Gregor199d9912009-06-05 00:53:49 +000023/// \brief If the given expression is of a form that permits the deduction
24/// of a non-type template parameter, return the declaration of that
25/// non-type template parameter.
26static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) {
27 if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E))
28 E = IC->getSubExpr();
29
30 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
31 return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl());
32
33 return 0;
34}
35
36/// \brief Deduce the value of the given non-type template parameter
37/// from the given constant.
38///
39/// \returns true if deduction succeeded, false otherwise.
40static bool DeduceNonTypeTemplateArgument(ASTContext &Context,
41 NonTypeTemplateParmDecl *NTTP,
42 llvm::APInt Value,
43 llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
44 assert(NTTP->getDepth() == 0 &&
45 "Cannot deduce non-type template argument with depth > 0");
46
47 if (Deduced[NTTP->getIndex()].isNull()) {
48 Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(),
49 llvm::APSInt(Value),
50 NTTP->getType());
51 return true;
52 }
53
54 if (Deduced[NTTP->getIndex()].getKind() != TemplateArgument::Integral)
55 return false;
56
57 // If the template argument was previously deduced to a negative value,
58 // then our deduction fails.
59 const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral();
60 assert(PrevValuePtr && "Not an integral template argument?");
61 if (PrevValuePtr->isSigned() && PrevValuePtr->isNegative())
62 return false;
63
64 llvm::APInt PrevValue = *PrevValuePtr;
65 if (Value.getBitWidth() > PrevValue.getBitWidth())
66 PrevValue.zext(Value.getBitWidth());
67 else if (Value.getBitWidth() < PrevValue.getBitWidth())
68 Value.zext(PrevValue.getBitWidth());
69 return Value == PrevValue;
70}
71
72/// \brief Deduce the value of the given non-type template parameter
73/// from the given type- or value-dependent expression.
74///
75/// \returns true if deduction succeeded, false otherwise.
76
77static bool DeduceNonTypeTemplateArgument(ASTContext &Context,
78 NonTypeTemplateParmDecl *NTTP,
79 Expr *Value,
80 llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
81 assert(NTTP->getDepth() == 0 &&
82 "Cannot deduce non-type template argument with depth > 0");
83 assert((Value->isTypeDependent() || Value->isValueDependent()) &&
84 "Expression template argument must be type- or value-dependent.");
85
86 if (Deduced[NTTP->getIndex()].isNull()) {
87 // FIXME: Clone the Value?
88 Deduced[NTTP->getIndex()] = TemplateArgument(Value);
89 return true;
90 }
91
92 if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral) {
93 // Okay, we deduced a constant in one case and a dependent expression
94 // in another case. FIXME: Later, we will check that instantiating the
95 // dependent expression gives us the constant value.
96 return true;
97 }
98
99 // FIXME: Compare the expressions for equality!
100 return true;
101}
102
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000103static bool DeduceTemplateArguments(ASTContext &Context, QualType Param,
104 QualType Arg,
105 llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
106 // We only want to look at the canonical types, since typedefs and
107 // sugar are not part of template argument deduction.
108 Param = Context.getCanonicalType(Param);
109 Arg = Context.getCanonicalType(Arg);
110
111 // If the parameter type is not dependent, just compare the types
112 // directly.
113 if (!Param->isDependentType())
114 return Param == Arg;
115
Douglas Gregor199d9912009-06-05 00:53:49 +0000116 // C++ [temp.deduct.type]p9:
117 //
118 // A template type argument T, a template template argument TT or a
119 // template non-type argument i can be deduced if P and A have one of
120 // the following forms:
121 //
122 // T
123 // cv-list T
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000124 if (const TemplateTypeParmType *TemplateTypeParm
125 = Param->getAsTemplateTypeParmType()) {
126 // The argument type can not be less qualified than the parameter
127 // type.
128 if (Param.isMoreQualifiedThan(Arg))
129 return false;
130
131 assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
132
133 unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers();
134 QualType DeducedType = Arg.getQualifiedType(Quals);
135 unsigned Index = TemplateTypeParm->getIndex();
136
137 if (Deduced[Index].isNull())
138 Deduced[Index] = TemplateArgument(SourceLocation(), DeducedType);
139 else {
140 // C++ [temp.deduct.type]p2:
141 // [...] If type deduction cannot be done for any P/A pair, or if for
142 // any pair the deduction leads to more than one possible set of
143 // deduced values, or if different pairs yield different deduced
144 // values, or if any template argument remains neither deduced nor
145 // explicitly specified, template argument deduction fails.
146 if (Deduced[Index].getAsType() != DeducedType)
147 return false;
148 }
149 return true;
150 }
151
152 if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
153 return false;
154
Douglas Gregord560d502009-06-04 00:21:18 +0000155 switch (Param->getTypeClass()) {
Douglas Gregor199d9912009-06-05 00:53:49 +0000156 // No deduction possible for these types
157 case Type::Builtin:
158 return false;
159
160
161 // T *
Douglas Gregord560d502009-06-04 00:21:18 +0000162 case Type::Pointer: {
163 const PointerType *PointerArg = Arg->getAsPointerType();
164 if (!PointerArg)
165 return false;
166
167 return DeduceTemplateArguments(Context,
168 cast<PointerType>(Param)->getPointeeType(),
169 PointerArg->getPointeeType(),
170 Deduced);
171 }
172
Douglas Gregor199d9912009-06-05 00:53:49 +0000173 // T &
Douglas Gregord560d502009-06-04 00:21:18 +0000174 case Type::LValueReference: {
175 const LValueReferenceType *ReferenceArg = Arg->getAsLValueReferenceType();
176 if (!ReferenceArg)
177 return false;
178
179 return DeduceTemplateArguments(Context,
180 cast<LValueReferenceType>(Param)->getPointeeType(),
181 ReferenceArg->getPointeeType(),
182 Deduced);
183 }
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000184
Douglas Gregor199d9912009-06-05 00:53:49 +0000185 // T && [C++0x]
Douglas Gregord560d502009-06-04 00:21:18 +0000186 case Type::RValueReference: {
187 const RValueReferenceType *ReferenceArg = Arg->getAsRValueReferenceType();
188 if (!ReferenceArg)
189 return false;
190
191 return DeduceTemplateArguments(Context,
192 cast<RValueReferenceType>(Param)->getPointeeType(),
193 ReferenceArg->getPointeeType(),
194 Deduced);
195 }
196
Douglas Gregor199d9912009-06-05 00:53:49 +0000197 // T [] (implied, but not stated explicitly)
Anders Carlsson4d6fb502009-06-04 04:11:30 +0000198 case Type::IncompleteArray: {
199 const IncompleteArrayType *IncompleteArrayArg =
200 Context.getAsIncompleteArrayType(Arg);
201 if (!IncompleteArrayArg)
202 return false;
203
204 return DeduceTemplateArguments(Context,
205 Context.getAsIncompleteArrayType(Param)->getElementType(),
206 IncompleteArrayArg->getElementType(),
207 Deduced);
208 }
Douglas Gregor199d9912009-06-05 00:53:49 +0000209
210 // T [integer-constant]
Anders Carlsson4d6fb502009-06-04 04:11:30 +0000211 case Type::ConstantArray: {
212 const ConstantArrayType *ConstantArrayArg =
213 Context.getAsConstantArrayType(Arg);
214 if (!ConstantArrayArg)
215 return false;
216
217 const ConstantArrayType *ConstantArrayParm =
218 Context.getAsConstantArrayType(Param);
219 if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
220 return false;
221
222 return DeduceTemplateArguments(Context,
223 ConstantArrayParm->getElementType(),
224 ConstantArrayArg->getElementType(),
225 Deduced);
226 }
227
Douglas Gregor199d9912009-06-05 00:53:49 +0000228 // type [i]
229 case Type::DependentSizedArray: {
230 const ArrayType *ArrayArg = dyn_cast<ArrayType>(Arg);
231 if (!ArrayArg)
232 return false;
233
234 // Check the element type of the arrays
235 const DependentSizedArrayType *DependentArrayParm
236 = cast<DependentSizedArrayType>(Param);
237 if (!DeduceTemplateArguments(Context,
238 DependentArrayParm->getElementType(),
239 ArrayArg->getElementType(),
240 Deduced))
241 return false;
242
243 // Determine the array bound is something we can deduce.
244 NonTypeTemplateParmDecl *NTTP
245 = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr());
246 if (!NTTP)
247 return true;
248
249 // We can perform template argument deduction for the given non-type
250 // template parameter.
251 assert(NTTP->getDepth() == 0 &&
252 "Cannot deduce non-type template argument at depth > 0");
253 if (const ConstantArrayType *ConstantArrayArg
254 = dyn_cast<ConstantArrayType>(ArrayArg))
255 return DeduceNonTypeTemplateArgument(Context, NTTP,
256 ConstantArrayArg->getSize(),
257 Deduced);
258 if (const DependentSizedArrayType *DependentArrayArg
259 = dyn_cast<DependentSizedArrayType>(ArrayArg))
260 return DeduceNonTypeTemplateArgument(Context, NTTP,
261 DependentArrayArg->getSizeExpr(),
262 Deduced);
263
264 // Incomplete type does not match a dependently-sized array type
265 return false;
266 }
267
Douglas Gregor0fce0ae2009-06-08 15:59:14 +0000268 // type(*)(T)
269 // T(*)()
270 // T(*)(T)
Anders Carlssona27fad52009-06-08 15:19:08 +0000271 case Type::FunctionProto: {
272 const FunctionProtoType *FunctionProtoArg =
273 dyn_cast<FunctionProtoType>(Arg);
274 if (!FunctionProtoArg)
275 return false;
276
277 const FunctionProtoType *FunctionProtoParam =
278 cast<FunctionProtoType>(Param);
279
280 // Check return types.
281 if (!DeduceTemplateArguments(Context,
282 FunctionProtoParam->getResultType(),
283 FunctionProtoArg->getResultType(),
284 Deduced))
285 return false;
286
287 if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
288 return false;
289
290 for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
291 // Check argument types.
292 if (!DeduceTemplateArguments(Context,
293 FunctionProtoParam->getArgType(I),
294 FunctionProtoArg->getArgType(I),
295 Deduced))
296 return false;
297 }
298
299 return true;
300 }
301
Douglas Gregord560d502009-06-04 00:21:18 +0000302 default:
303 break;
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000304 }
305
306 // FIXME: Many more cases to go (to go).
307 return false;
308}
309
310static bool
311DeduceTemplateArguments(ASTContext &Context, const TemplateArgument &Param,
312 const TemplateArgument &Arg,
313 llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000314 switch (Param.getKind()) {
Douglas Gregor199d9912009-06-05 00:53:49 +0000315 case TemplateArgument::Null:
316 assert(false && "Null template argument in parameter list");
317 break;
318
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000319 case TemplateArgument::Type:
Douglas Gregor199d9912009-06-05 00:53:49 +0000320 assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000321 return DeduceTemplateArguments(Context, Param.getAsType(),
322 Arg.getAsType(), Deduced);
323
Douglas Gregor199d9912009-06-05 00:53:49 +0000324 case TemplateArgument::Declaration:
325 // FIXME: Implement this check
326 assert(false && "Unimplemented template argument deduction case");
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000327 return false;
Douglas Gregor199d9912009-06-05 00:53:49 +0000328
329 case TemplateArgument::Integral:
330 if (Arg.getKind() == TemplateArgument::Integral) {
331 // FIXME: Zero extension + sign checking here?
332 return *Param.getAsIntegral() == *Arg.getAsIntegral();
333 }
334 if (Arg.getKind() == TemplateArgument::Expression)
335 return false;
336
337 assert(false && "Type/value mismatch");
338 return false;
339
340 case TemplateArgument::Expression: {
341 if (NonTypeTemplateParmDecl *NTTP
342 = getDeducedParameterFromExpr(Param.getAsExpr())) {
343 if (Arg.getKind() == TemplateArgument::Integral)
344 // FIXME: Sign problems here
345 return DeduceNonTypeTemplateArgument(Context, NTTP,
346 *Arg.getAsIntegral(), Deduced);
347 if (Arg.getKind() == TemplateArgument::Expression)
348 return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(),
349 Deduced);
350
351 assert(false && "Type/value mismatch");
352 return false;
353 }
354
355 // Can't deduce anything, but that's okay.
356 return true;
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000357 }
Douglas Gregor199d9912009-06-05 00:53:49 +0000358 }
359
360 return true;
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000361}
362
363static bool
364DeduceTemplateArguments(ASTContext &Context,
365 const TemplateArgumentList &ParamList,
366 const TemplateArgumentList &ArgList,
367 llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
368 assert(ParamList.size() == ArgList.size());
369 for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
370 if (!DeduceTemplateArguments(Context, ParamList[I], ArgList[I], Deduced))
371 return false;
372 }
373 return true;
374}
375
376
Douglas Gregor199d9912009-06-05 00:53:49 +0000377TemplateArgumentList *
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000378Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
379 const TemplateArgumentList &TemplateArgs) {
Douglas Gregor199d9912009-06-05 00:53:49 +0000380 // Deduce the template arguments for the partial specialization
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000381 llvm::SmallVector<TemplateArgument, 4> Deduced;
382 Deduced.resize(Partial->getTemplateParameters()->size());
Douglas Gregor199d9912009-06-05 00:53:49 +0000383 if (! ::DeduceTemplateArguments(Context, Partial->getTemplateArgs(),
384 TemplateArgs, Deduced))
385 return 0;
386
387 // FIXME: Substitute the deduced template arguments into the template
388 // arguments of the class template partial specialization; the resulting
389 // template arguments should match TemplateArgs exactly.
390
391 for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
392 TemplateArgument &Arg = Deduced[I];
393
394 // FIXME: If this template argument was not deduced, but the corresponding
395 // template parameter has a default argument, instantiate the default
396 // argument.
397 if (Arg.isNull()) // FIXME: Result->Destroy(Context);
398 return 0;
399
400 if (Arg.getKind() == TemplateArgument::Integral) {
401 // FIXME: Instantiate the type, but we need some context!
402 const NonTypeTemplateParmDecl *Parm
403 = cast<NonTypeTemplateParmDecl>(Partial->getTemplateParameters()
404 ->getParam(I));
405 // QualType T = InstantiateType(Parm->getType(), *Result,
406 // Parm->getLocation(), Parm->getDeclName());
407 // if (T.isNull()) // FIXME: Result->Destroy(Context);
408 // return 0;
409 QualType T = Parm->getType();
410
411 // FIXME: Make sure we didn't overflow our data type!
412 llvm::APSInt &Value = *Arg.getAsIntegral();
413 unsigned AllowedBits = Context.getTypeSize(T);
414 if (Value.getBitWidth() != AllowedBits)
415 Value.extOrTrunc(AllowedBits);
416 Value.setIsSigned(T->isSignedIntegerType());
417 Arg.setIntegralType(T);
418 }
419 }
420
Anders Carlssone9c904b2009-06-05 04:47:51 +0000421 // FIXME: This is terrible. DeduceTemplateArguments should use a
422 // TemplateArgumentListBuilder directly.
Anders Carlsson9ba41642009-06-05 05:31:27 +0000423 TemplateArgumentListBuilder Builder(Context);
Anders Carlssone9c904b2009-06-05 04:47:51 +0000424 for (unsigned I = 0, N = Deduced.size(); I != N; ++I)
425 Builder.push_back(Deduced[I]);
426
427 return new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true,
428 /*FlattenArgs=*/true);
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000429}