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

[clang] StmtPrinter: Handle DeclRefExpr to a Decomposition #125001

Merged
merged 1 commit into from
Jan 30, 2025

Conversation

mizvekov
Copy link
Contributor

A DeclRefExpr could never refer to a Decomposition in valid C++ code, but somehow the Analyzer creates these entities and then it tries to print them.

There is no sensible answer here, so we print 'decomposition' followed by the names of all of its bindings, separated by dashes.

@mizvekov mizvekov self-assigned this Jan 30, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 30, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 30, 2025

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

Changes

A DeclRefExpr could never refer to a Decomposition in valid C++ code, but somehow the Analyzer creates these entities and then it tries to print them.

There is no sensible answer here, so we print 'decomposition' followed by the names of all of its bindings, separated by dashes.


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

3 Files Affected:

  • (modified) clang/lib/AST/StmtPrinter.cpp (+7)
  • (added) clang/test/Analysis/anonymous-decls.cpp (+89)
  • (removed) clang/test/Analysis/anonymous-parameter.cpp (-30)
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 9efc88436f928d..280192fcc7984e 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1291,6 +1291,13 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
          << PD->getFunctionScopeIndex();
       break;
     }
+    case Decl::Decomposition: {
+      auto *DD = cast<DecompositionDecl>(VD);
+      OS << "decomposition";
+      for (const auto &I : DD->bindings())
+        OS << '-' << I->getName();
+      break;
+    }
     default:
       llvm_unreachable("Unhandled anonymous declaration kind");
     }
diff --git a/clang/test/Analysis/anonymous-decls.cpp b/clang/test/Analysis/anonymous-decls.cpp
new file mode 100644
index 00000000000000..211184523aa51c
--- /dev/null
+++ b/clang/test/Analysis/anonymous-decls.cpp
@@ -0,0 +1,89 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++20 %s 2>&1 | FileCheck %s
+
+struct A {
+  static A a;
+  char b;
+  friend bool operator==(A, A) = default;
+};
+bool _ = A() == A::a;
+
+// FIXME: steps 1 and 5 show anonymous function parameters are
+// not handled correctly.
+
+// CHECK-LABEL: bool operator==(A, A) noexcept = default
+// CHECK-NEXT: [B2 (ENTRY)]
+// CHECK-NEXT:    Succs (1): B1
+// CHECK:      [B1]
+// CHECK-NEXT:    1: function-parameter-0-0
+// CHECK-NEXT:    2: [B1.1].b
+// CHECK-NEXT:    3: [B1.2] (ImplicitCastExpr, LValueToRValue, char)
+// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, IntegralCast, int)
+// CHECK-NEXT:    5: function-parameter-0-1
+// CHECK-NEXT:    6: [B1.5].b
+// CHECK-NEXT:    7: [B1.6] (ImplicitCastExpr, LValueToRValue, char)
+// CHECK-NEXT:    8: [B1.7] (ImplicitCastExpr, IntegralCast, int)
+// CHECK-NEXT:    9: [B1.4] == [B1.8]
+// CHECK-NEXT:   10: return [B1.9];
+// CHECK-NEXT:    Preds (1): B2
+// CHECK-NEXT:    Succs (1): B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:    Preds (1): B1
+
+namespace std {
+template <class> struct iterator_traits;
+template <class, class> struct pair;
+template <class _Tp> struct iterator_traits<_Tp *> {
+  typedef _Tp &reference;
+};
+template <long, class> struct tuple_element;
+template <class> struct tuple_size;
+template <class _T1, class _T2> struct tuple_size<pair<_T1, _T2>> {
+  static const int value = 2;
+};
+template <class _T1, class _T2> struct tuple_element<0, pair<_T1, _T2>> {
+  using type = _T1;
+};
+template <class _T1, class _T2> struct tuple_element<1, pair<_T1, _T2>> {
+  using type = _T2;
+};
+template <long _Ip, class _T1, class _T2>
+tuple_element<_Ip, pair<_T1, _T2>>::type get(pair<_T1, _T2> &);
+struct __wrap_iter {
+  iterator_traits<pair<int, int> *>::reference operator*();
+  void operator++();
+};
+bool operator!=(__wrap_iter, __wrap_iter);
+struct vector {
+  __wrap_iter begin();
+  __wrap_iter end();
+};
+} // namespace std
+int main() {
+  std::vector v;
+  for (auto &[a, b] : v)
+    ;
+}
+
+// FIXME: On steps 8 and 14, a decomposition is referred by name, which they never have.
+
+// CHECK-LABEL: int main()
+// CHECK:      [B3]
+// CHECK-NEXT:   1: operator*
+// CHECK-NEXT:   2: [B3.1] (ImplicitCastExpr, FunctionToPointerDecay, iterator_traits<pair<int, int> *>::reference (*)(void))
+// CHECK-NEXT:   3: __begin1
+// CHECK-NEXT:   4: * [B3.3] (OperatorCall)
+// CHECK-NEXT:   5: auto &;
+// CHECK-NEXT:   6: get<0UL>
+// CHECK-NEXT:   7: [B3.6] (ImplicitCastExpr, FunctionToPointerDecay, typename tuple_element<0L, pair<int, int> >::type (*)(pair<int, int> &))
+// CHECK-NEXT:   8: decomposition-a-b
+// CHECK-NEXT:   9: [B3.7]([B3.8])
+// CHECK-NEXT:  10: [B3.9]
+// CHECK-NEXT:  11: std::tuple_element<0, std::pair<int, int>>::type a = get<0UL>(decomposition-a-b);
+// CHECK-NEXT:  12: get<1UL>
+// CHECK-NEXT:  13: [B3.12] (ImplicitCastExpr, FunctionToPointerDecay, typename tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
+// CHECK-NEXT:  14: decomposition-a-b
+// CHECK-NEXT:  15: [B3.13]([B3.14])
+// CHECK-NEXT:  16: [B3.15]
+// CHECK-NEXT:  17: std::tuple_element<1, std::pair<int, int>>::type b = get<1UL>(decomposition-a-b);
+// CHECK-NEXT:   Preds (1): B1
+// CHECK-NEXT:   Succs (1): B2
diff --git a/clang/test/Analysis/anonymous-parameter.cpp b/clang/test/Analysis/anonymous-parameter.cpp
deleted file mode 100644
index ad2a00b3329cb3..00000000000000
--- a/clang/test/Analysis/anonymous-parameter.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -std=c++20 %s 2>&1 | FileCheck %s
-
-struct A {
-  static A a;
-  char b;
-  friend bool operator==(A, A) = default;
-};
-bool _ = A() == A::a;
-
-// FIXME: steps 1 and 5 show anonymous function parameters are
-// not handled correctly.
-
-// CHECK-LABEL: bool operator==(A, A) noexcept = default
-// CHECK-NEXT: [B2 (ENTRY)]
-// CHECK-NEXT:    Succs (1): B1
-// CHECK:      [B1]
-// CHECK-NEXT:    1: function-parameter-0-0
-// CHECK-NEXT:    2: [B1.1].b
-// CHECK-NEXT:    3: [B1.2] (ImplicitCastExpr, LValueToRValue, char)
-// CHECK-NEXT:    4: [B1.3] (ImplicitCastExpr, IntegralCast, int)
-// CHECK-NEXT:    5: function-parameter-0-1
-// CHECK-NEXT:    6: [B1.5].b
-// CHECK-NEXT:    7: [B1.6] (ImplicitCastExpr, LValueToRValue, char)
-// CHECK-NEXT:    8: [B1.7] (ImplicitCastExpr, IntegralCast, int)
-// CHECK-NEXT:    9: [B1.4] == [B1.8]
-// CHECK-NEXT:   10: return [B1.9];
-// CHECK-NEXT:    Preds (1): B2
-// CHECK-NEXT:    Succs (1): B0
-// CHECK:      [B0 (EXIT)]
-// CHECK-NEXT:    Preds (1): B1

A DeclRefExpr could never refer to a Decomposition in valid C++ code,
but somehow the Analyzer creates these entities and then it tries to
print them.

There is no sensible answer here, so we print 'decomposition' followed
by the names of all of its bindings, separated by dashes.
@mizvekov mizvekov force-pushed the users/mizvekov/clang-print-declref-decomposition branch from dfba1f7 to 7e687ef Compare January 30, 2025 00:21
Copy link
Collaborator

@slackito slackito left a comment

Choose a reason for hiding this comment

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

I'm not very familiar with any of this code, but this looks like a straightforward workaround to me. I'll leave to you and the other reviewer the decision about what should be done to make the Analyzer do the right thing in the long-term to not hit these weird cases.

Thanks for the quick fix!

@mizvekov mizvekov merged commit 00c096e into main Jan 30, 2025
6 of 7 checks passed
@mizvekov mizvekov deleted the users/mizvekov/clang-print-declref-decomposition branch January 30, 2025 00:58
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 30, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-libc-amdgpu-runtime running on omp-vega20-1 while building clang at step 7 "Add check check-offload".

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

Here is the relevant piece of the build log for the reference
Step 7 (Add check check-offload) failure: test (failure)
******************** TEST 'libomptarget :: amdgcn-amd-amdhsa :: mapping/data_member_ref.cpp' FAILED ********************
Exit Code: 2

Command Output (stdout):
--
# RUN: at line 1
/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang++ -fopenmp    -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src  -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib  -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/mapping/data_member_ref.cpp -o /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/mapping/Output/data_member_ref.cpp.tmp -Xoffload-linker -lc -Xoffload-linker -lm /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a && /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/mapping/Output/data_member_ref.cpp.tmp | /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/mapping/data_member_ref.cpp
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/clang++ -fopenmp -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/mapping/data_member_ref.cpp -o /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/mapping/Output/data_member_ref.cpp.tmp -Xoffload-linker -lc -Xoffload-linker -lm /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/mapping/Output/data_member_ref.cpp.tmp
# note: command had no output on stdout or stderr
# error: command failed with exit status: -11
# executed command: /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/mapping/data_member_ref.cpp
# .---command stderr------------
# | FileCheck error: '<stdin>' is empty.
# | FileCheck command line:  /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-libc-amdgpu-runtime/llvm.src/offload/test/mapping/data_member_ref.cpp
# `-----------------------------
# error: command failed with exit status: 2

--

********************


@wjristow
Copy link
Collaborator

Could we backport this to release/20.x to avoid a regression?

@wjristow
Copy link
Collaborator

/cherry-pick 00c096e

@llvmbot
Copy link
Member

llvmbot commented Feb 11, 2025

/cherry-pick 00c096e

Error: Command failed due to missing milestone.

@wjristow wjristow added this to the LLVM 20.X Release milestone Feb 11, 2025
@wjristow
Copy link
Collaborator

/cherry-pick 00c096e

@llvmbot
Copy link
Member

llvmbot commented Feb 11, 2025

/pull-request #126659

swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Feb 18, 2025
A DeclRefExpr could never refer to a Decomposition in valid C++ code,
but somehow the Analyzer creates these entities and then it tries to
print them.

There is no sensible answer here, so we print 'decomposition' followed
by the names of all of its bindings, separated by dashes.

(cherry picked from commit 00c096e)
@mizvekov mizvekov removed this from the LLVM 20.X Release milestone Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
Development

Successfully merging this pull request may close these issues.

5 participants