diff options
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 38 | ||||
| -rw-r--r-- | clang/test/CodeGen/vla.c | 9 |
2 files changed, 46 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 4ee2373793b..f15c1b7321a 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1486,13 +1486,49 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, 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, diff --git a/clang/test/CodeGen/vla.c b/clang/test/CodeGen/vla.c index 1757ef77879..e6cdd5d2a32 100644 --- a/clang/test/CodeGen/vla.c +++ b/clang/test/CodeGen/vla.c @@ -195,3 +195,12 @@ void test7(int a[b(0)]) { // 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) + |

