Index: lib/Analysis/Lint.cpp =================================================================== --- lib/Analysis/Lint.cpp +++ lib/Analysis/Lint.cpp @@ -219,6 +219,29 @@ "Undefined behavior: Call return type mismatches " "callee return type", &I); + // Conservatively check the inalloca argument. + if (CS.hasInAllocaArgument()) { + Value *InAllocaArg = + CS.getArgument(FT->getNumParams() - 1)->stripInBoundsOffsets(); + // We have a bug if we can find that there is an underlying alloca without + // inalloca. + if (auto AI = dyn_cast(InAllocaArg)) + Assert2(AI->isUsedWithInAlloca(), + "inalloca argument for call has mismatched alloca", AI, &I); + + // If our inalloca argument came from one of our arguments, check it for + // inalloca as well. + if (auto A = dyn_cast(InAllocaArg)) { + Assert2(A->hasInAllocaAttr(), "inalloca argument for call originated " + "from argument without inalloca", + A, &I); + Assert1(CS.isMustTailCall(), "inalloca argument comes from previous " + "caller, call site should be annotated " + "with musttail", + &I); + } + } + // Check argument types (in case the callee was casted) and attributes. // TODO: Verify that caller and callee attributes are compatible. Function::arg_iterator PI = F->arg_begin(), PE = F->arg_end(); Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -1490,16 +1490,6 @@ // Verify call attributes. VerifyFunctionAttrs(FTy, Attrs, I); - // Conservatively check the inalloca argument. - // We have a bug if we can find that there is an underlying alloca without - // inalloca. - if (CS.hasInAllocaArgument()) { - Value *InAllocaArg = CS.getArgument(FTy->getNumParams() - 1); - if (auto AI = dyn_cast(InAllocaArg->stripInBoundsOffsets())) - Assert2(AI->isUsedWithInAlloca(), - "inalloca argument for call has mismatched alloca", AI, I); - } - if (FTy->isVarArg()) { // FIXME? is 'nest' even legal here? bool SawNest = false; Index: test/Analysis/Lint/inalloca1.ll =================================================================== --- test/Analysis/Lint/inalloca1.ll +++ test/Analysis/Lint/inalloca1.ll @@ -1,4 +1,4 @@ -; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s +; RUN: opt -lint %s -o /dev/null 2>&1 | FileCheck %s declare void @doit(i64* inalloca %a) Index: test/Analysis/Lint/inalloca2.ll =================================================================== --- /dev/null +++ test/Analysis/Lint/inalloca2.ll @@ -0,0 +1,10 @@ +; RUN: opt -lint %s -o /dev/null 2>&1 | FileCheck %s + +declare void @doit(i64* inalloca %a) + +define void @a(i64* %a) { +entry: + call void @doit(i64* inalloca %a) +; CHECK: inalloca argument for call originated from argument without inalloca + ret void +} Index: test/Analysis/Lint/inalloca3.ll =================================================================== --- /dev/null +++ test/Analysis/Lint/inalloca3.ll @@ -0,0 +1,10 @@ +; RUN: opt -lint %s -o /dev/null 2>&1 | FileCheck %s + +declare void @doit(i64* inalloca %a) + +define void @a(i64* inalloca %a) { +entry: + call void @doit(i64* inalloca %a) +; CHECK: inalloca argument comes from previous caller, call site should be annotated with musttail + ret void +}