courbet updated this revision to Diff 332931.
courbet added a comment.

Forgot to add test file.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D99248/new/

https://reviews.llvm.org/D99248

Files:
  clang/lib/CodeGen/CGExpr.cpp
  clang/test/CodeGen/array-bounds.cpp

Index: clang/test/CodeGen/array-bounds.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/array-bounds.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -triple x86_64-linux -O1 -disable-llvm-passes %s \
+// RUN:     -emit-llvm -o - | FileCheck %s
+//
+// Check that we generate array bound information for accesses to array
+// elements.
+
+struct A { int i; };
+struct B { A a[1]; };
+struct C { int i; int x[3]; };
+struct D { int i; int* x; };
+struct E { int x[3][5]; };
+
+//TODO: std::array
+
+int deref(C *c, int j) {
+// CHECK-LABEL: _Z5derefP1Ci
+// CHECK: [[INDEX:%.*]] = call i64 @llvm.annotation{{.*}}, !range [[RANGE_0_3:!.*]]
+// CHECK: getelementptr {{.*}} [[INDEX]]
+  return c->x[j];
+}
+
+int deref_noindex(B *b) {
+// CHECK-LABEL: _Z13deref_noindexP1B
+// CHECK-NOT: llvm.annotation
+// CHECK: getelementptr {{.*}}
+  return b->a->i;
+}
+
+int deref_ptr(D *d, int j) {
+// CHECK-LABEL: _Z9deref_ptrP1Di
+// CHECK-NOT: llvm.annotation
+// CHECK: getelementptr {{.*}}
+  return d->x[j];
+}
+
+int deref_multi(E *e, int j, int k) {
+// CHECK-LABEL: _Z11deref_multiP1Eii
+// CHECK: [[INDEX1:%.*]] =  call i64 @llvm.annotation{{.*}}, !range [[RANGE_0_3]]
+// CHECK: getelementptr {{.*}} [[INDEX1]]
+// CHECK: [[INDEX2:%.*]] =  call i64 @llvm.annotation{{.*}}, !range [[RANGE_0_5:!.*]]
+// CHECK: getelementptr {{.*}} [[INDEX2]]
+  return e->x[j][k];
+}
+
+// We are not dereferencing the computed address, it is valid to compute a
+// past-the-end address.
+int* addr(C *c, int j) {
+// CHECK-LABEL: _Z4addrP1Ci
+// CHECK: [[INDEX:%.*]] = call i64 @llvm.annotation{{.*}}, !range [[RANGE_0_4:!.*]]
+// CHECK: getelementptr {{.*}} [[INDEX]]
+  return &c->x[j];
+}
+
+// CHECK-DAG: [[RANGE_0_3]] = !{i64 0, i64 3}
+// CHECK-DAG: [[RANGE_0_4]] = !{i64 0, i64 4}
+// CHECK-DAG: [[RANGE_0_5]] = !{i64 0, i64 5}
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -1249,7 +1249,7 @@
 
 LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
   LValue LV;
-  if (SanOpts.has(SanitizerKind::ArrayBounds) && isa<ArraySubscriptExpr>(E))
+  if (isa<ArraySubscriptExpr>(E))
     LV = EmitArraySubscriptExpr(cast<ArraySubscriptExpr>(E), /*Accessed*/true);
   else
     LV = EmitLValue(E);
@@ -3691,6 +3691,32 @@
   return Address(eltPtr, eltAlign);
 }
 
+// Add range metadata: It is UB to subscript outside of the array, therefore
+// array indices are known to be in range:
+//   * [0, indexing_bound) if the array is accessed.
+//   * [0, indexing_bound] if only address computation is preformed.
+static llvm::Value *addArrayIndexingRangeMetadata(CodeGenFunction &CGF,
+                                                  const Expr *Base,
+                                                  llvm::Value *Idx,
+                                                  bool Accessed) {
+  QualType IdxTy;
+  llvm::ConstantInt *Bound = dyn_cast_or_null<llvm::ConstantInt>(
+      getArrayIndexingBound(CGF, Base, IdxTy));
+  if (Bound == nullptr)
+    return Idx;
+  llvm::Instruction *AnnotatedIdx =
+      CGF.Builder.CreateIntrinsic(llvm::Intrinsic::annotation, {Idx->getType()},
+                                  {Idx, llvm::UndefValue::get(CGF.Int8PtrTy),
+                                   llvm::UndefValue::get(CGF.Int8PtrTy),
+                                   llvm::UndefValue::get(CGF.Int32Ty)});
+  llvm::MDBuilder MDHelper(CGF.getLLVMContext());
+  AnnotatedIdx->setMetadata(
+      llvm::LLVMContext::MD_range,
+      MDHelper.createRange(llvm::APInt(Bound->getBitWidth(), 0),
+                           Bound->getValue() + (Accessed ? 0 : 1)));
+  return AnnotatedIdx;
+}
+
 LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E,
                                                bool Accessed) {
   // The index must always be an integer, which is not an aggregate.  Emit it
@@ -3716,6 +3742,9 @@
     if (Promote && Idx->getType() != IntPtrTy)
       Idx = Builder.CreateIntCast(Idx, IntPtrTy, IdxSigned, "idxprom");
 
+    if (CGM.getCodeGenOpts().OptimizationLevel > 0)
+      Idx = addArrayIndexingRangeMetadata(*this, E->getBase(), Idx, Accessed);
+
     return Idx;
   };
   IdxPre = nullptr;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D99248: [RFC][Code... Clement Courbet via Phabricator via cfe-commits
    • [PATCH] D99248: [RFC]... Clement Courbet via Phabricator via cfe-commits

Reply via email to