diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a8bca592df..154d3197f3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1206,6 +1206,9 @@ def err_template_arg_not_integral_or_enumeral : Error< def err_template_arg_not_ice : Error< "non-type template argument of type %0 is not an integral constant " "expression">; +def err_deduced_non_type_template_arg_type_mismatch : Error< + "deduced non-type template argument does not have the same type as the " + "its corresponding template parameter (%0 vs %1)">; def err_template_arg_not_convertible : Error< "non-type template argument of type %0 cannot be converted to a value " "of type %1">; @@ -1585,6 +1588,8 @@ def err_typecheck_invalid_restrict_invalid_pointee : Error< "pointer to function type %0 may not be 'restrict' qualified">; def ext_typecheck_zero_array_size : Extension< "zero size arrays are an extension">; +def err_typecheck_zero_array_size : Error< + "zero-length arrays are not permitted in C++">; def err_at_least_one_initializer_needed_to_size_array : Error< "at least one initializer value required to size array">; def err_array_size_non_int : Error<"size of array has non-integer type %0">; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7187f529ce..d0a4f7cbf6 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2862,12 +2862,29 @@ public: Decl *Param, TemplateArgumentListBuilder &Converted); + /// \brief Specifies the context in which a particular template + /// argument is being checked. + enum CheckTemplateArgumentKind { + /// \brief The template argument was specified in the code or was + /// instantiated with some deduced template arguments. + CTAK_Specified, + + /// \brief The template argument was deduced via template argument + /// deduction. + CTAK_Deduced, + + /// \brief The template argument was deduced from an array bound + /// via template argument deduction. + CTAK_DeducedFromArrayBound + }; + bool CheckTemplateArgument(NamedDecl *Param, const TemplateArgumentLoc &Arg, TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, - TemplateArgumentListBuilder &Converted); + TemplateArgumentListBuilder &Converted, + CheckTemplateArgumentKind CTAK = CTAK_Specified); bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, @@ -2887,9 +2904,18 @@ public: TemplateArgument &Converted); bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, - TemplateArgument &Converted); + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK = CTAK_Specified); bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, const TemplateArgumentLoc &Arg); + + OwningExprResult + BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, + QualType ParamType, + SourceLocation Loc); + OwningExprResult + BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, + SourceLocation Loc); /// \brief Enumeration describing how template parameter lists are compared /// for equality. @@ -3112,14 +3138,15 @@ public: TemplateDeductionResult SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate, const TemplateArgumentListInfo &ExplicitTemplateArgs, - llvm::SmallVectorImpl &Deduced, + llvm::SmallVectorImpl &Deduced, llvm::SmallVectorImpl &ParamTypes, QualType *FunctionType, TemplateDeductionInfo &Info); TemplateDeductionResult FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, - llvm::SmallVectorImpl &Deduced, + llvm::SmallVectorImpl &Deduced, + unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, TemplateDeductionInfo &Info); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ba9e3c7df9..08329e8996 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1897,7 +1897,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, - TemplateArgumentListBuilder &Converted) { + TemplateArgumentListBuilder &Converted, + CheckTemplateArgumentKind CTAK) { // Check template type parameters. if (TemplateTypeParmDecl *TTP = dyn_cast(Param)) return CheckTemplateTypeArgument(TTP, Arg, Converted); @@ -1937,7 +1938,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, case TemplateArgument::Expression: { Expr *E = Arg.getArgument().getAsExpr(); TemplateArgument Result; - if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) + if (CheckTemplateArgument(NTTP, NTTPType, E, Result, CTAK)) return true; Converted.Append(Result); @@ -2478,7 +2479,8 @@ bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, /// If no error was detected, Converted receives the converted template argument. bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, - TemplateArgument &Converted) { + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK) { SourceLocation StartLoc = Arg->getSourceRange().getBegin(); // If either the parameter has a dependent type or the argument is @@ -2525,17 +2527,27 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - // FIXME: We need some way to more easily get the unqualified form - // of the types without going all the way to the - // canonical type. - if (Context.getCanonicalType(ParamType).getCVRQualifiers()) - ParamType = Context.getCanonicalType(ParamType).getUnqualifiedType(); - if (Context.getCanonicalType(ArgType).getCVRQualifiers()) - ArgType = Context.getCanonicalType(ArgType).getUnqualifiedType(); + // From here on out, all we care about are the unqualified forms + // of the parameter and argument types. + ParamType = ParamType.getUnqualifiedType(); + ArgType = ArgType.getUnqualifiedType(); // Try to convert the argument to the parameter's type. if (Context.hasSameType(ParamType, ArgType)) { // Okay: no conversion necessary + } else if (CTAK == CTAK_Deduced) { + // C++ [temp.deduct.type]p17: + // If, in the declaration of a function template with a non-type + // template-parameter, the non-type template- parameter is used + // in an expression in the function parameter-list and, if the + // corresponding template-argument is deduced, the + // template-argument type shall match the type of the + // template-parameter exactly, except that a template-argument + // deduced from an array bound may be of any integral type. + Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) + << ArgType << ParamType; + Diag(Param->getLocation(), diag::note_template_param_here); + return true; } else if (IsIntegralPromotion(Arg, ArgType, ParamType) || !ParamType->isEnumeralType()) { // This is an integral promotion or conversion. @@ -2838,6 +2850,112 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, Arg.getLocation()); } +/// \brief Given a non-type template argument that refers to a +/// declaration and the type of its corresponding non-type template +/// parameter, produce an expression that properly refers to that +/// declaration. +Sema::OwningExprResult +Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, + QualType ParamType, + SourceLocation Loc) { + assert(Arg.getKind() == TemplateArgument::Declaration && + "Only declaration template arguments permitted here"); + ValueDecl *VD = cast(Arg.getAsDecl()); + + if (VD->getDeclContext()->isRecord() && + (isa(VD) || isa(VD))) { + // If the value is a class member, we might have a pointer-to-member. + // Determine whether the non-type template template parameter is of + // pointer-to-member type. If so, we need to build an appropriate + // expression for a pointer-to-member, since a "normal" DeclRefExpr + // would refer to the member itself. + if (ParamType->isMemberPointerType()) { + QualType ClassType + = Context.getTypeDeclType(cast(VD->getDeclContext())); + NestedNameSpecifier *Qualifier + = NestedNameSpecifier::Create(Context, 0, false, ClassType.getTypePtr()); + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + OwningExprResult RefExpr = BuildDeclRefExpr(VD, + VD->getType().getNonReferenceType(), + Loc, + &SS); + if (RefExpr.isInvalid()) + return ExprError(); + + RefExpr = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(RefExpr)); + assert(!RefExpr.isInvalid() && + Context.hasSameType(((Expr*) RefExpr.get())->getType(), + ParamType)); + return move(RefExpr); + } + } + + QualType T = VD->getType().getNonReferenceType(); + if (ParamType->isPointerType()) { + // C++03 [temp.arg.nontype]p5: + // - For a non-type template-parameter of type pointer to + // object, qualification conversions and the array-to-pointer + // conversion are applied. + // - For a non-type template-parameter of type pointer to + // function, only the function-to-pointer conversion is + // applied. + OwningExprResult RefExpr = BuildDeclRefExpr(VD, T, Loc); + if (RefExpr.isInvalid()) + return ExprError(); + + // Decay functions and arrays. + Expr *RefE = (Expr *)RefExpr.get(); + DefaultFunctionArrayConversion(RefE); + if (RefE != RefExpr.get()) { + RefExpr.release(); + RefExpr = Owned(RefE); + } + + // Qualification conversions. + RefExpr.release(); + ImpCastExprToType(RefE, ParamType.getUnqualifiedType(), CastExpr::CK_NoOp); + return Owned(RefE); + } + + // If the non-type template parameter has reference type, qualify the + // resulting declaration reference with the extra qualifiers on the + // type that the reference refers to. + if (const ReferenceType *TargetRef = ParamType->getAs()) + T = Context.getQualifiedType(T, TargetRef->getPointeeType().getQualifiers()); + + return BuildDeclRefExpr(VD, T, Loc); +} + +/// \brief Construct a new expression that refers to the given +/// integral template argument with the given source-location +/// information. +/// +/// This routine takes care of the mapping from an integral template +/// argument (which may have any integral type) to the appropriate +/// literal value. +Sema::OwningExprResult +Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, + SourceLocation Loc) { + assert(Arg.getKind() == TemplateArgument::Integral && + "Operation is only value for integral template arguments"); + QualType T = Arg.getIntegralType(); + if (T->isCharType() || T->isWideCharType()) + return Owned(new (Context) CharacterLiteral( + Arg.getAsIntegral()->getZExtValue(), + T->isWideCharType(), + T, + Loc)); + if (T->isBooleanType()) + return Owned(new (Context) CXXBoolLiteralExpr( + Arg.getAsIntegral()->getBoolValue(), + T, + Loc)); + + return Owned(new (Context) IntegerLiteral(*Arg.getAsIntegral(), T, Loc)); +} + + /// \brief Determine whether the given template parameter lists are /// equivalent. /// diff --git a/lib/Sema/SemaTemplate.h b/lib/Sema/SemaTemplate.h index 2bfb25a3d1..ca59e27355 100644 --- a/lib/Sema/SemaTemplate.h +++ b/lib/Sema/SemaTemplate.h @@ -99,6 +99,40 @@ namespace clang { /// template specialization to a function template. TPOC_Other }; + + /// \brief Captures a template argument whose value has been deduced + /// via c++ template argument deduction. + class DeducedTemplateArgument : public TemplateArgument { + /// \brief For a non-type template argument, whether the value was + /// deduced from an array bound. + bool DeducedFromArrayBound; + + public: + DeducedTemplateArgument() + : TemplateArgument(), DeducedFromArrayBound(false) { } + + DeducedTemplateArgument(const TemplateArgument &Arg, + bool DeducedFromArrayBound = false) + : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { } + + /// \brief Construct an integral non-type template argument that + /// has been deduced, possible from an array bound. + DeducedTemplateArgument(const llvm::APSInt &Value, + QualType ValueType, + bool DeducedFromArrayBound) + : TemplateArgument(Value, ValueType), + DeducedFromArrayBound(DeducedFromArrayBound) { } + + /// \brief For a non-type template argument, determine whether the + /// template argument was deduced from an array bound. + bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } + + /// \brief Specify whether the given non-type template argument + /// was deduced from an array bound. + void setDeducedFromArrayBound(bool Deduced) { + DeducedFromArrayBound = Deduced; + } + }; } #endif // LLVM_CLANG_SEMA_TEMPLATE_H diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index ed3e3c4c22..31a642fd05 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -75,7 +75,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgument &Param, const TemplateArgument &Arg, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced); + llvm::SmallVectorImpl &Deduced); /// \brief If the given expression is of a form that permits the deduction /// of a non-type template parameter, return the declaration of that @@ -96,13 +96,15 @@ static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, llvm::APSInt Value, QualType ValueType, + bool DeducedFromArrayBound, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced) { + llvm::SmallVectorImpl &Deduced) { assert(NTTP->getDepth() == 0 && "Cannot deduce non-type template argument with depth > 0"); if (Deduced[NTTP->getIndex()].isNull()) { - Deduced[NTTP->getIndex()] = TemplateArgument(Value, ValueType); + Deduced[NTTP->getIndex()] = DeducedTemplateArgument(Value, ValueType, + DeducedFromArrayBound); return Sema::TDK_Success; } @@ -122,6 +124,9 @@ DeduceNonTypeTemplateArgument(Sema &S, return Sema::TDK_Inconsistent; } + if (!DeducedFromArrayBound) + Deduced[NTTP->getIndex()].setDeducedFromArrayBound(false); + return Sema::TDK_Success; } @@ -134,7 +139,7 @@ DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, Expr *Value, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced) { + llvm::SmallVectorImpl &Deduced) { assert(NTTP->getDepth() == 0 && "Cannot deduce non-type template argument with depth > 0"); assert((Value->isTypeDependent() || Value->isValueDependent()) && @@ -176,7 +181,7 @@ DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, Decl *D, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced) { + llvm::SmallVectorImpl &Deduced) { assert(NTTP->getDepth() == 0 && "Cannot deduce non-type template argument with depth > 0"); @@ -210,7 +215,7 @@ DeduceTemplateArguments(Sema &S, TemplateName Param, TemplateName Arg, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced) { + llvm::SmallVectorImpl &Deduced) { TemplateDecl *ParamDecl = Param.getAsTemplateDecl(); if (!ParamDecl) { // The parameter type is dependent and is not a template template parameter, @@ -274,7 +279,7 @@ DeduceTemplateArguments(Sema &S, const TemplateSpecializationType *Param, QualType Arg, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced) { + llvm::SmallVectorImpl &Deduced) { assert(Arg.isCanonical() && "Argument type must be canonical"); // Check whether the template argument is a dependent template-id. @@ -366,7 +371,7 @@ DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, QualType ParamIn, QualType ArgIn, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced, + llvm::SmallVectorImpl &Deduced, unsigned TDF) { // We only want to look at the canonical types, since typedefs and // sugar are not part of template argument deduction. @@ -574,6 +579,7 @@ DeduceTemplateArguments(Sema &S, llvm::APSInt Size(ConstantArrayArg->getSize()); return DeduceNonTypeTemplateArgument(S, NTTP, Size, S.Context.getSizeType(), + /*ArrayBound=*/true, Info, Deduced); } if (const DependentSizedArrayType *DependentArrayArg @@ -785,7 +791,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgument &Param, const TemplateArgument &Arg, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced) { + llvm::SmallVectorImpl &Deduced) { switch (Param.getKind()) { case TemplateArgument::Null: assert(false && "Null template argument in parameter list"); @@ -846,6 +852,7 @@ DeduceTemplateArguments(Sema &S, return DeduceNonTypeTemplateArgument(S, NTTP, *Arg.getAsIntegral(), Arg.getIntegralType(), + /*ArrayBound=*/false, Info, Deduced); if (Arg.getKind() == TemplateArgument::Expression) return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(), @@ -877,7 +884,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgumentList &ParamList, const TemplateArgumentList &ArgList, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced) { + llvm::SmallVectorImpl &Deduced) { assert(ParamList.size() == ArgList.size()); for (unsigned I = 0, N = ParamList.size(); I != N; ++I) { if (Sema::TemplateDeductionResult Result @@ -966,7 +973,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, // specialization can be deduced from the actual template argument // list (14.8.2). SFINAETrap Trap(*this); - llvm::SmallVector Deduced; + llvm::SmallVector Deduced; Deduced.resize(Partial->getTemplateParameters()->size()); if (TemplateDeductionResult Result = ::DeduceTemplateArguments(*this, @@ -1007,6 +1014,8 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, // verify that the instantiated template arguments are both valid // and are equivalent to the template arguments originally provided // to the class template. + // FIXME: Do we have to correct the types of deduced non-type template + // arguments (in particular, integral non-type template arguments?). Sema::LocalInstantiationScope InstScope(*this); ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate(); const TemplateArgumentLoc *PartialTemplateArgs @@ -1110,7 +1119,7 @@ Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, const TemplateArgumentListInfo &ExplicitTemplateArgs, - llvm::SmallVectorImpl &Deduced, + llvm::SmallVectorImpl &Deduced, llvm::SmallVectorImpl &ParamTypes, QualType *FunctionType, TemplateDeductionInfo &Info) { @@ -1223,12 +1232,67 @@ Sema::SubstituteExplicitTemplateArguments( return TDK_Success; } +/// \brief Allocate a TemplateArgumentLoc where all locations have +/// been initialized to the given location. +/// +/// \param S The semantic analysis object. +/// +/// \param The template argument we are producing template argument +/// location information for. +/// +/// \param NTTPType For a declaration template argument, the type of +/// the non-type template parameter that corresponds to this template +/// argument. +/// +/// \param Loc The source location to use for the resulting template +/// argument. +static TemplateArgumentLoc +getTrivialTemplateArgumentLoc(Sema &S, + const TemplateArgument &Arg, + QualType NTTPType, + SourceLocation Loc) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Can't get a NULL template argument here"); + break; + + case TemplateArgument::Type: + return TemplateArgumentLoc(Arg, + S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc)); + + case TemplateArgument::Declaration: { + Expr *E + = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc) + .takeAs(); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case TemplateArgument::Integral: { + Expr *E + = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs(); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case TemplateArgument::Template: + return TemplateArgumentLoc(Arg, SourceRange(), Loc); + + case TemplateArgument::Expression: + return TemplateArgumentLoc(Arg, Arg.getAsExpr()); + + case TemplateArgument::Pack: + llvm_unreachable("Template parameter packs are not yet supported"); + } + + return TemplateArgumentLoc(); +} + /// \brief Finish template argument deduction for a function template, /// checking the deduced template arguments for completeness and forming /// the function template specialization. Sema::TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, - llvm::SmallVectorImpl &Deduced, + llvm::SmallVectorImpl &Deduced, + unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { TemplateParameterList *TemplateParams @@ -1251,13 +1315,71 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, // explicitly specified, template argument deduction fails. TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size()); for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { + NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I); if (!Deduced[I].isNull()) { - Builder.Append(Deduced[I]); + if (I < NumExplicitlySpecified || + Deduced[I].getKind() == TemplateArgument::Type) { + // We have already fully type-checked and converted this + // argument (because it was explicitly-specified) or no + // additional checking is necessary (because it's a template + // type parameter). Just record the presence of this + // parameter. + Builder.Append(Deduced[I]); + continue; + } + + // We have deduced this argument, so it still needs to be + // checked and converted. + + // First, for a non-type template parameter type that is + // initialized by a declaration, we need the type of the + // corresponding non-type template parameter. + QualType NTTPType; + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast(Param)) { + if (Deduced[I].getKind() == TemplateArgument::Declaration) { + NTTPType = NTTP->getType(); + if (NTTPType->isDependentType()) { + TemplateArgumentList TemplateArgs(Context, Builder, + /*TakeArgs=*/false); + NTTPType = SubstType(NTTPType, + MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), + NTTP->getDeclName()); + if (NTTPType.isNull()) { + Info.Param = makeTemplateParameter(Param); + return TDK_SubstitutionFailure; + } + } + } + } + + // Convert the deduced template argument into a template + // argument that we can check, almost as if the user had written + // the template argument explicitly. + TemplateArgumentLoc Arg = getTrivialTemplateArgumentLoc(*this, + Deduced[I], + NTTPType, + SourceLocation()); + + // Check the template argument, converting it as necessary. + if (CheckTemplateArgument(Param, Arg, + FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + Builder, + Deduced[I].wasDeducedFromArrayBound() + ? CTAK_DeducedFromArrayBound + : CTAK_Deduced)) { + Info.Param = makeTemplateParameter( + const_cast(TemplateParams->getParam(I))); + return TDK_SubstitutionFailure; + } + continue; } // Substitute into the default template argument, if available. - NamedDecl *Param = FunctionTemplate->getTemplateParameters()->getParam(I); TemplateArgumentLoc DefArg = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate, FunctionTemplate->getLocation(), @@ -1277,7 +1399,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, FunctionTemplate, FunctionTemplate->getLocation(), FunctionTemplate->getSourceRange().getEnd(), - Builder)) { + Builder, + CTAK_Deduced)) { Info.Param = makeTemplateParameter( const_cast(TemplateParams->getParam(I))); return TDK_SubstitutionFailure; @@ -1388,7 +1511,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, // Type deduction is done independently for each P/A pair, and // the deduced template argument values are then combined. // So we do not reject deductions which were made elsewhere. - llvm::SmallVector Deduced(TemplateParams->size()); + llvm::SmallVector + Deduced(TemplateParams->size()); Sema::TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc()); unsigned TDF = 0; @@ -1459,8 +1583,9 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, Sema::LocalInstantiationScope InstScope(*this); TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); - llvm::SmallVector Deduced; + llvm::SmallVector Deduced; llvm::SmallVector ParamTypes; + unsigned NumExplicitlySpecified = 0; if (ExplicitTemplateArgs) { TemplateDeductionResult Result = SubstituteExplicitTemplateArguments(FunctionTemplate, @@ -1471,6 +1596,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, Info); if (Result) return Result; + + NumExplicitlySpecified = Deduced.size(); } else { // Just fill in the parameter types from the function declaration. for (unsigned I = 0; I != CheckArgs; ++I) @@ -1573,6 +1700,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, } return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, + NumExplicitlySpecified, Specialization, Info); } @@ -1612,7 +1740,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // Substitute any explicit template arguments. Sema::LocalInstantiationScope InstScope(*this); - llvm::SmallVector Deduced; + llvm::SmallVector Deduced; + unsigned NumExplicitlySpecified = 0; llvm::SmallVector ParamTypes; if (ExplicitTemplateArgs) { if (TemplateDeductionResult Result @@ -1621,6 +1750,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, Deduced, ParamTypes, &FunctionType, Info)) return Result; + + NumExplicitlySpecified = Deduced.size(); } // Template argument deduction for function templates in a SFINAE context. @@ -1639,6 +1770,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, } return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, + NumExplicitlySpecified, Specialization, Info); } @@ -1707,7 +1839,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // A) as described in 14.8.2.4. TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); - llvm::SmallVector Deduced; + llvm::SmallVector Deduced; Deduced.resize(TemplateParams->size()); // C++0x [temp.deduct.conv]p4: @@ -1742,7 +1874,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, Sema::LocalInstantiationScope InstScope(*this); FunctionDecl *Spec = 0; TemplateDeductionResult Result - = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, Spec, Info); + = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec, + Info); Specialization = cast_or_null(Spec); return Result; } @@ -1800,11 +1933,11 @@ enum DeductionQualifierComparison { /// but it may still fail, later, for other reasons. static Sema::TemplateDeductionResult DeduceTemplateArgumentsDuringPartialOrdering(Sema &S, - TemplateParameterList *TemplateParams, + TemplateParameterList *TemplateParams, QualType ParamIn, QualType ArgIn, Sema::TemplateDeductionInfo &Info, - llvm::SmallVectorImpl &Deduced, - llvm::SmallVectorImpl *QualifierComparisons) { + llvm::SmallVectorImpl &Deduced, + llvm::SmallVectorImpl *QualifierComparisons) { CanQualType Param = S.Context.getCanonicalType(ParamIn); CanQualType Arg = S.Context.getCanonicalType(ArgIn); @@ -1878,7 +2011,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, assert(Proto1 && Proto2 && "Function templates must have prototypes"); TemplateParameterList *TemplateParams = FT2->getTemplateParameters(); - llvm::SmallVector Deduced; + llvm::SmallVector Deduced; Deduced.resize(TemplateParams->size()); // C++0x [temp.deduct.partial]p3: @@ -2205,7 +2338,7 @@ Sema::getMoreSpecializedPartialSpecialization( // computation is slightly simpler than the general problem of function // template partial ordering, because class template partial specializations // are more constrained. We know that every template parameter is deduc - llvm::SmallVector Deduced; + llvm::SmallVector Deduced; Sema::TemplateDeductionInfo Info(Context, Loc); // Determine whether PS1 is at least as specialized as PS2 @@ -2526,8 +2659,9 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, /// \brief Marks all of the template parameters that will be deduced by a /// call to the given function template. -void Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, - llvm::SmallVectorImpl &Deduced) { +void +Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, + llvm::SmallVectorImpl &Deduced) { TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); Deduced.clear(); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 89a660c79f..4da1fcb924 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -745,101 +745,13 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, DeclarationName()); assert(!TargetType.isNull() && "type substitution failed for param type"); assert(!TargetType->isDependentType() && "param type still dependent"); - - if (VD->getDeclContext()->isRecord() && - (isa(VD) || isa(VD))) { - // If the value is a class member, we might have a pointer-to-member. - // Determine whether the non-type template template parameter is of - // pointer-to-member type. If so, we need to build an appropriate - // expression for a pointer-to-member, since a "normal" DeclRefExpr - // would refer to the member itself. - if (TargetType->isMemberPointerType()) { - QualType ClassType - = SemaRef.Context.getTypeDeclType( - cast(VD->getDeclContext())); - NestedNameSpecifier *Qualifier - = NestedNameSpecifier::Create(SemaRef.Context, 0, false, - ClassType.getTypePtr()); - CXXScopeSpec SS; - SS.setScopeRep(Qualifier); - OwningExprResult RefExpr - = SemaRef.BuildDeclRefExpr(VD, - VD->getType().getNonReferenceType(), - E->getLocation(), - &SS); - if (RefExpr.isInvalid()) - return SemaRef.ExprError(); - - RefExpr = SemaRef.CreateBuiltinUnaryOp(E->getLocation(), - UnaryOperator::AddrOf, - move(RefExpr)); - assert(!RefExpr.isInvalid() && - SemaRef.Context.hasSameType(((Expr*) RefExpr.get())->getType(), - TargetType)); - return move(RefExpr); - } - } - - QualType T = VD->getType().getNonReferenceType(); - - if (TargetType->isPointerType()) { - // C++03 [temp.arg.nontype]p5: - // - For a non-type template-parameter of type pointer to - // object, qualification conversions and the array-to-pointer - // conversion are applied. - // - For a non-type template-parameter of type pointer to - // function, only the function-to-pointer conversion is - // applied. - - OwningExprResult RefExpr - = SemaRef.BuildDeclRefExpr(VD, T, E->getLocation()); - if (RefExpr.isInvalid()) - return SemaRef.ExprError(); - - // Decay functions and arrays. - Expr *RefE = (Expr *)RefExpr.get(); - SemaRef.DefaultFunctionArrayConversion(RefE); - if (RefE != RefExpr.get()) { - RefExpr.release(); - RefExpr = SemaRef.Owned(RefE); - } - - // Qualification conversions. - RefExpr.release(); - SemaRef.ImpCastExprToType(RefE, TargetType.getUnqualifiedType(), - CastExpr::CK_NoOp); - return SemaRef.Owned(RefE); - } - - // If the non-type template parameter has reference type, qualify the - // resulting declaration reference with the extra qualifiers on the - // type that the reference refers to. - if (const ReferenceType *TargetRef = TargetType->getAs()) - T = SemaRef.Context.getQualifiedType(T, - TargetRef->getPointeeType().getQualifiers()); - - return SemaRef.BuildDeclRefExpr(VD, T, E->getLocation()); + return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, + TargetType, + E->getLocation()); } - assert(Arg.getKind() == TemplateArgument::Integral); - QualType T = Arg.getIntegralType(); - if (T->isCharType() || T->isWideCharType()) - return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral( - Arg.getAsIntegral()->getZExtValue(), - T->isWideCharType(), - T, - E->getSourceRange().getBegin())); - if (T->isBooleanType()) - return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr( - Arg.getAsIntegral()->getBoolValue(), - T, - E->getSourceRange().getBegin())); - - assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T)); - return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral( - *Arg.getAsIntegral(), - T, - E->getSourceRange().getBegin())); + return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg, + E->getSourceRange().getBegin()); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 80e1a05111..c7b1ef15aa 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -680,8 +680,11 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return QualType(); } if (ConstVal == 0) { - // GCC accepts zero sized static arrays. - Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size) + // GCC accepts zero sized static arrays. We allow them when + // we're not in a SFINAE context. + Diag(ArraySize->getLocStart(), + isSFINAEContext()? diag::err_typecheck_zero_array_size + : diag::ext_typecheck_zero_array_size) << ArraySize->getSourceRange(); } T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp new file mode 100644 index 0000000000..2a7f16dc6b --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template class A { }; +template void f(A); // expected-note{{failed template argument deduction}} + +void k1() { + A<1> a; + f(a); // expected-error{{no matching function for call}} + f<1>(a); +} +template class B { }; +template void g(B); +void k2() { + B<1> b; + g(b); // OK: cv-qualifiers are ignored on template parameter types +} + +template void h(int (&)[s]); // expected-note{{failed template argument deduction}} +void k3() { + int array[5]; + h(array); + h<5>(array); +} + +template void h(int (&)[s], A); // expected-note{{failed template argument deduction}} +void k4() { + A<5> a; + int array[5]; + h(array, a); // expected-error{{no matching function for call}} + h<5>(array, a); +} diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp index d077a35930..51e12e994c 100644 --- a/test/SemaTemplate/temp_arg_nontype.cpp +++ b/test/SemaTemplate/temp_arg_nontype.cpp @@ -171,3 +171,12 @@ namespace pr6249 { int h(); template int f(); } + +namespace PR6723 { + template void f(int (&a)[C]); // expected-note 2{{candidate template ignored}} + void g() { + int arr512[512]; + f(arr512); // expected-error{{no matching function for call}} + f<512>(arr512); // expected-error{{no matching function for call}} + } +}