From 724651c3523e25fbf2f6cd0419bc3466e0afdb07 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 28 Feb 2009 01:04:19 +0000 Subject: [PATCH] Template instantiation for function types git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65668 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/Sema.h | 4 ++ lib/Sema/SemaTemplateInstantiate.cpp | 27 +++++++-- lib/Sema/SemaType.cpp | 60 +++++++++++++++++++ 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 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 *d5a, Def5 *d5b) { d5b->bar(); } +template + struct Def6; + +template<> struct Def6 { + void foo(); +}; + +template<> struct Def6 { + void bar(); +}; + +bool test_Def6(Def6 *d6a, + Def6 *d6b, + Def6 *d6c) { + d6a->foo(); + d6b->foo(); + d6c->bar(); + return d6a == d6b; +} -- 2.40.0