Skip to content

Conversation

@steakhal
Copy link
Contributor

If we see a variable declaration (aka. DeclStmt), and the VarRegion it declared doesn't have Stack memspace, we assumed that it must be a local static variable.
However, the declared variable may be an extern declaration of a global.

In this patch, let's admit that local extern declarations are a thing.

For the sake of completeness, I also added one more test for thread_locals - which are implicitly considered statics btw. (the isStaticLocal() correctly also considers thread locals as local statics).

Fixes #124975

…nOfVar

If we see a variable declaration (aka. DeclStmt), and the VarRegion it
declared doesn't have Stack memspace, we assumed that it must be a
local static variable.
However, the declared variable may be an extern declaration of a global.

In this patch, let's admit that local extern declarations are a thing.

For the sake of completeness, I also added one more test for
thread_locals - which are implicitly considered statics btw.
(the isStaticLocal correctly also considers thread locals as local
statics).
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Jan 30, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 30, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Balazs Benics (steakhal)

Changes

If we see a variable declaration (aka. DeclStmt), and the VarRegion it declared doesn't have Stack memspace, we assumed that it must be a local static variable.
However, the declared variable may be an extern declaration of a global.

In this patch, let's admit that local extern declarations are a thing.

For the sake of completeness, I also added one more test for thread_locals - which are implicitly considered statics btw. (the isStaticLocal() correctly also considers thread locals as local statics).

Fixes #124975


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

2 Files Affected:

  • (modified) clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp (+4-1)
  • (modified) clang/test/Analysis/null-deref-path-notes.cpp (+35)
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index a9b4dbb39b5bd6..a6142063895dbd 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -1198,7 +1198,10 @@ static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
     // If we ever directly evaluate global DeclStmts, this assertion will be
     // invalid, but this still seems preferable to silently accepting an
     // initialization that may be for a path-sensitive variable.
-    assert(VR->getDecl()->isStaticLocal() && "non-static stackless VarRegion");
+    [[maybe_unused]] bool IsLocalStaticOrLocalExtern =
+        VR->getDecl()->isStaticLocal() || VR->getDecl()->isLocalExternDecl();
+    assert(IsLocalStaticOrLocalExtern &&
+           "Declared a variable on the stack without Stack memspace?");
     return true;
   }
 
diff --git a/clang/test/Analysis/null-deref-path-notes.cpp b/clang/test/Analysis/null-deref-path-notes.cpp
index c7b0619e297b3c..a37bbfe41a2c70 100644
--- a/clang/test/Analysis/null-deref-path-notes.cpp
+++ b/clang/test/Analysis/null-deref-path-notes.cpp
@@ -23,3 +23,38 @@ void c::f(B &g, int &i) {
   f(h, b); // expected-note{{Calling 'c::f'}}
 }
 }
+
+namespace GH124975 {
+void no_crash_in_br_visitors(int *p) {
+  if (p) {}
+  // expected-note@-1 {{Assuming 'p' is null}}
+  // expected-note@-2 {{Taking false branch}}
+
+  extern bool ExternLocalCoin;
+  // expected-note@+2 {{Assuming 'ExternLocalCoin' is false}}
+  // expected-note@+1 {{Taking false branch}}
+  if (ExternLocalCoin)
+    return;
+
+  *p = 4;
+  // expected-warning@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+  // expected-note@-2    {{Dereference of null pointer (loaded from variable 'p')}}
+}
+
+// Thread local variables are implicitly static, so let's test them too.
+void thread_local_alternative(int *p) {
+  if (p) {}
+  // expected-note@-1 {{Assuming 'p' is null}}
+  // expected-note@-2 {{Taking false branch}}
+
+  thread_local bool ThreadLocalCoin;
+  // expected-note@+2 {{'ThreadLocalCoin' is false}}
+  // expected-note@+1 {{Taking false branch}}
+  if (ThreadLocalCoin)
+    return;
+
+  *p = 4;
+  // expected-warning@-1 {{Dereference of null pointer (loaded from variable 'p')}}
+  // expected-note@-2    {{Dereference of null pointer (loaded from variable 'p')}}
+}
+} // namespace GH124975

Copy link
Collaborator

@Xazax-hun Xazax-hun left a comment

Choose a reason for hiding this comment

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

Thanks!

@steakhal steakhal merged commit 025541d into llvm:main Jan 30, 2025
11 checks passed
@steakhal steakhal deleted the bb/gh-124975-relax-assertion branch January 30, 2025 11:48
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 30, 2025

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/9625

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
181.521 [1503/1/5299] Building CXX object tools/mlir/lib/Dialect/SPIRV/Transforms/CMakeFiles/obj.MLIRSPIRVTransforms.dir/UpdateVCEPass.cpp.o
181.735 [1502/1/5300] Building CXX object tools/mlir/lib/Dialect/SPIRV/Utils/CMakeFiles/obj.MLIRSPIRVUtils.dir/LayoutUtils.cpp.o
181.774 [1501/1/5301] Building CXX object tools/mlir/lib/Dialect/Tensor/Extensions/CMakeFiles/obj.MLIRTensorAllExtensions.dir/AllExtensions.cpp.o
181.913 [1500/1/5302] Building CXX object tools/mlir/tools/mlir-rewrite/CMakeFiles/mlir-rewrite.dir/mlir-rewrite.cpp.o
182.013 [1499/1/5303] Building CXX object tools/mlir/lib/Dialect/Tensor/IR/CMakeFiles/obj.MLIRTensorDialect.dir/TensorDialect.cpp.o
182.103 [1498/1/5304] Building CXX object tools/mlir/lib/Dialect/Tensor/IR/CMakeFiles/obj.MLIRTensorDialect.dir/ValueBoundsOpInterfaceImpl.cpp.o
182.209 [1497/1/5305] Building CXX object tools/mlir/lib/Dialect/Tensor/IR/CMakeFiles/obj.MLIRTensorTilingInterfaceImpl.dir/TensorTilingInterfaceImpl.cpp.o
182.309 [1496/1/5306] Building CXX object tools/mlir/lib/Dialect/Tensor/IR/CMakeFiles/obj.MLIRTensorDialect.dir/TensorOps.cpp.o
182.408 [1495/1/5307] Building CXX object tools/mlir/lib/Dialect/Tensor/IR/CMakeFiles/obj.MLIRTensorInferTypeOpInterfaceImpl.dir/TensorInferTypeOpInterfaceImpl.cpp.o
193.490 [1494/1/5308] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestClone.cpp.o
FAILED: tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestClone.cpp.o 
/usr/local/bin/c++ -DGTEST_HAS_RTTI=0 -DMLIR_INCLUDE_TESTS -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/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR/../Dialect/Test -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 -Wundef -Werror=mismatched-tags -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestClone.cpp.o -MF tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestClone.cpp.o.d -o tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestClone.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestClone.cpp
In file included from /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestClone.cpp:9:
/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test/TestOps.h:148:10: fatal error: 'TestOps.h.inc' file not found
  148 | #include "TestOps.h.inc"
      |          ^~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.

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

Labels

clang:static analyzer clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[analyzer] "non-static stackless VarRegion" crash

4 participants