[clang] f21c704 - clang-format: Add ControlStatementsExceptForEachMacros option to SpaceBeforeParens

2020-05-06 Thread Daan De Meyer via cfe-commits

Author: Daan De Meyer
Date: 2020-05-06T20:59:24+02:00
New Revision: f21c704553a8af7012eaf1ab777e2aa1a55cc86d

URL: 
https://github.com/llvm/llvm-project/commit/f21c704553a8af7012eaf1ab777e2aa1a55cc86d
DIFF: 
https://github.com/llvm/llvm-project/commit/f21c704553a8af7012eaf1ab777e2aa1a55cc86d.diff

LOG: clang-format: Add ControlStatementsExceptForEachMacros option to 
SpaceBeforeParens

Summary: systemd recently added a clang-format file. One issue I
encountered in using clang-format on systemd is that systemd does
not add a space before the parens of their foreach macros but
clang-format always adds a space. This does not seem to be
configurable in clang-format. This revision adds the
ControlStatementsExceptForEachMacros option to SpaceBeforeParens
which puts a space before all control statement parens except
ForEach macros. This drastically reduces the amount of changes
when running clang-format on systemd's source code.

Reviewers: MyDeveloperDay, krasimir, mitchell-stellar

Reviewed By: MyDeveloperDay

Subscribers: cfe-commits

Tags: #clang-format, #clang

Differential Revision: https://reviews.llvm.org/D78869

Added: 


Modified: 
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp

Removed: 




diff  --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index ce26b06bf171..3ea503a592ac 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -2336,6 +2336,19 @@ the configuration (without a prefix: ``Auto``).
  }
}
 
+  * ``SBPO_ControlStatementsExceptForEachMacros`` (in configuration: 
``ControlStatementsExceptForEachMacros``)
+Same as ``SBPO_ControlStatements`` except this option doesn't apply to
+ForEach macros. This is useful in projects where ForEach macros are
+treated as function calls instead of control statements.
+
+.. code-block:: c++
+
+   void f() {
+ Q_FOREACH(...) {
+   f();
+ }
+   }
+
   * ``SBPO_NonEmptyParentheses`` (in configuration: ``NonEmptyParentheses``)
 Put a space before opening parentheses only if the parentheses are not
 empty i.e. '()'

diff  --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 011cf599d526..f8f2903dde57 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -1983,6 +1983,17 @@ struct FormatStyle {
 ///}
 /// \endcode
 SBPO_ControlStatements,
+/// Same as ``SBPO_ControlStatements`` except this option doesn't apply to
+/// ForEach macros. This is useful in projects where ForEach macros are 
+/// treated as function calls instead of control statements. 
+/// \code
+///void f() {
+///  Q_FOREACH(...) {
+///f();
+///  }
+///}
+/// \endcode
+SBPO_ControlStatementsExceptForEachMacros,
 /// Put a space before opening parentheses only if the parentheses are not
 /// empty i.e. '()'
 /// \code

diff  --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 961cb92ebd40..1fd7d613f9fb 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -329,6 +329,8 @@ struct 
ScalarEnumerationTraits {
 IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
 IO.enumCase(Value, "ControlStatements",
 FormatStyle::SBPO_ControlStatements);
+IO.enumCase(Value, "ControlStatementsExceptForEachMacros",
+FormatStyle::SBPO_ControlStatementsExceptForEachMacros);
 IO.enumCase(Value, "NonEmptyParentheses",
 FormatStyle::SBPO_NonEmptyParentheses);
 IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);

diff  --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 734dbdc1b6f3..408f68e35418 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2900,6 +2900,10 @@ bool TokenAnnotator::spaceRequiredBetween(const 
AnnotatedLine &Line,
 if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
 (Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
   return true;
+if (Style.SpaceBeforeParens ==
+FormatStyle::SBPO_ControlStatementsExceptForEachMacros &&
+Left.is(TT_ForEachMacro))
+  return false;
 return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
(Style.SpaceBeforeParens != FormatStyle::SBPO_Never &&
 (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while,

diff  --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 9fdf2e728472..aba209b4252d 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -972,6 +972,17 @@ 

[clang] 7dd42ec - clang: Exclude efi_main from -Wmissing-prototypes

2021-02-20 Thread Daan De Meyer via cfe-commits

Author: Daan De Meyer
Date: 2021-02-20T20:00:50Z
New Revision: 7dd42ecfa2a29bac89c965544c14b32805c8f02b

URL: 
https://github.com/llvm/llvm-project/commit/7dd42ecfa2a29bac89c965544c14b32805c8f02b
DIFF: 
https://github.com/llvm/llvm-project/commit/7dd42ecfa2a29bac89c965544c14b32805c8f02b.diff

LOG: clang: Exclude efi_main from -Wmissing-prototypes

When compiling UEFI applications, the main function is named
efi_main() instead of main(). Let's exclude efi_main() from
-Wmissing-prototypes as well to avoid warnings when working
on UEFI applications.

Differential Revision: https://reviews.llvm.org/D95746

Added: 


Modified: 
clang/lib/Sema/SemaDecl.cpp
clang/test/Sema/no-warn-missing-prototype.c

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index cee107096947..0f5b5332364a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13873,7 +13873,7 @@ ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
   // Don't warn about 'main'.
   if (isa(FD->getDeclContext()->getRedeclContext()))
 if (IdentifierInfo *II = FD->getIdentifier())
-  if (II->isStr("main"))
+  if (II->isStr("main") || II->isStr("efi_main"))
 return false;
 
   // Don't warn about inline functions.

diff  --git a/clang/test/Sema/no-warn-missing-prototype.c 
b/clang/test/Sema/no-warn-missing-prototype.c
index 4dbc25755922..6059b6aa0f14 100644
--- a/clang/test/Sema/no-warn-missing-prototype.c
+++ b/clang/test/Sema/no-warn-missing-prototype.c
@@ -4,3 +4,7 @@
 int main() {
   return 0;
 }
+
+int efi_main() {
+  return 0;
+}



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 5a6dac6 - LiteralSupport: Don't assert() on invalid input

2021-11-17 Thread Daan De Meyer via cfe-commits

Author: Daan De Meyer
Date: 2021-11-17T23:51:30Z
New Revision: 5a6dac66db67225e2443f4e61dfe9d2f96780611

URL: 
https://github.com/llvm/llvm-project/commit/5a6dac66db67225e2443f4e61dfe9d2f96780611
DIFF: 
https://github.com/llvm/llvm-project/commit/5a6dac66db67225e2443f4e61dfe9d2f96780611.diff

LOG: LiteralSupport: Don't assert() on invalid input

When using clangd, it's possible to trigger assertions in
NumericLiteralParser and CharLiteralParser when switching git branches.
This commit removes the initial asserts on invalid input and replaces
those asserts with the error handling mechanism from those respective
classes instead. This allows clangd to gracefully recover without
crashing.

See https://github.com/clangd/clangd/issues/888 for more information
on the clangd crashes.

Added: 


Modified: 
clang/include/clang/Basic/DiagnosticLexKinds.td
clang/lib/Lex/LiteralSupport.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticLexKinds.td 
b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 805dcab2e0084..a4436208799f9 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -269,7 +269,9 @@ def err_bad_character_encoding : Error<
 def warn_bad_character_encoding : ExtWarn<
   "illegal character encoding in character literal">,
   InGroup;
-def err_lexing_string : Error<"failure when lexing a string">;
+def err_lexing_string : Error<"failure when lexing a string literal">;
+def err_lexing_char : Error<"failure when lexing a character literal">;
+def err_lexing_numeric : Error<"failure when lexing a numeric literal">;
 def err_placeholder_in_source : Error<"editor placeholder in source file">;
 
 
//===--===//

diff  --git a/clang/lib/Lex/LiteralSupport.cpp 
b/clang/lib/Lex/LiteralSupport.cpp
index a8022812a3636..76c8b324671d7 100644
--- a/clang/lib/Lex/LiteralSupport.cpp
+++ b/clang/lib/Lex/LiteralSupport.cpp
@@ -693,12 +693,6 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
 : SM(SM), LangOpts(LangOpts), Diags(Diags),
   ThisTokBegin(TokSpelling.begin()), ThisTokEnd(TokSpelling.end()) {
 
-  // This routine assumes that the range begin/end matches the regex for 
integer
-  // and FP constants (specifically, the 'pp-number' regex), and assumes that
-  // the byte at "*end" is both valid and not part of the regex.  Because of
-  // this, it doesn't have to check for 'overscan' in various places.
-  assert(!isPreprocessingNumberBody(*ThisTokEnd) && "didn't maximally munch?");
-
   s = DigitsBegin = ThisTokBegin;
   saw_exponent = false;
   saw_period = false;
@@ -718,6 +712,16 @@ NumericLiteralParser::NumericLiteralParser(StringRef 
TokSpelling,
   isAccum = false;
   hadError = false;
 
+  // This routine assumes that the range begin/end matches the regex for 
integer
+  // and FP constants (specifically, the 'pp-number' regex), and assumes that
+  // the byte at "*end" is both valid and not part of the regex.  Because of
+  // this, it doesn't have to check for 'overscan' in various places.
+  if (isPreprocessingNumberBody(*ThisTokEnd)) {
+Diags.Report(TokLoc, diag::err_lexing_numeric);
+hadError = true;
+return;
+  }
+
   if (*s == '0') { // parse radix
 ParseNumberStartingWithZero(TokLoc);
 if (hadError)
@@ -1432,7 +1436,12 @@ CharLiteralParser::CharLiteralParser(const char *begin, 
const char *end,
 ++begin;
 
   // Skip over the entry quote.
-  assert(begin[0] == '\'' && "Invalid token lexed");
+  if (begin[0] != '\'') {
+PP.Diag(Loc, diag::err_lexing_char);
+HadError = true;
+return;
+  }
+
   ++begin;
 
   // Remove an optional ud-suffix.



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From 00f2edbda351d0790f4f71aabaf59342cd6ce424 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst  |  2 ++
 .../disable-format-enable-include-sorting.cpp   |  9 +
 clang/tools/clang-format/ClangFormat.cpp| 13 +++--
 3 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..0ad5948e0a448 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -58,6 +58,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
Verilog: .sv .svh .v .vh
 --cursor=- The position of the cursor when invoking
  clang-format from an editor integration
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --dry-run  - If set, do not actually make the 
formatting changes
 --dump-config  - Dump configuration options to stdout and 
exit.
  Can be used with -style option.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..62acf4ab71fbd
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -style=LLVM -disable-format | FileCheck 
%s
+
+#include 
+#include 
+// CHECK: 
+// CHECK-NEXT: 
+
+// CHECK: int *a  ;
+int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..9d40b6db4329a 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -214,6 +214,12 @@ static cl::opt ListIgnored("list-ignored",
  cl::desc("List ignored files."),
  cl::cat(ClangFormatCategory), cl::Hidden);
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 namespace clang {
 namespace format {
 
@@ -506,8 +512,11 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat) {
+FormatChanges =
+reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  }
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] include-cleaner: Report function decls from __cleanup__ as used (PR #138669)

2025-05-06 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/138669

None



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-05-01 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer edited 
https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-05-01 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer edited 
https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-05-01 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From 4edcb6e0a0d4272a72a272ae97b32439f597ebf3 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IncludeSortKey option

Sorting by stem gives nicer results when various header file names
are substrings of other header file names, for example, a CLI application
with a main header named analyze.h and a analyze-xxx.h header for each
subcommand currently will always put analyze.h last after all the
analyze-xxx.h headers, but putting analyze.h first instead of last is arguable
nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting by stem instead of full path by introducing a new
option IncludeSortKey with two values "Path" and "Stem".
---
 clang/docs/ClangFormatStyleOptions.rst| 13 +
 clang/include/clang/Format/Format.h   |  1 +
 .../clang/Tooling/Inclusions/IncludeStyle.h   | 17 
 clang/lib/Format/Format.cpp   | 27 +--
 clang/lib/Tooling/Inclusions/IncludeStyle.cpp |  6 +
 clang/unittests/Format/SortIncludesTest.cpp   | 16 +++
 6 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 3f8a5f49313b2..248d489b1a878 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4226,6 +4226,19 @@ the configuration (without a prefix: ``Auto``).
   ``ClassImpl.hpp`` would not have the main include file put on top
   before any other include.
 
+.. _IncludeSortKey:
+
+**IncludeSortKey** (``IncludeSortKeyDiscriminator``) 
:versionbadge:`clang-format 20` :ref:`¶ `
+  When sorting includes in each block, sort by the specified sort key
+
+  Possible values:
+
+  * ``ISK_Path`` (in configuration: ``Path``)
+Includes are sorted by their full path (the default).
+
+  * ``ISK_Stem`` (in configuration: ``AngleBracket``)
+Includes are sorted by their full path without the file extension.
+
 .. _IndentAccessModifiers:
 
 **IndentAccessModifiers** (``Boolean``) :versionbadge:`clang-format 13` 
:ref:`¶ `
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index f6ceef08b46da..23ce34b560198 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -5368,6 +5368,7 @@ struct FormatStyle {
IncludeStyle.IncludeIsMainSourceRegex ==
R.IncludeStyle.IncludeIsMainSourceRegex &&
IncludeStyle.MainIncludeChar == R.IncludeStyle.MainIncludeChar &&
+   IncludeStyle.IncludeSortKey == R.IncludeStyle.IncludeSortKey &&
IndentAccessModifiers == R.IndentAccessModifiers &&
IndentCaseBlocks == R.IndentCaseBlocks &&
IndentCaseLabels == R.IndentCaseLabels &&
diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h 
b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
index fba90d8c51a66..8df8f54e7ee0e 100644
--- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -166,6 +166,15 @@ struct IncludeStyle {
   /// directives that use the specified character are considered.
   /// \version 19
   MainIncludeCharDiscriminator MainIncludeChar;
+
+  enum IncludeSortKeyDiscriminator : int8_t {
+/// Includes are sorted alphabetically by their full path.
+ISK_Path,
+/// Includes are sorted alphabetically by their full path without file 
extension.
+ISK_Stem,
+  };
+
+  IncludeSortKeyDiscriminator IncludeSortKey;
 };
 
 } // namespace tooling
@@ -197,6 +206,14 @@ struct ScalarEnumerationTraits<
   clang::tooling::IncludeStyle::MainIncludeCharDiscriminator &Value);
 };
 
+template <>
+struct ScalarEnumerationTraits<
+clang::tooling::IncludeStyle::IncludeSortKeyDiscriminator> {
+  static void enumeration(
+  IO &IO,
+  clang::tooling::IncludeStyle::IncludeSortKeyDiscriminator &Value);
+};
+
 } // namespace yaml
 } // namespace llvm
 
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5a1c3f556b331..12abc753d9058 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1062,6 +1062,7 @@ template <> struct MappingTraits {
 IO.mapOptional("IncludeIsMainRegex", 
Style.IncludeStyle.IncludeIsMainRegex);
 IO.mapOptional("IncludeIsMainSourceRegex",
Style.IncludeStyle.IncludeIsMainSourceRegex);
+IO.mapOptional("IncludeSortKey", Style.IncludeStyle.IncludeSortKey);
 IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
 IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
@@ -3219,17 +3220,27 @@ static void sortCppIncludes(const FormatStyle &Style

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-01 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer edited 
https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-01 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

@HazardyKnusperkeks @owenca Updated PR to introduce a new option 
`IncludeSortKey`, PTAL!

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-01 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From 73a18a033e0d978d1662a391fedf731dbad7de27 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IncludeSortKey option

Sorting by stem gives nicer results when various header file names
are substrings of other header file names, for example, a CLI application
with a main header named analyze.h and a analyze-xxx.h header for each
subcommand currently will always put analyze.h last after all the
analyze-xxx.h headers, but putting analyze.h first instead of last is arguable
nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting by stem instead of full path by introducing a new
option IncludeSortKey with two values "Path" and "Stem".
---
 clang/docs/ClangFormatStyleOptions.rst| 13 +
 clang/include/clang/Format/Format.h   |  1 +
 .../clang/Tooling/Inclusions/IncludeStyle.h   | 18 
 clang/lib/Format/Format.cpp   | 29 ++-
 clang/lib/Tooling/Inclusions/IncludeStyle.cpp |  6 
 clang/unittests/Format/SortIncludesTest.cpp   | 16 ++
 6 files changed, 75 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 3f8a5f49313b2..248d489b1a878 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4226,6 +4226,19 @@ the configuration (without a prefix: ``Auto``).
   ``ClassImpl.hpp`` would not have the main include file put on top
   before any other include.
 
+.. _IncludeSortKey:
+
+**IncludeSortKey** (``IncludeSortKeyDiscriminator``) 
:versionbadge:`clang-format 20` :ref:`¶ `
+  When sorting includes in each block, sort by the specified sort key
+
+  Possible values:
+
+  * ``ISK_Path`` (in configuration: ``Path``)
+Includes are sorted by their full path (the default).
+
+  * ``ISK_Stem`` (in configuration: ``AngleBracket``)
+Includes are sorted by their full path without the file extension.
+
 .. _IndentAccessModifiers:
 
 **IndentAccessModifiers** (``Boolean``) :versionbadge:`clang-format 13` 
:ref:`¶ `
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index f6ceef08b46da..23ce34b560198 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -5368,6 +5368,7 @@ struct FormatStyle {
IncludeStyle.IncludeIsMainSourceRegex ==
R.IncludeStyle.IncludeIsMainSourceRegex &&
IncludeStyle.MainIncludeChar == R.IncludeStyle.MainIncludeChar &&
+   IncludeStyle.IncludeSortKey == R.IncludeStyle.IncludeSortKey &&
IndentAccessModifiers == R.IndentAccessModifiers &&
IndentCaseBlocks == R.IndentCaseBlocks &&
IndentCaseLabels == R.IndentCaseLabels &&
diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h 
b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
index fba90d8c51a66..6699a667c6daa 100644
--- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -166,6 +166,16 @@ struct IncludeStyle {
   /// directives that use the specified character are considered.
   /// \version 19
   MainIncludeCharDiscriminator MainIncludeChar;
+
+  enum IncludeSortKeyDiscriminator : int8_t {
+/// Includes are sorted alphabetically by their full path.
+ISK_Path,
+/// Includes are sorted alphabetically by their full path without file
+/// extension.
+ISK_Stem,
+  };
+
+  IncludeSortKeyDiscriminator IncludeSortKey;
 };
 
 } // namespace tooling
@@ -197,6 +207,14 @@ struct ScalarEnumerationTraits<
   clang::tooling::IncludeStyle::MainIncludeCharDiscriminator &Value);
 };
 
+template <>
+struct ScalarEnumerationTraits<
+clang::tooling::IncludeStyle::IncludeSortKeyDiscriminator> {
+  static void
+  enumeration(IO &IO,
+  clang::tooling::IncludeStyle::IncludeSortKeyDiscriminator 
&Value);
+};
+
 } // namespace yaml
 } // namespace llvm
 
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5a1c3f556b331..c2aa44e4d1f25 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1062,6 +1062,7 @@ template <> struct MappingTraits {
 IO.mapOptional("IncludeIsMainRegex", 
Style.IncludeStyle.IncludeIsMainRegex);
 IO.mapOptional("IncludeIsMainSourceRegex",
Style.IncludeStyle.IncludeIsMainSourceRegex);
+IO.mapOptional("IncludeSortKey", Style.IncludeStyle.IncludeSortKey);
 IO.mapOptional("IndentAccessModifiers", Style.IndentAccessModifiers);
 IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks);
 IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
@@ -3219,17 +3220,29 @@ static void sortCppIncludes(const FormatSt

[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From e4d8ac466061f098f399c9a662420da4acb5bb8b Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst  |  2 ++
 .../disable-format-enable-include-sorting.cpp   |  9 +
 clang/tools/clang-format/ClangFormat.cpp| 13 +++--
 3 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..a0de662b5c93b 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -95,6 +95,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
  determined by the QualifierAlignment 
style flag
 --sort-includes- If set, overrides the include sorting 
behavior
  determined by the SortIncludes style flag
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --style=   - Set coding style.  can be:
  1. A preset: LLVM, GNU, Google, Chromium, 
Microsoft,
 Mozilla, WebKit.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..62acf4ab71fbd
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -style=LLVM -disable-format | FileCheck 
%s
+
+#include 
+#include 
+// CHECK: 
+// CHECK-NEXT: 
+
+// CHECK: int *a  ;
+int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..d7cc37e799c9e 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -120,6 +120,12 @@ static cl::opt
   "determined by the SortIncludes style flag"),
  cl::cat(ClangFormatCategory));
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 static cl::opt QualifierAlignment(
 "qualifier-alignment",
 cl::desc("If set, overrides the qualifier alignment style\n"
@@ -506,8 +512,11 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat) {
+FormatChanges =
+reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  }
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From b023d2698915ea7d269a9afe8f11de162a39e53d Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst|  2 ++
 .../Format/disable-format-enable-include-sorting.cpp  |  9 +
 clang/tools/clang-format/ClangFormat.cpp  | 11 +--
 3 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..a0de662b5c93b 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -95,6 +95,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
  determined by the QualifierAlignment 
style flag
 --sort-includes- If set, overrides the include sorting 
behavior
  determined by the SortIncludes style flag
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --style=   - Set coding style.  can be:
  1. A preset: LLVM, GNU, Google, Chromium, 
Microsoft,
 Mozilla, WebKit.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..595309d478a1e
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -disable-format | FileCheck %s
+
+#include 
+#include 
+// CHECK: 
+// CHECK-NEXT: 
+
+// CHECK: int *a  ;
+int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..c23d3dda4b444 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -120,6 +120,12 @@ static cl::opt
   "determined by the SortIncludes style flag"),
  cl::cat(ClangFormatCategory));
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 static cl::opt QualifierAlignment(
 "qualifier-alignment",
 cl::desc("If set, overrides the qualifier alignment style\n"
@@ -506,8 +512,9 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  // if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat)
+  FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, 
AssumedFileName, &Status);
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From 10e997e7707f0d04b7c66da8ab4d85435dc2f8ba Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst|  2 ++
 .../Format/disable-format-enable-include-sorting.cpp  |  9 +
 clang/tools/clang-format/ClangFormat.cpp  | 11 +--
 3 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..a0de662b5c93b 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -95,6 +95,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
  determined by the QualifierAlignment 
style flag
 --sort-includes- If set, overrides the include sorting 
behavior
  determined by the SortIncludes style flag
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --style=   - Set coding style.  can be:
  1. A preset: LLVM, GNU, Google, Chromium, 
Microsoft,
 Mozilla, WebKit.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..595309d478a1e
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -disable-format | FileCheck %s
+
+#include 
+#include 
+// CHECK: 
+// CHECK-NEXT: 
+
+// CHECK: int *a  ;
+int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..da3d7edf2649f 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -120,6 +120,12 @@ static cl::opt
   "determined by the SortIncludes style flag"),
  cl::cat(ClangFormatCategory));
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 static cl::opt QualifierAlignment(
 "qualifier-alignment",
 cl::desc("If set, overrides the qualifier alignment style\n"
@@ -506,8 +512,9 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat)
+FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, 
AssumedFileName, &Status);
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From 5a2912abe37c04e1ad15e282867e16f010ec1fe6 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst|  2 ++
 .../Format/disable-format-enable-include-sorting.cpp  |  9 +
 clang/tools/clang-format/ClangFormat.cpp  | 11 +--
 3 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..a0de662b5c93b 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -95,6 +95,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
  determined by the QualifierAlignment 
style flag
 --sort-includes- If set, overrides the include sorting 
behavior
  determined by the SortIncludes style flag
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --style=   - Set coding style.  can be:
  1. A preset: LLVM, GNU, Google, Chromium, 
Microsoft,
 Mozilla, WebKit.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..62acf4ab71fbd
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -style=LLVM -disable-format | FileCheck 
%s
+
+#include 
+#include 
+// CHECK: 
+// CHECK-NEXT: 
+
+// CHECK: int *a  ;
+int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..da3d7edf2649f 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -120,6 +120,12 @@ static cl::opt
   "determined by the SortIncludes style flag"),
  cl::cat(ClangFormatCategory));
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 static cl::opt QualifierAlignment(
 "qualifier-alignment",
 cl::desc("If set, overrides the qualifier alignment style\n"
@@ -506,8 +512,9 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat)
+FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, 
AssumedFileName, &Status);
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From c7b25ee74e78a6ff6f0fc1fdf2cf0ea24381be89 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst|  2 ++
 .../Format/disable-format-enable-include-sorting.cpp  |  9 +
 clang/tools/clang-format/ClangFormat.cpp  | 11 +--
 3 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..a0de662b5c93b 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -95,6 +95,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
  determined by the QualifierAlignment 
style flag
 --sort-includes- If set, overrides the include sorting 
behavior
  determined by the SortIncludes style flag
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --style=   - Set coding style.  can be:
  1. A preset: LLVM, GNU, Google, Chromium, 
Microsoft,
 Mozilla, WebKit.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..d2cbca0d3eb50
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -disable-format | FileCheck %s
+
+#include 
+#include 
+
+int *a  ;
+// CHECK: 
+// CHECK-NEXT: 
+// CHECK: int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..da3d7edf2649f 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -120,6 +120,12 @@ static cl::opt
   "determined by the SortIncludes style flag"),
  cl::cat(ClangFormatCategory));
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 static cl::opt QualifierAlignment(
 "qualifier-alignment",
 cl::desc("If set, overrides the qualifier alignment style\n"
@@ -506,8 +512,9 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat)
+FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, 
AssumedFileName, &Status);
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From 55b9af0981da56e777e10fd959edcc91c31f03f6 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst|  2 ++
 .../Format/disable-format-enable-include-sorting.cpp  |  9 +
 clang/tools/clang-format/ClangFormat.cpp  | 11 +--
 3 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..a0de662b5c93b 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -95,6 +95,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
  determined by the QualifierAlignment 
style flag
 --sort-includes- If set, overrides the include sorting 
behavior
  determined by the SortIncludes style flag
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --style=   - Set coding style.  can be:
  1. A preset: LLVM, GNU, Google, Chromium, 
Microsoft,
 Mozilla, WebKit.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..595309d478a1e
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -disable-format | FileCheck %s
+
+#include 
+#include 
+// CHECK: 
+// CHECK-NEXT: 
+
+// CHECK: int *a  ;
+int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..da3d7edf2649f 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -120,6 +120,12 @@ static cl::opt
   "determined by the SortIncludes style flag"),
  cl::cat(ClangFormatCategory));
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 static cl::opt QualifierAlignment(
 "qualifier-alignment",
 cl::desc("If set, overrides the qualifier alignment style\n"
@@ -506,8 +512,9 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat)
+FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, 
AssumedFileName, &Status);
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/137617

When https://github.com/llvm/llvm-project/issues/27416 was fixed it became 
impossible to only use clang-format for include sorting. Let's introduce an 
option -disable-format to make it possible again to only sort includes with 
clang-format without doing any other formatting.

>From f81803b7b81634871a1a8d96a599e85196979eef Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst   |  2 ++
 clang/tools/clang-format/ClangFormat.cpp | 11 +--
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..a0de662b5c93b 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -95,6 +95,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
  determined by the QualifierAlignment 
style flag
 --sort-includes- If set, overrides the include sorting 
behavior
  determined by the SortIncludes style flag
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --style=   - Set coding style.  can be:
  1. A preset: LLVM, GNU, Google, Chromium, 
Microsoft,
 Mozilla, WebKit.
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..da3d7edf2649f 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -120,6 +120,12 @@ static cl::opt
   "determined by the SortIncludes style flag"),
  cl::cat(ClangFormatCategory));
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 static cl::opt QualifierAlignment(
 "qualifier-alignment",
 cl::desc("If set, overrides the qualifier alignment style\n"
@@ -506,8 +512,9 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat)
+FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, 
AssumedFileName, &Status);
   Replaces = Replaces.merge(FormatChanges);
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-29 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

> Can't you just run the `llvm-include-order` clang-tidy check instead?

Does that take `IncludeBlocks` and `IncludeCategories` from `.clang-format` 
into account?

https://github.com/llvm/llvm-project/pull/137617
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-29 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

I don't mind the exact interface too much tbh, I would just like to be able to 
run clang-format again to only sort includes without doing any other 
formatting. Happy to implement whatever makes folks happy.

https://github.com/llvm/llvm-project/pull/137617
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-04-28 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137617

>From ab0fe63baf2044a4768835c359f7068dfba7d81d Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 28 Apr 2025 13:07:50 +0200
Subject: [PATCH] clang-format: Add -disable-format option

When https://github.com/llvm/llvm-project/issues/27416 was fixed it
became impossible to only use clang-format for include sorting. Let's
introduce an option -disable-format to make it possible again to only
sort includes with clang-format without doing any other formatting.
---
 clang/docs/ClangFormat.rst|  2 ++
 .../disable-format-enable-include-sorting.cpp |  9 +
 clang/tools/clang-format/ClangFormat.cpp  | 15 ---
 3 files changed, 23 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Format/disable-format-enable-include-sorting.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 92af06e5083d6..0ad5948e0a448 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -58,6 +58,8 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
Verilog: .sv .svh .v .vh
 --cursor=- The position of the cursor when invoking
  clang-format from an editor integration
+--disable-format   - If set, only sort includes if include 
sorting
+ is enabled
 --dry-run  - If set, do not actually make the 
formatting changes
 --dump-config  - Dump configuration options to stdout and 
exit.
  Can be used with -style option.
diff --git a/clang/test/Format/disable-format-enable-include-sorting.cpp 
b/clang/test/Format/disable-format-enable-include-sorting.cpp
new file mode 100644
index 0..62acf4ab71fbd
--- /dev/null
+++ b/clang/test/Format/disable-format-enable-include-sorting.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-format %s -sort-includes -style=LLVM -disable-format | FileCheck 
%s
+
+#include 
+#include 
+// CHECK: 
+// CHECK-NEXT: 
+
+// CHECK: int *a  ;
+int *a  ;
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index c45e3a2c28327..ed5b4fdd87293 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -214,6 +214,12 @@ static cl::opt ListIgnored("list-ignored",
  cl::desc("List ignored files."),
  cl::cat(ClangFormatCategory), cl::Hidden);
 
+static cl::opt
+DisableFormat("disable-format",
+  cl::desc("If set, only sort includes if include sorting\n"
+   "is enabled"),
+  cl::cat(ClangFormatCategory));
+
 namespace clang {
 namespace format {
 
@@ -506,9 +512,12 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // Get new affected ranges after sorting `#includes`.
   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
   FormattingAttemptStatus Status;
-  Replacements FormatChanges =
-  reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
-  Replaces = Replaces.merge(FormatChanges);
+  Replacements FormatChanges;
+  if (DisableFormat.getNumOccurrences() == 0 || !DisableFormat) {
+FormatChanges =
+reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
+Replaces = Replaces.merge(FormatChanges);
+  }
   if (DryRun) {
 return Replaces.size() > (IsJson ? 1u : 0u) &&
emitReplacementWarnings(Replaces, AssumedFileName, Code);

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-04-29 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

> You definitely need some tests. And I'm not sure if everyone would like that, 
> of if it should be an option.

I was hoping to get some feedback on whether it should be an option or not 
before adding tests.

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-04-29 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/137840

Sorting by stem gives nicer results when various header file names are 
substrings of other header file names, for example, a CLI application with a 
main header named analyze.h and a analyze-xxx.h header for each subcommand 
currently will always put analyze.h last after all the analyze-xxx.h headers, 
but putting analyze.h first instead of last is arguable nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

We'll now get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

>From 33b26cd645f814c83d2cc3b621c34526d0be1d29 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Sort includes by stem rather than full filename

Sorting by stem gives nicer results when various header file names
are substrings of other header file names, for example, a CLI application
with a main header named analyze.h and a analyze-xxx.h header for each
subcommand currently will always put analyze.h last after all the
analyze-xxx.h headers, but putting analyze.h first instead of last is arguable
nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

We'll now get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""
---
 clang/lib/Format/Format.cpp | 18 ++
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5a1c3f556b331..bc1e681c9be78 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3219,17 +3219,19 @@ static void sortCppIncludes(const FormatStyle &Style,
 
   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
+  const auto LHSStem = llvm::sys::path::stem(Includes[LHSI].Filename);
+  const auto RHSStem = llvm::sys::path::stem(Includes[RHSI].Filename);
+  const auto LHSStemLower = LHSStem.lower();
+  const auto RHSStemLower = RHSStem.lower();
+  return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem) <
+ std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem);
 });
   } else {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
+  const auto LHSStem = llvm::sys::path::stem(Includes[LHSI].Filename);
+  const auto RHSStem = llvm::sys::path::stem(Includes[RHSI].Filename);
+  return std::tie(Includes[LHSI].Priority, LHSStem) <
+ std::tie(Includes[RHSI].Priority, RHSStem);
 });
   }
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-04-29 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer edited 
https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-04-29 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer edited 
https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-04-29 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From 4747e31443d9dc273f875782f32e2e47ca9c2cbf Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Sort includes by stem rather than full filename

Sorting by stem gives nicer results when various header file names
are substrings of other header file names, for example, a CLI application
with a main header named analyze.h and a analyze-xxx.h header for each
subcommand currently will always put analyze.h last after all the
analyze-xxx.h headers, but putting analyze.h first instead of last is arguable
nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

We'll now get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""
---
 clang/lib/Format/Format.cpp | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5a1c3f556b331..3dc663e6fa872 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3219,17 +3219,23 @@ static void sortCppIncludes(const FormatStyle &Style,
 
   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
+  SmallString<128> LHSStem = Includes[LHSI].Filename;
+  SmallString<128> RHSStem = Includes[RHSI].Filename;
+  llvm::sys::path::replace_extension(LHSStem, "");
+  llvm::sys::path::replace_extension(RHSStem, "");
+  const auto LHSStemLower = LHSStem.str().lower();
+  const auto RHSStemLower = RHSStem.str().lower();
+  return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem) <
+ std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem);
 });
   } else {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
+  SmallString<128> LHSStem = Includes[LHSI].Filename;
+  SmallString<128> RHSStem = Includes[RHSI].Filename;
+  llvm::sys::path::replace_extension(LHSStem, "");
+  llvm::sys::path::replace_extension(RHSStem, "");
+  return std::tie(Includes[LHSI].Priority, LHSStem) <
+ std::tie(Includes[RHSI].Priority, RHSStem);
 });
   }
 

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Sort includes by stem rather than full filename (PR #137840)

2025-04-29 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From ce0cb8586871f30f7e0883209f4bd30bf63471c5 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Sort includes by stem rather than full filename

Sorting by stem gives nicer results when various header file names
are substrings of other header file names, for example, a CLI application
with a main header named analyze.h and a analyze-xxx.h header for each
subcommand currently will always put analyze.h last after all the
analyze-xxx.h headers, but putting analyze.h first instead of last is arguable
nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

We'll now get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""
---
 clang/lib/Format/Format.cpp | 22 +
 clang/unittests/Format/SortIncludesTest.cpp |  8 
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5a1c3f556b331..3dc663e6fa872 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3219,17 +3219,23 @@ static void sortCppIncludes(const FormatStyle &Style,
 
   if (Style.SortIncludes == FormatStyle::SI_CaseInsensitive) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
+  SmallString<128> LHSStem = Includes[LHSI].Filename;
+  SmallString<128> RHSStem = Includes[RHSI].Filename;
+  llvm::sys::path::replace_extension(LHSStem, "");
+  llvm::sys::path::replace_extension(RHSStem, "");
+  const auto LHSStemLower = LHSStem.str().lower();
+  const auto RHSStemLower = RHSStem.str().lower();
+  return std::tie(Includes[LHSI].Priority, LHSStemLower, LHSStem) <
+ std::tie(Includes[RHSI].Priority, RHSStemLower, RHSStem);
 });
   } else {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
+  SmallString<128> LHSStem = Includes[LHSI].Filename;
+  SmallString<128> RHSStem = Includes[RHSI].Filename;
+  llvm::sys::path::replace_extension(LHSStem, "");
+  llvm::sys::path::replace_extension(RHSStem, "");
+  return std::tie(Includes[LHSI].Priority, LHSStem) <
+ std::tie(Includes[RHSI].Priority, RHSStem);
 });
   }
 
diff --git a/clang/unittests/Format/SortIncludesTest.cpp 
b/clang/unittests/Format/SortIncludesTest.cpp
index f20862f5f7461..030e328bd3c68 100644
--- a/clang/unittests/Format/SortIncludesTest.cpp
+++ b/clang/unittests/Format/SortIncludesTest.cpp
@@ -1485,6 +1485,14 @@ TEST_F(SortIncludesTest, BlockCommentedOutIncludes) {
   verifyFormat(Code, sort(Code, "input.cpp", 0));
 }
 
+TEST_F(SortIncludesTest, SortViaStem) {
+  verifyFormat("#include \n"
+   "#include ",
+   sort("#include \n"
+"#include ",
+"input.h", 1));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-02 Thread Daan De Meyer via cfe-commits


@@ -4226,6 +4226,19 @@ the configuration (without a prefix: ``Auto``).
   ``ClassImpl.hpp`` would not have the main include file put on top
   before any other include.
 
+.. _IncludeSortKey:
+
+**IncludeSortKey** (``IncludeSortKeyDiscriminator``) 
:versionbadge:`clang-format 20` :ref:`¶ `
+  When sorting includes in each block, sort by the specified sort key
+
+  Possible values:
+
+  * ``ISK_Path`` (in configuration: ``Path``)

DaanDeMeyer wrote:

I think the comment is sufficient explanation of what `stem` means in this case?

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-02 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From 7e2463f6fb9a3d64b1be25f2ea6ea91de2d4e982 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IncludeSortKey option

Sorting by stem gives nicer results when various header file names
are substrings of other header file names, for example, a CLI application
with a main header named analyze.h and a analyze-xxx.h header for each
subcommand currently will always put analyze.h last after all the
analyze-xxx.h headers, but putting analyze.h first instead of last is arguable
nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting by stem instead of full path by introducing a new
option IncludeSortKey with two values "Path" and "Stem".
---
 clang/docs/ClangFormatStyleOptions.rst| 16 ++
 clang/include/clang/Format/Format.h   |  1 +
 .../clang/Tooling/Inclusions/IncludeStyle.h   | 21 +
 clang/lib/Format/Format.cpp   | 30 ++-
 clang/lib/Tooling/Inclusions/IncludeStyle.cpp |  6 
 clang/unittests/Format/SortIncludesTest.cpp   | 16 ++
 6 files changed, 82 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 3f8a5f49313b2..dbde3b5af 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4226,6 +4226,22 @@ the configuration (without a prefix: ``Auto``).
   ``ClassImpl.hpp`` would not have the main include file put on top
   before any other include.
 
+.. _IncludeSortKey:
+
+**IncludeSortKey** (``IncludeSortKeyDiscriminator``) 
:versionbadge:`clang-format 21` :ref:`¶ `
+  When sorting includes in each block, sort by the specified sort key.
+
+  Possible values:
+
+  * ``ISK_Path`` (in configuration: ``Path``)
+Includes are sorted alphabetically by their full path.
+
+  * ``ISK_Stem`` (in configuration: ``Stem``)
+Includes are sorted alphabetically by their full path without the
+file extension.
+
+
+
 .. _IndentAccessModifiers:
 
 **IndentAccessModifiers** (``Boolean``) :versionbadge:`clang-format 13` 
:ref:`¶ `
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index f6ceef08b46da..23ce34b560198 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -5368,6 +5368,7 @@ struct FormatStyle {
IncludeStyle.IncludeIsMainSourceRegex ==
R.IncludeStyle.IncludeIsMainSourceRegex &&
IncludeStyle.MainIncludeChar == R.IncludeStyle.MainIncludeChar &&
+   IncludeStyle.IncludeSortKey == R.IncludeStyle.IncludeSortKey &&
IndentAccessModifiers == R.IndentAccessModifiers &&
IndentCaseBlocks == R.IndentCaseBlocks &&
IndentCaseLabels == R.IndentCaseLabels &&
diff --git a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h 
b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
index fba90d8c51a66..8145616757b2b 100644
--- a/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
+++ b/clang/include/clang/Tooling/Inclusions/IncludeStyle.h
@@ -152,6 +152,19 @@ struct IncludeStyle {
   /// \version 10
   std::string IncludeIsMainSourceRegex;
 
+  /// Available sort keys that can be used to sort includes in each block.
+  enum IncludeSortKeyDiscriminator : int8_t {
+/// Includes are sorted alphabetically by their full path.
+ISK_Path,
+/// Includes are sorted alphabetically by their full path without the
+/// file extension.
+ISK_Stem,
+  };
+
+  /// When sorting includes in each block, sort by the specified sort key.
+  /// \version 21
+  IncludeSortKeyDiscriminator IncludeSortKey;
+
   /// Character to consider in the include directives for the main header.
   enum MainIncludeCharDiscriminator : int8_t {
 /// Main include uses quotes: ``#include "foo.hpp"`` (the default).
@@ -197,6 +210,14 @@ struct ScalarEnumerationTraits<
   clang::tooling::IncludeStyle::MainIncludeCharDiscriminator &Value);
 };
 
+template <>
+struct ScalarEnumerationTraits<
+clang::tooling::IncludeStyle::IncludeSortKeyDiscriminator> {
+  static void
+  enumeration(IO &IO,
+  clang::tooling::IncludeStyle::IncludeSortKeyDiscriminator 
&Value);
+};
+
 } // namespace yaml
 } // namespace llvm
 
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 5a1c3f556b331..6423166fc3c44 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1062,6 +1062,7 @@ template <> struct MappingTraits {
 IO.mapOptional("IncludeIsMainRegex", 
Style.IncludeStyle.IncludeIsMainRegex);
 IO.mapOptional("IncludeIsMainSourceRegex",
Style.IncludeStyle.IncludeIsMainSourceRegex);
+IO.mapOptional("IncludeSortKey", Style.IncludeStyle

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-12 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

Ping @owenca @HazardyKnusperkeks 

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] include-cleaner: Report function decls from __cleanup__ as used (PR #138669)

2025-05-12 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

Ping @llvm/pr-subscribers-clangd @kadircet 

https://github.com/llvm/llvm-project/pull/138669
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-13 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

> I would expect that file extensions be sorted regardless. For example:
> 
> ```
> #include "a.h"
> #include "a.inc"
> #include "a-util.def"
> #include "a-util.h"
> ```

Addressed

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-13 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] include-cleaner: Report function decls from __cleanup__ as used (PR #138669)

2025-05-13 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

@kadircet Can you merge this for me? I got rid of my contributor access as I 
don't contribute enough to justify having it.

https://github.com/llvm/llvm-project/pull/138669
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-include-cleaner] Make cleanup attr report expr location (PR #140233)

2025-05-16 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/140233

Instead of reporting the location of the attribute, let's report the location 
of the function reference that's passed to the cleanup attribute as the first 
argument. This is required as the attribute might be coming from a macro which 
means clang-include-cleaner skips the use as it gets attributed to the header 
file declaringt the macro and not to the main file.

To make this work, we have to add a fake argument to the CleanupAttr 
constructor so we can pass in the original Expr alongside the function 
declaration.

Fixes #140212

>From e430624ff48b4f64d110dcadae321a69e1ecc039 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Fri, 16 May 2025 12:08:47 +0200
Subject: [PATCH] [clang-include-cleaner] Make cleanup attr report expr
 location

Instead of reporting the location of the attribute, let's report
the location of the function reference that's passed to the cleanup
attribute as the first argument. This is required as the attribute
might be coming from a macro which means clang-include-cleaner skips
the use as it gets attributed to the header file declaringt the macro
and not to the main file.

To make this work, we have to add a fake argument to the CleanupAttr
constructor so we can pass in the original Expr alongside the function
declaration.

Fixes #140212
---
 clang-tools-extra/include-cleaner/lib/WalkAST.cpp   | 2 +-
 clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp | 2 +-
 clang/include/clang/Basic/Attr.td   | 6 --
 clang/lib/Sema/SemaDeclAttr.cpp | 2 +-
 4 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp 
b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index ba6eff49e9c98..a6f2559dd8e93 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -322,7 +322,7 @@ class ASTWalker : public RecursiveASTVisitor {
   }
 
   bool VisitCleanupAttr(CleanupAttr *attr) {
-report(attr->getLocation(), attr->getFunctionDecl());
+report(attr->getExpr()->getExprLoc(), attr->getFunctionDecl());
 return true;
   }
 
diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp 
b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
index 19695a34bd63e..0de0b77f33daf 100644
--- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -573,7 +573,7 @@ TEST(WalkAST, OperatorNewDelete) {
 
 TEST(WalkAST, CleanupAttr) {
   testWalk("void* $explicit^freep(void *p);",
-   "void foo() { __attribute__((^__cleanup__(freep))) char* x = 0; }");
+   "void foo() { __attribute__((__cleanup__(^freep))) char* x = 0; }");
 }
 
 } // namespace
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index ccd13a4cca4dd..e90d18d8435bf 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -226,7 +226,8 @@ class BoolArgument 
: Argument : Argument;
 class IntArgument : Argument;
 class StringArgument : Argument;
-class ExprArgument : Argument;
+class ExprArgument : Argument;
 class DeclArgument
 : Argument {
   DeclNode Kind = kind;
@@ -1351,7 +1352,8 @@ def OSConsumesThis : InheritableAttr {
 
 def Cleanup : InheritableAttr {
   let Spellings = [GCC<"cleanup">];
-  let Args = [DeclArgument];
+  let Args = [DeclArgument,
+  ExprArgument<"Expr", /*fake=*/1>];
   let Subjects = SubjectList<[LocalVar]>;
   let Documentation = [CleanupDocs];
 }
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 377595639bef1..6b1a42bcc392f 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3620,7 +3620,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const 
ParsedAttr &AL) {
 return;
   }
 
-  D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD));
+  D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD, E));
 }
 
 static void handleEnumExtensibilityAttr(Sema &S, Decl *D,

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-20 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

@kadircet Can you land this one as well?

(Feel free to give me back the commit bit if that's in your power if you want 
me to land stuff myself after review)

https://github.com/llvm/llvm-project/pull/140600
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140600

>From 0e6f4f49197748d470c8839e6c3117fad35adbfa Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 19 May 2025 21:39:32 +0200
Subject: [PATCH] [clang-tidy] Add UnusedIncludes/MissingIncludes options to
 misc-include-cleaner

These mimick the same options from clangd and allow using the check to
only check for unused includes or missing includes.
---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   | 77 +++
 .../clang-tidy/misc/IncludeCleanerCheck.h |  4 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  7 +-
 .../checks/misc/include-cleaner.rst   | 11 +++
 .../clang-tidy/IncludeCleanerTest.cpp | 58 ++
 5 files changed, 124 insertions(+), 33 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc103d16..52a94f3c040aa 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
 : ClangTidyCheck(Name, Context),
   IgnoreHeaders(
   utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
-  DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+  DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+  UnusedIncludes(Options.get("UnusedIncludes", true)),
+  MissingIncludes(Options.get("MissingIncludes", true)) {
   for (const auto &Header : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
   HeaderSuffix += "$";
 IgnoreHeadersRegex.emplace_back(HeaderSuffix);
   }
+
+  if (UnusedIncludes == false && MissingIncludes == false)
+this->configurationDiag("The check 'misc-include-cleaner' will not "
+"perform any analysis because 'UnusedIncludes' and 
"
+"'MissingIncludes' are both false.");
 }
 
 void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));
   Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+  Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+  Options.store(Opts, "MissingIncludes", MissingIncludes);
 }
 
 bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult &Result) {
   if (!FileStyle)
 FileStyle = format::getLLVMStyle();
 
-  for (const auto *Inc : Unused) {
-diag(Inc->HashLocation, "included header %0 is not used directly")
-<< llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
-<< FixItHint::CreateRemoval(CharSourceRange::getCharRange(
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+  if (UnusedIncludes) {
+for (const auto *Inc : Unused) {
+  diag(Inc->HashLocation, "included header %0 is not used directly")
+  << llvm::sys::path::filename(Inc->Spelled,
+   llvm::sys::path::Style::posix)
+  << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+}
   }
 
-  tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
-  // Deduplicate insertions when running in bulk fix mode.
-  llvm::StringSet<> InsertedHeaders{};
-  for (const auto &Inc : Missing) {
-std::string Spelling = include_cleaner::spellHeader(
-{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
-bool Angled = llvm::StringRef{Spelling}.starts_with("<");
-// We might suggest insertion of an existing include in edge cases, e.g.,
-// include is present in a PP-disabled region, or spelling of the header
-// turns out to be the same as one of the unresolved includes in the
-// main file.
-if (auto Replacement =
-HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include)) 
{
-  DiagnosticBuilder DB =
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name();
-  if (areDiagsSelfContained() ||
-  InsertedHeaders.insert(Replacement->getReplacementText()).second) {
-DB << FixItHint::CreateInsertion(
- 

[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140600

>From 900e6b24fb244d9034cdf81f337dd457a451b915 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 19 May 2025 21:39:32 +0200
Subject: [PATCH] [clang-tidy] Add UnusedIncludes/MissingIncludes options to
 misc-include-cleaner

These mimick the same options from clangd and allow using the check to
only check for unused includes or missing includes.
---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   | 77 +++
 .../clang-tidy/misc/IncludeCleanerCheck.h |  4 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  7 +-
 .../checks/misc/include-cleaner.rst   | 11 +++
 .../misc/include-cleaner-wrong-config.cpp | 13 
 .../clang-tidy/IncludeCleanerTest.cpp | 58 ++
 6 files changed, 137 insertions(+), 33 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner-wrong-config.cpp

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc103d16..52a94f3c040aa 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
 : ClangTidyCheck(Name, Context),
   IgnoreHeaders(
   utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
-  DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+  DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+  UnusedIncludes(Options.get("UnusedIncludes", true)),
+  MissingIncludes(Options.get("MissingIncludes", true)) {
   for (const auto &Header : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
   HeaderSuffix += "$";
 IgnoreHeadersRegex.emplace_back(HeaderSuffix);
   }
+
+  if (UnusedIncludes == false && MissingIncludes == false)
+this->configurationDiag("The check 'misc-include-cleaner' will not "
+"perform any analysis because 'UnusedIncludes' and 
"
+"'MissingIncludes' are both false.");
 }
 
 void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));
   Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+  Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+  Options.store(Opts, "MissingIncludes", MissingIncludes);
 }
 
 bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult &Result) {
   if (!FileStyle)
 FileStyle = format::getLLVMStyle();
 
-  for (const auto *Inc : Unused) {
-diag(Inc->HashLocation, "included header %0 is not used directly")
-<< llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
-<< FixItHint::CreateRemoval(CharSourceRange::getCharRange(
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+  if (UnusedIncludes) {
+for (const auto *Inc : Unused) {
+  diag(Inc->HashLocation, "included header %0 is not used directly")
+  << llvm::sys::path::filename(Inc->Spelled,
+   llvm::sys::path::Style::posix)
+  << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+}
   }
 
-  tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
-  // Deduplicate insertions when running in bulk fix mode.
-  llvm::StringSet<> InsertedHeaders{};
-  for (const auto &Inc : Missing) {
-std::string Spelling = include_cleaner::spellHeader(
-{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
-bool Angled = llvm::StringRef{Spelling}.starts_with("<");
-// We might suggest insertion of an existing include in edge cases, e.g.,
-// include is present in a PP-disabled region, or spelling of the header
-// turns out to be the same as one of the unresolved includes in the
-// main file.
-if (auto Replacement =
-HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include)) 
{
-  DiagnosticBuilder DB =
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name();
-  

[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140600

>From 5f4601e6cfa185a6eacb044a9cfbd88008df60ea Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 19 May 2025 21:39:32 +0200
Subject: [PATCH] [clang-tidy] Add UnusedIncludes/MissingIncludes options to
 misc-include-cleaner

These mimick the same options from clangd and allow using the check to
only check for unused includes or missing includes.
---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   | 77 +++
 .../clang-tidy/misc/IncludeCleanerCheck.h |  4 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  7 +-
 .../checks/misc/include-cleaner.rst   | 11 +++
 .../clang-tidy/IncludeCleanerTest.cpp | 58 ++
 5 files changed, 124 insertions(+), 33 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc103d16..52a94f3c040aa 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
 : ClangTidyCheck(Name, Context),
   IgnoreHeaders(
   utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
-  DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+  DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+  UnusedIncludes(Options.get("UnusedIncludes", true)),
+  MissingIncludes(Options.get("MissingIncludes", true)) {
   for (const auto &Header : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
   HeaderSuffix += "$";
 IgnoreHeadersRegex.emplace_back(HeaderSuffix);
   }
+
+  if (UnusedIncludes == false && MissingIncludes == false)
+this->configurationDiag("The check 'misc-include-cleaner' will not "
+"perform any analysis because 'UnusedIncludes' and 
"
+"'MissingIncludes' are both false.");
 }
 
 void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));
   Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+  Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+  Options.store(Opts, "MissingIncludes", MissingIncludes);
 }
 
 bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult &Result) {
   if (!FileStyle)
 FileStyle = format::getLLVMStyle();
 
-  for (const auto *Inc : Unused) {
-diag(Inc->HashLocation, "included header %0 is not used directly")
-<< llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
-<< FixItHint::CreateRemoval(CharSourceRange::getCharRange(
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+  if (UnusedIncludes) {
+for (const auto *Inc : Unused) {
+  diag(Inc->HashLocation, "included header %0 is not used directly")
+  << llvm::sys::path::filename(Inc->Spelled,
+   llvm::sys::path::Style::posix)
+  << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+}
   }
 
-  tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
-  // Deduplicate insertions when running in bulk fix mode.
-  llvm::StringSet<> InsertedHeaders{};
-  for (const auto &Inc : Missing) {
-std::string Spelling = include_cleaner::spellHeader(
-{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
-bool Angled = llvm::StringRef{Spelling}.starts_with("<");
-// We might suggest insertion of an existing include in edge cases, e.g.,
-// include is present in a PP-disabled region, or spelling of the header
-// turns out to be the same as one of the unresolved includes in the
-// main file.
-if (auto Replacement =
-HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include)) 
{
-  DiagnosticBuilder DB =
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name();
-  if (areDiagsSelfContained() ||
-  InsertedHeaders.insert(Replacement->getReplacementText()).second) {
-DB << FixItHint::CreateInsertion(
- 

[clang-tools-extra] [clang-tools-extra] Add include mappings for getopt.h (PR #140726)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/140726

None

>From 6345651bcbcee651922b04121662763e4cec48a3 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 20 May 2025 15:05:21 +0200
Subject: [PATCH] [clang-tools-extra] Add include mappings for getopt.h

---
 .../find-all-symbols/STLPostfixHeaderMap.cpp   | 3 +++
 clang-tools-extra/clangd/index/CanonicalIncludes.cpp   | 3 +++
 2 files changed, 6 insertions(+)

diff --git 
a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
 
b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
index 469323f0ee9d7..5b6919d446304 100644
--- 
a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
+++ 
b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
@@ -606,6 +606,9 @@ const HeaderMapCollector::RegexHeaderMap 
*getSTLPostfixHeaderMap() {
   {"sys/xattr.h$", ""},
   {"bits/epoll.h$", ""},
   {"bits/eventfd.h$", ""},
+  {"bits/getopt_core.h$", ""},
+  {"bits/getopt_ext.h$", ""},
+  {"bits/getopt_posix.h$", ""},
   {"bits/inotify.h$", ""},
   {"bits/ipc.h$", ""},
   {"bits/ipctypes.h$", ""},
diff --git a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp 
b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
index 785ec4086ea76..e3518e9beb6d2 100644
--- a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
+++ b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
@@ -621,6 +621,9 @@ const std::pair 
IncludeMappings[] = {
 {"sys/xattr.h", ""},
 {"bits/epoll.h", ""},
 {"bits/eventfd.h", ""},
+{"bits/getopt_core.h", ""},
+{"bits/getopt_ext.h", ""},
+{"bits/getopt_posix.h", ""},
 {"bits/inotify.h", ""},
 {"bits/ipc.h", ""},
 {"bits/ipctypes.h", ""},

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tools-extra] Add include mappings for getopt.h (PR #140726)

2025-05-20 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

@kadircet Do you know if either of these two mappings get used by 
clang-include-cleaner? I couldn't find out where it does the mapping from glibc 
internal headers to public ones.

https://github.com/llvm/llvm-project/pull/140726
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tools-extra] Add include mappings for (PR #140755)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/140755

None

>From 2f84d866f97d5bb378327e102105e214803cec56 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 20 May 2025 18:16:36 +0200
Subject: [PATCH] [clang-tools-extra] Add include mappings for 

---
 .../clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp | 1 +
 clang-tools-extra/clangd/index/CanonicalIncludes.cpp | 1 +
 2 files changed, 2 insertions(+)

diff --git 
a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
 
b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
index 469323f0ee9d7..81db67d965754 100644
--- 
a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
+++ 
b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
@@ -654,6 +654,7 @@ const HeaderMapCollector::RegexHeaderMap 
*getSTLPostfixHeaderMap() {
   {"bits/syscall.h$", ""},
   {"bits/syslog-path.h$", ""},
   {"bits/termios.h$", ""},
+  {"bits/timex.h$", ""},
   {"bits/types.h$", ""},
   {"bits/typesizes.h$", ""},
   {"bits/uio.h$", ""},
diff --git a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp 
b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
index 785ec4086ea76..d0a351df2a2ee 100644
--- a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
+++ b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
@@ -669,6 +669,7 @@ const std::pair 
IncludeMappings[] = {
 {"bits/syscall.h", ""},
 {"bits/syslog-path.h", ""},
 {"bits/termios.h", ""},
+{"bits/timex.h", ""},
 {"bits/types.h", ""},
 {"bits/types/siginfo_t.h", ""},
 {"bits/types/struct_itimerspec.h", ""},

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140600

>From e68b81b128fd1c8a6fb7a462d0e610c4a7dcfa6a Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 19 May 2025 21:39:32 +0200
Subject: [PATCH] [clang-tidy] Add UnusedIncludes/MissingIncludes options to
 misc-include-cleaner

These mimick the same options from clangd and allow using the check to
only check for unused includes or missing includes.
---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   | 78 +++
 .../clang-tidy/misc/IncludeCleanerCheck.h |  4 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/misc/include-cleaner.rst   | 13 +++-
 .../clang-tidy/IncludeCleanerTest.cpp | 58 ++
 5 files changed, 125 insertions(+), 33 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc103d16..b59b15e4617eb 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
 : ClangTidyCheck(Name, Context),
   IgnoreHeaders(
   utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
-  DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+  DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+  UnusedIncludes(Options.get("UnusedIncludes", true)),
+  MissingIncludes(Options.get("MissingIncludes", true)) {
   for (const auto &Header : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -68,12 +70,20 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
   HeaderSuffix += "$";
 IgnoreHeadersRegex.emplace_back(HeaderSuffix);
   }
+
+  if (UnusedIncludes == false && MissingIncludes == false)
+this->configurationDiag(
+  "The check 'misc-include-cleaner' will not "
+  "perform any analysis because 'UnusedIncludes' and "
+  "'MissingIncludes' are both false.");
 }
 
 void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));
   Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+  Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+  Options.store(Opts, "MissingIncludes", MissingIncludes);
 }
 
 bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +210,43 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult &Result) {
   if (!FileStyle)
 FileStyle = format::getLLVMStyle();
 
-  for (const auto *Inc : Unused) {
-diag(Inc->HashLocation, "included header %0 is not used directly")
-<< llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
-<< FixItHint::CreateRemoval(CharSourceRange::getCharRange(
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+  if (UnusedIncludes) {
+for (const auto *Inc : Unused) {
+  diag(Inc->HashLocation, "included header %0 is not used directly")
+  << llvm::sys::path::filename(Inc->Spelled,
+   llvm::sys::path::Style::posix)
+  << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+}
   }
 
-  tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
-  // Deduplicate insertions when running in bulk fix mode.
-  llvm::StringSet<> InsertedHeaders{};
-  for (const auto &Inc : Missing) {
-std::string Spelling = include_cleaner::spellHeader(
-{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
-bool Angled = llvm::StringRef{Spelling}.starts_with("<");
-// We might suggest insertion of an existing include in edge cases, e.g.,
-// include is present in a PP-disabled region, or spelling of the header
-// turns out to be the same as one of the unresolved includes in the
-// main file.
-if (auto Replacement =
-HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include)) 
{
-  DiagnosticBuilder DB =
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name();
-  if (areDiagsSelfContained() ||
-  InsertedHeaders.insert(Replacement->getReplacementText()).second) {
-DB << FixItHint::CreateInsertion(
-SM->getComposedLoc(SM->getMai

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From 3cf3ada4cfe78d943815e59f8df9ea74212e76e3 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IgnoreExtension option to
 SortIncludesOptions

Sorting without taking the file extension into account gives nicer results
when various header file names are substrings of other header file names,
for example, a CLI application with a main header named analyze.h and a
analyze-xxx.h header for each subcommand currently will always put analyze.h
last after all the analyze-xxx.h headers, but putting analyze.h first instead
of last is arguable nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting without taking the file extension into account unless two
headers otherwise compare equal by introducing a new boolean option 
IgnoreExtension
for SortIncludesOptions.
---
 clang/docs/ClangFormatStyleOptions.rst  | 10 ++
 clang/include/clang/Format/Format.h | 12 ++-
 clang/lib/Format/Format.cpp | 35 
 clang/unittests/Format/SortIncludesTest.cpp | 36 +
 4 files changed, 79 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..ba17558173e3e 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6010,6 +6010,16 @@ the configuration (without a prefix: ``Auto``).
#include "B/A.h"   #include "B/a.h"
#include "B/a.h"   #include "a/b.h"
 
+  * ``bool IgnoreExtension`` When sorting includes in each block, Only take 
file extensions into
+account if two includes compare equal otherwise.
+
+.. code-block:: c++
+
+   true:  false:
+   # include "A.h" vs.# include "A-util.h"
+   # include "A.inc"  # include "A.h"
+   # include "A-util.h"   # include "A.inc"
+
 
 .. _SortJavaStaticImport:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3ac4318824ac0..667ada10802e1 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4382,8 +4382,18 @@ struct FormatStyle {
 ///#include "B/a.h"   #include "a/b.h"
 /// \endcode
 bool IgnoreCase;
+/// When sorting includes in each block, Only take file extensions into
+/// account if two includes compare equal otherwise.
+/// \code
+///true:  false:
+///# include "A.h" vs.# include "A-util.h"
+///# include "A.inc"  # include "A.h"
+///# include "A-util.h"   # include "A.inc"
+/// \endcode
+bool IgnoreExtension;
 bool operator==(const SortIncludesOptions &R) const {
-  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase;
+  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase &&
+ IgnoreExtension == R.IgnoreExtension;
 }
 bool operator!=(const SortIncludesOptions &R) const {
   return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b41a98ecb5be1..c5f69e6349d71 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1647,7 +1647,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false,
+/*IgnoreExtension=*/false};
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
@@ -3230,19 +3231,27 @@ static void sortCppIncludes(const FormatStyle &Style,
   SmallVector Indices =
   llvm::to_vector<16>(llvm::seq(0, Includes.size()));
 
-  if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) {
+  if (Style.SortIncludes.Enabled) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
-});
-  } else {
-stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, In

[clang-tools-extra] [clang-tools-extra] Add include mappings for (PR #140755)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer closed 
https://github.com/llvm/llvm-project/pull/140755
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140600

>From 371cbcd352d1fc7031a4f30f40eb5f515dc03e50 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 19 May 2025 21:39:32 +0200
Subject: [PATCH] [clang-tidy] Add UnusedIncludes/MissingIncludes options to
 misc-include-cleaner

These mimick the same options from clangd and allow using the check to
only check for unused includes or missing includes.
---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   | 77 +++
 .../clang-tidy/misc/IncludeCleanerCheck.h |  4 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/misc/include-cleaner.rst   | 13 +++-
 .../clang-tidy/IncludeCleanerTest.cpp | 58 ++
 5 files changed, 124 insertions(+), 33 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc103d16..52a94f3c040aa 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
 : ClangTidyCheck(Name, Context),
   IgnoreHeaders(
   utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
-  DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+  DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+  UnusedIncludes(Options.get("UnusedIncludes", true)),
+  MissingIncludes(Options.get("MissingIncludes", true)) {
   for (const auto &Header : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
   HeaderSuffix += "$";
 IgnoreHeadersRegex.emplace_back(HeaderSuffix);
   }
+
+  if (UnusedIncludes == false && MissingIncludes == false)
+this->configurationDiag("The check 'misc-include-cleaner' will not "
+"perform any analysis because 'UnusedIncludes' and 
"
+"'MissingIncludes' are both false.");
 }
 
 void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));
   Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+  Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+  Options.store(Opts, "MissingIncludes", MissingIncludes);
 }
 
 bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult &Result) {
   if (!FileStyle)
 FileStyle = format::getLLVMStyle();
 
-  for (const auto *Inc : Unused) {
-diag(Inc->HashLocation, "included header %0 is not used directly")
-<< llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
-<< FixItHint::CreateRemoval(CharSourceRange::getCharRange(
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+  if (UnusedIncludes) {
+for (const auto *Inc : Unused) {
+  diag(Inc->HashLocation, "included header %0 is not used directly")
+  << llvm::sys::path::filename(Inc->Spelled,
+   llvm::sys::path::Style::posix)
+  << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+}
   }
 
-  tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
-  // Deduplicate insertions when running in bulk fix mode.
-  llvm::StringSet<> InsertedHeaders{};
-  for (const auto &Inc : Missing) {
-std::string Spelling = include_cleaner::spellHeader(
-{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
-bool Angled = llvm::StringRef{Spelling}.starts_with("<");
-// We might suggest insertion of an existing include in edge cases, e.g.,
-// include is present in a PP-disabled region, or spelling of the header
-// turns out to be the same as one of the unresolved includes in the
-// main file.
-if (auto Replacement =
-HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include)) 
{
-  DiagnosticBuilder DB =
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name();
-  if (areDiagsSelfContained() ||
-  InsertedHeaders.insert(Replacement->getReplacementText()).second) {
-DB << FixItHint::CreateInsertion(
-

[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-20 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140600

>From e8916f61952e3d6f041e3682acaee1e266ea1ee4 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 19 May 2025 21:39:32 +0200
Subject: [PATCH] [clang-tidy] Add UnusedIncludes/MissingIncludes options to
 misc-include-cleaner

These mimick the same options from clangd and allow using the check to
only check for unused includes or missing includes.
---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   | 77 +++
 .../clang-tidy/misc/IncludeCleanerCheck.h |  4 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  7 +-
 .../checks/misc/include-cleaner.rst   | 11 +++
 .../misc/include-cleaner-wrong-config.cpp | 10 +++
 .../clang-tidy/IncludeCleanerTest.cpp | 58 ++
 6 files changed, 134 insertions(+), 33 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner-wrong-config.cpp

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc103d16..52a94f3c040aa 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
 : ClangTidyCheck(Name, Context),
   IgnoreHeaders(
   utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
-  DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+  DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+  UnusedIncludes(Options.get("UnusedIncludes", true)),
+  MissingIncludes(Options.get("MissingIncludes", true)) {
   for (const auto &Header : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -68,12 +70,19 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
   HeaderSuffix += "$";
 IgnoreHeadersRegex.emplace_back(HeaderSuffix);
   }
+
+  if (UnusedIncludes == false && MissingIncludes == false)
+this->configurationDiag("The check 'misc-include-cleaner' will not "
+"perform any analysis because 'UnusedIncludes' and 
"
+"'MissingIncludes' are both false.");
 }
 
 void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));
   Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+  Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+  Options.store(Opts, "MissingIncludes", MissingIncludes);
 }
 
 bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +209,43 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult &Result) {
   if (!FileStyle)
 FileStyle = format::getLLVMStyle();
 
-  for (const auto *Inc : Unused) {
-diag(Inc->HashLocation, "included header %0 is not used directly")
-<< llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
-<< FixItHint::CreateRemoval(CharSourceRange::getCharRange(
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+  if (UnusedIncludes) {
+for (const auto *Inc : Unused) {
+  diag(Inc->HashLocation, "included header %0 is not used directly")
+  << llvm::sys::path::filename(Inc->Spelled,
+   llvm::sys::path::Style::posix)
+  << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+}
   }
 
-  tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
-  // Deduplicate insertions when running in bulk fix mode.
-  llvm::StringSet<> InsertedHeaders{};
-  for (const auto &Inc : Missing) {
-std::string Spelling = include_cleaner::spellHeader(
-{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
-bool Angled = llvm::StringRef{Spelling}.starts_with("<");
-// We might suggest insertion of an existing include in edge cases, e.g.,
-// include is present in a PP-disabled region, or spelling of the header
-// turns out to be the same as one of the unresolved includes in the
-// main file.
-if (auto Replacement =
-HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include)) 
{
-  DiagnosticBuilder DB =
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name();
-  i

[clang-tools-extra] [clang-tools-extra] Add include mappings for getopt.h (PR #140726)

2025-05-21 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

> unfortunately neither is used by include-cleaner. we only support mappings 
> for c++ STL, through 
> https://github.com/llvm/llvm-project/blob/main/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
>  and friends.
> 
> we didn't want to add any system specific libraries, especially based on file 
> path mappings, because some of these are platform-specific and dependent on 
> the version of the library. Hence we were worried about accuracy.
> 
> you can use `-ignore-headers` to prevent analysis for such headers (e.g. 
> `-ignore-headers=/usr/lib/.*`), or we might actually be more clever in 
> include-cleaner and try to disable these based on system-headerness of a 
> header, but that's also a losing battle since people can have various include 
> search paths in their command line.
> 
> (still happy to land this once you ack the message though, as it should be an 
> improvement for other tools)

Sure, makes sense to me, but yeah, this will still be useful for other tools, 
so feel free to land.

https://github.com/llvm/llvm-project/pull/140726
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format][NFC] Upgrade SortIncludes option to a struct (PR #140497)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer approved this pull request.

Thank you! FWIW, I went over the changes and they all look sensible to me

https://github.com/llvm/llvm-project/pull/140497
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From ab2206d22a9d71df807753f193f4110b191ab77b Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IgnoreExtension option to
 SortIncludesOptions

Sorting without taking the file extension into account gives nicer results
when various header file names are substrings of other header file names,
for example, a CLI application with a main header named analyze.h and a
analyze-xxx.h header for each subcommand currently will always put analyze.h
last after all the analyze-xxx.h headers, but putting analyze.h first instead
of last is arguable nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting without taking the file extension into account unless two
headers otherwise compare equal by introducing a new boolean option 
IgnoreExtension
for SortIncludesOptions.
---
 clang/docs/ClangFormatStyleOptions.rst  |  3 ++
 clang/include/clang/Format/Format.h | 11 ++-
 clang/lib/Format/Format.cpp | 34 +
 clang/unittests/Format/SortIncludesTest.cpp | 20 
 4 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..18095cc09afbe 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6010,6 +6010,9 @@ the configuration (without a prefix: ``Auto``).
#include "B/A.h"   #include "B/a.h"
#include "B/a.h"   #include "a/b.h"
 
+  * ``bool IgnoreExtension`` :versionbadge:`clang-format 21`
+  When sorting includes in each block, ignore file extensions.
+
 
 .. _SortJavaStaticImport:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3ac4318824ac0..18e314426c1ae 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4382,8 +4382,17 @@ struct FormatStyle {
 ///#include "B/a.h"   #include "a/b.h"
 /// \endcode
 bool IgnoreCase;
+/// When sorting includes in each block, Only take file extensions into
+/// account if two includes compare equal otherwise.
+/// \code
+///true:  false:
+///# include "A.h" # include "A-util.h"
+///# include "A.inc"   # include "A.h"
+///# include "A-util.h"# include "A.inc"
+/// \version 21
+bool IgnoreExtension;
 bool operator==(const SortIncludesOptions &R) const {
-  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase;
+  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase && 
IgnoreExtension == R.IgnoreExtension;
 }
 bool operator!=(const SortIncludesOptions &R) const {
   return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b41a98ecb5be1..6bf951ff61bf0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
@@ -3230,19 +3230,27 @@ static void sortCppIncludes(const FormatStyle &Style,
   SmallVector Indices =
   llvm::to_vector<16>(llvm::seq(0, Includes.size()));
 
-  if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) {
+  if (Style.SortIncludes.Enabled) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
-});
-  } else {
-stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, Includes[RHSI].Filename);
+  SmallString<128> LHSStem, RHSStem;
+  if (Style.SortIncludes.IgnoreExtension) {
+LHSStem = Includes[LHSI].Filename;
+RHSStem = Includes[RHSI].Filename;
+llvm::sys::path::replace_extension(LHSStem, "");
+llvm::sys::path::replace_extension(R

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

@owenca @HazardyKnusperkeks Rebased onto latest main to take advantage of 
@owenca's rework and addressed comments.

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits


@@ -152,6 +152,10 @@ struct IncludeStyle {
   /// \version 10
   std::string IncludeIsMainSourceRegex;
 
+  /// When sorting includes in each block, ignore file extensions.

DaanDeMeyer wrote:

I added more explanation and added an example

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From 33f84b217caab01a5ebbf93e4e5ac2182810c8db Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IgnoreExtension option to
 SortIncludesOptions

Sorting without taking the file extension into account gives nicer results
when various header file names are substrings of other header file names,
for example, a CLI application with a main header named analyze.h and a
analyze-xxx.h header for each subcommand currently will always put analyze.h
last after all the analyze-xxx.h headers, but putting analyze.h first instead
of last is arguable nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting without taking the file extension into account unless two
headers otherwise compare equal by introducing a new boolean option 
IgnoreExtension
for SortIncludesOptions.
---
 clang/docs/ClangFormatStyleOptions.rst  | 11 +++
 clang/include/clang/Format/Format.h | 11 ++-
 clang/lib/Format/Format.cpp | 34 +
 clang/unittests/Format/SortIncludesTest.cpp | 20 
 4 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..8ec658ef4b855 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6010,6 +6010,17 @@ the configuration (without a prefix: ``Auto``).
#include "B/A.h"   #include "B/a.h"
#include "B/a.h"   #include "a/b.h"
 
+  * ``bool IgnoreExtension`` :versionbadge:`clang-format 21`
+  When sorting includes in each block, Only take file extensions into
+account if two includes compare equal otherwise.
+
+.. code-block:: c++
+
+   true:  false:
+   # include "A.h" # include "A-util.h"
+   # include "A.inc"   # include "A.h"
+   # include "A-util.h"# include "A.inc"
+
 
 .. _SortJavaStaticImport:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3ac4318824ac0..18e314426c1ae 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4382,8 +4382,17 @@ struct FormatStyle {
 ///#include "B/a.h"   #include "a/b.h"
 /// \endcode
 bool IgnoreCase;
+/// When sorting includes in each block, Only take file extensions into
+/// account if two includes compare equal otherwise.
+/// \code
+///true:  false:
+///# include "A.h" # include "A-util.h"
+///# include "A.inc"   # include "A.h"
+///# include "A-util.h"# include "A.inc"
+/// \version 21
+bool IgnoreExtension;
 bool operator==(const SortIncludesOptions &R) const {
-  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase;
+  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase && 
IgnoreExtension == R.IgnoreExtension;
 }
 bool operator!=(const SortIncludesOptions &R) const {
   return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b41a98ecb5be1..6bf951ff61bf0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
@@ -3230,19 +3230,27 @@ static void sortCppIncludes(const FormatStyle &Style,
   SmallVector Indices =
   llvm::to_vector<16>(llvm::seq(0, Includes.size()));
 
-  if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) {
+  if (Style.SortIncludes.Enabled) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
-});
-  } else {
-stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, Include

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From beab0ecdeda1454de56cf1851dc03dda6d02673e Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IgnoreExtension option to
 SortIncludesOptions

Sorting without taking the file extension into account gives nicer results
when various header file names are substrings of other header file names,
for example, a CLI application with a main header named analyze.h and a
analyze-xxx.h header for each subcommand currently will always put analyze.h
last after all the analyze-xxx.h headers, but putting analyze.h first instead
of last is arguable nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting without taking the file extension into account unless two
headers otherwise compare equal by introducing a new boolean option 
IgnoreExtension
for SortIncludesOptions.
---
 clang/docs/ClangFormatStyleOptions.rst  | 11 +++
 clang/include/clang/Format/Format.h | 12 +++-
 clang/lib/Format/Format.cpp | 34 +
 clang/unittests/Format/SortIncludesTest.cpp | 20 
 4 files changed, 63 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..8ec658ef4b855 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6010,6 +6010,17 @@ the configuration (without a prefix: ``Auto``).
#include "B/A.h"   #include "B/a.h"
#include "B/a.h"   #include "a/b.h"
 
+  * ``bool IgnoreExtension`` :versionbadge:`clang-format 21`
+  When sorting includes in each block, Only take file extensions into
+account if two includes compare equal otherwise.
+
+.. code-block:: c++
+
+   true:  false:
+   # include "A.h" # include "A-util.h"
+   # include "A.inc"   # include "A.h"
+   # include "A-util.h"# include "A.inc"
+
 
 .. _SortJavaStaticImport:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3ac4318824ac0..fba16897b133a 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4382,8 +4382,18 @@ struct FormatStyle {
 ///#include "B/a.h"   #include "a/b.h"
 /// \endcode
 bool IgnoreCase;
+/// When sorting includes in each block, Only take file extensions into
+/// account if two includes compare equal otherwise.
+/// \code
+///true:  false:
+///# include "A.h" # include "A-util.h"
+///# include "A.inc"   # include "A.h"
+///# include "A-util.h"# include "A.inc"
+/// \endcode
+/// \version 21
+bool IgnoreExtension;
 bool operator==(const SortIncludesOptions &R) const {
-  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase;
+  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase && 
IgnoreExtension == R.IgnoreExtension;
 }
 bool operator!=(const SortIncludesOptions &R) const {
   return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b41a98ecb5be1..6bf951ff61bf0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
@@ -3230,19 +3230,27 @@ static void sortCppIncludes(const FormatStyle &Style,
   SmallVector Indices =
   llvm::to_vector<16>(llvm::seq(0, Includes.size()));
 
-  if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) {
+  if (Style.SortIncludes.Enabled) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
-});
-  } else {
-stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Includes[RHSI

[clang] [clang-tools-extra] [clang-include-cleaner] Make cleanup attr report expr location (PR #140233)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140233

>From 75b6d33d0b46a4d3eaf794afc9224bcef9434cb9 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Fri, 16 May 2025 12:08:47 +0200
Subject: [PATCH] [clang-include-cleaner] Make cleanup attr report expr
 location

Instead of reporting the location of the attribute, let's report
the location of the function reference that's passed to the cleanup
attribute as the first argument. This is required as the attribute
might be coming from a macro which means clang-include-cleaner skips
the use as it gets attributed to the header file declaringt the macro
and not to the main file.

To make this work, we have to add a fake argument to the CleanupAttr
constructor so we can pass in the original Expr alongside the function
declaration.

Fixes #140212
---
 clang-tools-extra/include-cleaner/lib/WalkAST.cpp   | 2 +-
 clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp | 2 +-
 clang/include/clang/Basic/Attr.td   | 6 --
 clang/lib/Sema/SemaDeclAttr.cpp | 2 +-
 4 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp 
b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index ba6eff49e9c98..a6f2559dd8e93 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -322,7 +322,7 @@ class ASTWalker : public RecursiveASTVisitor {
   }
 
   bool VisitCleanupAttr(CleanupAttr *attr) {
-report(attr->getLocation(), attr->getFunctionDecl());
+report(attr->getExpr()->getExprLoc(), attr->getFunctionDecl());
 return true;
   }
 
diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp 
b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
index 19695a34bd63e..0de0b77f33daf 100644
--- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -573,7 +573,7 @@ TEST(WalkAST, OperatorNewDelete) {
 
 TEST(WalkAST, CleanupAttr) {
   testWalk("void* $explicit^freep(void *p);",
-   "void foo() { __attribute__((^__cleanup__(freep))) char* x = 0; }");
+   "void foo() { __attribute__((__cleanup__(^freep))) char* x = 0; }");
 }
 
 } // namespace
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index a6a7482a94a29..96a88089a47a2 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -226,7 +226,8 @@ class BoolArgument 
: Argument : Argument;
 class IntArgument : Argument;
 class StringArgument : Argument;
-class ExprArgument : Argument;
+class ExprArgument : Argument;
 class DeclArgument
 : Argument {
   DeclNode Kind = kind;
@@ -1351,7 +1352,8 @@ def OSConsumesThis : InheritableAttr {
 
 def Cleanup : InheritableAttr {
   let Spellings = [GCC<"cleanup">];
-  let Args = [DeclArgument];
+  let Args = [DeclArgument,
+  ExprArgument<"Expr", /*opt=*/0, /*fake=*/1>];
   let Subjects = SubjectList<[LocalVar]>;
   let Documentation = [CleanupDocs];
 }
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 4d7f0455444f1..cbd75124478df 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3620,7 +3620,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const 
ParsedAttr &AL) {
 return;
   }
 
-  D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD));
+  D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD, E));
 }
 
 static void handleEnumExtensibilityAttr(Sema &S, Decl *D,

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-include-cleaner] Make cleanup attr report expr location (PR #140233)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140233

>From 736ab4d98adcdc4ec21639f59f5b1307ce678303 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Fri, 16 May 2025 12:08:47 +0200
Subject: [PATCH] [clang-include-cleaner] Make cleanup attr report expr
 location

Instead of reporting the location of the attribute, let's report
the location of the function reference that's passed to the cleanup
attribute as the first argument. This is required as the attribute
might be coming from a macro which means clang-include-cleaner skips
the use as it gets attributed to the header file declaringt the macro
and not to the main file.

To make this work, we have to add a fake argument to the CleanupAttr
constructor so we can pass in the original Expr alongside the function
declaration.

Fixes #140212
---
 .../include-cleaner/lib/WalkAST.cpp   |  2 +-
 .../include-cleaner/unittests/WalkASTTest.cpp |  2 +-
 clang/include/clang/Basic/Attr.td |  6 ++--
 clang/lib/Sema/SemaDeclAttr.cpp   |  2 +-
 clang/test/AST/ast-dump-attr-json.cpp | 32 ++-
 5 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp 
b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index ba6eff49e9c98..a6f2559dd8e93 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -322,7 +322,7 @@ class ASTWalker : public RecursiveASTVisitor {
   }
 
   bool VisitCleanupAttr(CleanupAttr *attr) {
-report(attr->getLocation(), attr->getFunctionDecl());
+report(attr->getExpr()->getExprLoc(), attr->getFunctionDecl());
 return true;
   }
 
diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp 
b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
index 19695a34bd63e..0de0b77f33daf 100644
--- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -573,7 +573,7 @@ TEST(WalkAST, OperatorNewDelete) {
 
 TEST(WalkAST, CleanupAttr) {
   testWalk("void* $explicit^freep(void *p);",
-   "void foo() { __attribute__((^__cleanup__(freep))) char* x = 0; }");
+   "void foo() { __attribute__((__cleanup__(^freep))) char* x = 0; }");
 }
 
 } // namespace
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index a6a7482a94a29..96a88089a47a2 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -226,7 +226,8 @@ class BoolArgument 
: Argument : Argument;
 class IntArgument : Argument;
 class StringArgument : Argument;
-class ExprArgument : Argument;
+class ExprArgument : Argument;
 class DeclArgument
 : Argument {
   DeclNode Kind = kind;
@@ -1351,7 +1352,8 @@ def OSConsumesThis : InheritableAttr {
 
 def Cleanup : InheritableAttr {
   let Spellings = [GCC<"cleanup">];
-  let Args = [DeclArgument];
+  let Args = [DeclArgument,
+  ExprArgument<"Expr", /*opt=*/0, /*fake=*/1>];
   let Subjects = SubjectList<[LocalVar]>;
   let Documentation = [CleanupDocs];
 }
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 4d7f0455444f1..cbd75124478df 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3620,7 +3620,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const 
ParsedAttr &AL) {
 return;
   }
 
-  D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD));
+  D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD, E));
 }
 
 static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
diff --git a/clang/test/AST/ast-dump-attr-json.cpp 
b/clang/test/AST/ast-dump-attr-json.cpp
index 883e584bfedf0..a78e2293af654 100644
--- a/clang/test/AST/ast-dump-attr-json.cpp
+++ b/clang/test/AST/ast-dump-attr-json.cpp
@@ -149,7 +149,37 @@ __thread __attribute__ ((tls_model ("local-exec"))) int 
tls_model_var;
 // CHECK-NEXT: "type": {
 // CHECK-NEXT:  "qualType": "void (int *)"
 // CHECK-NEXT: }
-// CHECK-NEXT:}
+// CHECK-NEXT:},
+// CHECK-NEXT:"inner": [
+// CHECK-NEXT: {
+// CHECK-NEXT:   "id": "0x{{.*}}",
+// CHECK-NEXT:   "kind": "DeclRefExpr",
+// CHECK-NEXT:   "range": {
+// CHECK-NEXT: "begin": {
+// CHECK-NEXT:   "offset": 242,
+// CHECK-NEXT:   "col": 26,
+// CHECK-NEXT:   "tokLen": 16
+// CHECK-NEXT: },
+// CHECK-NEXT: "end": {
+// CHECK-NEXT:   "offset": 242,
+// CHECK-NEXT:   "col": 26,
+// CHECK-NEXT:   "tokLen": 16
+// CHECK-NEXT: }
+// CHECK-NEXT:   },
+// CHECK-NEXT:   "type": {
+// CHECK-NEXT: "qualType": "void (int *)"
+// CHECK-NEXT:   },
+// CHECK-NEXT:   "valueCategory": "lvalue",
+// CHECK-NEXT:   "referencedDecl": {
+// CHECK-NEXT: "id": "0x{{.*}}",
+// CHECK-NEXT: "kind": "FunctionDecl",
+// CHECK-NEXT: "name": "clea

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits


@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};

DaanDeMeyer wrote:

@mydeveloperday The default is false, by default, the extension is not ignored.

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From bb5eb380a0f71cac0c734443b4fbfa4441f441b2 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IgnoreExtension option to
 SortIncludesOptions

Sorting without taking the file extension into account gives nicer results
when various header file names are substrings of other header file names,
for example, a CLI application with a main header named analyze.h and a
analyze-xxx.h header for each subcommand currently will always put analyze.h
last after all the analyze-xxx.h headers, but putting analyze.h first instead
of last is arguable nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting without taking the file extension into account unless two
headers otherwise compare equal by introducing a new boolean option 
IgnoreExtension
for SortIncludesOptions.
---
 clang/docs/ClangFormatStyleOptions.rst  | 11 +++
 clang/include/clang/Format/Format.h | 12 ++-
 clang/lib/Format/Format.cpp | 34 +++
 clang/unittests/Format/SortIncludesTest.cpp | 36 +
 4 files changed, 79 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..8ec658ef4b855 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6010,6 +6010,17 @@ the configuration (without a prefix: ``Auto``).
#include "B/A.h"   #include "B/a.h"
#include "B/a.h"   #include "a/b.h"
 
+  * ``bool IgnoreExtension`` :versionbadge:`clang-format 21`
+  When sorting includes in each block, Only take file extensions into
+account if two includes compare equal otherwise.
+
+.. code-block:: c++
+
+   true:  false:
+   # include "A.h" # include "A-util.h"
+   # include "A.inc"   # include "A.h"
+   # include "A-util.h"# include "A.inc"
+
 
 .. _SortJavaStaticImport:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3ac4318824ac0..fba16897b133a 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4382,8 +4382,18 @@ struct FormatStyle {
 ///#include "B/a.h"   #include "a/b.h"
 /// \endcode
 bool IgnoreCase;
+/// When sorting includes in each block, Only take file extensions into
+/// account if two includes compare equal otherwise.
+/// \code
+///true:  false:
+///# include "A.h" # include "A-util.h"
+///# include "A.inc"   # include "A.h"
+///# include "A-util.h"# include "A.inc"
+/// \endcode
+/// \version 21
+bool IgnoreExtension;
 bool operator==(const SortIncludesOptions &R) const {
-  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase;
+  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase && 
IgnoreExtension == R.IgnoreExtension;
 }
 bool operator!=(const SortIncludesOptions &R) const {
   return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b41a98ecb5be1..6bf951ff61bf0 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
@@ -3230,19 +3230,27 @@ static void sortCppIncludes(const FormatStyle &Style,
   SmallVector Indices =
   llvm::to_vector<16>(llvm::seq(0, Includes.size()));
 
-  if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) {
+  if (Style.SortIncludes.Enabled) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
-});
-  } else {
-stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI].Filename) <
- std::tie(Include

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits


@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};

DaanDeMeyer wrote:

@mydeveloperday Huh, I don't see how the length of the basename would affect 
this. I pushed more tests to verify this is the case.

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits


@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};

DaanDeMeyer wrote:

```
#include "A.h"
#include "A-util.h"
#include "A.inc"
```

I don't see how clang-format would ever return this today without disabling 
include sorting? `-` sorts before `.` so `A-util.h` will always be put before 
`A.h` and `A.inc` today if include sorting is enabled.

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-05-19 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

Right I get a feeling I'll have an easier time getting systemd to fully adapt 
clang-format than getting this into clang-format so closing

https://github.com/llvm/llvm-project/pull/137617
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add -disable-format option (PR #137617)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer closed 
https://github.com/llvm/llvm-project/pull/137617
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [include-cleaner] Add --fail-on-changes option (PR #140123)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer closed 
https://github.com/llvm/llvm-project/pull/140123
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [include-cleaner] Add --fail-on-changes option (PR #140123)

2025-05-19 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

I just found misc-include-cleaner in clang-tidy which is a way better fit for 
this so let me close this

https://github.com/llvm/llvm-project/pull/140123
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-include-cleaner] Make cleanup attr report expr location (PR #140233)

2025-05-19 Thread Daan De Meyer via cfe-commits


@@ -1351,7 +1352,8 @@ def OSConsumesThis : InheritableAttr {
 
 def Cleanup : InheritableAttr {
   let Spellings = [GCC<"cleanup">];
-  let Args = [DeclArgument];
+  let Args = [DeclArgument,
+  ExprArgument<"Expr", /*opt=*/0, /*fake=*/1>];

DaanDeMeyer wrote:

(I am very much a drive by contributor and this discussion is making me very 
scared of ever getting this landed :p)

https://github.com/llvm/llvm-project/pull/140233
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-include-cleaner] Make cleanup attr report expr location (PR #140233)

2025-05-19 Thread Daan De Meyer via cfe-commits


@@ -1351,7 +1352,8 @@ def OSConsumesThis : InheritableAttr {
 
 def Cleanup : InheritableAttr {
   let Spellings = [GCC<"cleanup">];
-  let Args = [DeclArgument];
+  let Args = [DeclArgument,
+  ExprArgument<"Expr", /*opt=*/0, /*fake=*/1>];

DaanDeMeyer wrote:

For 1) in handleCleanupAttr there's code to handle the case where the expr is 
not a declrefexpr. How does that work with passing in a DeclRefExpr to 
DeclArgument?

https://github.com/llvm/llvm-project/pull/140233
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/140600

These mimick the same options from clangd and allow using the check to only 
check for unused includes or missing includes.

>From 16d452394b0b7f92321b224de3daca99e929afad Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Mon, 19 May 2025 21:39:32 +0200
Subject: [PATCH] [clang-tidy] Add UnusedIncludes/MissingIncludes options to
 misc-include-cleaner

These mimick the same options from clangd and allow using the check to
only check for unused includes or missing includes.
---
 .../clang-tidy/misc/IncludeCleanerCheck.cpp   | 72 ++-
 .../clang-tidy/misc/IncludeCleanerCheck.h |  4 ++
 .../checks/misc/include-cleaner.rst   | 13 +++-
 .../clang-tidy/IncludeCleanerTest.cpp | 58 +++
 4 files changed, 114 insertions(+), 33 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp 
b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
index 7638bbc103d16..67129e87be22a 100644
--- a/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -59,7 +59,9 @@ IncludeCleanerCheck::IncludeCleanerCheck(StringRef Name,
 : ClangTidyCheck(Name, Context),
   IgnoreHeaders(
   utils::options::parseStringList(Options.get("IgnoreHeaders", ""))),
-  DeduplicateFindings(Options.get("DeduplicateFindings", true)) {
+  DeduplicateFindings(Options.get("DeduplicateFindings", true)),
+  UnusedIncludes(Options.get("UnusedIncludes", true)),
+  MissingIncludes(Options.get("MissingIncludes", true)) {
   for (const auto &Header : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -74,6 +76,8 @@ void 
IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));
   Options.store(Opts, "DeduplicateFindings", DeduplicateFindings);
+  Options.store(Opts, "UnusedIncludes", UnusedIncludes);
+  Options.store(Opts, "MissingIncludes", MissingIncludes);
 }
 
 bool IncludeCleanerCheck::isLanguageVersionSupported(
@@ -200,39 +204,43 @@ void IncludeCleanerCheck::check(const 
MatchFinder::MatchResult &Result) {
   if (!FileStyle)
 FileStyle = format::getLLVMStyle();
 
-  for (const auto *Inc : Unused) {
-diag(Inc->HashLocation, "included header %0 is not used directly")
-<< llvm::sys::path::filename(Inc->Spelled,
- llvm::sys::path::Style::posix)
-<< FixItHint::CreateRemoval(CharSourceRange::getCharRange(
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
-   SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+  if (UnusedIncludes) {
+for (const auto *Inc : Unused) {
+  diag(Inc->HashLocation, "included header %0 is not used directly")
+  << llvm::sys::path::filename(Inc->Spelled,
+   llvm::sys::path::Style::posix)
+  << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
+ SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
+}
   }
 
-  tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
- FileStyle->IncludeStyle);
-  // Deduplicate insertions when running in bulk fix mode.
-  llvm::StringSet<> InsertedHeaders{};
-  for (const auto &Inc : Missing) {
-std::string Spelling = include_cleaner::spellHeader(
-{Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
-bool Angled = llvm::StringRef{Spelling}.starts_with("<");
-// We might suggest insertion of an existing include in edge cases, e.g.,
-// include is present in a PP-disabled region, or spelling of the header
-// turns out to be the same as one of the unresolved includes in the
-// main file.
-if (auto Replacement =
-HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include)) 
{
-  DiagnosticBuilder DB =
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name();
-  if (areDiagsSelfContained() ||
-  InsertedHeaders.insert(Replacement->getReplacementText()).second) {
-DB << FixItHint::CreateInsertion(
-SM->getComposedLoc(SM->getMainFileID(), Replacement->getOffset()),
-Replacement->getReplacementText());
+  if (MissingIncludes) {
+tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
+   FileStyle->IncludeStyle);
+// Deduplicate insertions when running in bulk fix mode.
+llvm

[clang] [clang-tools-extra] [clang-include-cleaner] Make cleanup attr report expr location (PR #140233)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140233

>From 57687d8eebc1f8e2b59ed131791895d76f88e30a Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Fri, 16 May 2025 12:08:47 +0200
Subject: [PATCH] [clang-include-cleaner] Make cleanup attr report expr
 location

Instead of reporting the location of the attribute, let's report
the location of the function reference that's passed to the cleanup
attribute as the first argument. This is required as the attribute
might be coming from a macro which means clang-include-cleaner skips
the use as it gets attributed to the header file declaringt the macro
and not to the main file.

To make this work, we have to add a fake argument to the CleanupAttr
constructor so we can pass in the original Expr alongside the function
declaration.

Fixes #140212
---
 clang-tools-extra/include-cleaner/lib/WalkAST.cpp   |  2 +-
 .../include-cleaner/unittests/WalkASTTest.cpp   |  2 +-
 clang/include/clang/Basic/Attr.td   | 13 -
 clang/lib/Sema/SemaDeclAttr.cpp |  4 +++-
 4 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp 
b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
index ba6eff49e9c98..baff90faa6eae 100644
--- a/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
+++ b/clang-tools-extra/include-cleaner/lib/WalkAST.cpp
@@ -322,7 +322,7 @@ class ASTWalker : public RecursiveASTVisitor {
   }
 
   bool VisitCleanupAttr(CleanupAttr *attr) {
-report(attr->getLocation(), attr->getFunctionDecl());
+report(attr->getArgLoc(), attr->getFunctionDecl());
 return true;
   }
 
diff --git a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp 
b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
index 19695a34bd63e..0de0b77f33daf 100644
--- a/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
+++ b/clang-tools-extra/include-cleaner/unittests/WalkASTTest.cpp
@@ -573,7 +573,7 @@ TEST(WalkAST, OperatorNewDelete) {
 
 TEST(WalkAST, CleanupAttr) {
   testWalk("void* $explicit^freep(void *p);",
-   "void foo() { __attribute__((^__cleanup__(freep))) char* x = 0; }");
+   "void foo() { __attribute__((__cleanup__(^freep))) char* x = 0; }");
 }
 
 } // namespace
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index a6a7482a94a29..06462b8a26bc0 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1354,6 +1354,17 @@ def Cleanup : InheritableAttr {
   let Args = [DeclArgument];
   let Subjects = SubjectList<[LocalVar]>;
   let Documentation = [CleanupDocs];
+  // FIXME: DeclArgument should be reworked to also store the
+  // Expr instead of adding attr specific hacks like the following.
+  // See the discussion in https://github.com/llvm/llvm-project/pull/14023.
+  let AdditionalMembers = [{
+private:
+SourceLocation ArgLoc;
+
+public:
+void setArgLoc(const SourceLocation &Loc) { ArgLoc = Loc; }
+auto getArgLoc() const { return ArgLoc; }
+  }];
 }
 
 def CmseNSEntry : InheritableAttr, TargetSpecificAttr {
@@ -4815,7 +4826,7 @@ def HLSLResourceBinding: InheritableAttr {
   void setImplicitBindingOrderID(uint32_t Value) {
 ImplicitBindingOrderID = Value;
   }
-  bool hasImplicitBindingOrderID() const { 
+  bool hasImplicitBindingOrderID() const {
 return ImplicitBindingOrderID.has_value();
   }
   uint32_t getImplicitBindingOrderID() const {
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 4d7f0455444f1..ac77a7c2c58a5 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3620,7 +3620,9 @@ static void handleCleanupAttr(Sema &S, Decl *D, const 
ParsedAttr &AL) {
 return;
   }
 
-  D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD));
+  auto *attr = ::new (S.Context) CleanupAttr(S.Context, AL, FD);
+  attr->setArgLoc(E->getExprLoc());
+  D->addAttr(attr);
 }
 
 static void handleEnumExtensibilityAttr(Sema &S, Decl *D,

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [clang-include-cleaner] Make cleanup attr report expr location (PR #140233)

2025-05-19 Thread Daan De Meyer via cfe-commits


@@ -1351,7 +1352,8 @@ def OSConsumesThis : InheritableAttr {
 
 def Cleanup : InheritableAttr {
   let Spellings = [GCC<"cleanup">];
-  let Args = [DeclArgument];
+  let Args = [DeclArgument,
+  ExprArgument<"Expr", /*opt=*/0, /*fake=*/1>];

DaanDeMeyer wrote:

@erichkeane @AaronBallman I reworked this to use 2). I had a look at 1) but 
given how thinly stretched I already am, I don't have time to make such a 
change at this time.

https://github.com/llvm/llvm-project/pull/140233
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-19 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840

>From 6a3e7f091fbb8bc7117f5ef1d2803e73b8c6f061 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 29 Apr 2025 18:26:36 +0200
Subject: [PATCH] clang-format: Add IgnoreExtension option to
 SortIncludesOptions

Sorting without taking the file extension into account gives nicer results
when various header file names are substrings of other header file names,
for example, a CLI application with a main header named analyze.h and a
analyze-xxx.h header for each subcommand currently will always put analyze.h
last after all the analyze-xxx.h headers, but putting analyze.h first instead
of last is arguable nicer to read.

TLDR; Instead of

"""
/#include "analyze-blame.h"
/#include "analyze.h"
"""

You'd get

"""
/#include "analyze.h"
/#include "analyze-blame.h"
"""

Let's allow sorting without taking the file extension into account unless two
headers otherwise compare equal by introducing a new boolean option 
IgnoreExtension
for SortIncludesOptions.
---
 clang/docs/ClangFormatStyleOptions.rst  | 11 +++
 clang/include/clang/Format/Format.h | 13 +++-
 clang/lib/Format/Format.cpp | 35 
 clang/unittests/Format/SortIncludesTest.cpp | 36 +
 4 files changed, 81 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index 83716cc049ee3..8ec658ef4b855 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6010,6 +6010,17 @@ the configuration (without a prefix: ``Auto``).
#include "B/A.h"   #include "B/a.h"
#include "B/a.h"   #include "a/b.h"
 
+  * ``bool IgnoreExtension`` :versionbadge:`clang-format 21`
+  When sorting includes in each block, Only take file extensions into
+account if two includes compare equal otherwise.
+
+.. code-block:: c++
+
+   true:  false:
+   # include "A.h" # include "A-util.h"
+   # include "A.inc"   # include "A.h"
+   # include "A-util.h"# include "A.inc"
+
 
 .. _SortJavaStaticImport:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 3ac4318824ac0..6ce0d14a12f31 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4382,8 +4382,19 @@ struct FormatStyle {
 ///#include "B/a.h"   #include "a/b.h"
 /// \endcode
 bool IgnoreCase;
+/// When sorting includes in each block, Only take file extensions into
+/// account if two includes compare equal otherwise.
+/// \code
+///true:  false:
+///# include "A.h" # include "A-util.h"
+///# include "A.inc"   # include "A.h"
+///# include "A-util.h"# include "A.inc"
+/// \endcode
+/// \version 21
+bool IgnoreExtension;
 bool operator==(const SortIncludesOptions &R) const {
-  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase;
+  return Enabled == R.Enabled && IgnoreCase == R.IgnoreCase &&
+ IgnoreExtension == R.IgnoreExtension;
 }
 bool operator!=(const SortIncludesOptions &R) const {
   return !(*this == R);
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b41a98ecb5be1..c5f69e6349d71 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1647,7 +1647,8 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false,
+/*IgnoreExtension=*/false};
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
@@ -3230,19 +3231,27 @@ static void sortCppIncludes(const FormatStyle &Style,
   SmallVector Indices =
   llvm::to_vector<16>(llvm::seq(0, Includes.size()));
 
-  if (Style.SortIncludes.Enabled && Style.SortIncludes.IgnoreCase) {
+  if (Style.SortIncludes.Enabled) {
 stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  const auto LHSFilenameLower = Includes[LHSI].Filename.lower();
-  const auto RHSFilenameLower = Includes[RHSI].Filename.lower();
-  return std::tie(Includes[LHSI].Priority, LHSFilenameLower,
-  Includes[LHSI].Filename) <
- std::tie(Includes[RHSI].Priority, RHSFilenameLower,
-  Includes[RHSI].Filename);
-});
-  } else {
-stable_sort(Indices, [&](unsigned LHSI, unsigned RHSI) {
-  return std::tie(Includes[LHSI].Priority, Includes[LHSI]

[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-27 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

Ping? Would love to get this over the finish line

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-15 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

@owenca Thanks for the detailed review. Changed the name to 
IncludeSortIgnoreExtension, let me know if you have a better idea for the name.

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-15 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/137840



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [include-cleaner] Add --fail-on-changes option (PR #140123)

2025-05-15 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer updated 
https://github.com/llvm/llvm-project/pull/140123



  



Rate limit · GitHub


  body {
background-color: #f6f8fa;
color: #24292e;
font-family: -apple-system,BlinkMacSystemFont,Segoe 
UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol;
font-size: 14px;
line-height: 1.5;
margin: 0;
  }

  .container { margin: 50px auto; max-width: 600px; text-align: center; 
padding: 0 24px; }

  a { color: #0366d6; text-decoration: none; }
  a:hover { text-decoration: underline; }

  h1 { line-height: 60px; font-size: 48px; font-weight: 300; margin: 0px; 
text-shadow: 0 1px 0 #fff; }
  p { color: rgba(0, 0, 0, 0.5); margin: 20px 0 40px; }

  ul { list-style: none; margin: 25px 0; padding: 0; }
  li { display: table-cell; font-weight: bold; width: 1%; }

  .logo { display: inline-block; margin-top: 35px; }
  .logo-img-2x { display: none; }
  @media
  only screen and (-webkit-min-device-pixel-ratio: 2),
  only screen and (   min--moz-device-pixel-ratio: 2),
  only screen and ( -o-min-device-pixel-ratio: 2/1),
  only screen and (min-device-pixel-ratio: 2),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: 2dppx) {
.logo-img-1x { display: none; }
.logo-img-2x { display: inline-block; }
  }

  #suggestions {
margin-top: 35px;
color: #ccc;
  }
  #suggestions a {
color: #66;
font-weight: 200;
font-size: 14px;
margin: 0 10px;
  }


  
  



  Whoa there!
  You have exceeded a secondary rate limit.
Please wait a few minutes before you try again;
in some cases this may take up to an hour.
  
  
https://support.github.com/contact";>Contact Support —
https://githubstatus.com";>GitHub Status —
https://twitter.com/githubstatus";>@githubstatus
  

  

  

  

  

  


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [include-cleaner] Add --fail-on-changes option (PR #140123)

2025-05-15 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/140123

When integrating clang-include-cleaner into a test suite, it's useful to have 
it exit with a nonzero exit status when there are suggested changes to includes 
so let's add --fail-on-changes to make that possible.

>From 6f2a50adf7dc1d559421e83ad9605db96ead6fa6 Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Thu, 15 May 2025 21:07:46 +0200
Subject: [PATCH] [include-cleaner] Add --fail-on-changes option

When integrating clang-include-cleaner into a test suite, it's useful
to have it exit with a nonzero exit status when there are suggested
changes to includes so let's add --fail-on-changes to make that possible.
---
 clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp 
b/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
index 372ab5fa2706e..47e1400d8ccb2 100644
--- a/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ b/clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -115,6 +115,11 @@ cl::opt DisableRemove{
 cl::init(false),
 cl::cat(IncludeCleaner),
 };
+cl::opt FailOnChanges{
+   "fail-on-changes",
+   cl::desc("Exit with a non-zero exit code if changes are suggested"),
+   cl::cat(IncludeCleaner),
+};
 
 std::atomic Errors = ATOMIC_VAR_INIT(0);
 
@@ -410,5 +415,5 @@ int main(int argc, const char **argv) {
   }
 }
   }
-  return ErrorCode || Errors != 0;
+  return ErrorCode || Errors != 0 || (FailOnChanges && 
Factory.editedFiles().size() != 0);
 }

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] clang-format: Add IncludeSortKey option (PR #137840)

2025-05-22 Thread Daan De Meyer via cfe-commits


@@ -1647,7 +1647,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SeparateDefinitionBlocks = FormatStyle::SDS_Leave;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SkipMacroDefinitionBody = false;
-  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false};
+  LLVMStyle.SortIncludes = {/*Enabled=*/true, /*IgnoreCase=*/false, 
/*IgnoreExtension=*/false};

DaanDeMeyer wrote:

I'm very confused now what the suggestion is that I should apply here to make 
everyone happy

https://github.com/llvm/llvm-project/pull/137840
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tools-extra] Add include mappings for (PR #141216)

2025-05-23 Thread Daan De Meyer via cfe-commits

https://github.com/DaanDeMeyer created 
https://github.com/llvm/llvm-project/pull/141216

None

>From a6dd3873ef01268f5466bdeebf2bdcc4c314158e Mon Sep 17 00:00:00 2001
From: Daan De Meyer 
Date: Tue, 20 May 2025 15:46:29 +0200
Subject: [PATCH] [clang-tools-extra] Add include mappings for 

---
 .../clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp | 1 +
 clang-tools-extra/clangd/index/CanonicalIncludes.cpp | 1 +
 2 files changed, 2 insertions(+)

diff --git 
a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
 
b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
index 469323f0ee9d7..480dd204482cf 100644
--- 
a/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
+++ 
b/clang-tools-extra/clang-include-fixer/find-all-symbols/STLPostfixHeaderMap.cpp
@@ -655,6 +655,7 @@ const HeaderMapCollector::RegexHeaderMap 
*getSTLPostfixHeaderMap() {
   {"bits/syslog-path.h$", ""},
   {"bits/termios.h$", ""},
   {"bits/types.h$", ""},
+  {"bits/types/struct_iovec.h$", ""},
   {"bits/typesizes.h$", ""},
   {"bits/uio.h$", ""},
   {"bits/ustat.h$", ""},
diff --git a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp 
b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
index 785ec4086ea76..8ae78eff932fb 100644
--- a/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
+++ b/clang-tools-extra/clangd/index/CanonicalIncludes.cpp
@@ -671,6 +671,7 @@ const std::pair 
IncludeMappings[] = {
 {"bits/termios.h", ""},
 {"bits/types.h", ""},
 {"bits/types/siginfo_t.h", ""},
+{"bits/types/struct_iovec.h", ""},
 {"bits/types/struct_itimerspec.h", ""},
 {"bits/types/struct_rusage.h", ""},
 {"bits/uio.h", ""},

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add UnusedIncludes/MissingIncludes options to misc-include-cleaner (PR #140600)

2025-05-21 Thread Daan De Meyer via cfe-commits

DaanDeMeyer wrote:

@vbvictor Could you merge this one for me now that CI is green? Thanks!

https://github.com/llvm/llvm-project/pull/140600
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits