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;
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;
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);
// 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.
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.
///
/// 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.
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;
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.
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)) {
// 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)) {
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.
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;
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());
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();
}
--- /dev/null
+// 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
+
}
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}}