Skip to content

Conversation

carlosgalvezp
Copy link
Contributor

…uidelines-pro-bounds-pointer-arithmetic

Fixes #154907

@llvmbot
Copy link
Member

llvmbot commented Aug 22, 2025

@llvm/pr-subscribers-clang-tools-extra

@llvm/pr-subscribers-clang-tidy

Author: Carlos Galvez (carlosgalvezp)

Changes

…uidelines-pro-bounds-pointer-arithmetic

Fixes #154907


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

5 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp (+20-7)
  • (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h (+5-2)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+5)
  • (modified) clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst (+8)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic.cpp (+9-7)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
index 9ac7b9e057e35..51995c5f64ef6 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.cpp
@@ -14,6 +14,18 @@ using namespace clang::ast_matchers;
 
 namespace clang::tidy::cppcoreguidelines {
 
+ProBoundsPointerArithmeticCheck::ProBoundsPointerArithmeticCheck(
+    StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      AllowIncrementDecrementOperators(
+          Options.get("AllowIncrementDecrementOperators", false)) {}
+
+void ProBoundsPointerArithmeticCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "AllowIncrementDecrementOperators",
+                AllowIncrementDecrementOperators);
+}
+
 void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) {
   const auto AllPointerTypes =
       anyOf(hasType(hasUnqualifiedDesugaredType(pointerType())),
@@ -30,13 +42,14 @@ void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) {
       this);
 
   // Flag all operators ++, -- that result in a pointer
-  Finder->addMatcher(
-      unaryOperator(hasAnyOperatorName("++", "--"),
-                    hasType(hasUnqualifiedDesugaredType(pointerType())),
-                    unless(hasUnaryOperand(
-                        ignoringImpCasts(declRefExpr(to(isImplicit()))))))
-          .bind("expr"),
-      this);
+  if (!AllowIncrementDecrementOperators)
+    Finder->addMatcher(
+        unaryOperator(hasAnyOperatorName("++", "--"),
+                      hasType(hasUnqualifiedDesugaredType(pointerType())),
+                      unless(hasUnaryOperand(
+                          ignoringImpCasts(declRefExpr(to(isImplicit()))))))
+            .bind("expr"),
+        this);
 
   // Array subscript on a pointer (not an array) is also pointer arithmetic
   Finder->addMatcher(
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
index 3466c72a769e9..785f754055fb8 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsPointerArithmeticCheck.h
@@ -21,13 +21,16 @@ namespace clang::tidy::cppcoreguidelines {
 /// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.html
 class ProBoundsPointerArithmeticCheck : public ClangTidyCheck {
 public:
-  ProBoundsPointerArithmeticCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  ProBoundsPointerArithmeticCheck(StringRef Name, ClangTidyContext *Context);
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
     return LangOpts.CPlusPlus;
   }
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  const bool AllowIncrementDecrementOperators;
 };
 
 } // namespace clang::tidy::cppcoreguidelines
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 383286eb0c5a3..780e5b3fc21cf 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -180,6 +180,11 @@ Changes in existing checks
   <clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>` check to
   avoid false positives on inherited members in class templates.
 
+- Improved :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic
+  <clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic>` check
+  adding an option to allow pointer arithmetic via prefix/postfix increment or
+  decrement operators.
+
 - Improved :doc:`misc-header-include-cycle
   <clang-tidy/checks/misc/header-include-cycle>` check performance.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst
index 12a8f60184fe5..a3f13714e809c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic.rst
@@ -13,3 +13,11 @@ arrays of data.
 This rule is part of the `Bounds safety (Bounds 1)
 <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Pro-bounds-arithmetic>`_
 profile from the C++ Core Guidelines.
+
+Options
+-------
+
+.. option:: AllowIncrementDecrementOperators
+
+   When enabled, the check will allow using the prefix/postfix increment or
+   decrement operators on pointers. Default is ``false``.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic.cpp
index aed6080471e1f..fa81c135a1803 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/pro-bounds-pointer-arithmetic.cpp
@@ -1,4 +1,6 @@
-// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic -check-suffixes=,DEFAULT  %t
+// RUN: %check_clang_tidy %s cppcoreguidelines-pro-bounds-pointer-arithmetic %t -- \
+// RUN:   -config="{CheckOptions: {cppcoreguidelines-pro-bounds-pointer-arithmetic.AllowIncrementDecrementOperators: true}}" --
 
 enum E {
   ENUM_LITERAL = 1
@@ -42,14 +44,14 @@ void fail() {
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
 
   p++;
-  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
   ++p;
-  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
 
   p--;
-  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
   --p;
-  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:3: warning: do not use pointer arithmetic
 
   i = p[1];
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic
@@ -57,7 +59,7 @@ void fail() {
   p = ip + 1;
   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: do not use pointer arithmetic
   ip++;
-  // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:5: warning: do not use pointer arithmetic
   i = ip[1];
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic
 }
@@ -72,7 +74,7 @@ void template_fail() {
   q = p - 1;
   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not use pointer arithmetic
   p++;
-  // CHECK-MESSAGES: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
+  // CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:4: warning: do not use pointer arithmetic
   i = p[1];
   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not use pointer arithmetic
 }

Copy link
Contributor

@vbvictor vbvictor left a comment

Choose a reason for hiding this comment

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

LGTM

@carlosgalvezp carlosgalvezp merged commit efed984 into llvm:main Aug 23, 2025
13 checks passed
@carlosgalvezp carlosgalvezp deleted the pointer_inc_dec branch August 23, 2025 05:39
@llvm-ci
Copy link
Collaborator

llvm-ci commented Aug 23, 2025

LLVM Buildbot has detected a new failure on builder clang-aarch64-sve-vls running on linaro-g3-04 while building clang-tools-extra at step 7 "ninja check 1".

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

Here is the relevant piece of the build log for the reference
Step 7 (ninja check 1) failure: stage 1 checked (failure)
...
[3/8] Building CXX object compiler-rt/lib/hwasan/CMakeFiles/RTHwasan_dynamic_version_script_dummy.aarch64.dir/dummy.cpp.o
[4/8] Building CXX object compiler-rt/lib/ubsan/CMakeFiles/RTUbsan_dynamic_version_script_dummy.aarch64.dir/dummy.cpp.o
[5/8] Linking CXX shared library /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/clang/22/lib/aarch64-unknown-linux-gnu/libclang_rt.ubsan_standalone.so
[6/8] Linking CXX shared library /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/clang/22/lib/aarch64-unknown-linux-gnu/libclang_rt.hwasan.so
[7/8] Linking CXX shared library /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/clang/22/lib/aarch64-unknown-linux-gnu/libclang_rt.asan.so
[8/8] Generating /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/compile_commands.json
[111/115] cd /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins && /usr/local/bin/cmake --build /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/runtimes/runtimes-bins/ --target runtimes-test-depends --config Release
[1/3] Generating Rtsan-aarch64-FileOffset64-Test
[2/3] Generating Rtsan-aarch64-Test
[3/3] Linking CXX executable flang-rt/unittests/Runtime/RuntimeTests
FAILED: flang-rt/unittests/Runtime/RuntimeTests 
: && /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/./bin/clang++ --target=aarch64-unknown-linux-gnu -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 -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 -O3 -DNDEBUG -fuse-ld=lld -Wl,--color-diagnostics    -Wl,--gc-sections flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/AccessTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Allocatable.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/ArrayConstructor.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Assign.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/BufferTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/CharacterTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/CommandTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Complex.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/CrashHandlerFixture.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Derived.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Descriptor.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/ExternalIOTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Format.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/InputExtensions.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Inquiry.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/ListInputTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/LogicalFormatTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Matmul.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/MatmulTranspose.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/MiscIntrinsic.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Namelist.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Numeric.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/NumericalFormatTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Pointer.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Ragged.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Random.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Reduction.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/RuntimeCrashTest.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Stop.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Support.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Time.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/TemporaryStack.cpp.o flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Transformational.cpp.o -o flang-rt/unittests/Runtime/RuntimeTests  /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/libLLVMSupport.a  /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/libllvm_gtest_main.a  /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/libllvm_gtest.a  /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/clang/22/lib/aarch64-unknown-linux-gnu/libflang_rt.runtime.a  /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/libLLVMSupport.a  -lrt  -ldl  -lm  /usr/lib/aarch64-linux-gnu/libz.so  /home/tcwg-buildbot/worker/clang-aarch64-sve-vls/stage1/lib/libLLVMDemangle.a  -lpthread && :
ld.lld: error: undefined symbol: testing::internal::GetBoolAssertionFailureMessage[abi:cxx11](testing::AssertionResult const&, char const*, char const*, char const*)
>>> referenced by AccessTest.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/AccessTest.cpp.o:(AccessTests_TestExists_Test::TestBody())
>>> referenced by Allocatable.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Allocatable.cpp.o:(AllocatableTest_MoveAlloc_Test::TestBody())
>>> referenced by Allocatable.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Allocatable.cpp.o:(AllocatableTest_MoveAlloc_Test::TestBody())
>>> referenced 338 more times

ld.lld: error: undefined symbol: llvm::Twine::str[abi:cxx11]() const
>>> referenced by AccessTest.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/AccessTest.cpp.o:(createTemporaryFile[abi:cxx11](char const*, (anonymous namespace)::AccessType const&))

ld.lld: error: undefined symbol: testing::internal::EqFailure(char const*, char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool)
>>> referenced by Allocatable.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Allocatable.cpp.o:(testing::AssertionResult testing::internal::CmpHelperEQ<std::basic_string_view<char, std::char_traits<char>>, char [50]>(char const*, char const*, std::basic_string_view<char, std::char_traits<char>> const&, char const (&) [50]))
>>> referenced by Allocatable.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Allocatable.cpp.o:(testing::AssertionResult testing::internal::CmpHelperEQ<unsigned long, unsigned int>(char const*, char const*, unsigned long const&, unsigned int const&))
>>> referenced by Allocatable.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Allocatable.cpp.o:(testing::AssertionResult testing::internal::CmpHelperEQ<float, float>(char const*, char const*, float const&, float const&))
>>> referenced 46 more times

ld.lld: error: undefined symbol: testing::internal::PrintStringTo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, std::ostream*)
>>> referenced by Allocatable.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/Allocatable.cpp.o:(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> testing::PrintToString<std::basic_string_view<char, std::char_traits<char>>>(std::basic_string_view<char, std::char_traits<char>> const&))
>>> referenced by ArrayConstructor.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/ArrayConstructor.cpp.o:(testing::internal::MatchesRegexMatcher::DescribeTo(std::ostream*) const)
>>> referenced by ArrayConstructor.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/ArrayConstructor.cpp.o:(testing::internal::MatchesRegexMatcher::DescribeNegationTo(std::ostream*) const)
>>> referenced 4 more times

ld.lld: error: undefined symbol: testing::internal::DeathTest::Create(char const*, testing::Matcher<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&>, char const*, int, testing::internal::DeathTest**)
>>> referenced by ArrayConstructor.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/ArrayConstructor.cpp.o:(ArrayConstructor_CharacterRuntimeCheck_Test::TestBody())
>>> referenced by ListInputTest.cpp
>>>               flang-rt/unittests/Runtime/CMakeFiles/RuntimeTests.dir/ListInputTest.cpp.o:(InputTest_TestListInputInvalidFormatWithSingleSuccess_Test::TestBody())
>>> referenced by CommandTest.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang-tidy] Add AllowIteratorDecrementIncrement option to cppcoreguidelines-pro-bounds-pointer-arithmetic
5 participants