Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ObjC][CodeGen] Assume a for-in loop is in bounds and cannot overflow #94885

Merged
merged 1 commit into from
Jul 11, 2024

Conversation

AZero13
Copy link
Contributor

@AZero13 AZero13 commented Jun 9, 2024

When accessing data in the buffer, we know we won't overrun the buffer, so we know it is inbounds. In addition, we know that the addition to increase the index is also NUW because the buffer's end has to be unsigned-greater-than 0, which becomes untrue if the bounds ever has an unsigned wrap.

@AZero13 AZero13 marked this pull request as ready for review June 9, 2024 03:24
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen labels Jun 9, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 9, 2024

@llvm/pr-subscribers-clang-codegen

Author: AtariDreams (AtariDreams)

Changes

When accessing data in the buffer, we know we won't overrun the buffer, so we know it is inbounds. In addition, we know that the addition to increase the index is also NUW because the buffer's end has to be unsigned-greater-than 0, which becomes untrue if the bounds ever has an unsigned wrap.


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

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGObjC.cpp (+2-2)
  • (modified) clang/test/CodeGenObjC/arc-foreach.m (+2-2)
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 281b2d9795f6c..80a64d8e4cdd9 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1952,7 +1952,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
     Builder.CreateLoad(StateItemsPtr, "stateitems");
 
   // Fetch the value at the current index from the buffer.
-  llvm::Value *CurrentItemPtr = Builder.CreateGEP(
+  llvm::Value *CurrentItemPtr = Builder.CreateInBoundsGEP(
       ObjCIdType, EnumStateItems, index, "currentitem.ptr");
   llvm::Value *CurrentItem =
     Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign());
@@ -2028,7 +2028,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
 
   // First we check in the local buffer.
   llvm::Value *indexPlusOne =
-      Builder.CreateAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
+      Builder.CreateNUWAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
 
   // If we haven't overrun the buffer yet, we can continue.
   // Set the branch weights based on the simplifying assumption that this is
diff --git a/clang/test/CodeGenObjC/arc-foreach.m b/clang/test/CodeGenObjC/arc-foreach.m
index 71edc5161303c..9f7b60aef7a1b 100644
--- a/clang/test/CodeGenObjC/arc-foreach.m
+++ b/clang/test/CodeGenObjC/arc-foreach.m
@@ -53,7 +53,7 @@ void test0(NSArray *array) {
 
 // CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[STATE_T]], ptr [[STATE]], i32 0, i32 1
 // CHECK-LP64-NEXT: [[T1:%.*]] = load ptr, ptr [[T0]]
-// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr ptr, ptr [[T1]], i64
+// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64
 // CHECK-LP64-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]
 // CHECK-LP64-NEXT: store ptr [[T3]], ptr [[X]]
 
@@ -100,7 +100,7 @@ void test1(NSArray *array) {
 
 // CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[STATE_T]], ptr [[STATE]], i32 0, i32 1
 // CHECK-LP64-NEXT: [[T1:%.*]] = load ptr, ptr [[T0]]
-// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr ptr, ptr [[T1]], i64
+// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64
 // CHECK-LP64-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]
 // CHECK-LP64-NEXT: call ptr @llvm.objc.initWeak(ptr [[X]], ptr [[T3]])
 

@llvmbot
Copy link
Member

llvmbot commented Jun 9, 2024

@llvm/pr-subscribers-clang

Author: AtariDreams (AtariDreams)

Changes

When accessing data in the buffer, we know we won't overrun the buffer, so we know it is inbounds. In addition, we know that the addition to increase the index is also NUW because the buffer's end has to be unsigned-greater-than 0, which becomes untrue if the bounds ever has an unsigned wrap.


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

2 Files Affected:

  • (modified) clang/lib/CodeGen/CGObjC.cpp (+2-2)
  • (modified) clang/test/CodeGenObjC/arc-foreach.m (+2-2)
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 281b2d9795f6c..80a64d8e4cdd9 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -1952,7 +1952,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
     Builder.CreateLoad(StateItemsPtr, "stateitems");
 
   // Fetch the value at the current index from the buffer.
-  llvm::Value *CurrentItemPtr = Builder.CreateGEP(
+  llvm::Value *CurrentItemPtr = Builder.CreateInBoundsGEP(
       ObjCIdType, EnumStateItems, index, "currentitem.ptr");
   llvm::Value *CurrentItem =
     Builder.CreateAlignedLoad(ObjCIdType, CurrentItemPtr, getPointerAlign());
@@ -2028,7 +2028,7 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){
 
   // First we check in the local buffer.
   llvm::Value *indexPlusOne =
-      Builder.CreateAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
+      Builder.CreateNUWAdd(index, llvm::ConstantInt::get(NSUIntegerTy, 1));
 
   // If we haven't overrun the buffer yet, we can continue.
   // Set the branch weights based on the simplifying assumption that this is
diff --git a/clang/test/CodeGenObjC/arc-foreach.m b/clang/test/CodeGenObjC/arc-foreach.m
index 71edc5161303c..9f7b60aef7a1b 100644
--- a/clang/test/CodeGenObjC/arc-foreach.m
+++ b/clang/test/CodeGenObjC/arc-foreach.m
@@ -53,7 +53,7 @@ void test0(NSArray *array) {
 
 // CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[STATE_T]], ptr [[STATE]], i32 0, i32 1
 // CHECK-LP64-NEXT: [[T1:%.*]] = load ptr, ptr [[T0]]
-// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr ptr, ptr [[T1]], i64
+// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64
 // CHECK-LP64-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]
 // CHECK-LP64-NEXT: store ptr [[T3]], ptr [[X]]
 
@@ -100,7 +100,7 @@ void test1(NSArray *array) {
 
 // CHECK-LP64:      [[T0:%.*]] = getelementptr inbounds [[STATE_T]], ptr [[STATE]], i32 0, i32 1
 // CHECK-LP64-NEXT: [[T1:%.*]] = load ptr, ptr [[T0]]
-// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr ptr, ptr [[T1]], i64
+// CHECK-LP64-NEXT: [[T2:%.*]] = getelementptr inbounds ptr, ptr [[T1]], i64
 // CHECK-LP64-NEXT: [[T3:%.*]] = load ptr, ptr [[T2]]
 // CHECK-LP64-NEXT: call ptr @llvm.objc.initWeak(ptr [[X]], ptr [[T3]])
 

@AZero13 AZero13 changed the title [CodeGen] Assume a for-in loop is in bounds and cannot overflow [ObjC][CodeGen] Assume a for-in loop is in bounds and cannot overflow Jun 9, 2024
Copy link
Contributor

@rjmccall rjmccall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Do we not have any tests that actually test the add?

@AZero13
Copy link
Contributor Author

AZero13 commented Jun 23, 2024

@rjmccall do you think you could merge this? (I don't have commit perms)

@rjmccall
Copy link
Contributor

I don't usually do that for people, sorry.

@AZero13
Copy link
Contributor Author

AZero13 commented Jul 10, 2024

@JOE1994 Could you please merge this, as I do not have merge permissions?

When accessing data in the buffer, we know we won't overrun the buffer, so we know it is inbounds. In addition, we know that the addition to increase the index is also NUW because the buffer's end has to be unsigned-greater-than 0, which becomes untrue if the bounds ever has an unsigned wrap.
@davidchisnall davidchisnall merged commit eb61956 into llvm:main Jul 11, 2024
5 of 6 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 11, 2024

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building clang at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/1385

Here is the relevant piece of the build log for the reference:

Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentDelayWatchBreak.py (612 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointWatchpoint.py (613 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentDelayedCrashWithBreakpointSignal.py (614 of 1992)
PASS: lldb-api :: functionalities/progress_reporting/TestTrimmedProgressReporting.py (615 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentManyCrash.py (616 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentManyBreakpoints.py (617 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentSignalBreak.py (618 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentNWatchNBreak.py (619 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentSignalDelayBreak.py (620 of 1992)
PASS: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentSignalDelayWatch.py (621 of 1992)
FAIL: lldb-api :: functionalities/thread/concurrent_events/TestConcurrentSignalNWatchNBreak.py (622 of 1992)
******************** TEST 'lldb-api :: functionalities/thread/concurrent_events/TestConcurrentSignalNWatchNBreak.py' FAILED ********************
Script:
--
/usr/bin/python3.8 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env ARCHIVER=/usr/local/bin/llvm-ar --env OBJCOPY=/usr/bin/llvm-objcopy --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/functionalities/thread/concurrent_events -p TestConcurrentSignalNWatchNBreak.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 19.0.0git (https://github.com/llvm/llvm-project.git revision eb61956d1a039d9cb03e0d041f33ab2ecc80519e)
  clang revision eb61956d1a039d9cb03e0d041f33ab2ecc80519e
  llvm revision eb61956d1a039d9cb03e0d041f33ab2ecc80519e
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

Watchpoint 1 hit:
old value: 0
new value: 1

Watchpoint 1 hit:
old value: 1
new value: 1

Watchpoint 1 hit:
old value: 1
new value: 1

Watchpoint 1 hit:
old value: 1
new value: 1

Watchpoint 1 hit:
old value: 1
new value: 1

--
Command Output (stderr):
--
FAIL: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test (TestConcurrentSignalNWatchNBreak.ConcurrentSignalNWatchNBreak)

@llvm-ci
Copy link
Collaborator

llvm-ci commented Jul 11, 2024

LLVM Buildbot has detected a new failure on builder flang-aarch64-dylib running on linaro-flang-aarch64-dylib while building clang at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/50/builds/971

Here is the relevant piece of the build log for the reference:

Step 5 (build-unified-tree) failure: build (failure)
...
496.986 [2330/1/4239] Building CXX object tools/clang/tools/libclang/CMakeFiles/libclang.dir/CXType.cpp.o
497.815 [2329/1/4240] Building CXX object tools/clang/tools/libclang/CMakeFiles/libclang.dir/Indexing.cpp.o
497.885 [2328/1/4241] Building CXX object tools/clang/tools/libclang/CMakeFiles/libclang.dir/FatalErrorHandler.cpp.o
498.456 [2327/1/4242] Building CXX object tools/clang/tools/libclang/CMakeFiles/libclang.dir/Rewrite.cpp.o
498.581 [2326/1/4243] Building CXX object tools/clang/tools/amdgpu-arch/CMakeFiles/amdgpu-arch.dir/AMDGPUArchByHSA.cpp.o
498.714 [2325/1/4244] Building CXX object tools/clang/tools/amdgpu-arch/CMakeFiles/amdgpu-arch.dir/AMDGPUArch.cpp.o
498.856 [2324/1/4245] Building CXX object tools/clang/tools/amdgpu-arch/CMakeFiles/amdgpu-arch.dir/AMDGPUArchByHIP.cpp.o
498.964 [2323/1/4246] Building CXX object tools/clang/tools/nvptx-arch/CMakeFiles/nvptx-arch.dir/NVPTXArch.cpp.o
499.055 [2322/1/4247] Building FIREnumAttr.cpp.inc...
508.390 [2321/1/4248] Building CXX object tools/flang/lib/Optimizer/Dialect/CUF/CMakeFiles/obj.CUFDialect.dir/CUFOps.cpp.o
FAILED: tools/flang/lib/Optimizer/Dialect/CUF/CMakeFiles/obj.CUFDialect.dir/CUFOps.cpp.o 
/usr/local/bin/c++ -DFLANG_INCLUDE_TESTS=1 -DFLANG_LITTLE_ENDIAN=1 -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/flang/lib/Optimizer/Dialect/CUF -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/flang/lib/Optimizer/Dialect/CUF -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/flang/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/flang/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/../mlir/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/clang/include -isystem /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/../clang/include -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wno-deprecated-copy -Wno-string-conversion -Wno-ctad-maybe-unsupported -Wno-unused-command-line-argument -Wstring-conversion           -Wcovered-switch-default -Wno-nested-anon-types -O3 -DNDEBUG  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -std=c++17 -MD -MT tools/flang/lib/Optimizer/Dialect/CUF/CMakeFiles/obj.CUFDialect.dir/CUFOps.cpp.o -MF tools/flang/lib/Optimizer/Dialect/CUF/CMakeFiles/obj.CUFDialect.dir/CUFOps.cpp.o.d -o tools/flang/lib/Optimizer/Dialect/CUF/CMakeFiles/obj.CUFDialect.dir/CUFOps.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp
In file included from /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/flang/lib/Optimizer/Dialect/CUF/CUFOps.cpp:13:
In file included from /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/flang/include/flang/Optimizer/Dialect/CUF/CUFOps.h:14:
/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/flang/include/flang/Optimizer/Dialect/FIRType.h:71:10: fatal error: 'flang/Optimizer/Dialect/FIROpsTypes.h.inc' file not found
   71 | #include "flang/Optimizer/Dialect/FIROpsTypes.h.inc"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.

@davidchisnall
Copy link
Contributor

Those CI failures look unrelated.

@AZero13 AZero13 deleted the clang-nsw branch July 11, 2024 14:12
aaryanshukla pushed a commit to aaryanshukla/llvm-project that referenced this pull request Jul 14, 2024
…llvm#94885)

When accessing data in the buffer, we know we won't overrun the buffer,
so we know it is inbounds. In addition, we know that the addition to
increase the index is also NUW because the buffer's end has to be
unsigned-greater-than 0, which becomes untrue if the bounds ever has an
unsigned wrap.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants