Template instantiation for the declarations of member functions within
a class template. At present, we can only instantiation normal
methods, but not constructors, destructors, or conversion operators.
As ever, this contains a bit of refactoring in Sema's type-checking. In
particular:
- Split ActOnFunctionDeclarator into ActOnFunctionDeclarator
(handling the declarator itself) and CheckFunctionDeclaration
(checking for the the function declaration), the latter of which
is also used by template instantiation.
- We were performing the adjustment of function parameter types in
three places; collect those into a single new routine.
- When the type of a parameter is adjusted, allocate an
OriginalParmVarDecl to keep track of the type as it was written.
- Eliminate a redundant check for out-of-line declarations of member
functions; hide more C++-specific checks on function declarations
behind if(getLangOptions().CPlusPlus).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67575 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 3f4e78c..60ecb7a 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -19,6 +19,30 @@
#include "clang/Parse/DeclSpec.h"
using namespace clang;
+/// \brief Perform adjustment on the parameter type of a function.
+///
+/// This routine adjusts the given parameter type @p T to the actual
+/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8],
+/// C++ [dcl.fct]p3). The adjusted parameter type is returned.
+QualType Sema::adjustParameterType(QualType T) {
+ // C99 6.7.5.3p7:
+ if (T->isArrayType()) {
+ // C99 6.7.5.3p7:
+ // A declaration of a parameter as "array of type" shall be
+ // adjusted to "qualified pointer to type", where the type
+ // qualifiers (if any) are those specified within the [ and ] of
+ // the array type derivation.
+ return Context.getArrayDecayedType(T);
+ } else if (T->isFunctionType())
+ // C99 6.7.5.3p8:
+ // A declaration of a parameter as "function returning type"
+ // shall be adjusted to "pointer to function returning type", as
+ // in 6.3.2.1.
+ return Context.getPointerType(T);
+
+ return T;
+}
+
/// \brief Convert the specified declspec to the appropriate type
/// object.
/// \param DS the declaration specifiers
@@ -523,12 +547,8 @@
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()) {
+ QualType ParamType = adjustParameterType(ParamTypes[Idx]);
+ if (ParamType->isVoidType()) {
Diag(Loc, diag::err_param_with_void_type);
Invalid = true;
}
@@ -683,29 +703,14 @@
ParmVarDecl *Param = (ParmVarDecl *)FTI.ArgInfo[i].Param;
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
- //
- // Perform the default function/array conversion (C99 6.7.5.3p[7,8]).
- // This matches the conversion that is done in
- // Sema::ActOnParamDeclarator(). Without this conversion, the
- // argument type in the function prototype *will not* match the
- // type in ParmVarDecl (which makes the code generator unhappy).
- //
- // FIXME: We still apparently need the conversion in
- // Sema::ActOnParamDeclarator(). This doesn't make any sense, since
- // it should be driving off the type being created here.
- //
- // FIXME: If a source translation tool needs to see the original type,
- // then we need to consider storing both types somewhere...
- //
- if (ArgTy->isArrayType()) {
- ArgTy = Context.getArrayDecayedType(ArgTy);
- } else if (ArgTy->isFunctionType())
- ArgTy = Context.getPointerType(ArgTy);
-
+
+ // Adjust the parameter type.
+ ArgTy = adjustParameterType(ArgTy);
+
// Look for 'void'. void is allowed only as a single argument to a
// function with no other parameters (C99 6.7.5.3p10). We record
// int(void) as a FunctionProtoType with an empty argument list.
- else if (ArgTy->isVoidType()) {
+ if (ArgTy->isVoidType()) {
// If this is something like 'float(int, void)', reject it. 'void'
// is an incomplete type (C99 6.2.5p19) and function decls cannot
// have arguments of incomplete type.