Skip to content

[clang] Fix -Wuninitialized for values passed by const pointers #147221

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

igorkudrin
Copy link
Collaborator

This enables producing a "variable is uninitialized" warning when a value is passed to a pointer-to-const argument:

void foo(const int *);
void test() {
  int *v;
  foo(v);
}

Fixes #37460

This enables producing a "variable is uninitialized" warning when a
value is passed to a pointer-to-const argument:

```
void foo(const int *);
void test() {
  int *v;
  foo(v);
}
```

Fixes llvm#37460
@igorkudrin igorkudrin added clang Clang issues not falling into any other category clang:analysis labels Jul 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 7, 2025

@llvm/pr-subscribers-libcxx
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-analysis

Author: Igor Kudrin (igorkudrin)

Changes

This enables producing a "variable is uninitialized" warning when a value is passed to a pointer-to-const argument:

void foo(const int *);
void test() {
  int *v;
  foo(v);
}

Fixes #37460


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

2 Files Affected:

  • (modified) clang/lib/Analysis/UninitializedValues.cpp (+5-8)
  • (modified) clang/test/SemaCXX/uninitialized.cpp (+6-2)
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index b2a68b6c39a7e..540838f89f20c 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -438,13 +438,10 @@ void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
     return;
   }
   bool isTrivialBody = hasTrivialBody(CE);
-  // If a value is passed by const pointer to a function,
-  // we should not assume that it is initialized by the call, and we
-  // conservatively do not assume that it is used.
-  // If a value is passed by const reference to a function,
-  // it should already be initialized.
-  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
-       I != E; ++I) {
+  // A value passed by const pointer or reference to a function should already
+  // be initialized.
+  for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E;
+       ++I) {
     if ((*I)->isGLValue()) {
       if ((*I)->getType().isConstQualified())
         classify((*I), isTrivialBody ? Ignore : ConstRefUse);
@@ -453,7 +450,7 @@ void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
       const auto *UO = dyn_cast<UnaryOperator>(Ex);
       if (UO && UO->getOpcode() == UO_AddrOf)
         Ex = UO->getSubExpr();
-      classify(Ex, Ignore);
+      classify(Ex, Use);
     }
   }
 }
diff --git a/clang/test/SemaCXX/uninitialized.cpp b/clang/test/SemaCXX/uninitialized.cpp
index c7b987e2172e6..4a944ba830bc3 100644
--- a/clang/test/SemaCXX/uninitialized.cpp
+++ b/clang/test/SemaCXX/uninitialized.cpp
@@ -162,12 +162,16 @@ void test_const_ptr() {
   int a;
   int b;  // expected-note {{initialize the variable 'b' to silence this warning}}
   foo(&a);
-  bar(&b);
-  b = a + b; // expected-warning {{variable 'b' is uninitialized when used here}}
+  bar(&b); // expected-warning {{variable 'b' is uninitialized when used here}}
+  b = a + b;
   int *ptr;  //expected-note {{initialize the variable 'ptr' to silence this warning}}
   const int *ptr2;
   foo(ptr); // expected-warning {{variable 'ptr' is uninitialized when used here}}
   foobar(&ptr2);
+  int *ptr3; // expected-note {{initialize the variable 'ptr3' to silence this warning}}
+  const int *ptr4; // expected-note {{initialize the variable 'ptr4' to silence this warning}}
+  bar(ptr3); // expected-warning {{variable 'ptr3' is uninitialized when used here}}
+  bar(ptr4); // expected-warning {{variable 'ptr4' is uninitialized when used here}}
 }
 }
 

@igorkudrin igorkudrin requested a review from a team as a code owner July 7, 2025 01:41
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jul 7, 2025
@igorkudrin igorkudrin requested a review from philnik777 July 7, 2025 01:42
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.

LGTM! I have a nit inline for your consideration.

I != E; ++I) {
// A value passed by const pointer or reference to a function should already
// be initialized.
for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could this use CE->arguments() in a range based for loop instead?

@Xazax-hun
Copy link
Collaborator

Actually, before merging, did you manage to run this on any non-trivial projects to see if there are any false positives? I think this change is valuable and important but these sorts of changes can expose some false positives. If that is the case (or there are some noisy patterns), we might want to do the stricter version of the analysis under a different flag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:analysis clang Clang issues not falling into any other category libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

-Wuninitialized ignored if type is "const" pointer
3 participants