diff options
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 152 | ||||
-rw-r--r-- | test/SemaTemplate/deduction.cpp | 12 |
2 files changed, 92 insertions, 72 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 984aa6bb61..3edc7ff228 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -49,7 +49,7 @@ namespace clang { using namespace clang; static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgument &Param, const TemplateArgument &Arg, @@ -72,7 +72,7 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) { /// \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, @@ -84,7 +84,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, 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()); @@ -126,7 +126,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, /// /// \returns true if deduction succeeded, false otherwise. static Sema::TemplateDeductionResult -DeduceNonTypeTemplateArgument(ASTContext &Context, +DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, Expr *Value, Sema::TemplateDeductionInfo &Info, @@ -152,8 +152,8 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, 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; @@ -169,7 +169,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, /// /// \returns true if deduction succeeded, false otherwise. static Sema::TemplateDeductionResult -DeduceNonTypeTemplateArgument(ASTContext &Context, +DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, Decl *D, Sema::TemplateDeductionInfo &Info, @@ -202,7 +202,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, } static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, TemplateName Param, TemplateName Arg, @@ -221,13 +221,13 @@ DeduceTemplateArguments(ASTContext &Context, 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. @@ -238,7 +238,7 @@ DeduceTemplateArguments(ASTContext &Context, } // 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. @@ -250,7 +250,7 @@ DeduceTemplateArguments(ASTContext &Context, /// \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 /// @@ -266,7 +266,7 @@ DeduceTemplateArguments(ASTContext &Context, /// "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, @@ -279,7 +279,7 @@ DeduceTemplateArguments(ASTContext &Context, = 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)) @@ -291,7 +291,7 @@ DeduceTemplateArguments(ASTContext &Context, 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)) @@ -314,7 +314,7 @@ DeduceTemplateArguments(ASTContext &Context, // Perform template argument deduction for the template name. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, + = DeduceTemplateArguments(S, TemplateParams, Param->getTemplateName(), TemplateName(SpecArg->getSpecializedTemplate()), @@ -328,7 +328,7 @@ DeduceTemplateArguments(ASTContext &Context, 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)) @@ -340,7 +340,7 @@ DeduceTemplateArguments(ASTContext &Context, /// \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 /// @@ -359,7 +359,7 @@ DeduceTemplateArguments(ASTContext &Context, /// "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, @@ -367,8 +367,8 @@ DeduceTemplateArguments(ASTContext &Context, 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 @@ -376,10 +376,10 @@ DeduceTemplateArguments(ASTContext &Context, // 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. @@ -409,9 +409,9 @@ DeduceTemplateArguments(ASTContext &Context, // 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; } } @@ -426,11 +426,11 @@ DeduceTemplateArguments(ASTContext &Context, } 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); @@ -479,7 +479,7 @@ DeduceTemplateArguments(ASTContext &Context, 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); @@ -491,7 +491,7 @@ DeduceTemplateArguments(ASTContext &Context, if (!ReferenceArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, cast<LValueReferenceType>(Param)->getPointeeType(), ReferenceArg->getPointeeType(), Info, Deduced, 0); @@ -503,7 +503,7 @@ DeduceTemplateArguments(ASTContext &Context, if (!ReferenceArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, cast<RValueReferenceType>(Param)->getPointeeType(), ReferenceArg->getPointeeType(), Info, Deduced, 0); @@ -512,12 +512,12 @@ DeduceTemplateArguments(ASTContext &Context, // 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); } @@ -525,16 +525,16 @@ DeduceTemplateArguments(ASTContext &Context, // 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); @@ -542,15 +542,15 @@ DeduceTemplateArguments(ASTContext &Context, // 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)) @@ -569,12 +569,12 @@ DeduceTemplateArguments(ASTContext &Context, 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); @@ -606,7 +606,7 @@ DeduceTemplateArguments(ASTContext &Context, // Check return types. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, FunctionProtoParam->getResultType(), FunctionProtoArg->getResultType(), Info, Deduced, 0)) @@ -615,7 +615,7 @@ DeduceTemplateArguments(ASTContext &Context, 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)) @@ -636,7 +636,7 @@ DeduceTemplateArguments(ASTContext &Context, // 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)) { @@ -649,7 +649,15 @@ DeduceTemplateArguments(ASTContext &Context, // 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. @@ -670,7 +678,7 @@ DeduceTemplateArguments(ASTContext &Context, // 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, @@ -715,14 +723,14 @@ DeduceTemplateArguments(ASTContext &Context, 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); @@ -740,7 +748,7 @@ DeduceTemplateArguments(ASTContext &Context, if (!BlockPtrArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, BlockPtrParam->getPointeeType(), BlockPtrArg->getPointeeType(), Info, Deduced, 0); @@ -761,7 +769,7 @@ DeduceTemplateArguments(ASTContext &Context, } static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgument &Param, const TemplateArgument &Arg, @@ -774,7 +782,7 @@ DeduceTemplateArguments(ASTContext &Context, 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; @@ -782,7 +790,7 @@ DeduceTemplateArguments(ASTContext &Context, 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; @@ -826,14 +834,14 @@ DeduceTemplateArguments(ASTContext &Context, = 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"); @@ -854,7 +862,7 @@ DeduceTemplateArguments(ASTContext &Context, } static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgumentList &ParamList, const TemplateArgumentList &ArgList, @@ -863,7 +871,7 @@ DeduceTemplateArguments(ASTContext &Context, 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; @@ -951,7 +959,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, llvm::SmallVector<TemplateArgument, 4> Deduced; Deduced.resize(Partial->getTemplateParameters()->size()); if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, + = ::DeduceTemplateArguments(*this, Partial->getTemplateParameters(), Partial->getTemplateArgs(), TemplateArgs, Info, Deduced)) @@ -1380,7 +1388,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, unsigned TDF = 0; Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(S.Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, ParamType, ArgType, Info, Deduced, TDF); if (Result) continue; @@ -1549,7 +1557,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, TDF |= TDF_DerivedClass; if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, TemplateParams, + = ::DeduceTemplateArguments(*this, TemplateParams, ParamType, ArgType, Info, Deduced, TDF)) return Result; @@ -1617,7 +1625,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, 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; @@ -1716,7 +1724,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, (P->isMemberPointerType() && P->isMemberPointerType())) TDF |= TDF_IgnoreQualifiers; if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, TemplateParams, + = ::DeduceTemplateArguments(*this, TemplateParams, P, A, Info, Deduced, TDF)) return Result; @@ -1767,7 +1775,7 @@ enum DeductionQualifierComparison { /// \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 /// @@ -1783,14 +1791,14 @@ enum DeductionQualifierComparison { /// "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 @@ -1837,7 +1845,7 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context, // 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); } @@ -1874,7 +1882,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // 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), @@ -1889,7 +1897,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, 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(), @@ -1902,7 +1910,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, 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(), @@ -2191,7 +2199,7 @@ Sema::getMoreSpecializedPartialSpecialization( // 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), @@ -2202,7 +2210,7 @@ Sema::getMoreSpecializedPartialSpecialization( // 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), diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp index 375d199f58..8d00bb796e 100644 --- a/test/SemaTemplate/deduction.cpp +++ b/test/SemaTemplate/deduction.cpp @@ -86,3 +86,15 @@ int array4[is_same<Replace<vector<int, _2>, double, float>::type, vector<int, fl template <typename T, int N> void f(const T (&a)[N]); int iarr[] = { 1 }; void test_PR5911() { f(iarr); } + +// Must not examine base classes of incomplete type during template argument +// deduction. +namespace PR6257 { + template <typename T> struct X { + template <typename U> X(const X<U>& u); + }; + struct A; + void f(A& a); + void f(const X<A>& a); + void test(A& a) { (void)f(a); } +} |