aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2008-01-11 22:36:48 +0000
committerDuncan Sands <baldrick@free.fr>2008-01-11 22:36:48 +0000
commit623a389f623dfef44f07211bd12fbd2a93db09e3 (patch)
treefdaeaea0d3864dad9983412fe9f31d2c57912c81
parent10603e0c84d15f61443e8b17bc35f98cc46606d9 (diff)
downloadexternal_llvm-623a389f623dfef44f07211bd12fbd2a93db09e3.zip
external_llvm-623a389f623dfef44f07211bd12fbd2a93db09e3.tar.gz
external_llvm-623a389f623dfef44f07211bd12fbd2a93db09e3.tar.bz2
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
-rw-r--r--include/llvm/ParameterAttributes.h3
-rw-r--r--lib/VMCore/Verifier.cpp32
-rw-r--r--test/Verifier/2008-01-11-VarargAttrs.ll10
3 files changed, 38 insertions, 7 deletions
diff --git a/include/llvm/ParameterAttributes.h b/include/llvm/ParameterAttributes.h
index 0d138fe..4106dcb 100644
--- a/include/llvm/ParameterAttributes.h
+++ b/include/llvm/ParameterAttributes.h
@@ -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,
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 8b300ff..e42109e 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -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
index 0000000..1f4c9c7
--- /dev/null
+++ b/test/Verifier/2008-01-11-VarargAttrs.ll
@@ -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
+}