Do not allow attributes beyond a function's last

parameter, even if it is a varargs function.  Do
allow attributes on the varargs part of a call,
but not beyond the last argument.  Only allow
selected attributes to be on the varargs part of
a call (currently only 'byval' is allowed).  The
reasoning here is that most attributes, eg inreg,
simply make no sense here.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45887 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2008-01-11 22:36:48 +00:00
parent 10603e0c84
commit 623a389f62
3 changed files with 38 additions and 7 deletions

View File

@ -52,6 +52,9 @@ const uint16_t ParameterOnly = ByVal | InReg | Nest | StructRet;
/// @brief Attributes that only apply to function return values.
const uint16_t ReturnOnly = NoReturn | NoUnwind | ReadNone | ReadOnly;
/// @brief Attributes that can apply to vararg call arguments.
const uint16_t VarArgsCompatible = ByVal;
/// @brief Attributes that are mutually incompatible.
const uint16_t MutuallyIncompatible[3] = {
ByVal | InReg | Nest | StructRet,

View File

@ -390,11 +390,6 @@ void Verifier::VerifyParamAttrs(const FunctionType *FT,
if (!Attrs)
return;
Assert1(FT->isVarArg() ||
(Attrs->size() &&
Attrs->getParamIndex(Attrs->size()-1) <= FT->getNumParams()),
"Attributes after end of type!", V);
bool SawNest = false;
for (unsigned Idx = 0; Idx <= FT->getNumParams(); ++Idx) {
@ -450,8 +445,15 @@ void Verifier::visitFunction(Function &F) {
Assert1(!F.isStructReturn() || FT->getReturnType() == Type::VoidTy,
"Invalid struct-return function!", &F);
const ParamAttrsList *Attrs = F.getParamAttrs();
Assert1(!Attrs ||
(Attrs->size() &&
Attrs->getParamIndex(Attrs->size()-1) <= FT->getNumParams()),
"Attributes after last parameter!", &F);
// Check function attributes.
VerifyParamAttrs(FT, F.getParamAttrs(), &F);
VerifyParamAttrs(FT, Attrs, &F);
// Check that this function meets the restrictions on this calling convention.
switch (F.getCallingConv()) {
@ -847,8 +849,24 @@ void Verifier::VerifyCallSite(CallSite CS) {
"Call parameter type does not match function signature!",
CS.getArgument(i), FTy->getParamType(i), I);
const ParamAttrsList *Attrs = CS.getParamAttrs();
Assert1(!Attrs ||
(Attrs->size() &&
Attrs->getParamIndex(Attrs->size()-1) <= CS.arg_size()),
"Attributes after last argument!", I);
// Verify call attributes.
VerifyParamAttrs(FTy, CS.getParamAttrs(), I);
VerifyParamAttrs(FTy, Attrs, I);
if (Attrs && FTy->isVarArg())
// Check attributes on the varargs part.
for (unsigned Idx = 1 + FTy->getNumParams(); Idx <= CS.arg_size(); ++Idx) {
uint16_t Attr = Attrs->getParamAttrs(Idx);
uint16_t VArgI = Attr & ~ParamAttr::VarArgsCompatible;
Assert1(!VArgI, "Attribute " + Attrs->getParamAttrsText(VArgI) +
"cannot be used for vararg call arguments!", I);
}
visitInstruction(*I);
}

View File

@ -0,0 +1,10 @@
; RUN: not llvm-as < %s
%struct = type { }
declare void @foo(...)
define void @bar() {
call void (...)* @foo(%struct* inreg null )
ret void
}