using namespace clang;
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
/// \brief Deduce the value of the given non-type template parameter
/// from the given constant.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
+DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
llvm::APSInt Value,
Sema::TemplateDeductionInfo &Info,
QualType T = NTTP->getType();
// FIXME: Make sure we didn't overflow our data type!
- unsigned AllowedBits = Context.getTypeSize(T);
+ unsigned AllowedBits = S.Context.getTypeSize(T);
if (Value.getBitWidth() != AllowedBits)
Value.extOrTrunc(AllowedBits);
Value.setIsSigned(T->isSignedIntegerType());
///
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
+DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
Expr *Value,
Sema::TemplateDeductionInfo &Info,
if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) {
// Compare the expressions for equality
llvm::FoldingSetNodeID ID1, ID2;
- Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, Context, true);
- Value->Profile(ID2, Context, true);
+ Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, S.Context, true);
+ Value->Profile(ID2, S.Context, true);
if (ID1 == ID2)
return Sema::TDK_Success;
///
/// \returns true if deduction succeeded, false otherwise.
static Sema::TemplateDeductionResult
-DeduceNonTypeTemplateArgument(ASTContext &Context,
+DeduceNonTypeTemplateArgument(Sema &S,
NonTypeTemplateParmDecl *NTTP,
Decl *D,
Sema::TemplateDeductionInfo &Info,
}
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
TemplateName Param,
TemplateName Arg,
TemplateArgument &ExistingArg = Deduced[TempParam->getIndex()];
if (ExistingArg.isNull()) {
// This is the first deduction for this template template parameter.
- ExistingArg = TemplateArgument(Context.getCanonicalTemplateName(Arg));
+ ExistingArg = TemplateArgument(S.Context.getCanonicalTemplateName(Arg));
return Sema::TDK_Success;
}
// Verify that the previous binding matches this deduction.
assert(ExistingArg.getKind() == TemplateArgument::Template);
- if (Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg))
+ if (S.Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg))
return Sema::TDK_Success;
// Inconsistent deduction.
}
// Verify that the two template names are equivalent.
- if (Context.hasSameTemplateName(Param, Arg))
+ if (S.Context.hasSameTemplateName(Param, Arg))
return Sema::TDK_Success;
// Mismatch of non-dependent template parameter to argument.
/// \brief Deduce the template arguments by comparing the template parameter
/// type (which is a template-id) with the template argument type.
///
-/// \param Context the AST context in which this deduction occurs.
+/// \param S the Sema
///
/// \param TemplateParams the template parameters that we are deducing
///
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateSpecializationType *Param,
QualType Arg,
= dyn_cast<TemplateSpecializationType>(Arg)) {
// Perform template argument deduction for the template name.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
Param->getTemplateName(),
SpecArg->getTemplateName(),
Info, Deduced))
unsigned NumArgs = std::min(SpecArg->getNumArgs(), Param->getNumArgs());
for (unsigned I = 0; I != NumArgs; ++I)
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
Param->getArg(I),
SpecArg->getArg(I),
Info, Deduced))
// Perform template argument deduction for the template name.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context,
+ = DeduceTemplateArguments(S,
TemplateParams,
Param->getTemplateName(),
TemplateName(SpecArg->getSpecializedTemplate()),
for (unsigned I = 0; I != NumArgs; ++I)
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
Param->getArg(I),
ArgArgs.get(I),
Info, Deduced))
/// \brief Deduce the template arguments by comparing the parameter type and
/// the argument type (C++ [temp.deduct.type]).
///
-/// \param Context the AST context in which this deduction occurs.
+/// \param S the semantic analysis object within which we are deducing
///
/// \param TemplateParams the template parameters that we are deducing
///
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
Sema::TemplateDeductionInfo &Info,
unsigned TDF) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
- QualType Param = Context.getCanonicalType(ParamIn);
- QualType Arg = Context.getCanonicalType(ArgIn);
+ QualType Param = S.Context.getCanonicalType(ParamIn);
+ QualType Arg = S.Context.getCanonicalType(ArgIn);
// C++0x [temp.deduct.call]p4 bullet 1:
// - If the original P is a reference type, the deduced A (i.e., the type
// transformed A.
if (TDF & TDF_ParamWithReferenceType) {
Qualifiers Quals;
- QualType UnqualParam = Context.getUnqualifiedArrayType(Param, Quals);
+ QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals);
Quals.setCVRQualifiers(Quals.getCVRQualifiers() &
Arg.getCVRQualifiersThroughArrayTypes());
- Param = Context.getQualifiedType(UnqualParam, Quals);
+ Param = S.Context.getQualifiedType(UnqualParam, Quals);
}
// If the parameter type is not dependent, there is nothing to deduce.
// FIXME: address spaces, ObjC GC qualifiers
if (isa<ArrayType>(Arg)) {
Qualifiers Quals;
- Arg = Context.getUnqualifiedArrayType(Arg, Quals);
+ Arg = S.Context.getUnqualifiedArrayType(Arg, Quals);
if (Quals) {
- Arg = Context.getQualifiedType(Arg, Quals);
+ Arg = S.Context.getQualifiedType(Arg, Quals);
RecanonicalizeArg = true;
}
}
}
assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0");
- assert(Arg != Context.OverloadTy && "Unresolved overloaded function");
+ assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function");
QualType DeducedType = Arg;
DeducedType.removeCVRQualifiers(Param.getCVRQualifiers());
if (RecanonicalizeArg)
- DeducedType = Context.getCanonicalType(DeducedType);
+ DeducedType = S.Context.getCanonicalType(DeducedType);
if (Deduced[Index].isNull())
Deduced[Index] = TemplateArgument(DeducedType);
return Sema::TDK_NonDeducedMismatch;
unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
cast<PointerType>(Param)->getPointeeType(),
PointerArg->getPointeeType(),
Info, Deduced, SubTDF);
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
cast<LValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
Info, Deduced, 0);
if (!ReferenceArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
cast<RValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
Info, Deduced, 0);
// T [] (implied, but not stated explicitly)
case Type::IncompleteArray: {
const IncompleteArrayType *IncompleteArrayArg =
- Context.getAsIncompleteArrayType(Arg);
+ S.Context.getAsIncompleteArrayType(Arg);
if (!IncompleteArrayArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
- Context.getAsIncompleteArrayType(Param)->getElementType(),
+ return DeduceTemplateArguments(S, TemplateParams,
+ S.Context.getAsIncompleteArrayType(Param)->getElementType(),
IncompleteArrayArg->getElementType(),
Info, Deduced, 0);
}
// T [integer-constant]
case Type::ConstantArray: {
const ConstantArrayType *ConstantArrayArg =
- Context.getAsConstantArrayType(Arg);
+ S.Context.getAsConstantArrayType(Arg);
if (!ConstantArrayArg)
return Sema::TDK_NonDeducedMismatch;
const ConstantArrayType *ConstantArrayParm =
- Context.getAsConstantArrayType(Param);
+ S.Context.getAsConstantArrayType(Param);
if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize())
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
ConstantArrayParm->getElementType(),
ConstantArrayArg->getElementType(),
Info, Deduced, 0);
// type [i]
case Type::DependentSizedArray: {
- const ArrayType *ArrayArg = Context.getAsArrayType(Arg);
+ const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg);
if (!ArrayArg)
return Sema::TDK_NonDeducedMismatch;
// Check the element type of the arrays
const DependentSizedArrayType *DependentArrayParm
- = Context.getAsDependentSizedArrayType(Param);
+ = S.Context.getAsDependentSizedArrayType(Param);
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
DependentArrayParm->getElementType(),
ArrayArg->getElementType(),
Info, Deduced, 0))
if (const ConstantArrayType *ConstantArrayArg
= dyn_cast<ConstantArrayType>(ArrayArg)) {
llvm::APSInt Size(ConstantArrayArg->getSize());
- return DeduceNonTypeTemplateArgument(Context, NTTP, Size,
+ return DeduceNonTypeTemplateArgument(S, NTTP, Size,
Info, Deduced);
}
if (const DependentSizedArrayType *DependentArrayArg
= dyn_cast<DependentSizedArrayType>(ArrayArg))
- return DeduceNonTypeTemplateArgument(Context, NTTP,
+ return DeduceNonTypeTemplateArgument(S, NTTP,
DependentArrayArg->getSizeExpr(),
Info, Deduced);
// Check return types.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
FunctionProtoParam->getResultType(),
FunctionProtoArg->getResultType(),
Info, Deduced, 0))
for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
// Check argument types.
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
FunctionProtoParam->getArgType(I),
FunctionProtoArg->getArgType(I),
Info, Deduced, 0))
// Try to deduce template arguments from the template-id.
Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams, SpecParam, Arg,
+ = DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg,
Info, Deduced);
if (Result && (TDF & TDF_DerivedClass)) {
// More importantly:
// These alternatives are considered only if type deduction would
// otherwise fail.
- if (const RecordType *RecordT = dyn_cast<RecordType>(Arg)) {
+ if (const RecordType *RecordT = Arg->getAs<RecordType>()) {
+ // We cannot inspect base classes as part of deduction when the type
+ // is incomplete, so either instantiate any templates necessary to
+ // complete the type, or skip over it if it cannot be completed.
+ // FIXME: The location given becomes the PoI, so we should thread
+ // a better location through the TemplateDeductionInfo.
+ if (S.RequireCompleteType(RecordT->getDecl()->getLocStart(), Arg, 0))
+ return Result;
+
// Use data recursion to crawl through the list of base classes.
// Visited contains the set of nodes we have already visited, while
// ToVisit is our stack of records that we still need to visit.
// deduction from it.
if (NextT != RecordT) {
Sema::TemplateDeductionResult BaseResult
- = DeduceTemplateArguments(Context, TemplateParams, SpecParam,
+ = DeduceTemplateArguments(S, TemplateParams, SpecParam,
QualType(NextT, 0), Info, Deduced);
// If template argument deduction for this base was successful,
return Sema::TDK_NonDeducedMismatch;
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
MemPtrParam->getPointeeType(),
MemPtrArg->getPointeeType(),
Info, Deduced,
TDF & TDF_IgnoreQualifiers))
return Result;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
QualType(MemPtrParam->getClass(), 0),
QualType(MemPtrArg->getClass(), 0),
Info, Deduced, 0);
if (!BlockPtrArg)
return Sema::TDK_NonDeducedMismatch;
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
BlockPtrParam->getPointeeType(),
BlockPtrArg->getPointeeType(), Info,
Deduced, 0);
}
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgument &Param,
const TemplateArgument &Arg,
case TemplateArgument::Type:
if (Arg.getKind() == TemplateArgument::Type)
- return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
+ return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(),
Arg.getAsType(), Info, Deduced, 0);
Info.FirstArg = Param;
Info.SecondArg = Arg;
case TemplateArgument::Template:
if (Arg.getKind() == TemplateArgument::Template)
- return DeduceTemplateArguments(Context, TemplateParams,
+ return DeduceTemplateArguments(S, TemplateParams,
Param.getAsTemplate(),
Arg.getAsTemplate(), Info, Deduced);
Info.FirstArg = Param;
= getDeducedParameterFromExpr(Param.getAsExpr())) {
if (Arg.getKind() == TemplateArgument::Integral)
// FIXME: Sign problems here
- return DeduceNonTypeTemplateArgument(Context, NTTP,
+ return DeduceNonTypeTemplateArgument(S, NTTP,
*Arg.getAsIntegral(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Expression)
- return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(),
+ return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(),
Info, Deduced);
if (Arg.getKind() == TemplateArgument::Declaration)
- return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsDecl(),
+ return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(),
Info, Deduced);
assert(false && "Type/value mismatch");
}
static Sema::TemplateDeductionResult
-DeduceTemplateArguments(ASTContext &Context,
+DeduceTemplateArguments(Sema &S,
TemplateParameterList *TemplateParams,
const TemplateArgumentList &ParamList,
const TemplateArgumentList &ArgList,
assert(ParamList.size() == ArgList.size());
for (unsigned I = 0, N = ParamList.size(); I != N; ++I) {
if (Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
ParamList[I], ArgList[I],
Info, Deduced))
return Result;
llvm::SmallVector<TemplateArgument, 4> Deduced;
Deduced.resize(Partial->getTemplateParameters()->size());
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context,
+ = ::DeduceTemplateArguments(*this,
Partial->getTemplateParameters(),
Partial->getTemplateArgs(),
TemplateArgs, Info, Deduced))
unsigned TDF = 0;
Sema::TemplateDeductionResult Result
- = DeduceTemplateArguments(S.Context, TemplateParams,
+ = DeduceTemplateArguments(S, TemplateParams,
ParamType, ArgType,
Info, Deduced, TDF);
if (Result) continue;
TDF |= TDF_DerivedClass;
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context, TemplateParams,
+ = ::DeduceTemplateArguments(*this, TemplateParams,
ParamType, ArgType, Info, Deduced,
TDF))
return Result;
if (!ArgFunctionType.isNull()) {
// Deduce template arguments from the function type.
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context, TemplateParams,
+ = ::DeduceTemplateArguments(*this, TemplateParams,
FunctionType, ArgFunctionType, Info,
Deduced, 0))
return Result;
(P->isMemberPointerType() && P->isMemberPointerType()))
TDF |= TDF_IgnoreQualifiers;
if (TemplateDeductionResult Result
- = ::DeduceTemplateArguments(Context, TemplateParams,
+ = ::DeduceTemplateArguments(*this, TemplateParams,
P, A, Info, Deduced, TDF))
return Result;
/// \brief Deduce the template arguments during partial ordering by comparing
/// the parameter type and the argument type (C++0x [temp.deduct.partial]).
///
-/// \param Context the AST context in which this deduction occurs.
+/// \param S the semantic analysis object within which we are deducing
///
/// \param TemplateParams the template parameters that we are deducing
///
/// "success" result means that template argument deduction has not yet failed,
/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
-DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context,
+DeduceTemplateArgumentsDuringPartialOrdering(Sema &S,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
Sema::TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<TemplateArgument> &Deduced,
llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
- CanQualType Param = Context.getCanonicalType(ParamIn);
- CanQualType Arg = Context.getCanonicalType(ArgIn);
+ CanQualType Param = S.Context.getCanonicalType(ParamIn);
+ CanQualType Arg = S.Context.getCanonicalType(ArgIn);
// C++0x [temp.deduct.partial]p5:
// Before the partial ordering is done, certain transformations are
// described in 14.9.2.5. If deduction succeeds for a given type, the type
// from the argument template is considered to be at least as specialized
// as the type from the parameter template.
- return DeduceTemplateArguments(Context, TemplateParams, Param, Arg, Info,
+ return DeduceTemplateArguments(S, TemplateParams, Param, Arg, Info,
Deduced, TDF_None);
}
// used.
unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs());
for (unsigned I = 0; I != NumParams; ++I)
- if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S,
TemplateParams,
Proto2->getArgType(I),
Proto1->getArgType(I),
case TPOC_Conversion:
// - In the context of a call to a conversion operator, the return types
// of the conversion function templates are used.
- if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S,
TemplateParams,
Proto2->getResultType(),
Proto1->getResultType(),
case TPOC_Other:
// - In other contexts (14.6.6.2) the function template’s function type
// is used.
- if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context,
+ if (DeduceTemplateArgumentsDuringPartialOrdering(S,
TemplateParams,
FD2->getType(),
FD1->getType(),
// Determine whether PS1 is at least as specialized as PS2
Deduced.resize(PS2->getTemplateParameters()->size());
- bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(Context,
+ bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
PS2->getTemplateParameters(),
Context.getTypeDeclType(PS2),
Context.getTypeDeclType(PS1),
// Determine whether PS2 is at least as specialized as PS1
Deduced.clear();
Deduced.resize(PS1->getTemplateParameters()->size());
- bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(Context,
+ bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(*this,
PS1->getTemplateParameters(),
Context.getTypeDeclType(PS1),
Context.getTypeDeclType(PS2),