Do typechecking and codegen for K&R-style function declarations

correctly.  Not a regression, but made more obvious by my recent fix 
which made function type compatibility checking a bit more strict.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55339 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2008-08-25 21:31:01 +00:00
Родитель c9e56b2a63
Коммит eb4b7051a5
4 изменённых файлов: 34 добавлений и 17 удалений

Просмотреть файл

@ -138,10 +138,23 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD,
AI->setName("agg.result");
++AI;
}
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i, ++AI) {
assert(AI != CurFn->arg_end() && "Argument mismatch!");
EmitParmDecl(*FD->getParamDecl(i), AI);
if (FD->getNumParams()) {
const FunctionTypeProto* FProto = FD->getType()->getAsFunctionTypeProto();
assert(FProto && "Function def must have prototype!");
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i, ++AI) {
assert(AI != CurFn->arg_end() && "Argument mismatch!");
const ParmVarDecl* CurParam = FD->getParamDecl(i);
llvm::Value* V = AI;
if (!getContext().typesAreCompatible(FProto->getArgType(i),
CurParam->getType())) {
// This must be a promotion, for something like
// "void a(x) short x; {..."
V = EmitScalarConversion(V, FProto->getArgType(i),
CurParam->getType());
}
EmitParmDecl(*CurParam, V);
}
}
GenerateFunction(FD->getBody());
}

Просмотреть файл

@ -690,8 +690,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
// Copy the parameter declarations from the declarator D to
// the function declaration NewFD, if they are available.
if (D.getNumTypeObjects() > 0 &&
D.getTypeObject(0).Fun.hasPrototype) {
if (D.getNumTypeObjects() > 0) {
DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
// Create Decl objects for each parameter, adding them to the
@ -716,7 +715,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
Diag(Param->getLocation(), diag::ext_param_typedef_of_void);
}
} else {
} else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
}
@ -1540,11 +1539,6 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
FTI.ArgInfo[i].Param = ActOnParamDeclarator(FnBodyScope, ParamD);
}
}
// Since this is a function definition, act as though we have information
// about the arguments.
if (FTI.NumArgs)
FTI.hasPrototype = true;
} else {
// FIXME: Diagnose arguments without names in C.
}

Просмотреть файл

@ -397,14 +397,12 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
D.setInvalidType(true);
}
if (!FTI.hasPrototype) {
if (FTI.NumArgs == 0) {
// Simple void foo(), where the incoming T is the result type.
T = Context.getFunctionTypeNoProto(T);
} else if (FTI.ArgInfo[0].Param == 0) {
// C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.
if (FTI.NumArgs != 0)
Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
} else {
// Otherwise, we have a function with an argument list that is
// potentially variadic.
@ -458,6 +456,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
// Do not add 'void' to the ArgTys list.
break;
}
} else if (!FTI.hasPrototype) {
if (ArgTy->isPromotableIntegerType()) {
ArgTy = Context.IntTy;
} else if (const BuiltinType* BTy = ArgTy->getAsBuiltinType()) {
if (BTy->getKind() == BuiltinType::Float)
ArgTy = Context.DoubleTy;
}
}
ArgTys.push_back(ArgTy);

Просмотреть файл

@ -0,0 +1,5 @@
// RUN: clang %s -emit-llvm -o - | grep "i32 @a(i32)"
int a();
int a(x) short x; {return x;}