llvm::Value *V = AI;
if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
- if ((NNAtt && NNAtt->isNonNull(PVD->getFunctionScopeIndex())) ||
- PVD->hasAttr<NonNullAttr>())
+ // 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()))
AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
AI->getArgNo() + 1,
llvm::Attribute::NonNull));
return &a;
}
+// CHECK: define i32 @bar4(i32 %n, i32* nonnull %p)
+int bar4(int n, int *p) __attribute__((nonnull)) {
+ return n + *p;
+}
+
+// CHECK: define i32 @bar5(i32 %n, i32* nonnull %p)
+int bar5(int n, int *p) __attribute__((nonnull(1, 2))) {
+ return n + *p;
+}
+
+typedef union {
+ unsigned long long n;
+ int *p;
+ double d;
+} TransparentUnion __attribute__((transparent_union));
+
+// CHECK: define i32 @bar6(i64 %
+int bar6(TransparentUnion tu) __attribute__((nonnull(1))) {
+ return *tu.p;
+}