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 | 6eaaf30968b286568b96847a083171406986cb0c (patch) | |
| tree | 06f5497886a715eee32d5dbd341e472aa09b9ff1 | |
| parent | a079d31fd4808580b847892c63ba98385fe4ae03 (diff) | |
| download | bcm5719-llvm-6eaaf30968b286568b96847a083171406986cb0c.tar.gz bcm5719-llvm-6eaaf30968b286568b96847a083171406986cb0c.zip  | |
Template instantiation for function types
llvm-svn: 65668
| -rw-r--r-- | clang/lib/Sema/Sema.h | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 27 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaType.cpp | 60 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/instantiation-default-1.cpp | 21 | 
4 files changed, 106 insertions, 6 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 7a5a10287f2..45ea16df535 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index f864a50c5ec..f4653c1e99a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/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/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index bc2bce3883a..69cd884300f 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/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/clang/test/SemaTemplate/instantiation-default-1.cpp b/clang/test/SemaTemplate/instantiation-default-1.cpp index 026e879bd3e..57071f46402 100644 --- a/clang/test/SemaTemplate/instantiation-default-1.cpp +++ b/clang/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; +}  | 

