Template instantiation for function types
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65668 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 7a5a102..45ea16d 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -239,6 +239,10 @@
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 f864a50..f4653c1 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -65,7 +65,7 @@
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 @@
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 bc2bce3..69cd884 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -468,7 +468,67 @@
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.