assert(AI != Fn->arg_end() && "Argument mismatch!");
llvm::Value *V = AI;
- if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg))
+ if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) {
if ((NNAtt && NNAtt->isNonNull(PVD->getFunctionScopeIndex())) ||
PVD->hasAttr<NonNullAttr>())
AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
AI->getArgNo() + 1,
llvm::Attribute::NonNull));
+ QualType OTy = PVD->getOriginalType();
+ if (const auto *ArrTy =
+ getContext().getAsConstantArrayType(OTy)) {
+ // A C99 array parameter declaration with the static keyword also
+ // indicates dereferenceability, and if the size is constant we can
+ // use the dereferenceable attribute (which requires the size in
+ // bytes).
+ if (ArrTy->getSizeModifier() == VariableArrayType::Static) {
+ QualType ETy = ArrTy->getElementType();
+ uint64_t ArrSize = ArrTy->getSize().getZExtValue();
+ if (!ETy->isIncompleteType() && ETy->isConstantSizeType() &&
+ ArrSize) {
+ llvm::AttrBuilder Attrs;
+ Attrs.addDereferenceableAttr(
+ getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize);
+ AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
+ AI->getArgNo() + 1, Attrs));
+ } else if (getContext().getTargetAddressSpace(ETy) == 0) {
+ AI->addAttr(llvm::AttributeSet::get(getLLVMContext(),
+ AI->getArgNo() + 1,
+ llvm::Attribute::NonNull));
+ }
+ }
+ } else if (const auto *ArrTy =
+ getContext().getAsVariableArrayType(OTy)) {
+ // For C99 VLAs with the static keyword, we don't know the size so
+ // we can't use the dereferenceable attribute, but in addrspace(0)
+ // we know that it must be nonnull.
+ if (ArrTy->getSizeModifier() == VariableArrayType::Static &&
+ !getContext().getTargetAddressSpace(ArrTy->getElementType()))
+ 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,
// CHECK-LABEL: define void @test7(
// CHECK: call i32 @b(i8* null)
}
+
+// Make sure we emit dereferenceable or nonnull when the static keyword is
+// provided.
+void test8(int a[static 3]) { }
+// CHECK: define void @test8(i32* dereferenceable(12) %a)
+
+void test9(int n, int a[static n]) { }
+// CHECK: define void @test9(i32 %n, i32* nonnull %a)
+