]> granicus.if.org Git - clang/commitdiff
Template instantiation for function types
authorDouglas Gregor <dgregor@apple.com>
Sat, 28 Feb 2009 01:04:19 +0000 (01:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 28 Feb 2009 01:04:19 +0000 (01:04 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65668 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaType.cpp
test/SemaTemplate/instantiation-default-1.cpp

index 7a5a10287f275fd28b77f306e4c5adcadd5d8c96..45ea16df5350375bc221d14aaed2d1bc84271f37 100644 (file)
@@ -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);
 
index f864a50c5ec9543ad5b5b3939a6d7d03a99af653..f4653c1e99a81e3fcdcc61e33cb5ae76896bc403 100644 (file)
@@ -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();
 }
 
index bc2bce3883aee17a0ae7be328185bbd97e32c085..69cd884300f4be879791f2cf644c0e73467401db 100644 (file)
@@ -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.
index 026e879bd3e6a45e1694c0da7cf220fc6c59c91c..57071f46402a11df2cd0e74f8070b22ce55e42db 100644 (file)
@@ -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;
+}