diff options
-rw-r--r-- | include/clang/AST/TypeLoc.h | 10 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 18 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 56 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp | 47 | ||||
-rw-r--r-- | test/SemaTemplate/temp_arg_nontype.cpp | 3 |
7 files changed, 115 insertions, 40 deletions
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index c5497b8149..16a8cb40c8 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1008,11 +1008,6 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, FunctionTypeLoc, FunctionType, FunctionLocInfo> { - // ParmVarDecls* are stored after Info, one for each argument. - ParmVarDecl **getParmArray() const { - return (ParmVarDecl**) getExtraLocalData(); - } - public: SourceLocation getLParenLoc() const { return getLocalData()->LParenLoc; @@ -1035,6 +1030,11 @@ public: getLocalData()->TrailingReturn = Trailing; } + // ParmVarDecls* are stored after Info, one for each argument. + ParmVarDecl **getParmArray() const { + return (ParmVarDecl**) getExtraLocalData(); + } + unsigned getNumArgs() const { if (isa<FunctionNoProtoType>(getTypePtr())) return 0; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index ca169f04b5..101cf6acc2 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3890,6 +3890,10 @@ public: DeclarationName Entity); ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs); + bool SubstParmTypes(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, + const MultiLevelTemplateArgumentList &TemplateArgs, + llvm::SmallVectorImpl<QualType> &ParamTypes); ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index fcc73b8974..644ff35c3e 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1889,19 +1889,11 @@ Sema::SubstituteExplicitTemplateArguments( // Instantiate the types of each of the function parameters given the // explicitly-specified template arguments. - for (FunctionDecl::param_iterator P = Function->param_begin(), - PEnd = Function->param_end(); - P != PEnd; - ++P) { - QualType ParamType - = SubstType((*P)->getType(), - MultiLevelTemplateArgumentList(*ExplicitArgumentList), - (*P)->getLocation(), (*P)->getDeclName()); - if (ParamType.isNull() || Trap.hasErrorOccurred()) - return TDK_SubstitutionFailure; - - ParamTypes.push_back(ParamType); - } + if (SubstParmTypes(Function->getLocation(), + Function->param_begin(), Function->getNumParams(), + MultiLevelTemplateArgumentList(*ExplicitArgumentList), + ParamTypes)) + return TDK_SubstitutionFailure; // If the caller wants a full function type back, instantiate the return // type and form that function type. diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 7deb7cad3b..c4f91f9ff6 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1221,6 +1221,23 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, return NewParm; } +/// \brief Substitute the given template arguments into the given set of +/// parameters, producing the set of parameter types that would be generated +/// from such a substitution. +bool Sema::SubstParmTypes(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, + const MultiLevelTemplateArgumentList &TemplateArgs, + llvm::SmallVectorImpl<QualType> &ParamTypes) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, + DeclarationName()); + return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0, + ParamTypes, 0); +} + /// \brief Perform substitution on the base class specifiers of the /// given class template specialization. /// diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 25ead7bba5..60ec950c12 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -439,9 +439,11 @@ public: /// variables vector are acceptable. /// /// Return true on error. - bool TransformFunctionTypeParams(FunctionProtoTypeLoc TL, + bool TransformFunctionTypeParams(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, + const QualType *ParamTypes, llvm::SmallVectorImpl<QualType> &PTypes, - llvm::SmallVectorImpl<ParmVarDecl*> &PVars); + llvm::SmallVectorImpl<ParmVarDecl*> *PVars); /// \brief Transforms a single function-type parameter. Return null /// on error. @@ -3390,13 +3392,13 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm) { template<typename Derived> bool TreeTransform<Derived>:: - TransformFunctionTypeParams(FunctionProtoTypeLoc TL, - llvm::SmallVectorImpl<QualType> &PTypes, - llvm::SmallVectorImpl<ParmVarDecl*> &PVars) { - FunctionProtoType *T = TL.getTypePtr(); - - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { - if (ParmVarDecl *OldParm = TL.getArg(i)) { + TransformFunctionTypeParams(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, + const QualType *ParamTypes, + llvm::SmallVectorImpl<QualType> &OutParamTypes, + llvm::SmallVectorImpl<ParmVarDecl*> *PVars) { + for (unsigned i = 0; i != NumParams; ++i) { + if (ParmVarDecl *OldParm = Params[i]) { if (OldParm->isParameterPack()) { // We have a function parameter pack that may need to be expanded. llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; @@ -3428,8 +3430,9 @@ bool TreeTransform<Derived>:: if (!NewParm) return true; - PTypes.push_back(NewParm->getType()); - PVars.push_back(NewParm); + OutParamTypes.push_back(NewParm->getType()); + if (PVars) + PVars->push_back(NewParm); } // We're done with the pack expansion. @@ -3445,14 +3448,15 @@ bool TreeTransform<Derived>:: if (!NewParm) return true; - PTypes.push_back(NewParm->getType()); - PVars.push_back(NewParm); + OutParamTypes.push_back(NewParm->getType()); + if (PVars) + PVars->push_back(NewParm); continue; } // Deal with the possibility that we don't have a parameter // declaration for this parameter. - QualType OldType = T->getArgType(i); + QualType OldType = ParamTypes[i]; bool IsPackExpansion = false; if (const PackExpansionType *Expansion = dyn_cast<PackExpansionType>(OldType)) { @@ -3464,7 +3468,7 @@ bool TreeTransform<Derived>:: // Determine whether we should expand the parameter packs. bool ShouldExpand = false; unsigned NumExpansions = 0; - if (getDerived().TryExpandParameterPacks(TL.getBeginLoc(), SourceRange(), + if (getDerived().TryExpandParameterPacks(Loc, SourceRange(), Unexpanded.data(), Unexpanded.size(), ShouldExpand, NumExpansions)) { @@ -3480,8 +3484,9 @@ bool TreeTransform<Derived>:: if (NewType.isNull()) return true; - PTypes.push_back(NewType); - PVars.push_back(0); + OutParamTypes.push_back(NewType); + if (PVars) + PVars->push_back(0); } // We're done with the pack expansion. @@ -3502,8 +3507,9 @@ bool TreeTransform<Derived>:: if (IsPackExpansion) NewType = getSema().Context.getPackExpansionType(NewType); - PTypes.push_back(NewType); - PVars.push_back(0); + OutParamTypes.push_back(NewType); + if (PVars) + PVars->push_back(0); } return false; @@ -3530,7 +3536,11 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, QualType ResultType; if (TL.getTrailingReturn()) { - if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls)) + if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), + TL.getParmArray(), + TL.getNumArgs(), + TL.getTypePtr()->arg_type_begin(), + ParamTypes, &ParamDecls)) return QualType(); ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); @@ -3542,7 +3552,11 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, if (ResultType.isNull()) return QualType(); - if (getDerived().TransformFunctionTypeParams(TL, ParamTypes, ParamDecls)) + if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), + TL.getParmArray(), + TL.getNumArgs(), + TL.getTypePtr()->arg_type_begin(), + ParamTypes, &ParamDecls)) return QualType(); } diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp new file mode 100644 index 0000000000..ddee152e69 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// Metafunction to extract the Nth type from a set of types. +template<unsigned N, typename ...Types> struct get_nth_type; + +template<unsigned N, typename Head, typename ...Tail> +struct get_nth_type<N, Head, Tail...> : get_nth_type<N-1, Tail...> { }; + +template<typename Head, typename ...Tail> +struct get_nth_type<0, Head, Tail...> { + typedef Head type; +}; + +// Placeholder type when get_nth_type fails. +struct no_type {}; + +template<unsigned N> +struct get_nth_type<N> { + typedef no_type type; +}; + +template<typename ...Args> +typename get_nth_type<0, Args...>::type first_arg(Args...); + +template<typename ...Args> +typename get_nth_type<1, Args...>::type second_arg(Args...); + +// Test explicit specification of function template arguments. +void test_explicit_spec_simple() { + int *ip1 = first_arg<int *>(0); + int *ip2 = first_arg<int *, float*>(0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); +} + +// Template argument deduction can extend the sequence of template +// arguments corresponding to a template parameter pack, even when the +// sequence contains explicitly specified template arguments. +// FIXME: Actually test what this paragraph specifies. +#if 0 +void test_explicit_spec_extension() { + int *ip1 = first_arg<int *>(0, 0); + int *ip2 = first_arg<int *, float*>(0, 0, 0, 0); + float *fp1 = first_arg<float *, double*, int*>(0, 0, 0); + int i1 = second_arg<float *>(0, 0, 0); +} +#endif + diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp index e216ad110e..b5e382c93e 100644 --- a/test/SemaTemplate/temp_arg_nontype.cpp +++ b/test/SemaTemplate/temp_arg_nontype.cpp @@ -169,7 +169,8 @@ namespace pr6249 { } namespace PR6723 { - template<unsigned char C> void f(int (&a)[C]); // expected-note 2{{candidate template ignored}} + template<unsigned char C> void f(int (&a)[C]); // expected-note {{candidate template ignored}} \ + // expected-note{{candidate function [with C = 0] not viable: no known conversion from 'int [512]' to 'int (&)[0]' for 1st argument}} void g() { int arr512[512]; f(arr512); // expected-error{{no matching function for call}} |