[clang-tools-extra] [clangd] Add config option to analyze unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 created 
https://github.com/llvm/llvm-project/pull/87208

This PR adds a new `AnalyzeSystemHeaders` option to `Includes` section of 
clangd config. This option will allow to mark all system headers, not just the 
ones from standard library, as unused.

Why this change is useful?
In our codebase all includes from outside of local directory are written with 
angle brackets. For example,
```cpp
// foo.cpp
#include "foo.h"  // main header
#include "foo_utils.h"  // From the same directory
#include   // Other directory, path is relative the 
repository root
#include   // Header from standard library
```

I'd like to use the builtin include-cleaner of clangd to detect unused 
includes, but currently it ignores non-standard system headers

I understand that enabling unused include detection for system headers will 
probably produce some false positives due to lack of support for umbrella 
headers, but they can be filtered out by `IgnoreHeader`. This is not ideal, but 
still better than not having unused include detection for system headers at all.

>From f222e44f5586297ddd61ac0efff4a7115a766c53 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Mon, 1 Apr 2024 01:12:11 +0300
Subject: [PATCH] Add config option to analyze unused system headers

---
 clang-tools-extra/clangd/Config.h |  1 +
 clang-tools-extra/clangd/ConfigCompile.cpp| 56 +++
 clang-tools-extra/clangd/ConfigFragment.h |  4 ++
 clang-tools-extra/clangd/ConfigYAML.cpp   |  4 ++
 clang-tools-extra/clangd/IncludeCleaner.cpp   | 34 +++
 clang-tools-extra/clangd/IncludeCleaner.h | 13 +
 clang-tools-extra/clangd/ParsedAST.cpp|  3 +-
 .../clangd/unittests/ConfigCompileTests.cpp   |  6 ++
 .../clangd/unittests/ConfigYAMLTests.cpp  | 15 +
 .../clangd/unittests/IncludeCleanerTests.cpp  | 15 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 ++
 11 files changed, 110 insertions(+), 45 deletions(-)

diff --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index 4371c80a6c5877..9629854abff31b 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -114,6 +114,7 @@ struct Config {
 /// these regexes.
 struct {
   std::vector> IgnoreHeader;
+  bool AnalyzeSystemHeaders = false;
 } Includes;
   } Diagnostics;
 
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 5bb2eb4a9f803f..570f3cfc3ce2ed 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -572,32 +572,42 @@ struct FragmentCompiler {
 #else
 static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
 #endif
-auto Filters = std::make_shared>();
-for (auto &HeaderPattern : F.IgnoreHeader) {
-  // Anchor on the right.
-  std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
-  llvm::Regex CompiledRegex(AnchoredPattern, Flags);
-  std::string RegexError;
-  if (!CompiledRegex.isValid(RegexError)) {
-diag(Warning,
- llvm::formatv("Invalid regular expression '{0}': {1}",
-   *HeaderPattern, RegexError)
- .str(),
- HeaderPattern.Range);
-continue;
+std::shared_ptr> Filters;
+if (!F.IgnoreHeader.empty()) {
+  Filters = std::make_shared>();
+  for (auto &HeaderPattern : F.IgnoreHeader) {
+// Anchor on the right.
+std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern, Flags);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  diag(Warning,
+   llvm::formatv("Invalid regular expression '{0}': {1}",
+ *HeaderPattern, RegexError)
+   .str(), HeaderPattern.Range);
+  continue;
+}
+Filters->push_back(std::move(CompiledRegex));
   }
-  Filters->push_back(std::move(CompiledRegex));
 }
-if (Filters->empty())
+std::optional AnalyzeSystemHeaders;
+if (F.AnalyzeSystemHeaders.has_value())
+  AnalyzeSystemHeaders = **F.AnalyzeSystemHeaders;
+if (!Filters && !AnalyzeSystemHeaders.has_value())
   return;
-auto Filter = [Filters](llvm::StringRef Path) {
-  for (auto &Regex : *Filters)
-if (Regex.match(Path))
-  return true;
-  return false;
-};
-Out.Apply.push_back([Filter](const Params &, Config &C) {
-  C.Diagnostics.Includes.IgnoreHeader.emplace_back(Filter);
+Out.Apply.push_back([Filters = std::move(Filters),
+ AnalyzeSystemHeaders](const Params &, Config &C) {
+  if (Filters) {
+auto Filter = [Filters](llvm::StringRef Path) {
+  for (auto &Regex : *Filters)
+if (Regex.match(Path))
+  return true;
+  return false;
+

[clang-tools-extra] [clangd] Add config option to analyze unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clangd] Add config option to analyze unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clangd] Add config option to analyze unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/87208

>From 3e29095dbc2240b7a61d8d261224501a85753e7d Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Mon, 1 Apr 2024 02:26:14 +0300
Subject: [PATCH] Add config option to analyze unused system headers

---
 clang-tools-extra/clangd/Config.h |  1 +
 clang-tools-extra/clangd/ConfigCompile.cpp| 57 +++
 clang-tools-extra/clangd/ConfigFragment.h |  4 ++
 clang-tools-extra/clangd/ConfigYAML.cpp   |  4 ++
 clang-tools-extra/clangd/IncludeCleaner.cpp   | 34 +++
 clang-tools-extra/clangd/IncludeCleaner.h | 13 +
 clang-tools-extra/clangd/ParsedAST.cpp|  3 +-
 .../clangd/unittests/ConfigCompileTests.cpp   |  6 ++
 .../clangd/unittests/ConfigYAMLTests.cpp  | 15 +
 .../clangd/unittests/IncludeCleanerTests.cpp  | 15 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 ++
 11 files changed, 111 insertions(+), 45 deletions(-)

diff --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index 4371c80a6c5877..9629854abff31b 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -114,6 +114,7 @@ struct Config {
 /// these regexes.
 struct {
   std::vector> IgnoreHeader;
+  bool AnalyzeSystemHeaders = false;
 } Includes;
   } Diagnostics;
 
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 5bb2eb4a9f803f..f74c870adfb73d 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -572,32 +572,43 @@ struct FragmentCompiler {
 #else
 static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
 #endif
-auto Filters = std::make_shared>();
-for (auto &HeaderPattern : F.IgnoreHeader) {
-  // Anchor on the right.
-  std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
-  llvm::Regex CompiledRegex(AnchoredPattern, Flags);
-  std::string RegexError;
-  if (!CompiledRegex.isValid(RegexError)) {
-diag(Warning,
- llvm::formatv("Invalid regular expression '{0}': {1}",
-   *HeaderPattern, RegexError)
- .str(),
- HeaderPattern.Range);
-continue;
+std::shared_ptr> Filters;
+if (!F.IgnoreHeader.empty()) {
+  Filters = std::make_shared>();
+  for (auto &HeaderPattern : F.IgnoreHeader) {
+// Anchor on the right.
+std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern, Flags);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  diag(Warning,
+   llvm::formatv("Invalid regular expression '{0}': {1}",
+ *HeaderPattern, RegexError)
+   .str(),
+   HeaderPattern.Range);
+  continue;
+}
+Filters->push_back(std::move(CompiledRegex));
   }
-  Filters->push_back(std::move(CompiledRegex));
 }
-if (Filters->empty())
+std::optional AnalyzeSystemHeaders;
+if (F.AnalyzeSystemHeaders.has_value())
+  AnalyzeSystemHeaders = **F.AnalyzeSystemHeaders;
+if (!Filters && !AnalyzeSystemHeaders.has_value())
   return;
-auto Filter = [Filters](llvm::StringRef Path) {
-  for (auto &Regex : *Filters)
-if (Regex.match(Path))
-  return true;
-  return false;
-};
-Out.Apply.push_back([Filter](const Params &, Config &C) {
-  C.Diagnostics.Includes.IgnoreHeader.emplace_back(Filter);
+Out.Apply.push_back([Filters = std::move(Filters),
+ AnalyzeSystemHeaders](const Params &, Config &C) {
+  if (Filters) {
+auto Filter = [Filters](llvm::StringRef Path) {
+  for (auto &Regex : *Filters)
+if (Regex.match(Path))
+  return true;
+  return false;
+};
+C.Diagnostics.Includes.IgnoreHeader.emplace_back(std::move(Filter));
+  }
+  if (AnalyzeSystemHeaders.has_value())
+C.Diagnostics.Includes.AnalyzeSystemHeaders = *AnalyzeSystemHeaders;
 });
   }
 
diff --git a/clang-tools-extra/clangd/ConfigFragment.h 
b/clang-tools-extra/clangd/ConfigFragment.h
index 7fa61108c78a05..ac8b88c2454128 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -254,6 +254,10 @@ struct Fragment {
   /// unused or missing. These can match any suffix of the header file in
   /// question.
   std::vector> IgnoreHeader;
+
+  /// If false (default), unused system headers will be ignored.
+  /// Standard library headers are analyzed regardless of this option.
+  std::optional> AnalyzeSystemHeaders;
 };
 IncludesBlock Includes;
 
diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index ce09af819247ae..7608af42005386 100644
--- a/cla

[clang-tools-extra] [clangd] Add config option to analyze unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/87208

>From 35db92dfd0c2b43fc7afde5b093598763c4b8c89 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Mon, 1 Apr 2024 02:26:14 +0300
Subject: [PATCH] Add config option to analyze unused system headers

---
 clang-tools-extra/clangd/Config.h |  1 +
 clang-tools-extra/clangd/ConfigCompile.cpp| 57 +++
 clang-tools-extra/clangd/ConfigFragment.h |  4 ++
 clang-tools-extra/clangd/ConfigYAML.cpp   |  4 ++
 clang-tools-extra/clangd/IncludeCleaner.cpp   | 34 +++
 clang-tools-extra/clangd/IncludeCleaner.h | 13 +
 clang-tools-extra/clangd/ParsedAST.cpp|  3 +-
 .../clangd/unittests/ConfigCompileTests.cpp   |  6 ++
 .../clangd/unittests/ConfigYAMLTests.cpp  | 15 +
 .../clangd/unittests/IncludeCleanerTests.cpp  | 15 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 11 files changed, 112 insertions(+), 45 deletions(-)

diff --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index 4371c80a6c5877..9629854abff31b 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -114,6 +114,7 @@ struct Config {
 /// these regexes.
 struct {
   std::vector> IgnoreHeader;
+  bool AnalyzeSystemHeaders = false;
 } Includes;
   } Diagnostics;
 
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 5bb2eb4a9f803f..f74c870adfb73d 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -572,32 +572,43 @@ struct FragmentCompiler {
 #else
 static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
 #endif
-auto Filters = std::make_shared>();
-for (auto &HeaderPattern : F.IgnoreHeader) {
-  // Anchor on the right.
-  std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
-  llvm::Regex CompiledRegex(AnchoredPattern, Flags);
-  std::string RegexError;
-  if (!CompiledRegex.isValid(RegexError)) {
-diag(Warning,
- llvm::formatv("Invalid regular expression '{0}': {1}",
-   *HeaderPattern, RegexError)
- .str(),
- HeaderPattern.Range);
-continue;
+std::shared_ptr> Filters;
+if (!F.IgnoreHeader.empty()) {
+  Filters = std::make_shared>();
+  for (auto &HeaderPattern : F.IgnoreHeader) {
+// Anchor on the right.
+std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern, Flags);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  diag(Warning,
+   llvm::formatv("Invalid regular expression '{0}': {1}",
+ *HeaderPattern, RegexError)
+   .str(),
+   HeaderPattern.Range);
+  continue;
+}
+Filters->push_back(std::move(CompiledRegex));
   }
-  Filters->push_back(std::move(CompiledRegex));
 }
-if (Filters->empty())
+std::optional AnalyzeSystemHeaders;
+if (F.AnalyzeSystemHeaders.has_value())
+  AnalyzeSystemHeaders = **F.AnalyzeSystemHeaders;
+if (!Filters && !AnalyzeSystemHeaders.has_value())
   return;
-auto Filter = [Filters](llvm::StringRef Path) {
-  for (auto &Regex : *Filters)
-if (Regex.match(Path))
-  return true;
-  return false;
-};
-Out.Apply.push_back([Filter](const Params &, Config &C) {
-  C.Diagnostics.Includes.IgnoreHeader.emplace_back(Filter);
+Out.Apply.push_back([Filters = std::move(Filters),
+ AnalyzeSystemHeaders](const Params &, Config &C) {
+  if (Filters) {
+auto Filter = [Filters](llvm::StringRef Path) {
+  for (auto &Regex : *Filters)
+if (Regex.match(Path))
+  return true;
+  return false;
+};
+C.Diagnostics.Includes.IgnoreHeader.emplace_back(std::move(Filter));
+  }
+  if (AnalyzeSystemHeaders.has_value())
+C.Diagnostics.Includes.AnalyzeSystemHeaders = *AnalyzeSystemHeaders;
 });
   }
 
diff --git a/clang-tools-extra/clangd/ConfigFragment.h 
b/clang-tools-extra/clangd/ConfigFragment.h
index 7fa61108c78a05..ac8b88c2454128 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -254,6 +254,10 @@ struct Fragment {
   /// unused or missing. These can match any suffix of the header file in
   /// question.
   std::vector> IgnoreHeader;
+
+  /// If false (default), unused system headers will be ignored.
+  /// Standard library headers are analyzed regardless of this option.
+  std::optional> AnalyzeSystemHeaders;
 };
 IncludesBlock Includes;
 
diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index ce09af819247ae..7608af42005386 100644
--- a/cla

[clang-tools-extra] [clangd] Add config option to detect unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits


@@ -62,15 +64,6 @@ issueIncludeCleanerDiagnostics(ParsedAST &AST, 
llvm::StringRef Code,
const ThreadsafeFS &TFS,
HeaderFilter IgnoreHeader = {});
 
-/// Affects whether standard library includes should be considered for
-/// removal. This is off by default for now due to implementation limitations:
-/// - macros are not tracked
-/// - symbol names without a unique associated header are not tracked
-/// - references to std-namespaced C types are not properly tracked:
-///   instead of std::size_t ->  we see ::size_t -> 
-/// FIXME: remove this hack once the implementation is good enough.
-void setIncludeCleanerAnalyzesStdlib(bool B);

vvd170501 wrote:

This function was removed in e289ee99cec4607243aeaa01504f6b3cf65b65fe, but the 
declaration was left for some reason (overlooked?)

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits


@@ -62,15 +64,6 @@ issueIncludeCleanerDiagnostics(ParsedAST &AST, 
llvm::StringRef Code,
const ThreadsafeFS &TFS,
HeaderFilter IgnoreHeader = {});
 
-/// Affects whether standard library includes should be considered for
-/// removal. This is off by default for now due to implementation limitations:
-/// - macros are not tracked
-/// - symbol names without a unique associated header are not tracked
-/// - references to std-namespaced C types are not properly tracked:
-///   instead of std::size_t ->  we see ::size_t -> 
-/// FIXME: remove this hack once the implementation is good enough.
-void setIncludeCleanerAnalyzesStdlib(bool B);

vvd170501 wrote:

At first I considered adding a global flag similar to 
`--include-cleaner-stdlib`, but then thought that having more fine-grained 
control would be better.

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-03-31 Thread Vadim D. via cfe-commits

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-02-10 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 created 
https://github.com/llvm/llvm-project/pull/81364

Fixes  #68933.

>From aa48713c9bf23c24bbc0c22dd67f332ca970d2b8 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 10 Feb 2024 02:29:48 +0300
Subject: [PATCH] Add -Wmissing-designated-field-initializers, decide whether
 to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 975eca0ad9b642..bda533f77cc56a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -516,7 +516,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63a..69e197e26b9b45 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6165,6 +6165,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index b6de06464cd6f3..08aa50ebad331f 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) ||
+   

[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-02-10 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/81364

>From b7e3ffb25e1a50ac29e50ac8536ea93244f219a1 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 10 Feb 2024 19:19:52 +0300
Subject: [PATCH] Add -Wmissing-designated-field-initializers, decide whether
 to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 975eca0ad9b642..bda533f77cc56a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -516,7 +516,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b4dc4feee8e63a..69e197e26b9b45 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6165,6 +6165,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index b6de06464cd6f3..08aa50ebad331f 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(Sema

[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-02-10 Thread Vadim D. via cfe-commits

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-02-10 Thread Vadim D. via cfe-commits

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-02-10 Thread Vadim D. via cfe-commits

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-02-12 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/81364

>From 9701011a9c88397cf3bb2c089e7295f62c7e13fe Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 10 Feb 2024 19:19:52 +0300
Subject: [PATCH 1/4] Add -Wmissing-designated-field-initializers, decide
 whether to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 975eca0ad9b642..bda533f77cc56a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -516,7 +516,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 83b89d1449f420..bbb46a9d6f3c6a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6167,6 +6167,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index b6de06464cd6f3..08aa50ebad331f 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(

[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-02-12 Thread Vadim D. via cfe-commits


@@ -120,6 +120,10 @@ Non-comprehensive list of changes in this release
 New Compiler Flags
 --
 
+- ``-Wmissing-designated-field-initializers``, grouped under 
``-Wmissing-designated-field-initializers``.

vvd170501 wrote:

Would it be ok to also add this patch to the 18.x release branch?
It would be nice to have a way to keep old behavior of the m-f-i check when 
upgrading from Clang 16/17 to 18.

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/81364

>From f73060f7f09a747c90fa559641abd8c72f4ee66f Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 10 Feb 2024 19:19:52 +0300
Subject: [PATCH 1/4] Add -Wmissing-designated-field-initializers, decide
 whether to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index e8b4139d7893ce..0791a0002319de 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -517,7 +517,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 91105d4231f06a..8cf58299602ec7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6167,6 +6167,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0fd458837163e5..3227f16dd0c1ce 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(

[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

vvd170501 wrote:

Ping

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/81364

>From f73060f7f09a747c90fa559641abd8c72f4ee66f Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 10 Feb 2024 19:19:52 +0300
Subject: [PATCH 1/5] Add -Wmissing-designated-field-initializers, decide
 whether to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index e8b4139d7893ce..0791a0002319de 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -517,7 +517,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 91105d4231f06a..8cf58299602ec7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6167,6 +6167,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0fd458837163e5..3227f16dd0c1ce 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(

[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/81364

>From f73060f7f09a747c90fa559641abd8c72f4ee66f Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 10 Feb 2024 19:19:52 +0300
Subject: [PATCH 1/6] Add -Wmissing-designated-field-initializers, decide
 whether to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index e8b4139d7893ce..0791a0002319de 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -517,7 +517,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 91105d4231f06a..8cf58299602ec7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6167,6 +6167,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0fd458837163e5..3227f16dd0c1ce 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(

[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits


@@ -2363,8 +2356,11 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
+  // This check is disabled for designated initializers in C.
+  // This matches gcc behaviour.
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion() &&
+  !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
+  !(HasDesignatedInit && !SemaRef.getLangOpts().CPlusPlus)) {

vvd170501 wrote:

Unexpanded condition corresponds to the comment I left a few lines above:
> This check is disabled for designated initializers in C.

For me personally, it looks a bit less readable in expanded form ("check unused 
fields if there are no designated initializers or if language is C++")

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits


@@ -2363,8 +2356,11 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
+  // This check is disabled for designated initializers in C.
+  // This matches gcc behaviour.
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion() &&
+  !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
+  !(HasDesignatedInit && !SemaRef.getLangOpts().CPlusPlus)) {

vvd170501 wrote:

@erichkeane, I did something like this before 
83864610d6b6470a0f229c516821d8344d994562, but this adds another indentation 
level.

It's possible to calculate `DisableCheck` before the `if` statement, but it'll 
probably be less optimal than the current solution - if `VerifyOnly` is true, 
`DisableCheck` is not needed.

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits


@@ -2363,8 +2356,11 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
+  // This check is disabled for designated initializers in C.
+  // This matches gcc behaviour.
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion() &&
+  !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
+  !(HasDesignatedInit && !SemaRef.getLangOpts().CPlusPlus)) {

vvd170501 wrote:

> I am asking for the list of '!'s to be shorter/grouped into a couple of 
> 'bools' with descriptive names

Like this? Other checks seem unrelated to each other.
```diff
+ bool IsCDesignatedInitializer = HasDesignatedInit && 
!SemaRef.getLangOpts().CPlusPlus;
  if (!VerifyOnly && InitializedSomething && !RD->isUnion() &&
  !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()) &&
- !(HasDesignatedInit && !SemaRef.getLangOpts().CPlusPlus)) {
+ !IsCDesignatedInitializer) {
```

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

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


[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/81364

>From f73060f7f09a747c90fa559641abd8c72f4ee66f Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 10 Feb 2024 19:19:52 +0300
Subject: [PATCH 1/7] Add -Wmissing-designated-field-initializers, decide
 whether to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index e8b4139d7893ce..0791a0002319de 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -517,7 +517,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 91105d4231f06a..8cf58299602ec7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6167,6 +6167,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0fd458837163e5..3227f16dd0c1ce 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(

[clang] [clang] Add -Wmissing-designated-field-initializers (PR #81364)

2024-03-04 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/81364

>From f73060f7f09a747c90fa559641abd8c72f4ee66f Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 10 Feb 2024 19:19:52 +0300
Subject: [PATCH 1/8] Add -Wmissing-designated-field-initializers, decide
 whether to skip m-f-i check only when needed

---
 clang/include/clang/Basic/DiagnosticGroups.td | 10 +++-
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/lib/Sema/SemaInit.cpp   | 50 ++-
 .../SemaCXX/cxx2a-initializer-aggregates.cpp  | 11 ++--
 4 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index e8b4139d7893ce..0791a0002319de 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -517,7 +517,15 @@ def MethodSignatures : DiagGroup<"method-signatures">;
 def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
 def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
 def MismatchedTags : DiagGroup<"mismatched-tags">;
-def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def MissingDesignatedFieldInitializers : 
DiagGroup<"missing-designated-field-initializers">{
+  code Documentation = [{
+Warn about designated initializers with some fields missing (only in C++).
+  }];
+}
+// Default -Wmissing-field-initializers matches gcc behavior,
+// but missing-designated-field-initializers can be turned off to match old 
clang behavior.
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers",
+ [MissingDesignatedFieldInitializers]>;
 def ModuleLock : DiagGroup<"module-lock">;
 def ModuleBuild : DiagGroup<"module-build">;
 def ModuleImport : DiagGroup<"module-import">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 91105d4231f06a..8cf58299602ec7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -6167,6 +6167,10 @@ def ext_initializer_string_for_char_array_too_long : 
ExtWarn<
 def warn_missing_field_initializers : Warning<
   "missing field %0 initializer">,
   InGroup, DefaultIgnore;
+// The same warning, but another group is needed to disable it separately.
+def warn_missing_designated_field_initializers : Warning<
+  "missing field %0 initializer">,
+  InGroup, DefaultIgnore;
 def warn_braces_around_init : Warning<
   "braces around %select{scalar |}0initializer">,
   InGroup>;
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 0fd458837163e5..3227f16dd0c1ce 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2227,8 +2227,6 @@ void InitListChecker::CheckStructUnionTypes(
   size_t NumRecordDecls = llvm::count_if(RD->decls(), [&](const Decl *D) {
 return isa(D) || isa(D);
   });
-  bool CheckForMissingFields =
-!IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts());
   bool HasDesignatedInit = false;
 
   llvm::SmallPtrSet InitializedFields;
@@ -2269,11 +2267,6 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   InitializedSomething = true;
-
-  // Disable check for missing fields when designators are used.
-  // This matches gcc behaviour.
-  if (!SemaRef.getLangOpts().CPlusPlus)
-CheckForMissingFields = false;
   continue;
 }
 
@@ -2285,7 +2278,7 @@ void InitListChecker::CheckStructUnionTypes(
 // These are okay for randomized structures. [C99 6.7.8p19]
 //
 // Also, if there is only one element in the structure, we allow something
-// like this, because it's really not randomized in the tranditional sense.
+// like this, because it's really not randomized in the traditional sense.
 //
 //   struct foo h = {bar};
 auto IsZeroInitializer = [&](const Expr *I) {
@@ -2363,23 +2356,32 @@ void InitListChecker::CheckStructUnionTypes(
   }
 
   // Emit warnings for missing struct field initializers.
-  if (!VerifyOnly && InitializedSomething && CheckForMissingFields &&
-  !RD->isUnion()) {
-// It is possible we have one or more unnamed bitfields remaining.
-// Find first (if any) named field and emit warning.
-for (RecordDecl::field_iterator it = HasDesignatedInit ? RD->field_begin()
-   : Field,
-end = RD->field_end();
- it != end; ++it) {
-  if (HasDesignatedInit && InitializedFields.count(*it))
-continue;
+  if (!VerifyOnly && InitializedSomething && !RD->isUnion()) {
+// Disable missing fields check for:
+// - Zero initializers
+// - Designated initializers (only in C). This matches gcc behaviour.
+bool DisableCheck =
+IList->isIdiomaticZeroInitializer(

[clang-tools-extra] [include-cleaner] don't consider the associated header unused (PR #67228)

2024-02-14 Thread Vadim D. via cfe-commits


@@ -227,6 +230,7 @@ class PragmaIncludes::RecordPragma : public PPCallbacks, 
public CommentHandler {
   IncludedHeader = *File;
 checkForExport(HashFID, HashLine, std::move(IncludedHeader), File);

vvd170501 wrote:

`std::move` should be removed, because `IncludedHeader` is now also used for 
`checkForDeducedAssociated`.

Current implementation of `clang::include_cleaner::Header` is trivially 
movable, so `IncludedHeader` is unchanged, but it's safer to not rely on this 
fact.

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-04-08 Thread Vadim D. via cfe-commits

vvd170501 wrote:

Ping

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-13 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 created 
https://github.com/llvm/llvm-project/pull/88636

This PR aims to expand the list of classes that are considered to be "strings" 
by `readability-string-compare` check.

1. Currently `readability-string-compare` only checks `std::string;:compare`, 
but  `std::string_view` has a similar `compare` method, which also should not 
be used to check equality of two strings.
2. Some codebases use custom string-like classes that have public interfaces 
similar to `std::string` or `std::string_view`. Example: 
[TStringBase](https://github.com/yandex/yatool/blob/main/util/generic/strbase.h#L38),

Related to, but does not solve #28396 (only adds support for custom string-like 
classes, not custom functions)

>From eb5279fd83ba114b8eb094099d5993d6bfb003e3 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 75 +--
 .../readability/StringCompareCheck.h  | 10 ++-
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 41 ++
 .../checkers/readability/string-compare.cpp   | 14 
 5 files changed, 125 insertions(+), 25 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..30bde1f8b75b61 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,15 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +23,55 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const StringRef DefaultStringClassNames = "::std::basic_string;"
+ "::std::basic_string_view";
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringClassNames(optutils::parseStringList(
+  Options.get("StringClassNames", DefaultStringClassNames))),
+  // Both std::string and std::string_view are templates, so this check 
only
+  // needs to match template classes by default.
+  // Custom `StringClassNames` may contain non-template classes, and
+  // it's impossible to tell them apart from templates just by name.
+  CheckNonTemplateClasses(Options.get("StringClassNames").has_value()) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  if (StringClassNames.empty()) {
+return;
+  }
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-13 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-13 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 91eccdd291fa4f0753aa8e9970fa146516823e22 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 73 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 36 +
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 162 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..20218975ec121b 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,52 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTemplateSpecializationDecl(hasAnyName(PossiblyTemp

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-13 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From b63dd11ea87cd504c8972de6ed29330d6702abca Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 36 +
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 163 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTemplate

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-13 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 0db24a6806e9429b5e7b9cd9d0777315b3e6d87e Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 38 ++
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 165 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTemplat

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-13 Thread Vadim D. via cfe-commits


@@ -7,42 +7,70 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
 static const StringRef CompareMessage = "do not use 'compare' to test equality 
"
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {

vvd170501 wrote:

Type of `StringClassMatcher` dependinds on whether the check is used with or 
without `StringLikeClasses`, so a template lambda is needed.

It's possible to use `anyOf` and `cxxRecordDecl` in both cases and remove the 
lambda, but this will probably slow the check down in default case.

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-13 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits


@@ -50,5 +52,32 @@ Examples:
   }
 
 The above code examples show the list of if-statements that this check will
-give a warning for. All of them uses ``compare`` to check if equality or
+give a warning for. All of them use ``compare`` to check equality or
 inequality of two strings instead of using the correct operators.
+
+Options
+---
+
+.. option:: StringLikeClasses
+
+   A string containing comma-separated names of string-like classes. Default 
is an empty string.
+   If a class from this list has a ``compare`` method similar to 
``std::string``, it will be checked in the same way.
+
+Example
+^^^
+
+.. code-block:: c++
+
+  struct CustomString {
+  public:
+int compare (const CustomString& other) const;
+  }
+
+  CustomString str1;
+  CustomString str2;
+
+  // use str1 != str2 instead.
+  if (str1.compare(str2)) {
+  }
+
+If `StringLikeClasses` contains ``CustomString``, the check will suggest 
replacing ``compare`` with equality operator.

vvd170501 wrote:

Default value of what? If you mean `StringLikeClasses`, it is empty by default 
(see line 63)

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 0db24a6806e9429b5e7b9cd9d0777315b3e6d87e Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH 1/2] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 38 ++
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 165 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTem

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits


@@ -7,42 +7,70 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
 static const StringRef CompareMessage = "do not use 'compare' to test equality 
"
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}

vvd170501 wrote:

> put StringClasses as default

I thought about implementing the option this way, but it seems to me it'd be a 
bit harder to use than a list of additional classes.
if the user wanted to add custom classes, they'd need to also include 
`std::string` and `std::string_view` in the list to keep the check enabled for 
these classes.
So, I decided to append custom classes to the default list instead of 
overwriting it.

> Or call it like "AdditionalStringLikeClasses"

Ok.

> but still have common handling

Could you elaborate? I'm not sure what you mean by "common handling". Removing 
the lambda?

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits


@@ -7,42 +7,70 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
 static const StringRef CompareMessage = "do not use 'compare' to test equality 
"
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTemplateSpecializationDecl(hasAnyName(PossiblyTemplateClasses)),
+cxxRecordDecl(hasAnyName(StringLikeClasses;

vvd170501 wrote:

But would regex be useful here?
- Usually there would be a few (1-2) custom string-like classes, if any, and it 
shouldn't be hard to just put their names into the list.
- The defaults would be less readable (`^::std::string$;^::std::string_view$;` 
or `^::std::string(_view)?$` vs `::std::string;::std::string_view`)

Also, existing checks with a `StringLikeClasses` use `hasAnyName`

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 0db24a6806e9429b5e7b9cd9d0777315b3e6d87e Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH 1/4] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 38 ++
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 165 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTem

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 0db24a6806e9429b5e7b9cd9d0777315b3e6d87e Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH 1/5] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 38 ++
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 165 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTem

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 0db24a6806e9429b5e7b9cd9d0777315b3e6d87e Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH 1/6] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 38 ++
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 165 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTem

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-14 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-29 Thread Vadim D. via cfe-commits

vvd170501 wrote:

@HighCommander4, overall it looks good, but I'd replace "enables 
include-cleaner checks" with "enables unused include check", because the option 
doesn't affect missing include check.

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-04-20 Thread Vadim D. via cfe-commits

vvd170501 wrote:

@HighCommander4 Ping. Could you review this PR or suggest other reviewers, 
please?

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-22 Thread Vadim D. via cfe-commits

vvd170501 wrote:

Ping.
@PiotrZSL, I've added the changes you requested (except 
`matchesAnyListedName`), waiting for your feedback

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-22 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 0db24a6806e9429b5e7b9cd9d0777315b3e6d87e Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH 1/7] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 38 ++
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 165 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTem

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-22 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 0db24a6806e9429b5e7b9cd9d0777315b3e6d87e Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH 1/8] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 74 +--
 .../readability/StringCompareCheck.h  |  9 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 .../checks/readability/string-compare.rst | 33 -
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +++
 .../string-compare-custom-string-classes.cpp  | 38 ++
 .../checkers/readability/string-compare.cpp   | 23 ++
 7 files changed, 165 insertions(+), 27 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..905e5b156ef864 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,16 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
+#include 
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,29 +24,53 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const std::vector StringClasses = {
+"::std::basic_string", "::std::basic_string_view"};
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(
+  optutils::parseStringList(Options.get("StringLikeClasses", ""))) {}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
-  const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
-  hasArgument(0, expr().bind("str2")), argumentCountIs(1),
-  callee(memberExpr().bind("str1")));
-
-  // First and second case: cast str.compare(str) to boolean.
-  Finder->addMatcher(
-  traverse(TK_AsIs,
-   implicitCastExpr(hasImplicitDestinationType(booleanType()),
-has(StrCompare))
-   .bind("match1")),
-  this);
-
-  // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0.
-  Finder->addMatcher(
-  binaryOperator(hasAnyOperatorName("==", "!="),
- hasOperands(StrCompare.bind("compare"),
- integerLiteral(equals(0)).bind("zero")))
-  .bind("match2"),
-  this);
+  const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) {
+const auto StrCompare = cxxMemberCallExpr(
+callee(cxxMethodDecl(hasName("compare"), ofClass(StringClassMatcher))),
+hasArgument(0, expr().bind("str2")), argumentCountIs(1),
+callee(memberExpr().bind("str1")));
+
+// First and second case: cast str.compare(str) to boolean.
+Finder->addMatcher(
+traverse(TK_AsIs,
+ implicitCastExpr(hasImplicitDestinationType(booleanType()),
+  has(StrCompare))
+ .bind("match1")),
+this);
+
+// Third and fourth case: str.compare(str) == 0
+// and str.compare(str) !=  0.
+Finder->addMatcher(
+binaryOperator(hasAnyOperatorName("==", "!="),
+   hasOperands(StrCompare.bind("compare"),
+   integerLiteral(equals(0)).bind("zero")))
+.bind("match2"),
+this);
+  };
+  if (StringLikeClasses.empty()) {
+RegisterForClasses(
+classTemplateSpecializationDecl(hasAnyName(StringClasses)));
+  } else {
+// StringLikeClasses may or may not be templates, so we need to match both
+// template and non-template classes.
+std::vector PossiblyTemplateClasses = StringClasses;
+PossiblyTemplateClasses.insert(PossiblyTemplateClasses.end(),
+   StringLikeClasses.begin(),
+   StringLikeClasses.end());
+RegisterForClasses(anyOf(
+classTem

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-22 Thread Vadim D. via cfe-commits


@@ -50,5 +52,36 @@ Examples:
   }
 
 The above code examples show the list of if-statements that this check will
-give a warning for. All of them uses ``compare`` to check if equality or
+give a warning for. All of them use ``compare`` to check equality or
 inequality of two strings instead of using the correct operators.
+
+Options
+---
+
+.. option:: StringLikeClasses
+
+   A string containing semicolon-separated names of string-like classes.
+   By default contains only ``::std::basic_string``
+   and ``::std::basic_string_view``. If a class from this list has
+   a ``compare`` method similar to that of ``std::string``, it will be checked
+   in the same way.
+
+Example
+^^^
+
+.. code-block:: c++
+
+  struct CustomString {
+  public:
+int compare (const CustomString& other) const;
+  }
+
+  CustomString str1;
+  CustomString str2;
+
+  // use str1 != str2 instead.
+  if (str1.compare(str2)) {
+  }
+
+If `StringLikeClasses` contains ``CustomString``, the check will suggest

vvd170501 wrote:

Shouldn't `CustomString` be rendered as code here?

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-22 Thread Vadim D. via cfe-commits

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-24 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From ab87ad179f385934e2ec17517b47da33d29eb256 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH] readability-string-compare: check std::string_view, allow
 custom string-like classes

---
 .../readability/StringCompareCheck.cpp| 27 --
 .../readability/StringCompareCheck.h  | 10 -
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 +++
 .../checks/readability/string-compare.rst | 37 ++-
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +
 .../string-compare-custom-string-classes.cpp  | 35 ++
 .../checkers/readability/string-compare.cpp   | 23 
 7 files changed, 139 insertions(+), 8 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..7c0bbef3ca0878 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,15 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,11 +23,27 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const StringRef DefaultStringLikeClasses = "::std::basic_string;"
+  "::std::basic_string_view";
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(optutils::parseStringList(
+  Options.get("StringLikeClasses", DefaultStringLikeClasses))) {}
+
+void StringCompareCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StringLikeClasses",
+optutils::serializeStringList(StringLikeClasses));
+}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
+  if (StringLikeClasses.empty()) {
+return;
+  }
   const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
+  callee(cxxMethodDecl(hasName("compare"), 
ofClass(cxxRecordDecl(hasAnyName(
+   StringLikeClasses),
   hasArgument(0, expr().bind("str2")), argumentCountIs(1),
   callee(memberExpr().bind("str1")));
 
diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
index 812736d806b71d..150090901a6e97 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRINGCOMPARECHECK_H
 
 #include "../ClangTidyCheck.h"
+#include 
 
 namespace clang::tidy::readability {
 
@@ -20,13 +21,18 @@ namespace clang::tidy::readability {
 /// 
http://clang.llvm.org/extra/clang-tidy/checks/readability/string-compare.html
 class StringCompareCheck : public ClangTidyCheck {
 public:
-  StringCompareCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  StringCompareCheck(StringRef Name, ClangTidyContext *Context);
+
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
 return LangOpts.CPlusPlus;
   }
+
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector StringLikeClasses;
 };
 
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 5b1feffb89ea06..aa8b4a63b60946 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -314,6 +314,11 @@ Changes in existing checks
   check by resolving fix-it overlaps in template code by disregarding implicit
   instances.
 
+- 

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-24 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/88636

>From 54b68bdb6cdc6bdd81178e2abd78d211b6b7181a Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Sat, 13 Apr 2024 23:36:12 +0300
Subject: [PATCH] readability-string-compare: check std::string_view, allow
 custom string-like classes

Co-authored-by: EugeneZelenko 
---
 .../readability/StringCompareCheck.cpp| 27 --
 .../readability/StringCompareCheck.h  | 10 -
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 +++
 .../checks/readability/string-compare.rst | 37 ++-
 .../clang-tidy/checkers/Inputs/Headers/string | 10 +
 .../string-compare-custom-string-classes.cpp  | 35 ++
 .../checkers/readability/string-compare.cpp   | 23 
 7 files changed, 139 insertions(+), 8 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/string-compare-custom-string-classes.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
index 3b5d89c8c64719..7c0bbef3ca0878 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.cpp
@@ -7,12 +7,15 @@
 
//===--===//
 
 #include "StringCompareCheck.h"
-#include "../utils/FixItHintUtils.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Tooling/FixIt.h"
+#include "llvm/ADT/StringRef.h"
 
 using namespace clang::ast_matchers;
+namespace optutils = clang::tidy::utils::options;
 
 namespace clang::tidy::readability {
 
@@ -20,11 +23,27 @@ static const StringRef CompareMessage = "do not use 
'compare' to test equality "
 "of strings; use the string equality "
 "operator instead";
 
+static const StringRef DefaultStringLikeClasses = "::std::basic_string;"
+  "::std::basic_string_view";
+
+StringCompareCheck::StringCompareCheck(StringRef Name,
+   ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  StringLikeClasses(optutils::parseStringList(
+  Options.get("StringLikeClasses", DefaultStringLikeClasses))) {}
+
+void StringCompareCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "StringLikeClasses",
+optutils::serializeStringList(StringLikeClasses));
+}
+
 void StringCompareCheck::registerMatchers(MatchFinder *Finder) {
+  if (StringLikeClasses.empty()) {
+return;
+  }
   const auto StrCompare = cxxMemberCallExpr(
-  callee(cxxMethodDecl(hasName("compare"),
-   ofClass(classTemplateSpecializationDecl(
-   hasName("::std::basic_string"),
+  callee(cxxMethodDecl(hasName("compare"), 
ofClass(cxxRecordDecl(hasAnyName(
+   StringLikeClasses),
   hasArgument(0, expr().bind("str2")), argumentCountIs(1),
   callee(memberExpr().bind("str1")));
 
diff --git a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h 
b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
index 812736d806b71d..150090901a6e97 100644
--- a/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/StringCompareCheck.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STRINGCOMPARECHECK_H
 
 #include "../ClangTidyCheck.h"
+#include 
 
 namespace clang::tidy::readability {
 
@@ -20,13 +21,18 @@ namespace clang::tidy::readability {
 /// 
http://clang.llvm.org/extra/clang-tidy/checks/readability/string-compare.html
 class StringCompareCheck : public ClangTidyCheck {
 public:
-  StringCompareCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  StringCompareCheck(StringRef Name, ClangTidyContext *Context);
+
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
 return LangOpts.CPlusPlus;
   }
+
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const std::vector StringLikeClasses;
 };
 
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 5b1feffb89ea06..aa8b4a63b60946 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -314,6 +314,11 @@ Changes in existing checks
   check by resolving fix-it overlaps in template code by disregardi

[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-04-26 Thread Vadim D. via cfe-commits

vvd170501 wrote:

@PiotrZSL, can you merge this, please?
I've fixed merge conflicts caused by ef5906989ae2004100ff56dc5ab59be2be9d5c99 
(changes in the string header for tests), now everything should be ok

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-01 Thread Vadim D. via cfe-commits

vvd170501 wrote:

Ping. Can anyone review this, please?

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-09 Thread Vadim D. via cfe-commits

vvd170501 wrote:

Ping

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


[clang-tools-extra] [clang-tidy] check `std::string_view` and custom string-like classes in `readability-string-compare` (PR #88636)

2024-05-09 Thread Vadim D. via cfe-commits

vvd170501 wrote:

@EugeneZelenko, can you approve this, please? Or are 2 approves enough to merge?

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-10 Thread Vadim D. via cfe-commits


@@ -572,32 +572,43 @@ struct FragmentCompiler {
 #else
 static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
 #endif
-auto Filters = std::make_shared>();
-for (auto &HeaderPattern : F.IgnoreHeader) {
-  // Anchor on the right.
-  std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
-  llvm::Regex CompiledRegex(AnchoredPattern, Flags);
-  std::string RegexError;
-  if (!CompiledRegex.isValid(RegexError)) {
-diag(Warning,
- llvm::formatv("Invalid regular expression '{0}': {1}",
-   *HeaderPattern, RegexError)
- .str(),
- HeaderPattern.Range);
-continue;
+std::shared_ptr> Filters;
+if (!F.IgnoreHeader.empty()) {

vvd170501 wrote:

But then if `F.IgnoreHeader` is empty, we'll be allocating and deallocating an 
unneeded vector.

It's also possible to use `if (Filters->empty() && 
!AnalyzeSystemHeaders.has_value()) return;` and check `Filters->empty()`again  
in line 601, but I wanted to remove the unneeded allocation.

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-10 Thread Vadim D. via cfe-commits


@@ -572,32 +572,43 @@ struct FragmentCompiler {
 #else
 static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
 #endif
-auto Filters = std::make_shared>();
-for (auto &HeaderPattern : F.IgnoreHeader) {
-  // Anchor on the right.
-  std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
-  llvm::Regex CompiledRegex(AnchoredPattern, Flags);
-  std::string RegexError;
-  if (!CompiledRegex.isValid(RegexError)) {
-diag(Warning,
- llvm::formatv("Invalid regular expression '{0}': {1}",
-   *HeaderPattern, RegexError)
- .str(),
- HeaderPattern.Range);
-continue;
+std::shared_ptr> Filters;
+if (!F.IgnoreHeader.empty()) {
+  Filters = std::make_shared>();
+  for (auto &HeaderPattern : F.IgnoreHeader) {
+// Anchor on the right.
+std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern, Flags);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  diag(Warning,
+   llvm::formatv("Invalid regular expression '{0}': {1}",
+ *HeaderPattern, RegexError)
+   .str(),
+   HeaderPattern.Range);
+  continue;
+}
+Filters->push_back(std::move(CompiledRegex));
   }
-  Filters->push_back(std::move(CompiledRegex));
 }
-if (Filters->empty())
+std::optional AnalyzeSystemHeaders;
+if (F.AnalyzeSystemHeaders.has_value())
+  AnalyzeSystemHeaders = **F.AnalyzeSystemHeaders;

vvd170501 wrote:

Yes, it's intentional.
`F.AnalyzeSystemHeaders` is a `std::optional>`, but the lambda 
only needs to capture a `std::optional`.
Lines 594-596 are equivalent to the following c++23 code:
```cpp
auto AnalyzeSystemHeaders = F.AnalyzeSystemHeaders.transform(
[](const auto& LocatedValue) { return *LocatedValue; }
);
```

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-10 Thread Vadim D. via cfe-commits


@@ -135,6 +135,21 @@ TEST(IncludeCleaner, GetUnusedHeaders) {
Pointee(writtenInclusion("\"dir/unused.h\"";
 }
 
+TEST(IncludeCleaner, SystemUnusedHeaders) {
+  auto TU = TestTU::withCode(R"cpp(
+#include 
+#include 
+SystemClass x;
+  )cpp");
+  TU.AdditionalFiles["system/system_header.h"] = guard("class SystemClass 
{};");
+  TU.AdditionalFiles["system/system_unused.h"] = guard("");
+  TU.ExtraArgs = {"-isystem", testPath("system")};
+  auto AST = TU.build();
+  IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST, true);

vvd170501 wrote:

Isn;t this already covered by the `GetUnusedHeaders` test? There's an unused 
`` which must not present in `UnusedIncludes`.

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-10 Thread Vadim D. via cfe-commits


@@ -135,6 +135,21 @@ TEST(IncludeCleaner, GetUnusedHeaders) {
Pointee(writtenInclusion("\"dir/unused.h\"";
 }
 
+TEST(IncludeCleaner, SystemUnusedHeaders) {
+  auto TU = TestTU::withCode(R"cpp(
+#include 
+#include 
+SystemClass x;
+  )cpp");
+  TU.AdditionalFiles["system/system_header.h"] = guard("class SystemClass 
{};");
+  TU.AdditionalFiles["system/system_unused.h"] = guard("");
+  TU.ExtraArgs = {"-isystem", testPath("system")};

vvd170501 wrote:

I've copied `-isystem` from the `GetUnusedHeaders` test.
If `AnalyzeSystemHeaders` / `AnalyzeAngledIncludes` must work for inclusions of 
any type, then maybe it'd be better to test both `-I` and `-isystem`?

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


[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-10 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/87208

>From 35db92dfd0c2b43fc7afde5b093598763c4b8c89 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Mon, 1 Apr 2024 02:26:14 +0300
Subject: [PATCH 1/4] Add config option to analyze unused system headers

---
 clang-tools-extra/clangd/Config.h |  1 +
 clang-tools-extra/clangd/ConfigCompile.cpp| 57 +++
 clang-tools-extra/clangd/ConfigFragment.h |  4 ++
 clang-tools-extra/clangd/ConfigYAML.cpp   |  4 ++
 clang-tools-extra/clangd/IncludeCleaner.cpp   | 34 +++
 clang-tools-extra/clangd/IncludeCleaner.h | 13 +
 clang-tools-extra/clangd/ParsedAST.cpp|  3 +-
 .../clangd/unittests/ConfigCompileTests.cpp   |  6 ++
 .../clangd/unittests/ConfigYAMLTests.cpp  | 15 +
 .../clangd/unittests/IncludeCleanerTests.cpp  | 15 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 11 files changed, 112 insertions(+), 45 deletions(-)

diff --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index 4371c80a6c587..9629854abff31 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -114,6 +114,7 @@ struct Config {
 /// these regexes.
 struct {
   std::vector> IgnoreHeader;
+  bool AnalyzeSystemHeaders = false;
 } Includes;
   } Diagnostics;
 
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 5bb2eb4a9f803..f74c870adfb73 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -572,32 +572,43 @@ struct FragmentCompiler {
 #else
 static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
 #endif
-auto Filters = std::make_shared>();
-for (auto &HeaderPattern : F.IgnoreHeader) {
-  // Anchor on the right.
-  std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
-  llvm::Regex CompiledRegex(AnchoredPattern, Flags);
-  std::string RegexError;
-  if (!CompiledRegex.isValid(RegexError)) {
-diag(Warning,
- llvm::formatv("Invalid regular expression '{0}': {1}",
-   *HeaderPattern, RegexError)
- .str(),
- HeaderPattern.Range);
-continue;
+std::shared_ptr> Filters;
+if (!F.IgnoreHeader.empty()) {
+  Filters = std::make_shared>();
+  for (auto &HeaderPattern : F.IgnoreHeader) {
+// Anchor on the right.
+std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern, Flags);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  diag(Warning,
+   llvm::formatv("Invalid regular expression '{0}': {1}",
+ *HeaderPattern, RegexError)
+   .str(),
+   HeaderPattern.Range);
+  continue;
+}
+Filters->push_back(std::move(CompiledRegex));
   }
-  Filters->push_back(std::move(CompiledRegex));
 }
-if (Filters->empty())
+std::optional AnalyzeSystemHeaders;
+if (F.AnalyzeSystemHeaders.has_value())
+  AnalyzeSystemHeaders = **F.AnalyzeSystemHeaders;
+if (!Filters && !AnalyzeSystemHeaders.has_value())
   return;
-auto Filter = [Filters](llvm::StringRef Path) {
-  for (auto &Regex : *Filters)
-if (Regex.match(Path))
-  return true;
-  return false;
-};
-Out.Apply.push_back([Filter](const Params &, Config &C) {
-  C.Diagnostics.Includes.IgnoreHeader.emplace_back(Filter);
+Out.Apply.push_back([Filters = std::move(Filters),
+ AnalyzeSystemHeaders](const Params &, Config &C) {
+  if (Filters) {
+auto Filter = [Filters](llvm::StringRef Path) {
+  for (auto &Regex : *Filters)
+if (Regex.match(Path))
+  return true;
+  return false;
+};
+C.Diagnostics.Includes.IgnoreHeader.emplace_back(std::move(Filter));
+  }
+  if (AnalyzeSystemHeaders.has_value())
+C.Diagnostics.Includes.AnalyzeSystemHeaders = *AnalyzeSystemHeaders;
 });
   }
 
diff --git a/clang-tools-extra/clangd/ConfigFragment.h 
b/clang-tools-extra/clangd/ConfigFragment.h
index 7fa61108c78a0..ac8b88c245412 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -254,6 +254,10 @@ struct Fragment {
   /// unused or missing. These can match any suffix of the header file in
   /// question.
   std::vector> IgnoreHeader;
+
+  /// If false (default), unused system headers will be ignored.
+  /// Standard library headers are analyzed regardless of this option.
+  std::optional> AnalyzeSystemHeaders;
 };
 IncludesBlock Includes;
 
diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index ce09af819247a..7608af4200538 100644
--- a/clang-t

[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-13 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/87208

>From 35db92dfd0c2b43fc7afde5b093598763c4b8c89 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Mon, 1 Apr 2024 02:26:14 +0300
Subject: [PATCH 1/6] Add config option to analyze unused system headers

---
 clang-tools-extra/clangd/Config.h |  1 +
 clang-tools-extra/clangd/ConfigCompile.cpp| 57 +++
 clang-tools-extra/clangd/ConfigFragment.h |  4 ++
 clang-tools-extra/clangd/ConfigYAML.cpp   |  4 ++
 clang-tools-extra/clangd/IncludeCleaner.cpp   | 34 +++
 clang-tools-extra/clangd/IncludeCleaner.h | 13 +
 clang-tools-extra/clangd/ParsedAST.cpp|  3 +-
 .../clangd/unittests/ConfigCompileTests.cpp   |  6 ++
 .../clangd/unittests/ConfigYAMLTests.cpp  | 15 +
 .../clangd/unittests/IncludeCleanerTests.cpp  | 15 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 ++
 11 files changed, 112 insertions(+), 45 deletions(-)

diff --git a/clang-tools-extra/clangd/Config.h 
b/clang-tools-extra/clangd/Config.h
index 4371c80a6c587..9629854abff31 100644
--- a/clang-tools-extra/clangd/Config.h
+++ b/clang-tools-extra/clangd/Config.h
@@ -114,6 +114,7 @@ struct Config {
 /// these regexes.
 struct {
   std::vector> IgnoreHeader;
+  bool AnalyzeSystemHeaders = false;
 } Includes;
   } Diagnostics;
 
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp 
b/clang-tools-extra/clangd/ConfigCompile.cpp
index 5bb2eb4a9f803..f74c870adfb73 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -572,32 +572,43 @@ struct FragmentCompiler {
 #else
 static llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags;
 #endif
-auto Filters = std::make_shared>();
-for (auto &HeaderPattern : F.IgnoreHeader) {
-  // Anchor on the right.
-  std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
-  llvm::Regex CompiledRegex(AnchoredPattern, Flags);
-  std::string RegexError;
-  if (!CompiledRegex.isValid(RegexError)) {
-diag(Warning,
- llvm::formatv("Invalid regular expression '{0}': {1}",
-   *HeaderPattern, RegexError)
- .str(),
- HeaderPattern.Range);
-continue;
+std::shared_ptr> Filters;
+if (!F.IgnoreHeader.empty()) {
+  Filters = std::make_shared>();
+  for (auto &HeaderPattern : F.IgnoreHeader) {
+// Anchor on the right.
+std::string AnchoredPattern = "(" + *HeaderPattern + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern, Flags);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  diag(Warning,
+   llvm::formatv("Invalid regular expression '{0}': {1}",
+ *HeaderPattern, RegexError)
+   .str(),
+   HeaderPattern.Range);
+  continue;
+}
+Filters->push_back(std::move(CompiledRegex));
   }
-  Filters->push_back(std::move(CompiledRegex));
 }
-if (Filters->empty())
+std::optional AnalyzeSystemHeaders;
+if (F.AnalyzeSystemHeaders.has_value())
+  AnalyzeSystemHeaders = **F.AnalyzeSystemHeaders;
+if (!Filters && !AnalyzeSystemHeaders.has_value())
   return;
-auto Filter = [Filters](llvm::StringRef Path) {
-  for (auto &Regex : *Filters)
-if (Regex.match(Path))
-  return true;
-  return false;
-};
-Out.Apply.push_back([Filter](const Params &, Config &C) {
-  C.Diagnostics.Includes.IgnoreHeader.emplace_back(Filter);
+Out.Apply.push_back([Filters = std::move(Filters),
+ AnalyzeSystemHeaders](const Params &, Config &C) {
+  if (Filters) {
+auto Filter = [Filters](llvm::StringRef Path) {
+  for (auto &Regex : *Filters)
+if (Regex.match(Path))
+  return true;
+  return false;
+};
+C.Diagnostics.Includes.IgnoreHeader.emplace_back(std::move(Filter));
+  }
+  if (AnalyzeSystemHeaders.has_value())
+C.Diagnostics.Includes.AnalyzeSystemHeaders = *AnalyzeSystemHeaders;
 });
   }
 
diff --git a/clang-tools-extra/clangd/ConfigFragment.h 
b/clang-tools-extra/clangd/ConfigFragment.h
index 7fa61108c78a0..ac8b88c245412 100644
--- a/clang-tools-extra/clangd/ConfigFragment.h
+++ b/clang-tools-extra/clangd/ConfigFragment.h
@@ -254,6 +254,10 @@ struct Fragment {
   /// unused or missing. These can match any suffix of the header file in
   /// question.
   std::vector> IgnoreHeader;
+
+  /// If false (default), unused system headers will be ignored.
+  /// Standard library headers are analyzed regardless of this option.
+  std::optional> AnalyzeSystemHeaders;
 };
 IncludesBlock Includes;
 
diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp 
b/clang-tools-extra/clangd/ConfigYAML.cpp
index ce09af819247a..7608af4200538 100644
--- a/clang-t

[clang-tools-extra] [clangd] Add config option to allow detection of unused system headers (PR #87208)

2024-05-27 Thread Vadim D. via cfe-commits

vvd170501 wrote:

Ping. @kadircet, can you merge this, please? Or are additional approvals 
required?

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


[clang] [clang-tools-extra] Fix OOM in FormatDiagnostic (PR #108187)

2024-09-14 Thread Vadim D. via cfe-commits


@@ -945,50 +959,11 @@ class DiagnosticsEngine : public 
RefCountedBase {
 
   void Report(const StoredDiagnostic &storedDiag);
 
-  /// Determine whethere there is already a diagnostic in flight.
-  bool isDiagnosticInFlight() const {
-return CurDiagID != std::numeric_limits::max();
-  }
-
-  /// Set the "delayed" diagnostic that will be emitted once
-  /// the current diagnostic completes.
-  ///
-  ///  If a diagnostic is already in-flight but the front end must
-  ///  report a problem (e.g., with an inconsistent file system
-  ///  state), this routine sets a "delayed" diagnostic that will be
-  ///  emitted after the current diagnostic completes. This should
-  ///  only be used for fatal errors detected at inconvenient
-  ///  times. If emitting a delayed diagnostic causes a second delayed
-  ///  diagnostic to be introduced, that second delayed diagnostic
-  ///  will be ignored.
-  ///
-  /// \param DiagID The ID of the diagnostic being delayed.
-  ///
-  /// \param Arg1 A string argument that will be provided to the
-  /// diagnostic. A copy of this string will be stored in the
-  /// DiagnosticsEngine object itself.
-  ///
-  /// \param Arg2 A string argument that will be provided to the
-  /// diagnostic. A copy of this string will be stored in the
-  /// DiagnosticsEngine object itself.
-  ///
-  /// \param Arg3 A string argument that will be provided to the
-  /// diagnostic. A copy of this string will be stored in the
-  /// DiagnosticsEngine object itself.
-  void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
-StringRef Arg2 = "", StringRef Arg3 = "");
-
-  /// Clear out the current diagnostic.
-  void Clear() { CurDiagID = std::numeric_limits::max(); }
-
-  /// Return the value associated with this diagnostic flag.
-  StringRef getFlagValue() const { return FlagValue; }
-
 private:
   // This is private state used by DiagnosticBuilder.  We put it here instead 
of
   // in DiagnosticBuilder in order to keep DiagnosticBuilder a small 
lightweight
-  // object.  This implementation choice means that we can only have one
-  // diagnostic "in flight" at a time, but this seems to be a reasonable
+  // object.  This implementation choice means that we can only have a few
+  // diagnostics "in flight" at a time, but this seems to be a reasonable
   // tradeoff to keep these objects small.  Assertions verify that only one
   // diagnostic is in flight at a time.

vvd170501 wrote:

"Assertions verify that only one diagnostic is in flight at a time" is now 
outdated and can be removed.

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


[clang] Update std symbols mapping (fixes #113494) (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits


@@ -115,15 +115,17 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),

vvd170501 wrote:

This assertion could fail only if entries for a symbol were partially grouped, 
but it didn't fail if entries weren't grouped at all.
Example:
```cpp
// StdSpecialSymbolMap.inc
SYMBOL(any_cast, std::, )
SYMBOL(div, std::, )
// StdSymbolMap.inc
SYMBOL(any, std::, )
SYMBOL(any_cast, std::, )  // assertion doesn't fail because previous 
entry has a different name
...

```

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


[clang] Update std symbols mapping (fixes #113494) (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits

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


[clang] Update std symbols mapping (fixes #113494) (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits

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


[clang] Update std symbols mapping (fixes #113494) (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 8fac50dc444eeb6c9ad19eb11f7d95457b153528 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Thu, 24 Oct 2024 17:36:22 +0300
Subject: [PATCH 1/3] Move assertion to detect all ungrouped mappings

---
 clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 0832bcf66145fa..49e5765af112ff 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -115,15 +115,17 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
[&QName](const SymbolHeaderMapping::SymbolName &S) {
  return S.qualifiedName() == QName;
}) &&
  "The symbol has been added before, make sure entries in the .inc "
  "file are grouped by symbol name!");
+}
+if (SymIndex >= 0 &&
+Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
+  // Not a new symbol, use the same index.
 } else {
   // First symbol or new symbol, increment next available index.
   ++SymIndex;

>From ba2d997ba87e2a5193429d3ca4900d4ae39420b7 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Wed, 23 Oct 2024 23:22:56 +0300
Subject: [PATCH 2/3] Update std symbol mapping to v20230810

---
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc | 130 -
 .../Inclusions/Stdlib/StdSymbolMap.inc| 171 --
 2 files changed, 194 insertions(+), 107 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index 0d351d688a3296..156e1e8ad5321c 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -233,6 +233,23 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 
+// Overloads for different containers, actual header depends on function arg.
+// Probably should use a special handler, like with std::move.
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+
 // Add headers for generic integer-type abs.
 // Ignore other variants (std::complex, std::valarray, std::intmax_t)
 SYMBOL(abs, std::, )
@@ -242,9 +259,77 @@ SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 
-// Only add headers for the generic atomic template.
+// Same as abs - ignore variants (std::complex, std::valarray)
+SYMBOL(acos, std::, )
+SYMBOL(acos, None, )
+SYMBOL(acos, None, )
+SYMBOL(acosh, std::, )
+SYMBOL(acosh, None, )
+SYMBOL(acosh, None, )
+SYMBOL(asin, std::, )
+SYMBOL(asin, None, )
+SYMBOL(asin, None, )
+SYMBOL(asinh, std::, )
+SYMBOL(asinh, None, )
+SYMBOL(asinh, None, )
+SYMBOL(atan, std::, )
+SYMBOL(atan, None, )
+SYMBOL(atan, None, )
+SYMBOL(atan2, std::, )
+SYMBOL(atan2, None, )
+SYMBOL(atan2, None, )
+SYMBOL(atanh, std::, )
+SYMBOL(atanh, None, )
+SYMBOL(atanh, None, )
+SYMBOL(cos, std::, )
+SYMBOL(cos, None, )
+SYMBOL(cos, None, )
+SYMBOL(cosh, std::, )
+SYMBOL(cosh, None, )
+SYMBOL(cosh, None, )
+SYMBOL(exp, std::, )
+SYMBOL(exp, None, )
+SYMBOL(exp, None, )
+SYMBOL(log, std::, )
+SYMBOL(log, None, )
+SYMBOL(log, None, )
+SYMBOL(log10, std::, )
+SYMBOL(log10, None, )
+SYMBOL(log10, None, )
+SYMBOL(pow, std::, )
+SYMBOL(pow, None, )
+SYMBOL(pow, None, )
+SYMBOL(sin, std::, )
+SYMBOL(sin, None, )
+SYMBOL(sin, None, )
+SYMBOL(sinh, std::, )
+SYMBOL(sinh, None, )
+SYMBOL(sinh, None, )
+SYMBOL(sqrt, std::, )
+SYMBOL(sqrt, None, )
+SYMBOL(sqrt, None, )
+SYMBOL(tan, std::, )
+SYMBOL(tan, None, )
+SYMBOL(tan, None, )
+SYMBOL(tanh, std::, )
+SYMBOL(tanh, None, )
+SYMBOL(tanh, None, )
+
+// Only add headers for the generic atomic template and atomic_* template 
functions.
 // Ignore variants (std::weak_ptr, std::shared_ptr).
 SYMBOL(atomic, std::, )
+SYMBOL(atomic_compare_exchange_strong, std::, )
+SYMBOL(atomic_compare_exchange_strong_explicit, std::, )
+SYMBOL(atomic_compare_exchange_weak, std::, )
+SYMBOL(atomic_compare_exchange_weak_explicit, std::, )
+SYMBOL(atomic_exchange, std::, )
+SYMBOL(atomic_exchange_explicit, std::, )
+SYMBOL

[clang] Update std symbols mapping (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits

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


[clang] Update std symbols mapping (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 96662cb7f681e7158c05a0190894de70eee03d67 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Thu, 24 Oct 2024 23:18:52 +0300
Subject: [PATCH] Update std symbol mapping to v20230810; Move assertion to
 detect all ungrouped mappings

---
 .../Inclusions/Stdlib/StandardLibrary.cpp |   8 +-
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc | 131 +-
 .../Inclusions/Stdlib/StdSymbolMap.inc| 171 --
 3 files changed, 200 insertions(+), 110 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 0832bcf66145fa..49e5765af112ff 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -115,15 +115,17 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
[&QName](const SymbolHeaderMapping::SymbolName &S) {
  return S.qualifiedName() == QName;
}) &&
  "The symbol has been added before, make sure entries in the .inc "
  "file are grouped by symbol name!");
+}
+if (SymIndex >= 0 &&
+Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
+  // Not a new symbol, use the same index.
 } else {
   // First symbol or new symbol, increment next available index.
   ++SymIndex;
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index 0d351d688a3296..13060a0cc1d529 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -233,6 +233,23 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 
+// Overloads for different containers, actual header depends on function arg.
+// Probably should use a special handler, like with std::move.
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+
 // Add headers for generic integer-type abs.
 // Ignore other variants (std::complex, std::valarray, std::intmax_t)
 SYMBOL(abs, std::, )
@@ -242,9 +259,78 @@ SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 
-// Only add headers for the generic atomic template.
+// Same as abs - ignore variants (std::complex, std::valarray)
+SYMBOL(acos, std::, )
+SYMBOL(acos, None, )
+SYMBOL(acos, None, )
+SYMBOL(acosh, std::, )
+SYMBOL(acosh, None, )
+SYMBOL(acosh, None, )
+SYMBOL(asin, std::, )
+SYMBOL(asin, None, )
+SYMBOL(asin, None, )
+SYMBOL(asinh, std::, )
+SYMBOL(asinh, None, )
+SYMBOL(asinh, None, )
+SYMBOL(atan, std::, )
+SYMBOL(atan, None, )
+SYMBOL(atan, None, )
+SYMBOL(atan2, std::, )
+SYMBOL(atan2, None, )
+SYMBOL(atan2, None, )
+SYMBOL(atanh, std::, )
+SYMBOL(atanh, None, )
+SYMBOL(atanh, None, )
+SYMBOL(cos, std::, )
+SYMBOL(cos, None, )
+SYMBOL(cos, None, )
+SYMBOL(cosh, std::, )
+SYMBOL(cosh, None, )
+SYMBOL(cosh, None, )
+SYMBOL(exp, std::, )
+SYMBOL(exp, None, )
+SYMBOL(exp, None, )
+SYMBOL(log, std::, )
+SYMBOL(log, None, )
+SYMBOL(log, None, )
+SYMBOL(log10, std::, )
+SYMBOL(log10, None, )
+SYMBOL(log10, None, )
+SYMBOL(pow, std::, )
+SYMBOL(pow, None, )
+SYMBOL(pow, None, )
+SYMBOL(sin, std::, )
+SYMBOL(sin, None, )
+SYMBOL(sin, None, )
+SYMBOL(sinh, std::, )
+SYMBOL(sinh, None, )
+SYMBOL(sinh, None, )
+SYMBOL(sqrt, std::, )
+SYMBOL(sqrt, None, )
+SYMBOL(sqrt, None, )
+SYMBOL(tan, std::, )
+SYMBOL(tan, None, )
+SYMBOL(tan, None, )
+SYMBOL(tanh, std::, )
+SYMBOL(tanh, None, )
+SYMBOL(tanh, None, )
+
+// Only add headers for the generic atomic template
+// and atomic_* template functions.
 // Ignore variants (std::weak_ptr, std::shared_ptr).
 SYMBOL(atomic, std::, )
+SYMBOL(atomic_compare_exchange_strong, std::, )
+SYMBOL(atomic_compare_exchange_strong_explicit, std::, )
+SYMBOL(atomic_compare_exchange_weak, std::, )
+SYMBOL(atomic_compare_exchange_weak_explicit, std::, )
+SYMBOL(atomic_exchange, std::, )
+SYMBOL(atomic_exchange_explicit, std::, )
+SYMBOL(atomic_is_lock_free, std::, )
+SYMBOL(atomic_load, std::, )
+SYMBOL(atomic_load_explicit, std::, )
+SYMBOL(atomic_store, std::, )
+SYMBOL(atomic_store_explicit, std::, )
+
 // atomic_* family symbols.  is for C compatibility.
 SYMBOL(atomic_bool, std::, )
 SYMBOL(atomic_bool, None, )
@@ -355,18 +441,4

[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-10-29 Thread Vadim D. via cfe-commits


@@ -232,6 +232,37 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
+// C++ [range.access.general]: ... the customization point objects
+// in [range.access] are available when the header  is included.
+SYMBOL(begin, std::ranges::, )
+SYMBOL(begin, std::ranges::, )
+SYMBOL(cbegin, std::ranges::, )
+SYMBOL(cbegin, std::ranges::, )
+SYMBOL(cdata, std::ranges::, )
+SYMBOL(cdata, std::ranges::, )
+SYMBOL(cend, std::ranges::, )
+SYMBOL(cend, std::ranges::, )
+SYMBOL(crbegin, std::ranges::, )
+SYMBOL(crbegin, std::ranges::, )
+SYMBOL(crend, std::ranges::, )
+SYMBOL(crend, std::ranges::, )
+SYMBOL(data, std::ranges::, )
+SYMBOL(data, std::ranges::, )
+SYMBOL(empty, std::ranges::, )
+SYMBOL(empty, std::ranges::, )
+SYMBOL(end, std::ranges::, )
+SYMBOL(end, std::ranges::, )
+SYMBOL(rbegin, std::ranges::, )
+SYMBOL(rbegin, std::ranges::, )
+SYMBOL(rend, std::ranges::, )
+SYMBOL(rend, std::ranges::, )
+SYMBOL(size, std::ranges::, )
+SYMBOL(size, std::ranges::, )
+SYMBOL(ssize, std::ranges::, )
+SYMBOL(ssize, std::ranges::, )

vvd170501 wrote:

Done

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


[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-10-29 Thread Vadim D. via cfe-commits




vvd170501 wrote:

I've reverted the optimizations, will create a new PR when this one is merged 
(the commit depends on other changes that I've left in this PR)

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


[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-10-29 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 853881983faeeb5b7e0582d3e94037c12df12c7c Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 00:17:26 +0300
Subject: [PATCH 1/4] Fix variant parsing

---
 .../include-mapping/cppreference_parser.py| 33 ---
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index f2ea55384fac80..70e403bba64917 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -7,7 +7,7 @@
 #
 # 
======#
 
-from bs4 import BeautifulSoup, NavigableString
+from bs4 import BeautifulSoup, NavigableString, Tag
 
 import collections
 import multiprocessing
@@ -89,6 +89,23 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 return headers or all_headers
 
 
+def _ParseSymbolVariant(caption):
+if not (isinstance(caption, NavigableString) and "(" in caption):
+return None
+
+if ')' in caption.text:  # (locale), (algorithm), etc.
+return caption.text.strip(" ()")
+
+second_part = caption.next_sibling
+if isinstance(second_part, Tag) and second_part.name == "code":
+# (std::complex), etc.
+third_part = second_part.next_sibling
+if isinstance(third_part, NavigableString) and 
third_part.text.startswith(')'):
+return second_part.text
+return None
+
+
+
 def _ParseIndexPage(index_page_html):
 """Parse index page.
 The index page lists all std symbols and hrefs to their detailed pages
@@ -107,9 +124,7 @@ def _ParseIndexPage(index_page_html):
 # This accidentally accepts begin/end despite the (iterator) caption: 
the
 # (since C++11) note is first. They are good symbols, so the bug is 
unfixed.
 caption = symbol_href.next_sibling
-variant = None
-if isinstance(caption, NavigableString) and "(" in caption:
-variant = caption.text.strip(" ()")
+variant = _ParseSymbolVariant(caption)
 symbol_tt = symbol_href.find("tt")
 if symbol_tt:
 symbols.append(
@@ -192,6 +207,16 @@ def GetSymbols(parse_pages):
 variants_to_accept = {
 # std::remove<> has variant algorithm.
 "std::remove": ("algorithm"),
+# These functions don't have a generic version, and all variants are 
defined in 
+"std::chrono::abs": ("std::chrono::duration"),
+"std::chrono::ceil": ("std::chrono::duration"),
+"std::chrono::floor": ("std::chrono::duration"),
+"std::chrono::from_stream": ("std::chrono::day"),
+"std::chrono::round": ("std::chrono::duration"),
+# Same, but in 
+"std::filesystem::begin": ("std::filesystem::directory_iterator"),
+"std::filesystem::end": ("std::filesystem::directory_iterator"),
+"std::ranges::get": ("std::ranges::subrange"),
 }
 symbols = []
 # Run many workers to process individual symbol pages under the symbol 
index.

>From 76fd590931925f817f54f684af90a81305c7b1f5 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 06:38:41 +0300
Subject: [PATCH 2/4] Parse symbols with qualified name

---
 .../include-mapping/cppreference_parser.py| 24 ++-
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index 70e403bba64917..9101f3dbff0f94 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -40,7 +40,7 @@ def _HasClass(tag, *classes):
 return False
 
 
-def _ParseSymbolPage(symbol_page_html, symbol_name):
+def _ParseSymbolPage(symbol_page_html, symbol_name, qual_name):
 """Parse symbol page and retrieve the include header defined in this page.
 The symbol page provides header for the symbol, specifically in
 "Defined in header " section. An example:
@@ -69,7 +69,9 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 was_decl = True
 # Symbols are in the first cell.
 found_symbols = row.find("td").stripped_strings
-if not symbol_name in found_symbols:
+if not any(
+sym == symbol_name or sym == qual_name for sym in 
found_symbols
+):
 continue
 headers.update(current_headers)
 elif _HasClass(row, "t-dsc-header"):
@@ -93,19 +95,18 @@ def _ParseSymbolVariant(caption):
 if not (isinstance(caption, NavigableString) and "(" in caption):
 return None
 
-if ')' in caption.text:  # (locale), (algorithm), etc.
+if ")" 

[clang] [Tooling/Inclusion] Optimize cppreference parser (parse each page only once) (PR #114832)

2024-11-04 Thread Vadim D. via cfe-commits

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


[clang] [Tooling/Inclusion] Optimize cppreference parser (PR #114832)

2024-11-04 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 created 
https://github.com/llvm/llvm-project/pull/114832

These are reverted changes from  #113612. They don't affect clang itself, but 
speed up std symbol mapping generator by ~1.5x.
On a machine with 2 cores, it previously took 3 minutes to generate the 
mapping, now it only takes 2 minutes.
With 8 cores, the time goes down from ~50s to ~30s

>From cde239f6168e525d543f90a029ba643bc1b8c797 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Mon, 4 Nov 2024 19:53:35 +0300
Subject: [PATCH] Don't reparse symbol pages (speedup up to 1.5x)

---
 .../include-mapping/cppreference_parser.py| 48 +++
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index 9101f3dbff0f94..d26f4c4395ab92 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -40,7 +40,7 @@ def _HasClass(tag, *classes):
 return False
 
 
-def _ParseSymbolPage(symbol_page_html, symbol_name, qual_name):
+def _ParseSymbolPage(symbol_page_html, symbols):
 """Parse symbol page and retrieve the include header defined in this page.
 The symbol page provides header for the symbol, specifically in
 "Defined in header " section. An example:
@@ -51,8 +51,12 @@ def _ParseSymbolPage(symbol_page_html, symbol_name, 
qual_name):
 
 Returns a list of headers.
 """
-headers = set()
+headers = collections.defaultdict(set)
 all_headers = set()
+symbol_names = {}
+for symbol_name, qualified_symbol_name in symbols:
+symbol_names[symbol_name] = symbol_name
+symbol_names[qualified_symbol_name] = symbol_name
 
 soup = BeautifulSoup(symbol_page_html, "html.parser")
 # Rows in table are like:
@@ -69,11 +73,10 @@ def _ParseSymbolPage(symbol_page_html, symbol_name, 
qual_name):
 was_decl = True
 # Symbols are in the first cell.
 found_symbols = row.find("td").stripped_strings
-if not any(
-sym == symbol_name or sym == qual_name for sym in 
found_symbols
-):
-continue
-headers.update(current_headers)
+for found_symbol in found_symbols:
+symbol_name = symbol_names.get(found_symbol)
+if symbol_name:
+headers[symbol_name].update(current_headers)
 elif _HasClass(row, "t-dsc-header"):
 # If we saw a decl since the last header, this is a new block 
of headers
 # for a new block of decls.
@@ -88,7 +91,10 @@ def _ParseSymbolPage(symbol_page_html, symbol_name, 
qual_name):
 current_headers.append(header_code.text)
 all_headers.add(header_code.text)
 # If the symbol was never named, consider all named headers.
-return headers or all_headers
+return [
+(symbol_name, headers.get(symbol_name) or all_headers)
+for symbol_name, _ in symbols
+]
 
 
 def _ParseSymbolVariant(caption):
@@ -138,9 +144,9 @@ def _ParseIndexPage(index_page_html):
 return symbols
 
 
-def _ReadSymbolPage(path, name, qual_name):
+def _ReadSymbolPage(path, symbols):
 with open(path) as f:
-return _ParseSymbolPage(f.read(), name, qual_name)
+return _ParseSymbolPage(f.read(), symbols)
 
 
 def _GetSymbols(pool, root_dir, index_page_name, namespace, 
variants_to_accept):
@@ -159,6 +165,7 @@ def _GetSymbols(pool, root_dir, index_page_name, namespace, 
variants_to_accept):
 with open(index_page_path, "r") as f:
 # Read each symbol page in parallel.
 results = []  # (symbol_name, promise of [header...])
+symbols_by_page = collections.defaultdict(list)
 for symbol_name, symbol_page_path, variant in 
_ParseIndexPage(f.read()):
 # Variant symbols (e.g. the std::locale version of isalpha) add 
ambiguity.
 # FIXME: use these as a fallback rather than ignoring entirely.
@@ -167,25 +174,24 @@ def _GetSymbols(pool, root_dir, index_page_name, 
namespace, variants_to_accept):
 if variant and variant not in variants_for_symbol:
 continue
 path = os.path.join(root_dir, symbol_page_path)
-if os.path.isfile(path):
-results.append(
-(
-symbol_name,
-pool.apply_async(
-_ReadSymbolPage, (path, symbol_name, 
qualified_symbol_name)
-),
-)
-)
+if path in symbols_by_page or os.path.isfile(path):
+symbols_by_page[path].append((symbol_name, 
qualified_symbol_name))
 else:
 sys.stderr.write(
 "Discarding information for symbol: %s. Page %s does not

[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-11-03 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 1baa1c2aebd37da2f2ccc3918fa3425698860566 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 00:17:26 +0300
Subject: [PATCH] Update std symbol mapping to v20240610; Update mapping
 generator; Move assertion to detect all ungrouped mappings

(rebase to test with updated StdSpecialSymbolMap.inc)
---
 .../Inclusions/Stdlib/StandardLibrary.cpp |  10 +-
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc |  47 ++-
 .../Inclusions/Stdlib/StdSymbolMap.inc| 116 ++
 .../include-mapping/cppreference_parser.py|  51 ++--
 4 files changed, 178 insertions(+), 46 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 0832bcf66145fa..90c95d5cf60d86 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -115,19 +115,19 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
[&QName](const SymbolHeaderMapping::SymbolName &S) {
  return S.qualifiedName() == QName;
}) &&
  "The symbol has been added before, make sure entries in the .inc "
  "file are grouped by symbol name!");
-} else {
+}
+if (SymIndex < 0 ||
+Mapping->SymbolNames[SymIndex].qualifiedName() != QName) {
   // First symbol or new symbol, increment next available index.
   ++SymIndex;
-}
+} // Else use the same index.
 Mapping->SymbolNames[SymIndex] = {
 QName.data(), NSLen, static_cast(QName.size() - NSLen)};
 if (!HeaderName.empty())
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index 4d466013eeac3f..8f20ce98152f08 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -232,6 +232,38 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
+// C++ [range.access.general]: ... the customization point objects
+// in [range.access] are available when the header  is included.
+// (see https://eel.is/c++draft/range.access#general)
+SYMBOL(begin, std::ranges::, )
+SYMBOL(begin, std::ranges::, )
+SYMBOL(end, std::ranges::, )
+SYMBOL(end, std::ranges::, )
+SYMBOL(cbegin, std::ranges::, )
+SYMBOL(cbegin, std::ranges::, )
+SYMBOL(cend, std::ranges::, )
+SYMBOL(cend, std::ranges::, )
+SYMBOL(rbegin, std::ranges::, )
+SYMBOL(rbegin, std::ranges::, )
+SYMBOL(rend, std::ranges::, )
+SYMBOL(rend, std::ranges::, )
+SYMBOL(crbegin, std::ranges::, )
+SYMBOL(crbegin, std::ranges::, )
+SYMBOL(crend, std::ranges::, )
+SYMBOL(crend, std::ranges::, )
+SYMBOL(size, std::ranges::, )
+SYMBOL(size, std::ranges::, )
+SYMBOL(ssize, std::ranges::, )
+SYMBOL(ssize, std::ranges::, )
+SYMBOL(empty, std::ranges::, )
+SYMBOL(empty, std::ranges::, )
+SYMBOL(data, std::ranges::, )
+SYMBOL(data, std::ranges::, )
+SYMBOL(cdata, std::ranges::, )
+SYMBOL(cdata, std::ranges::, )
+
+// Ignore specializations
+SYMBOL(hash, std::, )
 
 // Add headers for generic integer-type abs.
 // Ignore other variants (std::complex, std::valarray, std::intmax_t)
@@ -352,20 +384,23 @@ SYMBOL(get, std::, /*no headers*/)
 // providing the type.
 SYMBOL(make_error_code, std::, /*no headers*/)
 SYMBOL(make_error_condition, std::, /*no headers*/)
+// Similar to std::get, has variants for multiple containers
+// (vector, deque, list, etc.)
+SYMBOL(erase, std::, /*no headers*/)
+SYMBOL(erase_if, std::, /*no headers*/)
 
 // cppreference symbol index page was missing these symbols.
 // Remove them when the cppreference offline archive catches up.
-SYMBOL(index_sequence, std::, )
-SYMBOL(index_sequence_for, std::, )
-SYMBOL(make_index_sequence, std::, )
-SYMBOL(make_integer_sequence, std::, )
+SYMBOL(regular_invocable, std::, )
 
 // Symbols missing from the generated symbol map as reported by users.
 // Remove when the generator starts producing them.
-SYMBOL(make_any, std::, )
-SYMBOL(any_cast, std::, )
 SYMBOL(div, std::, )
 SYMBOL(abort, std::, )
+SYMBOL(atomic_wait, std::, )
+SYMBOL(atomic_wait_explicit, std::, )
+SYMBOL(move_backward, std::, )
+SYMBOL(month_weekday, std::chrono::, )
 
 SYMBOL(binary_search, std::ranges::, )
 SYMBOL(equal_range, std::ranges::, )
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
index b46bd2e4d7a4b5..b4afd0228694ff 100644
--- a/clang/lib/Tooling

[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-11-03 Thread Vadim D. via cfe-commits

vvd170501 wrote:

@kadircet, ping. Could you commit these changes, please?

I've rebased to make sure that 68daf7d27ecc085fe7347552736197db6453f71c didn't 
cause any conflicts.

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


[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-10-30 Thread Vadim D. via cfe-commits

vvd170501 wrote:

> thanks a lot, lgtm!
> 
> LMK if i should commit this for you

Yes, commit it please, I don't have the permissions.

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


[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-10-29 Thread Vadim D. via cfe-commits


@@ -352,20 +383,23 @@ SYMBOL(get, std::, /*no headers*/)
 // providing the type.
 SYMBOL(make_error_code, std::, /*no headers*/)
 SYMBOL(make_error_condition, std::, /*no headers*/)
+// Similar to std::get, has variants for multiple containers
+// (vector, deque, list, etc.)
+SYMBOL(erase, std::, /*no headers*/)
+SYMBOL(erase_if, std::, /*no headers*/)
 
 // cppreference symbol index page was missing these symbols.
 // Remove them when the cppreference offline archive catches up.
-SYMBOL(index_sequence, std::, )
-SYMBOL(index_sequence_for, std::, )
-SYMBOL(make_index_sequence, std::, )
-SYMBOL(make_integer_sequence, std::, )
+SYMBOL(regular_invocable, std::, )
 
 // Symbols missing from the generated symbol map as reported by users.
 // Remove when the generator starts producing them.
-SYMBOL(make_any, std::, )
-SYMBOL(any_cast, std::, )
 SYMBOL(div, std::, )
 SYMBOL(abort, std::, )
+SYMBOL(atomic_wait, std::, )
+SYMBOL(atomic_wait_explicit, std::, )
+SYMBOL(move_backward, std::, )
+SYMBOL(month_weekday, std::chrono::, )

vvd170501 wrote:

I've suggested fixes to the corresponding cppreference pages, the editors have 
added them.

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


[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-10-30 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 853881983faeeb5b7e0582d3e94037c12df12c7c Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 00:17:26 +0300
Subject: [PATCH 1/5] Fix variant parsing

---
 .../include-mapping/cppreference_parser.py| 33 ---
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index f2ea55384fac80..70e403bba64917 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -7,7 +7,7 @@
 #
 # 
======#
 
-from bs4 import BeautifulSoup, NavigableString
+from bs4 import BeautifulSoup, NavigableString, Tag
 
 import collections
 import multiprocessing
@@ -89,6 +89,23 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 return headers or all_headers
 
 
+def _ParseSymbolVariant(caption):
+if not (isinstance(caption, NavigableString) and "(" in caption):
+return None
+
+if ')' in caption.text:  # (locale), (algorithm), etc.
+return caption.text.strip(" ()")
+
+second_part = caption.next_sibling
+if isinstance(second_part, Tag) and second_part.name == "code":
+# (std::complex), etc.
+third_part = second_part.next_sibling
+if isinstance(third_part, NavigableString) and 
third_part.text.startswith(')'):
+return second_part.text
+return None
+
+
+
 def _ParseIndexPage(index_page_html):
 """Parse index page.
 The index page lists all std symbols and hrefs to their detailed pages
@@ -107,9 +124,7 @@ def _ParseIndexPage(index_page_html):
 # This accidentally accepts begin/end despite the (iterator) caption: 
the
 # (since C++11) note is first. They are good symbols, so the bug is 
unfixed.
 caption = symbol_href.next_sibling
-variant = None
-if isinstance(caption, NavigableString) and "(" in caption:
-variant = caption.text.strip(" ()")
+variant = _ParseSymbolVariant(caption)
 symbol_tt = symbol_href.find("tt")
 if symbol_tt:
 symbols.append(
@@ -192,6 +207,16 @@ def GetSymbols(parse_pages):
 variants_to_accept = {
 # std::remove<> has variant algorithm.
 "std::remove": ("algorithm"),
+# These functions don't have a generic version, and all variants are 
defined in 
+"std::chrono::abs": ("std::chrono::duration"),
+"std::chrono::ceil": ("std::chrono::duration"),
+"std::chrono::floor": ("std::chrono::duration"),
+"std::chrono::from_stream": ("std::chrono::day"),
+"std::chrono::round": ("std::chrono::duration"),
+# Same, but in 
+"std::filesystem::begin": ("std::filesystem::directory_iterator"),
+"std::filesystem::end": ("std::filesystem::directory_iterator"),
+"std::ranges::get": ("std::ranges::subrange"),
 }
 symbols = []
 # Run many workers to process individual symbol pages under the symbol 
index.

>From 76fd590931925f817f54f684af90a81305c7b1f5 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 06:38:41 +0300
Subject: [PATCH 2/5] Parse symbols with qualified name

---
 .../include-mapping/cppreference_parser.py| 24 ++-
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index 70e403bba64917..9101f3dbff0f94 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -40,7 +40,7 @@ def _HasClass(tag, *classes):
 return False
 
 
-def _ParseSymbolPage(symbol_page_html, symbol_name):
+def _ParseSymbolPage(symbol_page_html, symbol_name, qual_name):
 """Parse symbol page and retrieve the include header defined in this page.
 The symbol page provides header for the symbol, specifically in
 "Defined in header " section. An example:
@@ -69,7 +69,9 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 was_decl = True
 # Symbols are in the first cell.
 found_symbols = row.find("td").stripped_strings
-if not symbol_name in found_symbols:
+if not any(
+sym == symbol_name or sym == qual_name for sym in 
found_symbols
+):
 continue
 headers.update(current_headers)
 elif _HasClass(row, "t-dsc-header"):
@@ -93,19 +95,18 @@ def _ParseSymbolVariant(caption):
 if not (isinstance(caption, NavigableString) and "(" in caption):
 return None
 
-if ')' in caption.text:  # (locale), (algorithm), etc.
+if ")" 

[clang] Update std symbols mapping (fixes #113494) (PR #113612)

2024-10-25 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 created 
https://github.com/llvm/llvm-project/pull/113612

None

>From 8fac50dc444eeb6c9ad19eb11f7d95457b153528 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Thu, 24 Oct 2024 17:36:22 +0300
Subject: [PATCH 1/2] Move assertion to detect all ungrouped mappings

---
 clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 0832bcf66145fa..49e5765af112ff 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -115,15 +115,17 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
[&QName](const SymbolHeaderMapping::SymbolName &S) {
  return S.qualifiedName() == QName;
}) &&
  "The symbol has been added before, make sure entries in the .inc "
  "file are grouped by symbol name!");
+}
+if (SymIndex >= 0 &&
+Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
+  // Not a new symbol, use the same index.
 } else {
   // First symbol or new symbol, increment next available index.
   ++SymIndex;

>From ba2d997ba87e2a5193429d3ca4900d4ae39420b7 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Wed, 23 Oct 2024 23:22:56 +0300
Subject: [PATCH 2/2] Update std symbol mapping to v20230810

---
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc | 130 -
 .../Inclusions/Stdlib/StdSymbolMap.inc| 171 --
 2 files changed, 194 insertions(+), 107 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index 0d351d688a3296..156e1e8ad5321c 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -233,6 +233,23 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 
+// Overloads for different containers, actual header depends on function arg.
+// Probably should use a special handler, like with std::move.
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+
 // Add headers for generic integer-type abs.
 // Ignore other variants (std::complex, std::valarray, std::intmax_t)
 SYMBOL(abs, std::, )
@@ -242,9 +259,77 @@ SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 
-// Only add headers for the generic atomic template.
+// Same as abs - ignore variants (std::complex, std::valarray)
+SYMBOL(acos, std::, )
+SYMBOL(acos, None, )
+SYMBOL(acos, None, )
+SYMBOL(acosh, std::, )
+SYMBOL(acosh, None, )
+SYMBOL(acosh, None, )
+SYMBOL(asin, std::, )
+SYMBOL(asin, None, )
+SYMBOL(asin, None, )
+SYMBOL(asinh, std::, )
+SYMBOL(asinh, None, )
+SYMBOL(asinh, None, )
+SYMBOL(atan, std::, )
+SYMBOL(atan, None, )
+SYMBOL(atan, None, )
+SYMBOL(atan2, std::, )
+SYMBOL(atan2, None, )
+SYMBOL(atan2, None, )
+SYMBOL(atanh, std::, )
+SYMBOL(atanh, None, )
+SYMBOL(atanh, None, )
+SYMBOL(cos, std::, )
+SYMBOL(cos, None, )
+SYMBOL(cos, None, )
+SYMBOL(cosh, std::, )
+SYMBOL(cosh, None, )
+SYMBOL(cosh, None, )
+SYMBOL(exp, std::, )
+SYMBOL(exp, None, )
+SYMBOL(exp, None, )
+SYMBOL(log, std::, )
+SYMBOL(log, None, )
+SYMBOL(log, None, )
+SYMBOL(log10, std::, )
+SYMBOL(log10, None, )
+SYMBOL(log10, None, )
+SYMBOL(pow, std::, )
+SYMBOL(pow, None, )
+SYMBOL(pow, None, )
+SYMBOL(sin, std::, )
+SYMBOL(sin, None, )
+SYMBOL(sin, None, )
+SYMBOL(sinh, std::, )
+SYMBOL(sinh, None, )
+SYMBOL(sinh, None, )
+SYMBOL(sqrt, std::, )
+SYMBOL(sqrt, None, )
+SYMBOL(sqrt, None, )
+SYMBOL(tan, std::, )
+SYMBOL(tan, None, )
+SYMBOL(tan, None, )
+SYMBOL(tanh, std::, )
+SYMBOL(tanh, None, )
+SYMBOL(tanh, None, )
+
+// Only add headers for the generic atomic template and atomic_* template 
functions.
 // Ignore variants (std::weak_ptr, std::shared_ptr).
 SYMBOL(atomic, std::, )
+SYMBOL(atomic_compare_exchange_strong, std::, )
+SYMBOL(atomic_compare_exchange_strong_explicit, std::, )
+SYMBOL(atomic_compare_exchange_weak, std::, )
+SYMBOL(atomic_compare_exchange_weak_explicit, std::, )
+SYMBOL(atomic_exchange, std::, )
+SYMBOL(atomic_exchange_explicit, std::, )
+

[clang] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits


@@ -143,32 +165,33 @@ def _GetSymbols(pool, root_dir, index_page_name, 
namespace, variants_to_accept):
 with open(index_page_path, "r") as f:
 # Read each symbol page in parallel.
 results = []  # (symbol_name, promise of [header...])
+symbols_by_page = collections.defaultdict(list)

vvd170501 wrote:

On my machine it took about 3 minutes for the generator to run, so I tried to 
optimize it by grouping symbols that are defined on the same page (now it takes 
2 minutes).
If the diff is too large or complex, I can move the commit with optimizations 
to a separate PR.

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


[clang] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 96662cb7f681e7158c05a0190894de70eee03d67 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Thu, 24 Oct 2024 23:18:52 +0300
Subject: [PATCH 01/13] Update std symbol mapping to v20230810; Move assertion
 to detect all ungrouped mappings

---
 .../Inclusions/Stdlib/StandardLibrary.cpp |   8 +-
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc | 131 +-
 .../Inclusions/Stdlib/StdSymbolMap.inc| 171 --
 3 files changed, 200 insertions(+), 110 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 0832bcf66145fa..49e5765af112ff 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -115,15 +115,17 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
[&QName](const SymbolHeaderMapping::SymbolName &S) {
  return S.qualifiedName() == QName;
}) &&
  "The symbol has been added before, make sure entries in the .inc "
  "file are grouped by symbol name!");
+}
+if (SymIndex >= 0 &&
+Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
+  // Not a new symbol, use the same index.
 } else {
   // First symbol or new symbol, increment next available index.
   ++SymIndex;
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index 0d351d688a3296..13060a0cc1d529 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -233,6 +233,23 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 
+// Overloads for different containers, actual header depends on function arg.
+// Probably should use a special handler, like with std::move.
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+
 // Add headers for generic integer-type abs.
 // Ignore other variants (std::complex, std::valarray, std::intmax_t)
 SYMBOL(abs, std::, )
@@ -242,9 +259,78 @@ SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 
-// Only add headers for the generic atomic template.
+// Same as abs - ignore variants (std::complex, std::valarray)
+SYMBOL(acos, std::, )
+SYMBOL(acos, None, )
+SYMBOL(acos, None, )
+SYMBOL(acosh, std::, )
+SYMBOL(acosh, None, )
+SYMBOL(acosh, None, )
+SYMBOL(asin, std::, )
+SYMBOL(asin, None, )
+SYMBOL(asin, None, )
+SYMBOL(asinh, std::, )
+SYMBOL(asinh, None, )
+SYMBOL(asinh, None, )
+SYMBOL(atan, std::, )
+SYMBOL(atan, None, )
+SYMBOL(atan, None, )
+SYMBOL(atan2, std::, )
+SYMBOL(atan2, None, )
+SYMBOL(atan2, None, )
+SYMBOL(atanh, std::, )
+SYMBOL(atanh, None, )
+SYMBOL(atanh, None, )
+SYMBOL(cos, std::, )
+SYMBOL(cos, None, )
+SYMBOL(cos, None, )
+SYMBOL(cosh, std::, )
+SYMBOL(cosh, None, )
+SYMBOL(cosh, None, )
+SYMBOL(exp, std::, )
+SYMBOL(exp, None, )
+SYMBOL(exp, None, )
+SYMBOL(log, std::, )
+SYMBOL(log, None, )
+SYMBOL(log, None, )
+SYMBOL(log10, std::, )
+SYMBOL(log10, None, )
+SYMBOL(log10, None, )
+SYMBOL(pow, std::, )
+SYMBOL(pow, None, )
+SYMBOL(pow, None, )
+SYMBOL(sin, std::, )
+SYMBOL(sin, None, )
+SYMBOL(sin, None, )
+SYMBOL(sinh, std::, )
+SYMBOL(sinh, None, )
+SYMBOL(sinh, None, )
+SYMBOL(sqrt, std::, )
+SYMBOL(sqrt, None, )
+SYMBOL(sqrt, None, )
+SYMBOL(tan, std::, )
+SYMBOL(tan, None, )
+SYMBOL(tan, None, )
+SYMBOL(tanh, std::, )
+SYMBOL(tanh, None, )
+SYMBOL(tanh, None, )
+
+// Only add headers for the generic atomic template
+// and atomic_* template functions.
 // Ignore variants (std::weak_ptr, std::shared_ptr).
 SYMBOL(atomic, std::, )
+SYMBOL(atomic_compare_exchange_strong, std::, )
+SYMBOL(atomic_compare_exchange_strong_explicit, std::, )
+SYMBOL(atomic_compare_exchange_weak, std::, )
+SYMBOL(atomic_compare_exchange_weak_explicit, std::, )
+SYMBOL(atomic_exchange, std::, )
+SYMBOL(atomic_exchange_explicit, std::, )
+SYMBOL(atomic_is_lock_free, std::, )
+SYMBOL(atomic_load, std::, )
+SYMBOL(atomic_load_explicit, std::, )
+SYMBOL(atomic_store, std::, )
+SYMBOL(atomic_store_explicit, std::, )
+
 // atomic_* family symbols.  is for C compatibility.
 SYMBOL(atomic_bool, std::, )
 SYMBOL(atomic_bool, None, )
@@ -355,18 

[clang] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits


@@ -232,6 +232,47 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
+// C++ [range.access.general]: ... the customization point objects
+// in [range.access] are available when the header  is included.
+SYMBOL(begin, std::ranges::, )
+SYMBOL(begin, std::ranges::, )
+SYMBOL(cbegin, std::ranges::, )
+SYMBOL(cbegin, std::ranges::, )
+SYMBOL(cdata, std::ranges::, )
+SYMBOL(cdata, std::ranges::, )
+SYMBOL(cend, std::ranges::, )
+SYMBOL(cend, std::ranges::, )
+SYMBOL(crbegin, std::ranges::, )
+SYMBOL(crbegin, std::ranges::, )
+SYMBOL(crend, std::ranges::, )
+SYMBOL(crend, std::ranges::, )
+SYMBOL(data, std::ranges::, )
+SYMBOL(data, std::ranges::, )
+SYMBOL(empty, std::ranges::, )
+SYMBOL(empty, std::ranges::, )
+SYMBOL(end, std::ranges::, )
+SYMBOL(end, std::ranges::, )
+SYMBOL(rbegin, std::ranges::, )
+SYMBOL(rbegin, std::ranges::, )
+SYMBOL(rend, std::ranges::, )
+SYMBOL(rend, std::ranges::, )
+SYMBOL(size, std::ranges::, )
+SYMBOL(size, std::ranges::, )
+SYMBOL(ssize, std::ranges::, )
+SYMBOL(ssize, std::ranges::, )
+
+// FIXME lost after generator update - variants, probably should not be removed
+SYMBOL(abs, std::chrono::, )
+SYMBOL(ceil, std::chrono::, )
+SYMBOL(floor, std::chrono::, )
+SYMBOL(from_stream, std::chrono::, )
+SYMBOL(round, std::chrono::, )
+SYMBOL(begin, std::filesystem::, )
+SYMBOL(end, std::filesystem::, )
+SYMBOL(get, std::ranges::, )
+
+// Ignore specializations
+SYMBOL(hash, std::, )

vvd170501 wrote:

Not sure if it's better to keep `` or replace it with `/*no 
headers*/`

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


[clang] [Tooling/Inclusion] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits

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


[clang] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 853881983faeeb5b7e0582d3e94037c12df12c7c Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 00:17:26 +0300
Subject: [PATCH 1/4] Fix variant parsing

---
 .../include-mapping/cppreference_parser.py| 33 ---
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index f2ea55384fac80..70e403bba64917 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -7,7 +7,7 @@
 #
 # 
======#
 
-from bs4 import BeautifulSoup, NavigableString
+from bs4 import BeautifulSoup, NavigableString, Tag
 
 import collections
 import multiprocessing
@@ -89,6 +89,23 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 return headers or all_headers
 
 
+def _ParseSymbolVariant(caption):
+if not (isinstance(caption, NavigableString) and "(" in caption):
+return None
+
+if ')' in caption.text:  # (locale), (algorithm), etc.
+return caption.text.strip(" ()")
+
+second_part = caption.next_sibling
+if isinstance(second_part, Tag) and second_part.name == "code":
+# (std::complex), etc.
+third_part = second_part.next_sibling
+if isinstance(third_part, NavigableString) and 
third_part.text.startswith(')'):
+return second_part.text
+return None
+
+
+
 def _ParseIndexPage(index_page_html):
 """Parse index page.
 The index page lists all std symbols and hrefs to their detailed pages
@@ -107,9 +124,7 @@ def _ParseIndexPage(index_page_html):
 # This accidentally accepts begin/end despite the (iterator) caption: 
the
 # (since C++11) note is first. They are good symbols, so the bug is 
unfixed.
 caption = symbol_href.next_sibling
-variant = None
-if isinstance(caption, NavigableString) and "(" in caption:
-variant = caption.text.strip(" ()")
+variant = _ParseSymbolVariant(caption)
 symbol_tt = symbol_href.find("tt")
 if symbol_tt:
 symbols.append(
@@ -192,6 +207,16 @@ def GetSymbols(parse_pages):
 variants_to_accept = {
 # std::remove<> has variant algorithm.
 "std::remove": ("algorithm"),
+# These functions don't have a generic version, and all variants are 
defined in 
+"std::chrono::abs": ("std::chrono::duration"),
+"std::chrono::ceil": ("std::chrono::duration"),
+"std::chrono::floor": ("std::chrono::duration"),
+"std::chrono::from_stream": ("std::chrono::day"),
+"std::chrono::round": ("std::chrono::duration"),
+# Same, but in 
+"std::filesystem::begin": ("std::filesystem::directory_iterator"),
+"std::filesystem::end": ("std::filesystem::directory_iterator"),
+"std::ranges::get": ("std::ranges::subrange"),
 }
 symbols = []
 # Run many workers to process individual symbol pages under the symbol 
index.

>From 09a421726314f2d9edb110e33106b3194e9f7014 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 06:38:41 +0300
Subject: [PATCH 2/4] Parse symbols with qualified name (not sure if it works
 in this revision)

---
 clang/tools/include-mapping/cppreference_parser.py | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index 70e403bba64917..d63be5d241884b 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -40,7 +40,7 @@ def _HasClass(tag, *classes):
 return False
 
 
-def _ParseSymbolPage(symbol_page_html, symbol_name):
+def _ParseSymbolPage(symbol_page_html, symbol_name, qual_name):
 """Parse symbol page and retrieve the include header defined in this page.
 The symbol page provides header for the symbol, specifically in
 "Defined in header " section. An example:
@@ -69,7 +69,7 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 was_decl = True
 # Symbols are in the first cell.
 found_symbols = row.find("td").stripped_strings
-if not symbol_name in found_symbols:
+if not (symbol_name in found_symbols or qual_name in 
found_symbols):
 continue
 headers.update(current_headers)
 elif _HasClass(row, "t-dsc-header"):
@@ -137,9 +137,9 @@ def _ParseIndexPage(index_page_html):
 return symbols
 
 
-def _ReadSymbolPage(path, name):
+def _ReadSymbolPage(path, name, qual_name):
 with open(path) as f:
-return _ParseSymbolPage(f.read(),

[clang] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits


@@ -352,20 +383,23 @@ SYMBOL(get, std::, /*no headers*/)
 // providing the type.
 SYMBOL(make_error_code, std::, /*no headers*/)
 SYMBOL(make_error_condition, std::, /*no headers*/)
+// Similar to std::get, has variants for multiple containers
+// (vector, deque, list, etc.)
+SYMBOL(erase, std::, /*no headers*/)
+SYMBOL(erase_if, std::, /*no headers*/)
 
 // cppreference symbol index page was missing these symbols.
 // Remove them when the cppreference offline archive catches up.
-SYMBOL(index_sequence, std::, )
-SYMBOL(index_sequence_for, std::, )
-SYMBOL(make_index_sequence, std::, )
-SYMBOL(make_integer_sequence, std::, )
+SYMBOL(regular_invocable, std::, )
 
 // Symbols missing from the generated symbol map as reported by users.
 // Remove when the generator starts producing them.
-SYMBOL(make_any, std::, )
-SYMBOL(any_cast, std::, )
 SYMBOL(div, std::, )
 SYMBOL(abort, std::, )
+SYMBOL(atomic_wait, std::, )
+SYMBOL(atomic_wait_explicit, std::, )
+SYMBOL(move_backward, std::, )
+SYMBOL(month_weekday, std::chrono::, )

vvd170501 wrote:

These symbols and `std::regular_invocable` were lost in newer edits, but should 
be back in the next release of offline archive

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


[clang] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits

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


[clang] Update std symbols mapping (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 8fac50dc444eeb6c9ad19eb11f7d95457b153528 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Thu, 24 Oct 2024 17:36:22 +0300
Subject: [PATCH 1/4] Move assertion to detect all ungrouped mappings

---
 clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 0832bcf66145fa..49e5765af112ff 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -115,15 +115,17 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
[&QName](const SymbolHeaderMapping::SymbolName &S) {
  return S.qualifiedName() == QName;
}) &&
  "The symbol has been added before, make sure entries in the .inc "
  "file are grouped by symbol name!");
+}
+if (SymIndex >= 0 &&
+Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
+  // Not a new symbol, use the same index.
 } else {
   // First symbol or new symbol, increment next available index.
   ++SymIndex;

>From ba2d997ba87e2a5193429d3ca4900d4ae39420b7 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Wed, 23 Oct 2024 23:22:56 +0300
Subject: [PATCH 2/4] Update std symbol mapping to v20230810

---
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc | 130 -
 .../Inclusions/Stdlib/StdSymbolMap.inc| 171 --
 2 files changed, 194 insertions(+), 107 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index 0d351d688a3296..156e1e8ad5321c 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -233,6 +233,23 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 
+// Overloads for different containers, actual header depends on function arg.
+// Probably should use a special handler, like with std::move.
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+
 // Add headers for generic integer-type abs.
 // Ignore other variants (std::complex, std::valarray, std::intmax_t)
 SYMBOL(abs, std::, )
@@ -242,9 +259,77 @@ SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 
-// Only add headers for the generic atomic template.
+// Same as abs - ignore variants (std::complex, std::valarray)
+SYMBOL(acos, std::, )
+SYMBOL(acos, None, )
+SYMBOL(acos, None, )
+SYMBOL(acosh, std::, )
+SYMBOL(acosh, None, )
+SYMBOL(acosh, None, )
+SYMBOL(asin, std::, )
+SYMBOL(asin, None, )
+SYMBOL(asin, None, )
+SYMBOL(asinh, std::, )
+SYMBOL(asinh, None, )
+SYMBOL(asinh, None, )
+SYMBOL(atan, std::, )
+SYMBOL(atan, None, )
+SYMBOL(atan, None, )
+SYMBOL(atan2, std::, )
+SYMBOL(atan2, None, )
+SYMBOL(atan2, None, )
+SYMBOL(atanh, std::, )
+SYMBOL(atanh, None, )
+SYMBOL(atanh, None, )
+SYMBOL(cos, std::, )
+SYMBOL(cos, None, )
+SYMBOL(cos, None, )
+SYMBOL(cosh, std::, )
+SYMBOL(cosh, None, )
+SYMBOL(cosh, None, )
+SYMBOL(exp, std::, )
+SYMBOL(exp, None, )
+SYMBOL(exp, None, )
+SYMBOL(log, std::, )
+SYMBOL(log, None, )
+SYMBOL(log, None, )
+SYMBOL(log10, std::, )
+SYMBOL(log10, None, )
+SYMBOL(log10, None, )
+SYMBOL(pow, std::, )
+SYMBOL(pow, None, )
+SYMBOL(pow, None, )
+SYMBOL(sin, std::, )
+SYMBOL(sin, None, )
+SYMBOL(sin, None, )
+SYMBOL(sinh, std::, )
+SYMBOL(sinh, None, )
+SYMBOL(sinh, None, )
+SYMBOL(sqrt, std::, )
+SYMBOL(sqrt, None, )
+SYMBOL(sqrt, None, )
+SYMBOL(tan, std::, )
+SYMBOL(tan, None, )
+SYMBOL(tan, None, )
+SYMBOL(tanh, std::, )
+SYMBOL(tanh, None, )
+SYMBOL(tanh, None, )
+
+// Only add headers for the generic atomic template and atomic_* template 
functions.
 // Ignore variants (std::weak_ptr, std::shared_ptr).
 SYMBOL(atomic, std::, )
+SYMBOL(atomic_compare_exchange_strong, std::, )
+SYMBOL(atomic_compare_exchange_strong_explicit, std::, )
+SYMBOL(atomic_compare_exchange_weak, std::, )
+SYMBOL(atomic_compare_exchange_weak_explicit, std::, )
+SYMBOL(atomic_exchange, std::, )
+SYMBOL(atomic_exchange_explicit, std::, )
+SYMBOL

[clang] Update std symbols mapping (PR #113612)

2024-10-24 Thread Vadim D. via cfe-commits

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


[clang] Update std symbols mapping (PR #113612)

2024-10-25 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 96662cb7f681e7158c05a0190894de70eee03d67 Mon Sep 17 00:00:00 2001
From: Vadim Dudkin 
Date: Thu, 24 Oct 2024 23:18:52 +0300
Subject: [PATCH 1/2] Update std symbol mapping to v20230810; Move assertion to
 detect all ungrouped mappings

---
 .../Inclusions/Stdlib/StandardLibrary.cpp |   8 +-
 .../Inclusions/Stdlib/StdSpecialSymbolMap.inc | 131 +-
 .../Inclusions/Stdlib/StdSymbolMap.inc| 171 --
 3 files changed, 200 insertions(+), 110 deletions(-)

diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp 
b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
index 0832bcf66145fa..49e5765af112ff 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -115,15 +115,17 @@ static int initialize(Lang Language) {
   NSLen = 0;
 }
 
-if (SymIndex >= 0 &&
-Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
-  // Not a new symbol, use the same index.
+if (SymIndex > 0) {
   assert(llvm::none_of(llvm::ArrayRef(Mapping->SymbolNames, SymIndex),
[&QName](const SymbolHeaderMapping::SymbolName &S) {
  return S.qualifiedName() == QName;
}) &&
  "The symbol has been added before, make sure entries in the .inc "
  "file are grouped by symbol name!");
+}
+if (SymIndex >= 0 &&
+Mapping->SymbolNames[SymIndex].qualifiedName() == QName) {
+  // Not a new symbol, use the same index.
 } else {
   // First symbol or new symbol, increment next available index.
   ++SymIndex;
diff --git a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc 
b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
index 0d351d688a3296..13060a0cc1d529 100644
--- a/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
+++ b/clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc
@@ -233,6 +233,23 @@ SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 SYMBOL(ssize, std::, )
 
+// Overloads for different containers, actual header depends on function arg.
+// Probably should use a special handler, like with std::move.
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+SYMBOL(erase_if, std::, )
+
 // Add headers for generic integer-type abs.
 // Ignore other variants (std::complex, std::valarray, std::intmax_t)
 SYMBOL(abs, std::, )
@@ -242,9 +259,78 @@ SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 SYMBOL(abs, None, )
 
-// Only add headers for the generic atomic template.
+// Same as abs - ignore variants (std::complex, std::valarray)
+SYMBOL(acos, std::, )
+SYMBOL(acos, None, )
+SYMBOL(acos, None, )
+SYMBOL(acosh, std::, )
+SYMBOL(acosh, None, )
+SYMBOL(acosh, None, )
+SYMBOL(asin, std::, )
+SYMBOL(asin, None, )
+SYMBOL(asin, None, )
+SYMBOL(asinh, std::, )
+SYMBOL(asinh, None, )
+SYMBOL(asinh, None, )
+SYMBOL(atan, std::, )
+SYMBOL(atan, None, )
+SYMBOL(atan, None, )
+SYMBOL(atan2, std::, )
+SYMBOL(atan2, None, )
+SYMBOL(atan2, None, )
+SYMBOL(atanh, std::, )
+SYMBOL(atanh, None, )
+SYMBOL(atanh, None, )
+SYMBOL(cos, std::, )
+SYMBOL(cos, None, )
+SYMBOL(cos, None, )
+SYMBOL(cosh, std::, )
+SYMBOL(cosh, None, )
+SYMBOL(cosh, None, )
+SYMBOL(exp, std::, )
+SYMBOL(exp, None, )
+SYMBOL(exp, None, )
+SYMBOL(log, std::, )
+SYMBOL(log, None, )
+SYMBOL(log, None, )
+SYMBOL(log10, std::, )
+SYMBOL(log10, None, )
+SYMBOL(log10, None, )
+SYMBOL(pow, std::, )
+SYMBOL(pow, None, )
+SYMBOL(pow, None, )
+SYMBOL(sin, std::, )
+SYMBOL(sin, None, )
+SYMBOL(sin, None, )
+SYMBOL(sinh, std::, )
+SYMBOL(sinh, None, )
+SYMBOL(sinh, None, )
+SYMBOL(sqrt, std::, )
+SYMBOL(sqrt, None, )
+SYMBOL(sqrt, None, )
+SYMBOL(tan, std::, )
+SYMBOL(tan, None, )
+SYMBOL(tan, None, )
+SYMBOL(tanh, std::, )
+SYMBOL(tanh, None, )
+SYMBOL(tanh, None, )
+
+// Only add headers for the generic atomic template
+// and atomic_* template functions.
 // Ignore variants (std::weak_ptr, std::shared_ptr).
 SYMBOL(atomic, std::, )
+SYMBOL(atomic_compare_exchange_strong, std::, )
+SYMBOL(atomic_compare_exchange_strong_explicit, std::, )
+SYMBOL(atomic_compare_exchange_weak, std::, )
+SYMBOL(atomic_compare_exchange_weak_explicit, std::, )
+SYMBOL(atomic_exchange, std::, )
+SYMBOL(atomic_exchange_explicit, std::, )
+SYMBOL(atomic_is_lock_free, std::, )
+SYMBOL(atomic_load, std::, )
+SYMBOL(atomic_load_explicit, std::, )
+SYMBOL(atomic_store, std::, )
+SYMBOL(atomic_store_explicit, std::, )
+
 // atomic_* family symbols.  is for C compatibility.
 SYMBOL(atomic_bool, std::, )
 SYMBOL(atomic_bool, None, )
@@ -355,18 +4

[clang] Update std symbols mapping (PR #113612)

2024-10-26 Thread Vadim D. via cfe-commits

https://github.com/vvd170501 updated 
https://github.com/llvm/llvm-project/pull/113612

>From 489d258577552cde839f0949a1ce24d4b1f72103 Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 00:17:26 +0300
Subject: [PATCH 1/4] Fix variant parsing

---
 .../include-mapping/cppreference_parser.py| 23 +++
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index f2ea55384fac80..ff8d16bd792b33 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -7,7 +7,7 @@
 #
 # 
======#
 
-from bs4 import BeautifulSoup, NavigableString
+from bs4 import BeautifulSoup, NavigableString, Tag
 
 import collections
 import multiprocessing
@@ -89,6 +89,23 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 return headers or all_headers
 
 
+def _ParseSymbolVariant(caption):
+if not (isinstance(caption, NavigableString) and "(" in caption):
+return None
+
+if ')' in caption.text:  # (locale), (algorithm), etc.
+return caption.text.strip(" ()")
+
+second_part = caption.next_sibling
+if isinstance(second_part, Tag) and second_part.name == "code":
+# (std::complex), etc.
+third_part = second_part.next_sibling
+if isinstance(third_part, NavigableString) and 
third_part.text.startswith(')'):
+return second_part.text
+return None
+
+
+
 def _ParseIndexPage(index_page_html):
 """Parse index page.
 The index page lists all std symbols and hrefs to their detailed pages
@@ -107,9 +124,7 @@ def _ParseIndexPage(index_page_html):
 # This accidentally accepts begin/end despite the (iterator) caption: 
the
 # (since C++11) note is first. They are good symbols, so the bug is 
unfixed.
 caption = symbol_href.next_sibling
-variant = None
-if isinstance(caption, NavigableString) and "(" in caption:
-variant = caption.text.strip(" ()")
+variant = _ParseSymbolVariant(caption)
 symbol_tt = symbol_href.find("tt")
 if symbol_tt:
 symbols.append(

>From 2a4796c7618575bac80817bfe33774860564b8be Mon Sep 17 00:00:00 2001
From: vvd170501 <36827317+vvd170...@users.noreply.github.com>
Date: Sat, 26 Oct 2024 06:38:41 +0300
Subject: [PATCH 2/4] Parse symbols with qualified name (not sure if it works
 in this revision)

---
 clang/tools/include-mapping/cppreference_parser.py | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/clang/tools/include-mapping/cppreference_parser.py 
b/clang/tools/include-mapping/cppreference_parser.py
index ff8d16bd792b33..110c8b1cf2b11f 100644
--- a/clang/tools/include-mapping/cppreference_parser.py
+++ b/clang/tools/include-mapping/cppreference_parser.py
@@ -40,7 +40,7 @@ def _HasClass(tag, *classes):
 return False
 
 
-def _ParseSymbolPage(symbol_page_html, symbol_name):
+def _ParseSymbolPage(symbol_page_html, symbol_name, qual_name):
 """Parse symbol page and retrieve the include header defined in this page.
 The symbol page provides header for the symbol, specifically in
 "Defined in header " section. An example:
@@ -69,7 +69,7 @@ def _ParseSymbolPage(symbol_page_html, symbol_name):
 was_decl = True
 # Symbols are in the first cell.
 found_symbols = row.find("td").stripped_strings
-if not symbol_name in found_symbols:
+if not (symbol_name in found_symbols or qual_name in 
found_symbols):
 continue
 headers.update(current_headers)
 elif _HasClass(row, "t-dsc-header"):
@@ -137,9 +137,9 @@ def _ParseIndexPage(index_page_html):
 return symbols
 
 
-def _ReadSymbolPage(path, name):
+def _ReadSymbolPage(path, name, qual_name):
 with open(path) as f:
-return _ParseSymbolPage(f.read(), name)
+return _ParseSymbolPage(f.read(), name, qual_name)
 
 
 def _GetSymbols(pool, root_dir, index_page_name, namespace, 
variants_to_accept):
@@ -161,8 +161,9 @@ def _GetSymbols(pool, root_dir, index_page_name, namespace, 
variants_to_accept):
 for symbol_name, symbol_page_path, variant in 
_ParseIndexPage(f.read()):
 # Variant symbols (e.g. the std::locale version of isalpha) add 
ambiguity.
 # FIXME: use these as a fallback rather than ignoring entirely.
+qualified_symbol_name = (namespace or "") + symbol_name
 variants_for_symbol = variants_to_accept.get(
-(namespace or "") + symbol_name, ()
+qualified_symbol_name, ()
 )
 if variant and variant not in variants_for_symbol:
 continue
@@ -171,7 +172,7 @@ def _GetSymbols(pool, root_dir

  1   2   >