summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-08-28 00:53:20 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-08-28 00:53:20 +0000
commit9fc9bf83a8a51693585cb9f20d73ffd4baa92203 (patch)
tree563b26b83afa13902c3dca10e54409f6ae7eaeeb
parent1bb0750b983751a9947d064d56dd1178551f7d90 (diff)
downloadbcm5719-llvm-9fc9bf83a8a51693585cb9f20d73ffd4baa92203.tar.gz
bcm5719-llvm-9fc9bf83a8a51693585cb9f20d73ffd4baa92203.zip
Properly handle multiple nonnull attributes in CodeGen
llvm-svn: 216638
-rw-r--r--clang/lib/CodeGen/CGCall.cpp40
-rw-r--r--clang/test/CodeGen/nonnull.c8
2 files changed, 33 insertions, 15 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index c95680ccda6..75713419aa1 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1419,6 +1419,30 @@ static llvm::Value *emitArgumentDemotion(CodeGenFunction &CGF,
return CGF.Builder.CreateFPCast(value, varType, "arg.unpromote");
}
+static bool shouldAddNonNullAttr(const Decl *FD, const ParmVarDecl *PVD) {
+ // FIXME: __attribute__((nonnull)) can also be applied to:
+ // - references to pointers, where the pointee is known to be
+ // nonnull (apparently a Clang extension)
+ // - transparent unions containing pointers
+ // In the former case, LLVM IR cannot represent the constraint. In
+ // the latter case, we have no guarantee that the transparent union
+ // is in fact passed as a pointer.
+ if (!PVD->getType()->isAnyPointerType() &&
+ !PVD->getType()->isBlockPointerType())
+ return false;
+ // First, check attribute on parameter itself.
+ if (PVD->hasAttr<NonNullAttr>())
+ return true;
+ // Check function attributes.
+ if (!FD)
+ return false;
+ for (const auto *NNAttr : FD->specific_attrs<NonNullAttr>()) {
+ if (NNAttr->isNonNull(PVD->getFunctionScopeIndex()))
+ return true;
+ }
+ return false;
+}
+
void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::Function *Fn,
const FunctionArgList &Args) {
@@ -1463,10 +1487,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::Attribute::NoAlias));
}
- // Get the function-level nonnull attribute if it exists.
- const NonNullAttr *NNAtt =
- CurCodeDecl ? CurCodeDecl->getAttr<NonNullAttr>() : 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.
@@ -1557,17 +1577,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::Value *V = AI;
if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
- // FIXME: __attribute__((nonnull)) can also be applied to:
- // - references to pointers, where the pointee is known to be
- // nonnull (apparently a Clang extension)
- // - transparent unions containing pointers
- // In the former case, LLVM IR cannot represent the constraint. In
- // the latter case, we have no guarantee that the transparent union
- // is in fact passed as a pointer.
- if (((NNAtt && NNAtt->isNonNull(PVD->getFunctionScopeIndex())) ||
- PVD->hasAttr<NonNullAttr>()) &&
- (PVD->getType()->isAnyPointerType() ||
- PVD->getType()->isBlockPointerType()))
+ if (shouldAddNonNullAttr(CurCodeDecl, PVD))
AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
AI->getArgNo() + 1,
llvm::Attribute::NonNull));
diff --git a/clang/test/CodeGen/nonnull.c b/clang/test/CodeGen/nonnull.c
index e234105d9ad..7c33e6329fd 100644
--- a/clang/test/CodeGen/nonnull.c
+++ b/clang/test/CodeGen/nonnull.c
@@ -41,3 +41,11 @@ typedef union {
int bar6(TransparentUnion tu) __attribute__((nonnull(1))) {
return *tu.p;
}
+
+// CHECK: define void @bar7(i32* nonnull %a, i32* nonnull %b)
+void bar7(int *a, int *b) __attribute__((nonnull(1)))
+__attribute__((nonnull(2))) {}
+
+// CHECK: define void @bar8(i32* nonnull %a, i32* nonnull %b)
+void bar8(int *a, int *b) __attribute__((nonnull))
+__attribute__((nonnull(1))) {}
OpenPOWER on IntegriCloud