llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Timm Baeder (tbaederr)

<details>
<summary>Changes</summary>

This fixes a few more tests from `pass-object-size.c`, but we still can't 
enable the entire file.

---
Full diff: https://github.com/llvm/llvm-project/pull/179271.diff


4 Files Affected:

- (modified) clang/lib/AST/ByteCode/Descriptor.h (+4) 
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+16-4) 
- (modified) clang/test/AST/ByteCode/builtin-object-size-codegen.cpp (+20) 
- (added) clang/test/AST/ByteCode/pass-object-size.c (+103) 


``````````diff
diff --git a/clang/lib/AST/ByteCode/Descriptor.h 
b/clang/lib/AST/ByteCode/Descriptor.h
index 8338585a1741b..b052971733567 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -227,6 +227,10 @@ struct Descriptor final {
     return dyn_cast_if_present<RecordDecl>(asDecl());
   }
 
+  template <typename T> const T *getAs() const {
+    return dyn_cast_if_present<T>(asDecl());
+  }
+
   /// Returns the size of the object without metadata.
   unsigned getSize() const {
     assert(!isUnknownSizeArray() && "Array of unknown size");
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 2921618b0c630..0edfc01fcbeba 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2278,7 +2278,8 @@ static bool pointsToLastObject(const Pointer &Ptr) {
 }
 
 /// Does Ptr point to the last object AND to a flexible array member?
-static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr) {
+static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr,
+                                   bool InvalidBase) {
   auto isFlexibleArrayMember = [&](const Descriptor *FieldDesc) {
     using FAMKind = LangOptions::StrictFlexArraysLevelKind;
     FAMKind StrictFlexArraysLevel =
@@ -2300,7 +2301,7 @@ static bool isUserWritingOffTheEnd(const ASTContext &Ctx, 
const Pointer &Ptr) {
   if (!FieldDesc->isArray())
     return false;
 
-  return Ptr.isDummy() && pointsToLastObject(Ptr) &&
+  return InvalidBase && pointsToLastObject(Ptr) &&
          isFlexibleArrayMember(FieldDesc);
 }
 
@@ -2312,6 +2313,14 @@ UnsignedOrNone evaluateBuiltinObjectSize(const 
ASTContext &ASTCtx,
   if (Ptr.isDummy() && Ptr.getType()->isPointerType())
     return std::nullopt;
 
+  bool InvalidBase = false;
+
+  if (Ptr.isDummy()) {
+    if (const VarDecl *VD = Ptr.getDeclDesc()->asVarDecl();
+        VD && VD->getType()->isPointerType())
+      InvalidBase = true;
+  }
+
   // According to the GCC documentation, we want the size of the subobject
   // denoted by the pointer. But that's not quite right -- what we actually
   // want is the size of the immediately-enclosing array, if there is one.
@@ -2326,14 +2335,17 @@ UnsignedOrNone evaluateBuiltinObjectSize(const 
ASTContext &ASTCtx,
   bool ReportMinimum = (Kind & 2u);
   if (!UseFieldDesc || DetermineForCompleteObject) {
     // Lower bound, so we can't fall back to this.
-    if (ReportMinimum && !DetermineForCompleteObject)
+    if (ReportMinimum && UseFieldDesc && !DetermineForCompleteObject)
       return std::nullopt;
 
     // Can't read beyond the pointer decl desc.
     if (!UseFieldDesc && !ReportMinimum && 
DeclDesc->getType()->isPointerType())
       return std::nullopt;
+
+    if (InvalidBase)
+      return std::nullopt;
   } else {
-    if (isUserWritingOffTheEnd(ASTCtx, Ptr)) {
+    if (isUserWritingOffTheEnd(ASTCtx, Ptr, InvalidBase)) {
       // If we cannot determine the size of the initial allocation, then we
       // can't given an accurate upper-bound. However, we are still able to 
give
       // conservative lower-bounds for Type=3.
diff --git a/clang/test/AST/ByteCode/builtin-object-size-codegen.cpp 
b/clang/test/AST/ByteCode/builtin-object-size-codegen.cpp
index c466c815e230a..a8071764219c5 100644
--- a/clang/test/AST/ByteCode/builtin-object-size-codegen.cpp
+++ b/clang/test/AST/ByteCode/builtin-object-size-codegen.cpp
@@ -15,6 +15,10 @@ void foo() {
   gi = __builtin_object_size(&c->bs[0], 2);
   // CHECK: store i32 16
   gi = __builtin_object_size(&c->bs[0], 3);
+
+  C c2{};
+  // CHECK: store i32 16
+  gi = __builtin_object_size(&c2.bs[0], 1);
 }
 
 
@@ -102,3 +106,19 @@ void test3() {
   gi = __builtin_object_size((B*)&c, 3);
 
 }
+
+struct A { char buf[16]; };
+struct B : A {};
+struct C { int i; B bs[1]; } *c;
+void globalPointer() {
+  int gi;
+  // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 
false)
+  gi = __builtin_object_size(&c->bs[0], 2);
+}
+
+void nonPtrParam(C c) {
+  int gi;
+  // CHECK: store i32 16
+  gi = __builtin_object_size(&c.bs[0], 2);
+}
+
diff --git a/clang/test/AST/ByteCode/pass-object-size.c 
b/clang/test/AST/ByteCode/pass-object-size.c
new file mode 100644
index 0000000000000..d8ea5e9d3160c
--- /dev/null
+++ b/clang/test/AST/ByteCode/pass-object-size.c
@@ -0,0 +1,103 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple 
x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1                                         -triple 
x86_64-apple-darwin -emit-llvm -o - %s | FileCheck %s
+
+/// This is the part of test/CodeGen/pass-object-size.c we can evaluate.
+
+typedef unsigned long size_t;
+
+struct Foo {
+  int t[10];
+};
+
+#define PS(N) __attribute__((pass_object_size(N)))
+#define PDS(N) __attribute__((pass_dynamic_object_size(N)))
+
+int gi = 0;
+
+// CHECK-LABEL: define{{.*}} i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef 
%0)
+int ObjectSize0(void *const p PS(0)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 0);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize0(ptr noundef %{{.*}}, i64 
noundef %0)
+int DynamicObjectSize0(void *const p PDS(0)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_dynamic_object_size(p, 0);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef 
%0)
+int ObjectSize1(void *const p PS(1)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 1);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize1(ptr noundef %{{.*}}, i64 
noundef %0)
+int DynamicObjectSize1(void *const p PDS(1)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_dynamic_object_size(p, 1);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef 
%0)
+int ObjectSize2(void *const p PS(2)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 2);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize2(ptr noundef %{{.*}}, i64 
noundef %0)
+int DynamicObjectSize2(void *const p PDS(2)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 2);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 
%0)
+int ObjectSize3(void *const p PS(3)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 3);
+}
+
+// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize3(ptr noundef %{{.*}}, i64 
noundef %0)
+int DynamicObjectSize3(void *const p PDS(3)) {
+  // CHECK-NOT: @llvm.objectsize
+  return __builtin_object_size(p, 3);
+}
+
+void *malloc(unsigned long) __attribute__((alloc_size(1)));
+
+// CHECK-LABEL: define{{.*}} void @test1
+void test1(unsigned long sz) {
+  struct Foo t[10];
+
+  // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef 360)
+  gi = ObjectSize0(&t[1]);
+  // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef 360)
+  gi = ObjectSize1(&t[1]);
+  // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef 360)
+  gi = ObjectSize2(&t[1]);
+  // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 360)
+  gi = ObjectSize3(&t[1]);
+
+  // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef 356)
+  gi = ObjectSize0(&t[1].t[1]);
+  // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef 36)
+  gi = ObjectSize1(&t[1].t[1]);
+  // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef 356)
+  gi = ObjectSize2(&t[1].t[1]);
+  // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 36)
+  gi = ObjectSize3(&t[1].t[1]);
+
+  char *ptr = (char *)malloc(sz);
+
+  // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0({{.*}}, i1 false, 
i1 true, i1 true)
+  // CHECK: call i32 @DynamicObjectSize0(ptr noundef %{{.*}}, i64 noundef 
[[REG]])
+  gi = DynamicObjectSize0(ptr);
+
+  // CHECK: [[WITH_OFFSET:%.*]] = getelementptr
+  // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr 
[[WITH_OFFSET]], i1 false, i1 true, i1 true)
+  // CHECK: call i32 @DynamicObjectSize0(ptr noundef {{.*}}, i64 noundef 
[[REG]])
+  gi = DynamicObjectSize0(ptr+10);
+
+  // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0({{.*}}, i1 true, i1 
true, i1 true)
+  // CHECK: call i32 @DynamicObjectSize2(ptr noundef {{.*}}, i64 noundef 
[[REG]])
+  gi = DynamicObjectSize2(ptr);
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/179271
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to