Do not allow attributes beyond a function's last
authorDuncan Sands <baldrick@free.fr>
Fri, 11 Jan 2008 22:36:48 +0000 (22:36 +0000)
committerDuncan Sands <baldrick@free.fr>
Fri, 11 Jan 2008 22:36:48 +0000 (22:36 +0000)
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

include/llvm/ParameterAttributes.h
lib/VMCore/Verifier.cpp
test/Verifier/2008-01-11-VarargAttrs.ll [new file with mode: 0644]

index 0d138fe0e2f7f2747a883d05cedb7874a65d660b..4106dcb2907ebc6d003b8b1b1db5eacfbd4691dc 100644 (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,
index 8b300ff07f91f26b046077375aca109bd2ca060d..e42109e0f30abf82e708d8fff33aa3d3cc9ad7f6 100644 (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);
 }
diff --git a/test/Verifier/2008-01-11-VarargAttrs.ll b/test/Verifier/2008-01-11-VarargAttrs.ll
new file mode 100644 (file)
index 0000000..1f4c9c7
--- /dev/null
@@ -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
+}