[clang] [clang codegen][regression] Add dso_local/hidden/etc. markings to VTT definitions and declarations (PR #72452)

2023-11-21 Thread Justin Cady via cfe-commits

https://github.com/justincady commented:

LGTM as well, as the original fix remains in place.

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


[clang-tools-extra] [clang-tidy] Fix false-positives in misc-static-assert caused by non-constexpr variables (PR #77203)

2024-01-12 Thread Justin Cady via cfe-commits

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

Context: I have limited experience writing AST matchers, but I saw [the request 
for 
reviewers](https://discourse.llvm.org/t/clang-tidy-18-reviewers-wanted/76108). 
I'm basing this review on that limited experience and the tests put in place 
with this diff.

On those grounds, these changes LGTM.

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


[clang-tools-extra] [clang-tidy] Fix false-positives in readability-container-size-empty (PR #74140)

2024-01-12 Thread Justin Cady via cfe-commits

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

[Context](https://github.com/llvm/llvm-project/pull/77203#pullrequestreview-1818501835).

LGTM.

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


[clang] Add option to avoid generating coverage mappings for unused functions (PR #92582)

2024-07-03 Thread Justin Cady via cfe-commits

justincady wrote:

@ZequanWu I tested your first suggestion (`-fprofile-list`) and I believe 
there's a bug preventing reduction of binary size. See 
https://github.com/llvm/llvm-project/issues/97588.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-29 Thread Justin Cady via cfe-commits

justincady wrote:

@codectile `--exclude-header-filter` is used in conjunction with 
`--header-filter` to exclude certain headers from analysis. Check out the tests 
that were modified as a part of this PR for more examples, but the basic idea 
is:

```
$ clang-tidy --header-filter='.*' --exclude-header-filter='header1\.h' [...]
```

In that example all headers will be analyzed using the enabled checks _except_ 
`header1.h`.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-07 Thread Justin Cady via cfe-commits

https://github.com/justincady created 
https://github.com/llvm/llvm-project/pull/91400

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).


>From a5de583aa94ef794a083c8b27df6dc6fc0762cb7 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp   | 10 +-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h |  5 +
 .../clang-tidy/ClangTidyOptions.cpp  |  4 
 clang-tools-extra/clang-tidy/ClangTidyOptions.h  |  4 
 .../clang-tidy/tool/ClangTidyMain.cpp| 16 
 .../clang-tidy/infrastructure/file-filter.cpp|  7 +++
 6 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..3cde0d2d68874 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -564,7 +564,8 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   StringRef FileName(File->getName());
   LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+   (getHeaderFilter()->match(FileName) &&
+!getExcludeHeaderFilter()->match(FileName));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
@@ -578,6 +579,13 @@ llvm::Regex 
*ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+  return ExcludeHeaderFilter.get();
+}
+
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..a3add5d52778d 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -299,6 +299,10 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   /// context.
   llvm::Regex *getHeaderFilter();
 
+  /// \brief Returns the \c ExcludeHeaderFilter constructed for the options set
+  /// in the context.
+  llvm::Regex *getExcludeHeaderFilter();
+
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
   void checkFilters(SourceLocation Location, const SourceManager &Sources);
@@ -313,6 +317,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..254ce7fc60fc9 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -170,6 +170,8 @

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-08 Thread Justin Cady via cfe-commits

justincady wrote:

> I wonder what is the target scenario for this feature.

This PR addresses clang-tidy's lack of ability to ignore some set of headers 
when analyzing a file (most commonly third party code that cannot be modified).

>  I remember regex can excluding some pattern, the we can exclude header file 
> in `HeaderFilterRegex`.

The underlying regex implementation for `HeaderFilterRegex` is `llvm::Regex` 
which does not support negative lookahead. See:

- https://reviews.llvm.org/D34654
- https://lists.llvm.org/pipermail/cfe-dev/2015-November/046203.html
- https://github.com/llvm/llvm-project/issues/25590

As I mentioned in the description, one option to allow exclusion of headers 
would be migrating to `std::regex`. But I think that has the potential to break 
existing configs, which is why reviving/reimplementing D34654 seems like the 
best path forward to me.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-08 Thread Justin Cady via cfe-commits


@@ -578,6 +579,13 @@ llvm::Regex 
*ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);

justincady wrote:

I'm not sure I follow here. If `ExcludeHeaderFilterRegex` isn't set via the 
command line or config, it will be initialized to an empty string. Then the 
`llvm::Regex` will be constructed with that empty string.

Is that different than what you mean?

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-08 Thread Justin Cady via cfe-commits


@@ -578,6 +579,13 @@ llvm::Regex 
*ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);

justincady wrote:

Ok, thanks for clarifying. I will look into this.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-08 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/91400

>From a5de583aa94ef794a083c8b27df6dc6fc0762cb7 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH 1/2] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp   | 10 +-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h |  5 +
 .../clang-tidy/ClangTidyOptions.cpp  |  4 
 clang-tools-extra/clang-tidy/ClangTidyOptions.h  |  4 
 .../clang-tidy/tool/ClangTidyMain.cpp| 16 
 .../clang-tidy/infrastructure/file-filter.cpp|  7 +++
 6 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..3cde0d2d68874 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -564,7 +564,8 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   StringRef FileName(File->getName());
   LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+   (getHeaderFilter()->match(FileName) &&
+!getExcludeHeaderFilter()->match(FileName));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
@@ -578,6 +579,13 @@ llvm::Regex 
*ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+  return ExcludeHeaderFilter.get();
+}
+
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..a3add5d52778d 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -299,6 +299,10 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   /// context.
   llvm::Regex *getHeaderFilter();
 
+  /// \brief Returns the \c ExcludeHeaderFilter constructed for the options set
+  /// in the context.
+  llvm::Regex *getExcludeHeaderFilter();
+
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
   void checkFilters(SourceLocation Location, const SourceManager &Sources);
@@ -313,6 +317,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..254ce7fc60fc9 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -170,6 +170,8 @@ template <> struct MappingTraits {
 IO.mapOptional("ImplementationFileExtensions",
Options.ImplementationFileExtensions);
 IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
+IO.mapOptional("ExcludeHeaderFilterRegex",
+   Options.ExcludeHeaderFilterRegex);
 IO.mapOptional("FormatStyle", Options.FormatStyle);
 IO.mapOptional("User", Options.User);
 IO.mapOptional("CheckOptions", Options.CheckOptions);
@@ -192,6 +194,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
   Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
   Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
   Optio

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-08 Thread Justin Cady via cfe-commits


@@ -578,6 +579,13 @@ llvm::Regex 
*ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);

justincady wrote:

I just pushed a commit that omits the check when `ExcludeHeaderFilter` is not 
set by the user. Please let me know if this aligns with your idea.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-09 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/91400

>From a5de583aa94ef794a083c8b27df6dc6fc0762cb7 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH 1/3] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp   | 10 +-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h |  5 +
 .../clang-tidy/ClangTidyOptions.cpp  |  4 
 clang-tools-extra/clang-tidy/ClangTidyOptions.h  |  4 
 .../clang-tidy/tool/ClangTidyMain.cpp| 16 
 .../clang-tidy/infrastructure/file-filter.cpp|  7 +++
 6 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..3cde0d2d68874 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -564,7 +564,8 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   StringRef FileName(File->getName());
   LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+   (getHeaderFilter()->match(FileName) &&
+!getExcludeHeaderFilter()->match(FileName));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
@@ -578,6 +579,13 @@ llvm::Regex 
*ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+  return ExcludeHeaderFilter.get();
+}
+
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..a3add5d52778d 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -299,6 +299,10 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   /// context.
   llvm::Regex *getHeaderFilter();
 
+  /// \brief Returns the \c ExcludeHeaderFilter constructed for the options set
+  /// in the context.
+  llvm::Regex *getExcludeHeaderFilter();
+
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
   void checkFilters(SourceLocation Location, const SourceManager &Sources);
@@ -313,6 +317,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..254ce7fc60fc9 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -170,6 +170,8 @@ template <> struct MappingTraits {
 IO.mapOptional("ImplementationFileExtensions",
Options.ImplementationFileExtensions);
 IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
+IO.mapOptional("ExcludeHeaderFilterRegex",
+   Options.ExcludeHeaderFilterRegex);
 IO.mapOptional("FormatStyle", Options.FormatStyle);
 IO.mapOptional("User", Options.User);
 IO.mapOptional("CheckOptions", Options.CheckOptions);
@@ -192,6 +194,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
   Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
   Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
   Optio

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-09 Thread Justin Cady via cfe-commits


@@ -562,9 +567,10 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   }
 
   StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-   Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+  LastErrorRelatesToUserCode =
+  LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
+  (getHeaderFilter()->match(FileName) &&
+   (ExcludeHeaderFilter ? !ExcludeHeaderFilter->match(FileName) : true));

justincady wrote:

Thank you! Simplified that snippet and added the tests as suggested.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-09 Thread Justin Cady via cfe-commits


@@ -311,7 +311,12 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+}

justincady wrote:

Well, in the initial PR `ExcludeHeaderFilter` mirrored `HeaderFilter` behavior 
exactly. I changed it because @PiotrZSL made a nearly identical comment to 
yours about saving the call to `match` on an empty regex (which I think is 
handled in the latest revision).

I _could_ migrate `HeaderFilter` to mirror the new and improved 
`ExcludeHeaderFilter`...though I worry a bit about this change growing larger 
and larger. What do you think?

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-09 Thread Justin Cady via cfe-commits


@@ -311,7 +311,12 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);

justincady wrote:

What makes you suspect it doesn't work? I did some testing by placing `abort()` 
in an else clause and it caused many unit tests to crash. That leads me to 
believe it remains `std::nullopt` when the option is not specified.

I will do some more thorough testing to confirm.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-10 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/91400

>From a5de583aa94ef794a083c8b27df6dc6fc0762cb7 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH 1/5] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../clang-tidy/ClangTidyDiagnosticConsumer.cpp   | 10 +-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h |  5 +
 .../clang-tidy/ClangTidyOptions.cpp  |  4 
 clang-tools-extra/clang-tidy/ClangTidyOptions.h  |  4 
 .../clang-tidy/tool/ClangTidyMain.cpp| 16 
 .../clang-tidy/infrastructure/file-filter.cpp|  7 +++
 6 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..3cde0d2d68874 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -564,7 +564,8 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   StringRef FileName(File->getName());
   LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+   (getHeaderFilter()->match(FileName) &&
+!getExcludeHeaderFilter()->match(FileName));
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
@@ -578,6 +579,13 @@ llvm::Regex 
*ClangTidyDiagnosticConsumer::getHeaderFilter() {
   return HeaderFilter.get();
 }
 
+llvm::Regex *ClangTidyDiagnosticConsumer::getExcludeHeaderFilter() {
+  if (!ExcludeHeaderFilter)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+  return ExcludeHeaderFilter.get();
+}
+
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..a3add5d52778d 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -299,6 +299,10 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   /// context.
   llvm::Regex *getHeaderFilter();
 
+  /// \brief Returns the \c ExcludeHeaderFilter constructed for the options set
+  /// in the context.
+  llvm::Regex *getExcludeHeaderFilter();
+
   /// Updates \c LastErrorRelatesToUserCode and LastErrorPassesLineFilter
   /// according to the diagnostic \p Location.
   void checkFilters(SourceLocation Location, const SourceManager &Sources);
@@ -313,6 +317,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..254ce7fc60fc9 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -170,6 +170,8 @@ template <> struct MappingTraits {
 IO.mapOptional("ImplementationFileExtensions",
Options.ImplementationFileExtensions);
 IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
+IO.mapOptional("ExcludeHeaderFilterRegex",
+   Options.ExcludeHeaderFilterRegex);
 IO.mapOptional("FormatStyle", Options.FormatStyle);
 IO.mapOptional("User", Options.User);
 IO.mapOptional("CheckOptions", Options.CheckOptions);
@@ -192,6 +194,7 @@ ClangTidyOptions ClangTidyOptions::getDefaults() {
   Options.HeaderFileExtensions = {"", "h", "hh", "hpp", "hxx"};
   Options.ImplementationFileExtensions = {"c", "cc", "cpp", "cxx"};
   Optio

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-10 Thread Justin Cady via cfe-commits


@@ -311,7 +311,12 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);

justincady wrote:

After further testing I came to understand what you meant and made this 
adjustment as suggested.

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-10 Thread Justin Cady via cfe-commits


@@ -311,7 +311,12 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex)
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+}

justincady wrote:

The change to make `HeaderFilter` mirror `ExcludeHeaderFilter` was not too bad, 
so I went ahead with it. I thought it might actually be better to do now while 
everything is fresh in my mind. 🙂 

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-13 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/91400

>From e65bd48ef896f3327a1397a1b2f6f0a34e3711d2 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../ClangTidyDiagnosticConsumer.cpp   |  28 ++-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h  |   1 +
 .../clang-tidy/ClangTidyOptions.cpp   |   6 +-
 .../clang-tidy/ClangTidyOptions.h |   4 +
 .../clang-tidy/tool/ClangTidyMain.cpp |  18 ++
 .../clang-tidy/tool/run-clang-tidy.py |  13 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   2 +
 clang-tools-extra/docs/clang-tidy/index.rst   | 235 +-
 .../Inputs/config-files/.clang-tidy   |   1 +
 .../Inputs/config-files/1/.clang-tidy |   1 +
 .../Inputs/config-files/3/.clang-tidy |   1 +
 .../infrastructure/config-files.cpp   |  15 +-
 .../clang-tidy/infrastructure/file-filter.cpp |   7 +
 13 files changed, 206 insertions(+), 126 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..200bb87a5ac3c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -311,7 +311,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().HeaderFilterRegex &&
+  !Context.getOptions().HeaderFilterRegex->empty())
+HeaderFilter =
+std::make_unique(*Context.getOptions().HeaderFilterRegex);
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex &&
+  !Context.getOptions().ExcludeHeaderFilterRegex->empty())
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+}
 
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
   if (!Errors.empty()) {
@@ -562,22 +573,17 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   }
 
   StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-   Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+  LastErrorRelatesToUserCode =
+  LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
+  (HeaderFilter &&
+   (HeaderFilter->match(FileName) &&
+!(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName;
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
   LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
 }
 
-llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
-  if (!HeaderFilter)
-HeaderFilter =
-std::make_unique(*Context.getOptions().HeaderFilterRegex);
-  return HeaderFilter.get();
-}
-
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..97e16a12febd0 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -313,6 +313,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..445c7f85c900c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-13 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/91400

>From e65bd48ef896f3327a1397a1b2f6f0a34e3711d2 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH 1/2] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../ClangTidyDiagnosticConsumer.cpp   |  28 ++-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h  |   1 +
 .../clang-tidy/ClangTidyOptions.cpp   |   6 +-
 .../clang-tidy/ClangTidyOptions.h |   4 +
 .../clang-tidy/tool/ClangTidyMain.cpp |  18 ++
 .../clang-tidy/tool/run-clang-tidy.py |  13 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   2 +
 clang-tools-extra/docs/clang-tidy/index.rst   | 235 +-
 .../Inputs/config-files/.clang-tidy   |   1 +
 .../Inputs/config-files/1/.clang-tidy |   1 +
 .../Inputs/config-files/3/.clang-tidy |   1 +
 .../infrastructure/config-files.cpp   |  15 +-
 .../clang-tidy/infrastructure/file-filter.cpp |   7 +
 13 files changed, 206 insertions(+), 126 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..200bb87a5ac3c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -311,7 +311,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().HeaderFilterRegex &&
+  !Context.getOptions().HeaderFilterRegex->empty())
+HeaderFilter =
+std::make_unique(*Context.getOptions().HeaderFilterRegex);
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex &&
+  !Context.getOptions().ExcludeHeaderFilterRegex->empty())
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+}
 
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
   if (!Errors.empty()) {
@@ -562,22 +573,17 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   }
 
   StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-   Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+  LastErrorRelatesToUserCode =
+  LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
+  (HeaderFilter &&
+   (HeaderFilter->match(FileName) &&
+!(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName;
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
   LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
 }
 
-llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
-  if (!HeaderFilter)
-HeaderFilter =
-std::make_unique(*Context.getOptions().HeaderFilterRegex);
-  return HeaderFilter.get();
-}
-
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..97e16a12febd0 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -313,6 +313,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..445c7f85c900c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-t

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-13 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/91400

>From e65bd48ef896f3327a1397a1b2f6f0a34e3711d2 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH 1/3] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../ClangTidyDiagnosticConsumer.cpp   |  28 ++-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h  |   1 +
 .../clang-tidy/ClangTidyOptions.cpp   |   6 +-
 .../clang-tidy/ClangTidyOptions.h |   4 +
 .../clang-tidy/tool/ClangTidyMain.cpp |  18 ++
 .../clang-tidy/tool/run-clang-tidy.py |  13 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   2 +
 clang-tools-extra/docs/clang-tidy/index.rst   | 235 +-
 .../Inputs/config-files/.clang-tidy   |   1 +
 .../Inputs/config-files/1/.clang-tidy |   1 +
 .../Inputs/config-files/3/.clang-tidy |   1 +
 .../infrastructure/config-files.cpp   |  15 +-
 .../clang-tidy/infrastructure/file-filter.cpp |   7 +
 13 files changed, 206 insertions(+), 126 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..200bb87a5ac3c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -311,7 +311,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().HeaderFilterRegex &&
+  !Context.getOptions().HeaderFilterRegex->empty())
+HeaderFilter =
+std::make_unique(*Context.getOptions().HeaderFilterRegex);
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex &&
+  !Context.getOptions().ExcludeHeaderFilterRegex->empty())
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+}
 
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
   if (!Errors.empty()) {
@@ -562,22 +573,17 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   }
 
   StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-   Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+  LastErrorRelatesToUserCode =
+  LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
+  (HeaderFilter &&
+   (HeaderFilter->match(FileName) &&
+!(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName;
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
   LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
 }
 
-llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
-  if (!HeaderFilter)
-HeaderFilter =
-std::make_unique(*Context.getOptions().HeaderFilterRegex);
-  return HeaderFilter.get();
-}
-
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..97e16a12febd0 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -313,6 +313,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..445c7f85c900c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-t

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-13 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/91400

>From 58d3d52c666bdaa3534cd16080bb895d49f61008 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 7 May 2024 16:54:35 -0400
Subject: [PATCH] Add option to exclude headers from clang-tidy analysis

This is a renewed attempt to land @toddlipcon's D34654. The comments on
that patch indicate a broad desire for some ability to ignore headers.

After considering various options, including migrating to std::regex, I
believe this is the best path forward. It's intuitive to have separate
regexes for including headers versus excluding them, and this approach
has the added benefit of being completely opt-in. No existing configs
will break, regardless of existing HeaderFilterRegex values.

This functionality is useful for improving performance when analyzing a
targeted subset of code, as well as in cases where some collection of
headers cannot be modified (third party source, for example).
---
 .../ClangTidyDiagnosticConsumer.cpp   |  28 ++-
 .../clang-tidy/ClangTidyDiagnosticConsumer.h  |   1 +
 .../clang-tidy/ClangTidyOptions.cpp   |   6 +-
 .../clang-tidy/ClangTidyOptions.h |   4 +
 .../clang-tidy/tool/ClangTidyMain.cpp |  18 ++
 .../clang-tidy/tool/run-clang-tidy.py |  13 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   3 +
 clang-tools-extra/docs/clang-tidy/index.rst   | 235 +-
 .../Inputs/config-files/.clang-tidy   |   1 +
 .../Inputs/config-files/1/.clang-tidy |   1 +
 .../Inputs/config-files/3/.clang-tidy |   1 +
 .../infrastructure/config-files.cpp   |  15 +-
 .../clang-tidy/infrastructure/file-filter.cpp |   7 +
 13 files changed, 207 insertions(+), 126 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
index de2a3b51422a5..200bb87a5ac3c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -311,7 +311,18 @@ ClangTidyDiagnosticConsumer::ClangTidyDiagnosticConsumer(
 : Context(Ctx), ExternalDiagEngine(ExternalDiagEngine),
   RemoveIncompatibleErrors(RemoveIncompatibleErrors),
   GetFixesFromNotes(GetFixesFromNotes),
-  EnableNolintBlocks(EnableNolintBlocks) {}
+  EnableNolintBlocks(EnableNolintBlocks) {
+
+  if (Context.getOptions().HeaderFilterRegex &&
+  !Context.getOptions().HeaderFilterRegex->empty())
+HeaderFilter =
+std::make_unique(*Context.getOptions().HeaderFilterRegex);
+
+  if (Context.getOptions().ExcludeHeaderFilterRegex &&
+  !Context.getOptions().ExcludeHeaderFilterRegex->empty())
+ExcludeHeaderFilter = std::make_unique(
+*Context.getOptions().ExcludeHeaderFilterRegex);
+}
 
 void ClangTidyDiagnosticConsumer::finalizeLastError() {
   if (!Errors.empty()) {
@@ -562,22 +573,17 @@ void 
ClangTidyDiagnosticConsumer::checkFilters(SourceLocation Location,
   }
 
   StringRef FileName(File->getName());
-  LastErrorRelatesToUserCode = LastErrorRelatesToUserCode ||
-   Sources.isInMainFile(Location) ||
-   getHeaderFilter()->match(FileName);
+  LastErrorRelatesToUserCode =
+  LastErrorRelatesToUserCode || Sources.isInMainFile(Location) ||
+  (HeaderFilter &&
+   (HeaderFilter->match(FileName) &&
+!(ExcludeHeaderFilter && ExcludeHeaderFilter->match(FileName;
 
   unsigned LineNumber = Sources.getExpansionLineNumber(Location);
   LastErrorPassesLineFilter =
   LastErrorPassesLineFilter || passesLineFilter(FileName, LineNumber);
 }
 
-llvm::Regex *ClangTidyDiagnosticConsumer::getHeaderFilter() {
-  if (!HeaderFilter)
-HeaderFilter =
-std::make_unique(*Context.getOptions().HeaderFilterRegex);
-  return HeaderFilter.get();
-}
-
 void ClangTidyDiagnosticConsumer::removeIncompatibleErrors() {
   // Each error is modelled as the set of intervals in which it applies
   // replacements. To detect overlapping replacements, we use a sweep line
diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h 
b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
index 9280eb1e1f218..97e16a12febd0 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h
@@ -313,6 +313,7 @@ class ClangTidyDiagnosticConsumer : public 
DiagnosticConsumer {
   bool EnableNolintBlocks;
   std::vector Errors;
   std::unique_ptr HeaderFilter;
+  std::unique_ptr ExcludeHeaderFilter;
   bool LastErrorRelatesToUserCode = false;
   bool LastErrorPassesLineFilter = false;
   bool LastErrorWasIgnored = false;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp 
b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index cbf21a0e2ae34..445c7f85c900c 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools

[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-05-14 Thread Justin Cady via cfe-commits

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


[clang-tools-extra] Add option to exclude headers from clang-tidy analysis (PR #91400)

2024-10-14 Thread Justin Cady via cfe-commits

justincady wrote:

@Baiyi27 Could you please file an issue as opposed to adding it as a comment 
here? It may or may not be related to this original change, and separating it 
out into its own discussion would be helpful. Thanks!

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


[clang] [compiler-rt] Revert "[Coverage] Fix region termination for GNU statement expressions" (PR #132095)

2025-03-19 Thread Justin Cady via cfe-commits

https://github.com/justincady created 
https://github.com/llvm/llvm-project/pull/132095

Reverts llvm/llvm-project#130976

Breaks clang-cmake-x86_64-avx512-linux bot.

>From 2f37c9ec685b8ba82fdc3bd8387ce59b3f8a77dc Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Wed, 19 Mar 2025 16:45:26 -0400
Subject: [PATCH] =?UTF-8?q?Revert=20"[Coverage]=20Fix=20region=20terminati?=
 =?UTF-8?q?on=20for=20GNU=20statement=20expressions=20(#130=E2=80=A6"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This reverts commit 0827e3aae6eb69c2a6fa842ffa780881feb45b5d.
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 ---
 .../CoverageMapping/terminate-statements.cpp  |  7 ---
 .../Linux/coverage-statement-expression.cpp   | 21 ---
 3 files changed, 36 deletions(-)
 delete mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 73811d15979d5..f09157771d2b5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,14 +1505,6 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
-  void VisitStmtExpr(const StmtExpr *E) {
-Visit(E->getSubStmt());
-// Any region termination (such as a noreturn CallExpr) within the 
statement
-// expression has been handled by visiting the sub-statement. The visitor
-// cannot be at a terminate statement leaving the statement expression.
-HasTerminateStmt = false;
-  }
-
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 3f8e43f0fbcb6..0067185fee8e6 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,12 +346,6 @@ int elsecondnoret(void) {
   return 0;
 }
 
-// CHECK-LABEL: _Z18statementexprnoretb
-int statementexprnoret(bool crash) {
-  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = 
(#0 - #1)
-  return rc; // CHECK-NOT: Gap
-}
-
 int main() {
   foo(0);
   foo(1);
@@ -374,6 +368,5 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
-  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
deleted file mode 100644
index 7c76555e3300b..0
--- a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
-// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
-// RUN: llvm-profdata merge -o %t.profdata %t.profraw
-// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
-
-#include 
-
-// clang-format off
-__attribute__ ((__noreturn__))
-void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
-_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
-// CHECK:  [[@LINE]]|  |
-int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
-  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
-  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
-// CHECK:  [[@LINE]]|  |
-  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
-  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
-  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
-}   // CHECK:  [[@LINE]]| 1|}
-// clang-format on

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


[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-19 Thread Justin Cady via cfe-commits

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


[clang] [compiler-rt] Reland [Coverage] Fix region termination for GNU statement expressions (PR #132222)

2025-03-21 Thread Justin Cady via cfe-commits

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


[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-17 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/130976

>From 6f3557780d06d6a2b1a7f315c49a3ad533d821e5 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Wed, 12 Mar 2025 11:23:19 -0400
Subject: [PATCH 1/3] [Coverage] Fix region termination for GNU statement
 expressions

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 
 .../CoverageMapping/terminate-statements.cpp  |  7 +++
 .../Linux/coverage-statement-expression.cpp   | 19 +++
 3 files changed, 34 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..d03e35630b317 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK-NOT: Gap,File 0, 
[[@LINE]]:41 -> [[@LINE+1]]:3 = 0
+  return rc;
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..5894275b941a2
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,19 @@
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
+}   // CHECK:  [[@LINE]]| 1|}

>From 0dc7ea6a13b34901bb6ca0253ad73e8ef5037244 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Fri, 14 Mar 2025 12:32:57 -0400
Subject: [PATCH 2/3] Avoid format warning to preserve readable CHECK lines

---
 .../test/profile/Linux/coverage-statement-expression.cpp| 2 ++
 1 file changed, 2 insertions(+)

diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
index 5894275b941a2..7c76555e3300b 100644
--- a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -5,6 +5,7 @@
 
 #include 
 
+// clang-f

[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-17 Thread Justin Cady via cfe-commits


@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK-NOT: Gap,File 0, 
[[@LINE]]:41 -> [[@LINE+1]]:3 = 0

justincady wrote:

Thanks, I pushed a commit to fix this.

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


[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-17 Thread Justin Cady via cfe-commits

justincady wrote:

@MaskRay If you're satisfied with the current diff, could you please commit 
this whenever you get the chance? Thank you.

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


[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-19 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/130976

>From 1b7884bbff037efa5c69eeecafe8db282561b2fc Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Wed, 12 Mar 2025 11:23:19 -0400
Subject: [PATCH] [Coverage] Fix region termination for GNU statement
 expressions

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 +++
 .../CoverageMapping/terminate-statements.cpp  |  7 +++
 .../Linux/coverage-statement-expression.cpp   | 21 +++
 3 files changed, 36 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..3f8e43f0fbcb6 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = 
(#0 - #1)
+  return rc; // CHECK-NOT: Gap
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..7c76555e3300b
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,21 @@
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+// clang-format off
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
+}   // CHECK:  [[@LINE]]| 1|}
+// clang-format on

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


[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-19 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/130976

>From 422fefad20557f1d9777afa363f558c92564f0ee Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Wed, 12 Mar 2025 11:23:19 -0400
Subject: [PATCH] [Coverage] Fix region termination for GNU statement
 expressions

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 +++
 .../CoverageMapping/terminate-statements.cpp  |  7 +++
 .../Linux/coverage-statement-expression.cpp   | 21 +++
 3 files changed, 36 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..3f8e43f0fbcb6 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = 
(#0 - #1)
+  return rc; // CHECK-NOT: Gap
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..7c76555e3300b
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,21 @@
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+// clang-format off
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
+}   // CHECK:  [[@LINE]]| 1|}
+// clang-format on

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


[clang] [compiler-rt] Reland [Coverage] Fix region termination for GNU statement expressions (PR #132222)

2025-03-20 Thread Justin Cady via cfe-commits

justincady wrote:

This is the buildbot failure from the initial commit: 
https://lab.llvm.org/buildbot/#/builders/133/builds/13131

I updated the failing test with the same restrictions as other tests using 
`-fuse-ld=lld` under `compiler-rt/test/profile/Linux`, specifically:

```
// REQUIRES: lld-available
// XFAIL: powerpc64-target-arch
```

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


[clang] [compiler-rt] Reland [Coverage] Fix region termination for GNU statement expressions (PR #132222)

2025-03-20 Thread Justin Cady via cfe-commits

https://github.com/justincady created 
https://github.com/llvm/llvm-project/pull/13

Relands #130976 with adjustments to test requirements.

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296


>From e282d307482eb598238da387322dfdb1b0b46ed3 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Thu, 20 Mar 2025 10:01:42 -0400
Subject: [PATCH] Reland [Coverage] Fix region termination for GNU statement
 expressions

Relands #130976 with adjustments to test requirements.

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 +++
 .../CoverageMapping/terminate-statements.cpp  |  7 ++
 .../Linux/coverage-statement-expression.cpp   | 24 +++
 3 files changed, 39 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..3f8e43f0fbcb6 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = 
(#0 - #1)
+  return rc; // CHECK-NOT: Gap
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..19300411d54a2
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,24 @@
+// REQUIRES: lld-available
+// XFAIL: powerpc64-target-arch
+
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+// clang-format off
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("c

[clang] [compiler-rt] Revert "[Coverage] Fix region termination for GNU statement expressions" (PR #132095)

2025-04-05 Thread Justin Cady via cfe-commits

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


[clang] [compiler-rt] [Coverage] Fix region creation after try statements (PR #133463)

2025-04-05 Thread Justin Cady via cfe-commits

justincady wrote:

Coverage report before:
https://github.com/user-attachments/assets/80bb84a0-a76e-4f45-aca8-fd53378caa73";
 />

Coverage report after:
https://github.com/user-attachments/assets/987ae207-0eaf-4f33-aeb0-387c27cb382f";
 />


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


[clang] [compiler-rt] [Coverage] Fix region creation after try statements (PR #133463)

2025-03-28 Thread Justin Cady via cfe-commits

https://github.com/justincady created 
https://github.com/llvm/llvm-project/pull/133463

In cases where a terminating statement exists within the try or catch
block the coverage mapping can be incorrect. Coverage reports display
lines following the last catch block as uncovered, when the lines have
been executed.

This change adjusts the mapping such that an extra region is only
created after a try block if the try itself contains the terminating
statement.

The testing validates coverage more broadly than the above to ensure
other mapping around exception handling does not regress with this
change.


>From 6f79ddba80fa391a8c1ddbd3b2217f2e5a9ce21b Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Fri, 28 Mar 2025 12:07:44 -0400
Subject: [PATCH] [Coverage] Fix region creation after try statements

In cases where a terminating statement exists within the try or catch
block the coverage mapping can be incorrect. Coverage reports display
lines following the last catch block as uncovered, when the lines have
been executed.

This change adjusts the mapping such that an extra region is only
created after a try block if the try itself contains the terminating
statement.

The testing validates coverage more broadly than the above to ensure
other mapping around exception handling does not regress with this
change.
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  10 +-
 clang/test/CoverageMapping/trycatch.cpp   |   4 +-
 .../test/profile/Linux/coverage-exception.cpp | 142 ++
 3 files changed, 152 insertions(+), 4 deletions(-)
 create mode 100644 compiler-rt/test/profile/Linux/coverage-exception.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 73811d15979d5..f3b819bcf3b20 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -2123,11 +2123,17 @@ struct CounterCoverageMappingBuilder
 Counter ParentCount = getRegion().getCounter();
 propagateCounts(ParentCount, S->getTryBlock());
 
+bool TryHasTerminateStmt = HasTerminateStmt;
+
 for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
   Visit(S->getHandler(I));
 
-Counter ExitCount = getRegionCounter(S);
-pushRegion(ExitCount);
+if (TryHasTerminateStmt) {
+  Counter ExitCount = getRegionCounter(S);
+  pushRegion(ExitCount);
+}
+
+HasTerminateStmt = TryHasTerminateStmt;
   }
 
   void VisitCXXCatchStmt(const CXXCatchStmt *S) {
diff --git a/clang/test/CoverageMapping/trycatch.cpp 
b/clang/test/CoverageMapping/trycatch.cpp
index 89fae8af9b720..e5d2482c6b151 100644
--- a/clang/test/CoverageMapping/trycatch.cpp
+++ b/clang/test/CoverageMapping/trycatch.cpp
@@ -33,5 +33,5 @@ int main() {  // CHECK-NEXT: File 0, 
[[@LINE]]:12 -> [[@
   catch(const Warning &w) {   // CHECK-NEXT: File 0, [[@LINE]]:27 -> 
[[@LINE+2]]:4 = #4
 j = 0;
   }
-  return 0;   // CHECK-NEXT: File 0, [[@LINE]]:3 -> 
[[@LINE]]:11 = #1
-}
+  return 0;   // CHECK-NOT: File 0
+} // CHECK-NOT: File 0
diff --git a/compiler-rt/test/profile/Linux/coverage-exception.cpp 
b/compiler-rt/test/profile/Linux/coverage-exception.cpp
new file mode 100644
index 0..c12303363fbb6
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-exception.cpp
@@ -0,0 +1,142 @@
+// REQUIRES: lld-available
+// XFAIL: powerpc64-target-arch
+
+// RUN: %clangxx_profgen -std=c++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+#include 
+
+#define TRY_AND_CATCH_ALL(x)   
\
+  try {
\
+(x);   
\
+  } catch (...) {  
\
+  }
+
+#define TRY_MAYBE_CRASH(x) 
\
+  try {
\
+if ((x)) { 
\
+  printf("no crash\n");
\
+} else {   
\
+  abort(); 
\
+}  
\
+  } catch (...) {  
\
+  }
+
+#define TRY_AND_CATCH_CRASHES(x)   
\
+  try {
\
+(x);   

[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-14 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/130976

>From 6f3557780d06d6a2b1a7f315c49a3ad533d821e5 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Wed, 12 Mar 2025 11:23:19 -0400
Subject: [PATCH 1/2] [Coverage] Fix region termination for GNU statement
 expressions

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 
 .../CoverageMapping/terminate-statements.cpp  |  7 +++
 .../Linux/coverage-statement-expression.cpp   | 19 +++
 3 files changed, 34 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..d03e35630b317 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK-NOT: Gap,File 0, 
[[@LINE]]:41 -> [[@LINE+1]]:3 = 0
+  return rc;
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..5894275b941a2
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,19 @@
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
+}   // CHECK:  [[@LINE]]| 1|}

>From 0dc7ea6a13b34901bb6ca0253ad73e8ef5037244 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Fri, 14 Mar 2025 12:32:57 -0400
Subject: [PATCH 2/2] Avoid format warning to preserve readable CHECK lines

---
 .../test/profile/Linux/coverage-statement-expression.cpp| 2 ++
 1 file changed, 2 insertions(+)

diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
index 5894275b941a2..7c76555e3300b 100644
--- a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -5,6 +5,7 @@
 
 #include 
 
+// clang-f

[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-17 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/130976

>From 6f3557780d06d6a2b1a7f315c49a3ad533d821e5 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Wed, 12 Mar 2025 11:23:19 -0400
Subject: [PATCH 1/2] [Coverage] Fix region termination for GNU statement
 expressions

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 
 .../CoverageMapping/terminate-statements.cpp  |  7 +++
 .../Linux/coverage-statement-expression.cpp   | 19 +++
 3 files changed, 34 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..d03e35630b317 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK-NOT: Gap,File 0, 
[[@LINE]]:41 -> [[@LINE+1]]:3 = 0
+  return rc;
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..5894275b941a2
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,19 @@
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
+}   // CHECK:  [[@LINE]]| 1|}

>From 0dc7ea6a13b34901bb6ca0253ad73e8ef5037244 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Fri, 14 Mar 2025 12:32:57 -0400
Subject: [PATCH 2/2] Avoid format warning to preserve readable CHECK lines

---
 .../test/profile/Linux/coverage-statement-expression.cpp| 2 ++
 1 file changed, 2 insertions(+)

diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
index 5894275b941a2..7c76555e3300b 100644
--- a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -5,6 +5,7 @@
 
 #include 
 
+// clang-f

[clang] [compiler-rt] [Coverage] Fix region termination for GNU statement expressions (PR #130976)

2025-03-12 Thread Justin Cady via cfe-commits

https://github.com/justincady created 
https://github.com/llvm/llvm-project/pull/130976

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296


>From 6f3557780d06d6a2b1a7f315c49a3ad533d821e5 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Wed, 12 Mar 2025 11:23:19 -0400
Subject: [PATCH] [Coverage] Fix region termination for GNU statement
 expressions

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 
 .../CoverageMapping/terminate-statements.cpp  |  7 +++
 .../Linux/coverage-statement-expression.cpp   | 19 +++
 3 files changed, 34 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..d03e35630b317 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK-NOT: Gap,File 0, 
[[@LINE]]:41 -> [[@LINE+1]]:3 = 0
+  return rc;
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..5894275b941a2
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,19 @@
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
+}   // CHECK:  [[@LINE]]| 1|}


[clang] [lld] [llvm] Integrated Distributed ThinLTO (DTLTO): Initial support (PR #126654)

2025-02-13 Thread Justin Cady via cfe-commits

justincady wrote:

I just want to double check my understanding. :)

If I were to convert [this 
example](https://gist.github.com/MaskRay/24f4e2eed208b9d8b0a3752575a665d4#distributed-thinlto)
 to its functional equivalent in DTLTO, would it be:

```
clang -fuse-ld=lld -O2 -flto=thin -fthinlto-distributor=distributor_process a.c 
b.c c.c
```

Where:

- `distributor_process` receives a JSON file specifying all intermediate jobs
- If necessary I can use `-Xthinlto-distributor=` to pass extra arguments 
to `distributor_process`
- Each job invokes `--thinlto-remote-opt-tool` (defaults to clang)
- LLD waits for the jobs to complete and performs the final link

Is that correct?

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


[clang] [compiler-rt] Reland [Coverage] Fix region termination for GNU statement expressions (PR #132222)

2025-04-04 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/13

>From fa652581d03c962b61e7a350e0e9da0874e67109 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Thu, 20 Mar 2025 10:01:42 -0400
Subject: [PATCH] Reland [Coverage] Fix region termination for GNU statement
 expressions

Relands #130976 with adjustments to test requirements.

Calls to __noreturn__ functions result in region termination for
coverage mapping. But this creates incorrect coverage results when
__noreturn__ functions (or other constructs that result in region
termination) occur within [GNU statement expressions][1].

In this scenario an extra gap region is introduced within VisitStmt,
such that if the following line does not introduce a new region it
is unconditionally counted as uncovered.

This change adjusts the mapping such that terminate statements
within statement expressions do not propagate that termination
state after the statement expression is processed.

[1]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

Fixes #124296
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  8 +++
 .../CoverageMapping/terminate-statements.cpp  |  7 ++
 .../Linux/coverage-statement-expression.cpp   | 24 +++
 3 files changed, 39 insertions(+)
 create mode 100644 
compiler-rt/test/profile/Linux/coverage-statement-expression.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index f09157771d2b5..73811d15979d5 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1505,6 +1505,14 @@ struct CounterCoverageMappingBuilder
 handleFileExit(getEnd(S));
   }
 
+  void VisitStmtExpr(const StmtExpr *E) {
+Visit(E->getSubStmt());
+// Any region termination (such as a noreturn CallExpr) within the 
statement
+// expression has been handled by visiting the sub-statement. The visitor
+// cannot be at a terminate statement leaving the statement expression.
+HasTerminateStmt = false;
+  }
+
   void VisitDecl(const Decl *D) {
 Stmt *Body = D->getBody();
 
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index 0067185fee8e6..ef6b6fd82687d 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -346,6 +346,12 @@ int elsecondnoret(void) {
   return 0;
 }
 
+// CHECK-LABEL: _Z18statementexprnoretb:
+int statementexprnoret(bool crash) {
+  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = 
(#0 - #1)
+  return rc; // CHECK-NOT: Gap
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -368,5 +374,6 @@ int main() {
   ornoret();
   abstractcondnoret();
   elsecondnoret();
+  statementexprnoret(false);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp 
b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
new file mode 100644
index 0..19300411d54a2
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-statement-expression.cpp
@@ -0,0 +1,24 @@
+// REQUIRES: lld-available
+// XFAIL: powerpc64-target-arch
+
+// RUN: %clangxx_profgen -std=gnu++17 -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+// clang-format off
+__attribute__ ((__noreturn__))
+void foo(void) { while (1); }   // CHECK:  [[@LINE]]| 0|void 
foo(void)
+_Noreturn void bar(void) { while (1); } // CHECK:  [[@LINE]]| 
0|_Noreturn void bar(void)
+// CHECK:  [[@LINE]]|  |
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int 
main(
+  int rc = ({ if (argc > 3) foo(); 0; });   // CHECK:  [[@LINE]]| 1|  int 
rc =
+  printf("coverage after foo is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+// CHECK:  [[@LINE]]|  |
+  int rc2 = ({ if (argc > 3) bar(); 0; });  // CHECK:  [[@LINE]]| 1|  int 
rc2 =
+  printf("coverage after bar is present\n");// CHECK:  [[@LINE]]| 1|  
printf(
+  return rc + rc2;  // CHECK:  [[@LINE]]| 1|  
return rc
+}   // CHECK:  [[@LINE]]| 1|}
+// clang-format on

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


[clang] [compiler-rt] [Coverage] Fix mapping for do-while loops with terminating statements (PR #139777)

2025-05-13 Thread Justin Cady via cfe-commits

https://github.com/justincady created 
https://github.com/llvm/llvm-project/pull/139777

The current region mapping for do-while loops that contain statements
such as break or continue results in inaccurate line coverage reports
for the line following the loop.

This change handles terminating statements the same way that other loop
constructs do, correcting the region mapping for accurate reports. It
also fixes a fragile test relying on exact line numbers.

Fixes #139122


>From fff85d9cc74e2fbcbf1b2f9c94463070155decd8 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 13 May 2025 15:08:45 -0400
Subject: [PATCH] [Coverage] Fix mapping for do-while loops with terminating
 statements

The current region mapping for do-while loops that contain statements
such as break or continue results in inaccurate line coverage reports
for the line following the loop.

This change handles terminating statements the same way that other loop
constructs do, correcting the region mapping for accurate reports. It
also fixes a fragile test relying on exact line numbers.

Fixes #139122
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  5 ++---
 .../CoverageMapping/terminate-statements.cpp  | 13 +++-
 .../test/profile/Linux/coverage-do-while.c| 21 +++
 3 files changed, 35 insertions(+), 4 deletions(-)
 create mode 100644 compiler-rt/test/profile/Linux/coverage-do-while.c

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 73811d15979d5..6170dc7f59107 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1703,14 +1703,13 @@ struct CounterCoverageMappingBuilder
 if (!IsCounterEqual(OutCount, ParentCount)) {
   pushRegion(OutCount);
   GapRegionCounter = OutCount;
+  if (BodyHasTerminateStmt)
+HasTerminateStmt = true;
 }
 
 // Create Branch Region around condition.
 if (!llvm::EnableSingleByteCoverage)
   createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
-
-if (BodyHasTerminateStmt)
-  HasTerminateStmt = true;
   }
 
   void VisitForStmt(const ForStmt *S) {
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index ef6b6fd82687d..93d655794ccf5 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -348,10 +348,20 @@ int elsecondnoret(void) {
 
 // CHECK-LABEL: _Z18statementexprnoretb:
 int statementexprnoret(bool crash) {
-  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = 
(#0 - #1)
+  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, [[@LINE]]:35 -> 
[[@LINE+1]]:12 = (#0 - #1)
   return rc; // CHECK-NOT: Gap
 }
 
+// CHECK-LABEL: _Z13do_with_breaki:
+int do_with_break(int n) {
+  do {
+if (n == 87) {
+  break;
+}   // CHECK: File 0, [[@LINE-2]]:18 -> [[@LINE]]:6 = #2
+  } while (0);  // CHECK: File 0, [[@LINE]]:12 -> [[@LINE]]:13 = ((#0 + 
#1) - #2)
+  return 0; // CHECK-NOT: Gap,File 0, [[@LINE-1]]:15
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -375,5 +385,6 @@ int main() {
   abstractcondnoret();
   elsecondnoret();
   statementexprnoret(false);
+  do_with_break(0);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-do-while.c 
b/compiler-rt/test/profile/Linux/coverage-do-while.c
new file mode 100644
index 0..9e112cbc4c6a3
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-do-while.c
@@ -0,0 +1,21 @@
+// REQUIRES: lld-available
+// XFAIL: powerpc64-target-arch
+
+// RUN: %clangxx_profgen -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+// clang-format off
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int main(
+  do {  // CHECK:  [[@LINE]]| 1|  do {
+if (argc == 87) {   // CHECK:  [[@LINE]]| 1|if 
(argc
+  break;// CHECK:  [[@LINE]]| 0|  break
+}   // CHECK:  [[@LINE]]| 0|}
+  } while (0);  // CHECK:  [[@LINE]]| 1|  } while
+  printf("coverage after do is present\n"); // CHECK:  [[@LINE]]| 1|  printf(
+  return 0; // CHECK:  [[@LINE]]| 1|  return
+}   // CHECK:  [[@LINE]]| 1|}
+// clang-format on

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


[clang] [compiler-rt] [Coverage] Fix mapping for do-while loops with terminating statements (PR #139777)

2025-05-13 Thread Justin Cady via cfe-commits

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


[clang] [compiler-rt] [Coverage] Fix mapping for do-while loops with terminating statements (PR #139777)

2025-05-19 Thread Justin Cady via cfe-commits

justincady wrote:

Ping. :)

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


[clang] [compiler-rt] [Coverage] Fix mapping for do-while loops with terminating statements (PR #139777)

2025-05-19 Thread Justin Cady via cfe-commits

https://github.com/justincady updated 
https://github.com/llvm/llvm-project/pull/139777

>From be83c3207bf195aa7c6df1ce155402fde5911821 Mon Sep 17 00:00:00 2001
From: Justin Cady 
Date: Tue, 13 May 2025 15:08:45 -0400
Subject: [PATCH] [Coverage] Fix mapping for do-while loops with terminating
 statements

The current region mapping for do-while loops that contain statements
such as break or continue results in inaccurate line coverage reports
for the line following the loop.

This change handles terminating statements the same way that other loop
constructs do, correcting the region mapping for accurate reports. It
also fixes a fragile test relying on exact line numbers.

Fixes #139122
---
 clang/lib/CodeGen/CoverageMappingGen.cpp  |  5 ++---
 .../CoverageMapping/terminate-statements.cpp  | 13 +++-
 .../test/profile/Linux/coverage-do-while.c| 21 +++
 3 files changed, 35 insertions(+), 4 deletions(-)
 create mode 100644 compiler-rt/test/profile/Linux/coverage-do-while.c

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp 
b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 73811d15979d5..6170dc7f59107 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1703,14 +1703,13 @@ struct CounterCoverageMappingBuilder
 if (!IsCounterEqual(OutCount, ParentCount)) {
   pushRegion(OutCount);
   GapRegionCounter = OutCount;
+  if (BodyHasTerminateStmt)
+HasTerminateStmt = true;
 }
 
 // Create Branch Region around condition.
 if (!llvm::EnableSingleByteCoverage)
   createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
-
-if (BodyHasTerminateStmt)
-  HasTerminateStmt = true;
   }
 
   void VisitForStmt(const ForStmt *S) {
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp 
b/clang/test/CoverageMapping/terminate-statements.cpp
index ef6b6fd82687d..93d655794ccf5 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -348,10 +348,20 @@ int elsecondnoret(void) {
 
 // CHECK-LABEL: _Z18statementexprnoretb:
 int statementexprnoret(bool crash) {
-  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = 
(#0 - #1)
+  int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, [[@LINE]]:35 -> 
[[@LINE+1]]:12 = (#0 - #1)
   return rc; // CHECK-NOT: Gap
 }
 
+// CHECK-LABEL: _Z13do_with_breaki:
+int do_with_break(int n) {
+  do {
+if (n == 87) {
+  break;
+}   // CHECK: File 0, [[@LINE-2]]:18 -> [[@LINE]]:6 = #2
+  } while (0);  // CHECK: File 0, [[@LINE]]:12 -> [[@LINE]]:13 = ((#0 + 
#1) - #2)
+  return 0; // CHECK-NOT: Gap,File 0, [[@LINE-1]]:15
+}
+
 int main() {
   foo(0);
   foo(1);
@@ -375,5 +385,6 @@ int main() {
   abstractcondnoret();
   elsecondnoret();
   statementexprnoret(false);
+  do_with_break(0);
   return 0;
 }
diff --git a/compiler-rt/test/profile/Linux/coverage-do-while.c 
b/compiler-rt/test/profile/Linux/coverage-do-while.c
new file mode 100644
index 0..9e112cbc4c6a3
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-do-while.c
@@ -0,0 +1,21 @@
+// REQUIRES: lld-available
+// XFAIL: powerpc64-target-arch
+
+// RUN: %clangxx_profgen -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include 
+
+// clang-format off
+int main(int argc, char **argv) {   // CHECK:  [[@LINE]]| 1|int main(
+  do {  // CHECK:  [[@LINE]]| 1|  do {
+if (argc == 87) {   // CHECK:  [[@LINE]]| 1|if 
(argc
+  break;// CHECK:  [[@LINE]]| 0|  break
+}   // CHECK:  [[@LINE]]| 0|}
+  } while (0);  // CHECK:  [[@LINE]]| 1|  } while
+  printf("coverage after do is present\n"); // CHECK:  [[@LINE]]| 1|  printf(
+  return 0; // CHECK:  [[@LINE]]| 1|  return
+}   // CHECK:  [[@LINE]]| 1|}
+// clang-format on

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


[clang] [compiler-rt] [Coverage] Fix mapping for do-while loops with terminating statements (PR #139777)

2025-05-19 Thread Justin Cady via cfe-commits

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