https://github.com/Ignition updated 
https://github.com/llvm/llvm-project/pull/178471

>From 21a74e7f65703a9293c81af27e5666b4f2787d6a Mon Sep 17 00:00:00 2001
From: Gareth Lloyd <[email protected]>
Date: Wed, 28 Jan 2026 17:10:30 +0000
Subject: [PATCH] [clang-tidy] Fix performance-trivially-destructible with
 C++20 modules

When a class definition is seen through both a header include and a C++20
module import, destructors may appear multiple times in the AST's
redeclaration chain. The original matcher used `isFirstDecl()` which fails
in this scenario because the same declaration can appear as both first and
non-first depending on the view.

Replace `unless(isFirstDecl())` with `isOutOfLine()` which correctly
identifies out-of-line definitions by checking whether the lexical context
differs from the semantic context.

Also update clang-tools-extra's lit.cfg.py to call `use_clang()` instead of
`clang_setup()` to make the `%clang` substitution available for tests.

Fixes #178102
---
 .../TriviallyDestructibleCheck.cpp            | 10 ++++---
 clang-tools-extra/docs/ReleaseNotes.rst       |  5 ++++
 .../trivially-destructible-module.cpp         | 27 +++++++++++++++++++
 clang-tools-extra/test/lit.cfg.py             |  4 +--
 4 files changed, 41 insertions(+), 5 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/trivially-destructible-module.cpp

diff --git 
a/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp
index 416c41d7acd66..5088cfb7ca503 100644
--- a/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/TriviallyDestructibleCheck.cpp
@@ -20,7 +20,11 @@ namespace clang::tidy::performance {
 
 namespace {
 
-AST_MATCHER(Decl, isFirstDecl) { return Node.isFirstDecl(); }
+// We use isOutOfLine() to find out-of-line defaulted destructor definitions.
+// This is more robust than !isFirstDecl() because with C++20 modules, when a
+// class is visible through both a header include and a module import, its
+// declarations may appear multiple times in the redeclaration chain.
+AST_MATCHER(CXXMethodDecl, isOutOfLine) { return Node.isOutOfLine(); }
 
 AST_MATCHER_P(CXXRecordDecl, hasBase, Matcher<QualType>, InnerMatcher) {
   return llvm::any_of(Node.bases(), [&](const CXXBaseSpecifier &BaseSpec) {
@@ -33,8 +37,8 @@ AST_MATCHER_P(CXXRecordDecl, hasBase, Matcher<QualType>, 
InnerMatcher) {
 void TriviallyDestructibleCheck::registerMatchers(MatchFinder *Finder) {
   Finder->addMatcher(
       cxxDestructorDecl(
-          isDefaulted(),
-          unless(anyOf(isFirstDecl(), isVirtual(),
+          isDefaulted(), isOutOfLine(),
+          unless(anyOf(isVirtual(),
                        ofClass(cxxRecordDecl(
                            anyOf(hasBase(unless(isTriviallyDestructible())),
                                  has(fieldDecl(unless(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 754880bd1a381..11ca4857ee40d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -166,6 +166,11 @@ Changes in existing checks
   <clang-tidy/checks/performance/move-const-arg>` check by avoiding false
   positives on trivially copyable types with a non-public copy constructor.
 
+- Improved :doc:`performance-trivially-destructible
+  <clang-tidy/checks/performance/trivially-destructible>` check by fixing
+  false positives when a class is seen through both a header include and
+  a C++20 module import.
+
 - Improved :doc:`readability-enum-initial-value
   <clang-tidy/checks/readability/enum-initial-value>` check: the warning 
message
   now uses separate note diagnostics for each uninitialized enumerator, making
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/performance/trivially-destructible-module.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/performance/trivially-destructible-module.cpp
new file mode 100644
index 0000000000000..b89c13daeaeea
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/performance/trivially-destructible-module.cpp
@@ -0,0 +1,27 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: %clang -std=c++20 -x c++-module --precompile %t/mymodule.cppm -o 
%t/mymodule.pcm -I%t
+// RUN: %check_clang_tidy %t/main.cpp performance-trivially-destructible 
%t/out -std=c++20 \
+// RUN:     -- -I%t -fmodule-file=mymodule=%t/mymodule.pcm
+
+//--- header.h
+#pragma once
+
+struct A {
+    ~A() = default;
+};
+
+struct X {
+    A a;
+};
+
+//--- mymodule.cppm
+module;
+#include "header.h"
+export module mymodule;
+
+//--- main.cpp
+#include "header.h"
+import mymodule;
+int main() { X x; }
diff --git a/clang-tools-extra/test/lit.cfg.py 
b/clang-tools-extra/test/lit.cfg.py
index c39ea29329674..61acefbd86235 100644
--- a/clang-tools-extra/test/lit.cfg.py
+++ b/clang-tools-extra/test/lit.cfg.py
@@ -49,8 +49,8 @@
 # test_exec_root: The root path where tests should be run.
 config.test_exec_root = os.path.join(config.clang_tools_binary_dir, "test")
 
-# Tools need the same environment setup as clang (we don't need clang itself).
-llvm_config.clang_setup()
+# Set up clang for use in tests. This makes %clang, %clangxx, etc. available.
+llvm_config.use_clang()
 
 if config.clang_tidy_staticanalyzer:
     config.available_features.add("static-analyzer")

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to