forked from OSchip/llvm-project
				
			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. llvm-svn: 45887
This commit is contained in:
		
							parent
							
								
									b5bd924e83
								
							
						
					
					
						commit
						b99f44aa5e
					
				| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue