blob: 1789ba785684af215d647fb807df8f497d14be8c [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);
Anders Carlsson994b6cb2009-06-08 19:22:23 +0000279
280 if (FunctionProtoParam->getTypeQuals() !=
281 FunctionProtoArg->getTypeQuals())
282 return false;
Anders Carlssona27fad52009-06-08 15:19:08 +0000283
Anders Carlsson994b6cb2009-06-08 19:22:23 +0000284 if (FunctionProtoParam->getNumArgs() != FunctionProtoArg->getNumArgs())
285 return false;
286
287 if (FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
288 return false;
289
Anders Carlssona27fad52009-06-08 15:19:08 +0000290 // Check return types.
291 if (!DeduceTemplateArguments(Context,
292 FunctionProtoParam->getResultType(),
293 FunctionProtoArg->getResultType(),
294 Deduced))
295 return false;
296
Anders Carlssona27fad52009-06-08 15:19:08 +0000297 for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
298 // Check argument types.
299 if (!DeduceTemplateArguments(Context,
300 FunctionProtoParam->getArgType(I),
301 FunctionProtoArg->getArgType(I),
302 Deduced))
303 return false;
304 }
305
306 return true;
307 }
308
Douglas Gregord560d502009-06-04 00:21:18 +0000309 default:
310 break;
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000311 }
312
313 // FIXME: Many more cases to go (to go).
314 return false;
315}
316
317static bool
318DeduceTemplateArguments(ASTContext &Context, const TemplateArgument &Param,
319 const TemplateArgument &Arg,
320 llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000321 switch (Param.getKind()) {
Douglas Gregor199d9912009-06-05 00:53:49 +0000322 case TemplateArgument::Null:
323 assert(false && "Null template argument in parameter list");
324 break;
325
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000326 case TemplateArgument::Type:
Douglas Gregor199d9912009-06-05 00:53:49 +0000327 assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000328 return DeduceTemplateArguments(Context, Param.getAsType(),
329 Arg.getAsType(), Deduced);
330
Douglas Gregor199d9912009-06-05 00:53:49 +0000331 case TemplateArgument::Declaration:
332 // FIXME: Implement this check
333 assert(false && "Unimplemented template argument deduction case");
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000334 return false;
Douglas Gregor199d9912009-06-05 00:53:49 +0000335
336 case TemplateArgument::Integral:
337 if (Arg.getKind() == TemplateArgument::Integral) {
338 // FIXME: Zero extension + sign checking here?
339 return *Param.getAsIntegral() == *Arg.getAsIntegral();
340 }
341 if (Arg.getKind() == TemplateArgument::Expression)
342 return false;
343
344 assert(false && "Type/value mismatch");
345 return false;
346
347 case TemplateArgument::Expression: {
348 if (NonTypeTemplateParmDecl *NTTP
349 = getDeducedParameterFromExpr(Param.getAsExpr())) {
350 if (Arg.getKind() == TemplateArgument::Integral)
351 // FIXME: Sign problems here
352 return DeduceNonTypeTemplateArgument(Context, NTTP,
353 *Arg.getAsIntegral(), Deduced);
354 if (Arg.getKind() == TemplateArgument::Expression)
355 return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(),
356 Deduced);
357
358 assert(false && "Type/value mismatch");
359 return false;
360 }
361
362 // Can't deduce anything, but that's okay.
363 return true;
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000364 }
Douglas Gregor199d9912009-06-05 00:53:49 +0000365 }
366
367 return true;
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000368}
369
370static bool
371DeduceTemplateArguments(ASTContext &Context,
372 const TemplateArgumentList &ParamList,
373 const TemplateArgumentList &ArgList,
374 llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
375 assert(ParamList.size() == ArgList.size());
376 for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
377 if (!DeduceTemplateArguments(Context, ParamList[I], ArgList[I], Deduced))
378 return false;
379 }
380 return true;
381}
382
383
Douglas Gregor199d9912009-06-05 00:53:49 +0000384TemplateArgumentList *
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000385Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
386 const TemplateArgumentList &TemplateArgs) {
Douglas Gregor199d9912009-06-05 00:53:49 +0000387 // Deduce the template arguments for the partial specialization
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000388 llvm::SmallVector<TemplateArgument, 4> Deduced;
389 Deduced.resize(Partial->getTemplateParameters()->size());
Douglas Gregor199d9912009-06-05 00:53:49 +0000390 if (! ::DeduceTemplateArguments(Context, Partial->getTemplateArgs(),
391 TemplateArgs, Deduced))
392 return 0;
393
394 // FIXME: Substitute the deduced template arguments into the template
395 // arguments of the class template partial specialization; the resulting
396 // template arguments should match TemplateArgs exactly.
397
398 for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
399 TemplateArgument &Arg = Deduced[I];
400
401 // FIXME: If this template argument was not deduced, but the corresponding
402 // template parameter has a default argument, instantiate the default
403 // argument.
404 if (Arg.isNull()) // FIXME: Result->Destroy(Context);
405 return 0;
406
407 if (Arg.getKind() == TemplateArgument::Integral) {
408 // FIXME: Instantiate the type, but we need some context!
409 const NonTypeTemplateParmDecl *Parm
410 = cast<NonTypeTemplateParmDecl>(Partial->getTemplateParameters()
411 ->getParam(I));
412 // QualType T = InstantiateType(Parm->getType(), *Result,
413 // Parm->getLocation(), Parm->getDeclName());
414 // if (T.isNull()) // FIXME: Result->Destroy(Context);
415 // return 0;
416 QualType T = Parm->getType();
417
418 // FIXME: Make sure we didn't overflow our data type!
419 llvm::APSInt &Value = *Arg.getAsIntegral();
420 unsigned AllowedBits = Context.getTypeSize(T);
421 if (Value.getBitWidth() != AllowedBits)
422 Value.extOrTrunc(AllowedBits);
423 Value.setIsSigned(T->isSignedIntegerType());
424 Arg.setIntegralType(T);
425 }
426 }
427
Anders Carlssone9c904b2009-06-05 04:47:51 +0000428 // FIXME: This is terrible. DeduceTemplateArguments should use a
429 // TemplateArgumentListBuilder directly.
Anders Carlsson9ba41642009-06-05 05:31:27 +0000430 TemplateArgumentListBuilder Builder(Context);
Anders Carlssone9c904b2009-06-05 04:47:51 +0000431 for (unsigned I = 0, N = Deduced.size(); I != N; ++I)
432 Builder.push_back(Deduced[I]);
433
434 return new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true,
435 /*FlattenArgs=*/true);
Douglas Gregor0b9247f2009-06-04 00:03:07 +0000436}