Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1381,6 +1381,10 @@ ++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 @@ 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, Index: test/CodeGen/nonnull.c =================================================================== --- /dev/null +++ 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; +} +