From c14b5c3b1e74405b22e62df4483c142de0487d0d Mon Sep 17 00:00:00 2001 From: Mikael Holmen Date: Wed, 15 Nov 2017 07:46:48 +0000 Subject: [PATCH] [Lint] Don't warn about passing alloca'd value to tail call if using byval Summary: This fixes PR35241. When using byval, the data is effectively copied as part of the call anyway, so the pointer returned by the alloca will not be leaked to the callee and thus there is no reason to issue a warning. Reviewers: rnk Reviewed By: rnk Subscribers: Ka-Ka, llvm-commits Differential Revision: https://reviews.llvm.org/D40009 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@318279 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/Lint.cpp | 25 +++++++++++++++++-------- test/Analysis/Lint/tail-call-byval.ll | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 test/Analysis/Lint/tail-call-byval.ll diff --git a/lib/Analysis/Lint.cpp b/lib/Analysis/Lint.cpp index ae92f502f5c..7b792ed0a2e 100644 --- a/lib/Analysis/Lint.cpp +++ b/lib/Analysis/Lint.cpp @@ -285,15 +285,24 @@ void Lint::visitCallSite(CallSite CS) { } } - if (CS.isCall() && cast(CS.getInstruction())->isTailCall()) - for (CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); - AI != AE; ++AI) { - Value *Obj = findValue(*AI, /*OffsetOk=*/true); - Assert(!isa(Obj), - "Undefined behavior: Call with \"tail\" keyword references " - "alloca", - &I); + if (CS.isCall()) { + const CallInst *CI = cast(CS.getInstruction()); + if (CI->isTailCall()) { + const AttributeList &PAL = CI->getAttributes(); + unsigned ArgNo = 0; + for (Value *Arg : CS.args()) { + // Skip ByVal arguments since they will be memcpy'd to the callee's + // stack anyway. + if (PAL.hasParamAttribute(ArgNo++, Attribute::ByVal)) + continue; + Value *Obj = findValue(Arg, /*OffsetOk=*/true); + Assert(!isa(Obj), + "Undefined behavior: Call with \"tail\" keyword references " + "alloca", + &I); + } } + } if (IntrinsicInst *II = dyn_cast(&I)) diff --git a/test/Analysis/Lint/tail-call-byval.ll b/test/Analysis/Lint/tail-call-byval.ll new file mode 100644 index 00000000000..9f274981898 --- /dev/null +++ b/test/Analysis/Lint/tail-call-byval.ll @@ -0,0 +1,33 @@ +; RUN: opt < %s -lint -disable-output 2>&1 | FileCheck %s + +%s = type { i8 } + +declare void @f1(%s*) + +define void @f2() { +entry: + %c = alloca %s + tail call void @f1(%s* %c) + ret void +} + +; Lint should complain about the tail call passing the alloca'd value %c to f1. +; CHECK: Undefined behavior: Call with "tail" keyword references alloca +; CHECK-NEXT: tail call void @f1(%s* %c) + +declare void @f3(%s* byval) + +define void @f4() { +entry: + %c = alloca %s + tail call void @f3(%s* byval %c) + ret void +} + +; Lint should not complain about passing the alloca'd %c since it's passed +; byval, effectively copying the data to the stack instead of leaking the +; pointer itself. +; CHECK-NOT: Undefined behavior: Call with "tail" keyword references alloca +; CHECK-NOT: tail call void @f3(%s* byval %c) + + -- 2.11.0