From: Hal Finkel Date: Fri, 11 Jul 2014 17:35:21 +0000 (+0000) Subject: Add nonnull in CodeGen for __attribute__((nonnull)) X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=82504f03ce98c30da60a12d84c71384e44734f15;p=platform%2Fupstream%2Fllvm.git Add nonnull in CodeGen for __attribute__((nonnull)) We now have an LLVM-level nonnull attribute that can be applied to function parameters, and we emit it for reference types (as of r209723), but did not emit it when an __attribute__((nonnull)) was provided. Now we will. llvm-svn: 212835 --- diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 44fd4d8..c32e4f2 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1381,6 +1381,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, ++AI; // Skip the sret parameter. } + // Get the function-level nonnull attribute if it exists. + const NonNullAttr *NNAtt = + CurCodeDecl ? CurCodeDecl->getAttr() : nullptr; + // Track if we received the parameter as a pointer (indirect, byval, or // inalloca). If already have a pointer, EmitParmDecl doesn't need to copy it // into a local alloca for us. @@ -1468,6 +1472,13 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, assert(AI != Fn->arg_end() && "Argument mismatch!"); llvm::Value *V = AI; + if (const ParmVarDecl *PVD = dyn_cast(Arg)) + if ((NNAtt && NNAtt->isNonNull(PVD->getFunctionScopeIndex())) || + PVD->hasAttr()) + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, + llvm::Attribute::NonNull)); + if (Arg->getType().isRestrictQualified()) AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), AI->getArgNo() + 1, diff --git a/clang/test/CodeGen/nonnull.c b/clang/test/CodeGen/nonnull.c new file mode 100644 index 0000000..b39a14c --- /dev/null +++ b/clang/test/CodeGen/nonnull.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm < %s | FileCheck %s + +// CHECK: define void @foo(i32* nonnull %x) +void foo(int * __attribute__((nonnull)) x) { + *x = 0; +} + +// CHECK: define void @bar(i32* nonnull %x) +void bar(int * x) __attribute__((nonnull(1))) { + *x = 0; +} + +// CHECK: define void @bar2(i32* %x, i32* nonnull %y) +void bar2(int * x, int * y) __attribute__((nonnull(2))) { + *x = 0; +} +