diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-02-28 01:04:19 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-02-28 01:04:19 +0000 |
commit | 724651c3523e25fbf2f6cd0419bc3466e0afdb07 (patch) | |
tree | 69cebded551363e1c7cf7c11400ad44fc4176e12 | |
parent | 5a1edf6c0dc70bd555e51bedba782da8e3552f94 (diff) |
Template instantiation for function types
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65668 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 27 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 60 | ||||
-rw-r--r-- | test/SemaTemplate/instantiation-default-1.cpp | 21 |
4 files changed, 106 insertions, 6 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 7a5a10287f..45ea16df53 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -239,6 +239,10 @@ public: QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, SourceLocation Loc, DeclarationName Entity); + QualType BuildFunctionType(QualType T, + QualType *ParamTypes, unsigned NumParamTypes, + bool Variadic, unsigned Quals, + SourceLocation Loc, DeclarationName Entity); QualType GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip = 0); DeclarationName GetNameForDeclarator(Declarator &D); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index f864a50c5e..f4653c1e99 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -65,7 +65,7 @@ TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T, QualType TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T, unsigned Quals) const { - assert(false && "BuiltinType is never dependent and cannot be instantiated"); + assert(false && "Builtin types are not dependent and cannot be instantiated"); return QualType(T, Quals); } @@ -191,17 +191,32 @@ QualType TemplateTypeInstantiator:: InstantiateFunctionProtoType(const FunctionProtoType *T, unsigned Quals) const { - // FIXME: Implement this - assert(false && "Cannot instantiate FunctionProtoType yet"); - return QualType(); + QualType ResultType = Instantiate(T->getResultType()); + if (ResultType.isNull()) + return ResultType; + + llvm::SmallVector<QualType, 16> ParamTypes; + for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(), + ParamEnd = T->arg_type_end(); + Param != ParamEnd; ++Param) { + QualType P = Instantiate(*Param); + if (P.isNull()) + return P; + + ParamTypes.push_back(P); + } + + return SemaRef.BuildFunctionType(ResultType, &ParamTypes[0], + ParamTypes.size(), + T->isVariadic(), T->getTypeQuals(), + Loc, Entity); } QualType TemplateTypeInstantiator:: InstantiateFunctionNoProtoType(const FunctionNoProtoType *T, unsigned Quals) const { - // FIXME: Implement this - assert(false && "Cannot instantiate FunctionNoProtoType yet"); + assert(false && "Functions without prototypes cannot be dependent."); return QualType(); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index bc2bce3883..69cd884300 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -468,7 +468,67 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return T; } +/// \brief Build a function type. +/// +/// This routine checks the function type according to C++ rules and +/// under the assumption that the result type and parameter types have +/// just been instantiated from a template. It therefore duplicates +/// some of the behavior of GetTypeForDeclaration, but in a much +/// simpler form that is only suitable for this narrow use case. +/// +/// \param T The return type of the function. +/// +/// \param ParamTypes The parameter types of the function. This array +/// will be modified to account for adjustments to the types of the +/// function parameters. +/// +/// \param NumParamTypes The number of parameter types in ParamTypes. +/// +/// \param Variadic Whether this is a variadic function type. +/// +/// \param Quals The cvr-qualifiers to be applied to the function type. +/// +/// \param Loc The location of the entity whose type involves this +/// function type or, if there is no such entity, the location of the +/// type that will have function type. +/// +/// \param Entity The name of the entity that involves the function +/// type, if known. +/// +/// \returns A suitable function type, if there are no +/// errors. Otherwise, returns a NULL type. +QualType Sema::BuildFunctionType(QualType T, + QualType *ParamTypes, + unsigned NumParamTypes, + bool Variadic, unsigned Quals, + SourceLocation Loc, DeclarationName Entity) { + if (T->isArrayType() || T->isFunctionType()) { + Diag(Loc, diag::err_func_returning_array_function) << T; + return QualType(); + } + + bool Invalid = false; + for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) { + QualType ParamType = ParamTypes[Idx]; + if (ParamType->isArrayType()) + ParamType = Context.getArrayDecayedType(ParamType); + else if (ParamType->isFunctionType()) + ParamType = Context.getPointerType(ParamType); + else if (ParamType->isVoidType()) { + Diag(Loc, diag::err_param_with_void_type); + Invalid = true; + } + ParamTypes[Idx] = ParamType; + } + + if (Invalid) + return QualType(); + + return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic, + Quals); +} + /// GetTypeForDeclarator - Convert the type for the specified /// declarator to Type instances. Skip the outermost Skip type /// objects. diff --git a/test/SemaTemplate/instantiation-default-1.cpp b/test/SemaTemplate/instantiation-default-1.cpp index 026e879bd3..57071f4640 100644 --- a/test/SemaTemplate/instantiation-default-1.cpp +++ b/test/SemaTemplate/instantiation-default-1.cpp @@ -78,3 +78,24 @@ void test_Def5(Def5<int, const int[12]> *d5a, Def5<int, const int[13]> *d5b) { d5b->bar(); } +template<typename R, typename Arg1, typename Arg2 = Arg1, + typename FuncType = R (*)(Arg1, Arg2)> + struct Def6; + +template<> struct Def6<int, float> { + void foo(); +}; + +template<> struct Def6<bool, int[5], float(double, double)> { + void bar(); +}; + +bool test_Def6(Def6<int, float, float> *d6a, + Def6<int, float, float, int (*)(float, float)> *d6b, + Def6<bool, int[5], float(double, double), + bool(*)(int*, float(*)(double, double))> *d6c) { + d6a->foo(); + d6b->foo(); + d6c->bar(); + return d6a == d6b; +} |