[PATCH] D158948: [clang][ASTImporter] Add import of type-related nodes

2023-09-08 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

@haowei I noticed https://github.com/llvm/llvm-project/pull/65823, is it 
related to your work?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158948/new/

https://reviews.llvm.org/D158948

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


[PATCH] D158948: [clang][ASTImporter] Add import of type-related nodes

2023-09-08 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158948#4642422 , @haowei wrote:

> Looking at 
> https://github.com/llvm/llvm-project/blob/37a20cc68f545647e614c5ba4ae311dc3fd277e9/clang/lib/Testing/CommandLineArgs.cpp#L47,
>  this is were the unreachable code was hit. Is it the intended behavior?
>
> Shall I enable `ImportMatrixType` and disable `ImportOpenCLPipe` tests so we 
> can update the GoogleTest in LLVM?

I'm not familiar with GoogleTest so I wasn't expecting this to happen.

To enabling `ImportOpenCLPipe` we might use `"-x", "cl", "-cl-no-stdinc", 
"-cl-std=CL2.0"` here 
.

See also https://reviews.llvm.org/D158872 for some extra context of both 
testing with `ImportMatrixType` and `ImportOpenCLPipe`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158948/new/

https://reviews.llvm.org/D158948

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


[PATCH] D159263: [clang-tidy] misc-include-cleaner: avoid duplicated fixes

2023-09-05 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

Duplicated to https://github.com/llvm/llvm-project/pull/65431, abandon this one.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159263/new/

https://reviews.llvm.org/D159263

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-09-05 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

Ping~, could anyone have a look at this revision please? Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D159263: [clang-tidy] misc-include-cleaner: avoid duplicated fixes

2023-09-05 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 555867.
danix800 edited the summary of this revision.
danix800 added a comment.

1. Revert to internal set (not using `IncludeCleaner`);
2. Only do deduplication when not `areDiagsSelfContained()`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159263/new/

https://reviews.llvm.org/D159263

Files:
  clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
  clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp


Index: clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
@@ -11,6 +11,8 @@
 int BarResult = bar();
 int BazResult = baz();
 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: no header providing "baz" is 
directly included [misc-include-cleaner]
+int BazResultAgain = BAZ; // Header should not be inserted more than once
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: no header providing "BAZ" is 
directly included [misc-include-cleaner]
 std::string HelloString;
 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: no header providing "std::string" 
is directly included [misc-include-cleaner]
 int FooBarResult = foobar();
Index: clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
+++ clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
@@ -1,2 +1,3 @@
 #pragma once
+#define BAZ 10
 int baz();
Index: clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
===
--- clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -33,6 +33,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
@@ -199,6 +200,7 @@
 
   tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
  FileStyle->IncludeStyle);
+  llvm::StringSet<> AlreadyInserted;
   for (const auto  : Missing) {
 std::string Spelling = include_cleaner::spellHeader(
 {Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
@@ -209,14 +211,17 @@
 // main file.
 if (auto Replacement =
 HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include))
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name()
-  << FixItHint::CreateInsertion(
- SM->getComposedLoc(SM->getMainFileID(),
-Replacement->getOffset()),
- Replacement->getReplacementText());
+  Angled, tooling::IncludeDirective::Include)) 
{
+  DiagnosticBuilder DB =
+  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
+   "no header providing \"%0\" is directly included")
+  << Inc.SymRef.Target.name();
+  if (areDiagsSelfContained() ||
+  AlreadyInserted.insert(Inc.Missing.resolvedPath()).second)
+DB << FixItHint::CreateInsertion(
+SM->getComposedLoc(SM->getMainFileID(), Replacement->getOffset()),
+Replacement->getReplacementText());
+}
   }
 }
 


Index: clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
@@ -11,6 +11,8 @@
 int BarResult = bar();
 int BazResult = baz();
 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: no header providing "baz" is directly included [misc-include-cleaner]
+int BazResultAgain = BAZ; // Header should not be inserted more than once
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: no header providing "BAZ" is directly included [misc-include-cleaner]
 std::string HelloString;
 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: no header providing "std::string" is directly included [misc-include-cleaner]
 int FooBarResult = foobar();
Index: clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
+++ clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
@@ -1,2 +1,3 @@
 #pragma once
+#define BAZ 10
 int baz();
Index: 

[PATCH] D159263: [clang-tidy] misc-include-cleaner: avoid duplicated fixes

2023-09-05 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D159263#4638167 , @kadircet wrote:

> Thanks a lot for the patch @danix800 !
>
> I initially was rather focused on behavior of this check in workflows that 
> require seeing "self-contained-diags", but also I rather see the bulk-apply 
> use cases as always requiring clang-format afterwards. Hence didn't really 
> try to polish that use case a lot, but I believe changes in this patch 
> improve those use cases reasonably. But users do still need to run 
> clang-format afterwards, e.g. if we first generate a finding that inserts 
> "b.h" and then "a.h", they'll be in wrong order. So this is only fixing  some 
> cases. If you'd like to work on a more complete approach, we can prepare all 
> the edits in a single `tooling::Replacements` and run 
> `clang::format::cleanupAroundReplacements` on top of it to generate proper 
> edits, and emit FixIts with those merged replacements. Note that this still 
> won't be enough in all cases, as there can be other checks that emit fixes 
> that are touching includes :/
>
> Regarding usage of `IncludeInserter`; we were deliberately not using 
> `IncludeInserter` here, as it has slightly different semantics to 
> `HeaderIncludes`, which is used by all the other applications of 
> include-cleaner when producing edits. That way it's easier for us to reason 
> about the behavior in various places (and also to fix them). But moreover, 
> `HeaderIncludes` uses clang-format config to figure out include-styles and 
> works with a bigger set of projects without requiring extra configurations 
> (hence this patch will actually be a regression for those). Therefore can you 
> keep using `HeaderIncludes`, while skipping generation of duplicate fixits 
> when we're in non-self-contained-diags mode (assuming you don't want to 
> generalize the approach as I explained above).

Thanks for the background!

If we have further plans from upstream on these checker/clang-format related 
logic, I can wait and abandon this revision.

Or if such issue does need fixing then coud you take a look at the previous 
diff 1 
which uses an internal set to prevent this issue?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159263/new/

https://reviews.llvm.org/D159263

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


[PATCH] D159263: [clang-tidy] misc-include-cleaner: avoid duplicated fixes

2023-09-03 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

Ping @kadircet~, could you please take a look at this revision?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159263/new/

https://reviews.llvm.org/D159263

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


[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-09-01 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158499#4634166 , @steakhal wrote:

> @danix800 FYI I think you used the wrong revision link in the commit. Maybe 
> mark this revision as "abandoned" again, to reflect the actual status.

Sorry for this mistake.

D158707  originates from this but I forgot to 
update the revision ID.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158499/new/

https://reviews.llvm.org/D158499

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


[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-09-01 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

https://github.com/llvm/llvm-project/commit/12559064e05a11e8418425de59d8745f0cfb1122
 mistakingly linked here. The actual revision is D158707 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158499/new/

https://reviews.llvm.org/D158499

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-31 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

Thanks for clarifying!

If no further comments I'll commit this revison in a day or two!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D159263: [clang-tidy] misc-include-cleaner: fix duplicated fixes

2023-08-31 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 555059.
danix800 retitled this revision from "[clang-tidy] misc-include-cleaner: remove 
duplicated includes & fixes" to "[clang-tidy] misc-include-cleaner: fix 
duplicated fixes".
danix800 edited the summary of this revision.
danix800 added a comment.

1. Use `clang::tidy::utils::IncludeInserter` to avoid repeated insertion;
2. Leave out the deduplication policy part.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159263/new/

https://reviews.llvm.org/D159263

Files:
  clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
  clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h
  clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
  clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
@@ -11,6 +11,8 @@
 int BarResult = bar();
 int BazResult = baz();
 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: no header providing "baz" is directly included [misc-include-cleaner]
+int BazResultAgain = BAZ; // Header should not be inserted more than once
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: no header providing "BAZ" is directly included [misc-include-cleaner]
 std::string HelloString;
 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: no header providing "std::string" is directly included [misc-include-cleaner]
 int FooBarResult = foobar();
Index: clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
+++ clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
@@ -1,2 +1,3 @@
 #pragma once
+#define BAZ 10
 int baz();
Index: clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h
===
--- clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h
+++ clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.h
@@ -12,13 +12,13 @@
 #include "../ClangTidyCheck.h"
 #include "../ClangTidyDiagnosticConsumer.h"
 #include "../ClangTidyOptions.h"
+#include "../utils/IncludeInserter.h"
 #include "clang-include-cleaner/Record.h"
 #include "clang-include-cleaner/Types.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceLocation.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/Preprocessor.h"
 #include "llvm/Support/Regex.h"
 #include 
 
@@ -47,6 +47,7 @@
   std::vector IgnoreHeaders;
   // Whether emit only one finding per usage of a symbol.
   const bool DeduplicateFindings;
+  utils::IncludeInserter IncludeInserter;
   llvm::SmallVector IgnoreHeadersRegex;
   bool shouldIgnore(const include_cleaner::Header );
 };
Index: clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
===
--- clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyCheck.h"
 #include "../ClangTidyDiagnosticConsumer.h"
 #include "../ClangTidyOptions.h"
+#include "../utils/IncludeSorter.h"
 #include "../utils/OptionsUtils.h"
 #include "clang-include-cleaner/Analysis.h"
 #include "clang-include-cleaner/IncludeSpeller.h"
@@ -25,10 +26,8 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceLocation.h"
-#include "clang/Format/Format.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Tooling/Core/Replacement.h"
-#include "clang/Tooling/Inclusions/HeaderIncludes.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
@@ -36,7 +35,6 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
-#include 
 #include 
 #include 
 
@@ -57,7 +55,10 @@
   IgnoreHeaders(utils::options::parseStringList(
   Options.getLocalOrGlobal("IgnoreHeaders", ""))),
   DeduplicateFindings(
-  Options.getLocalOrGlobal("DeduplicateFindings", true)) {
+  Options.getLocalOrGlobal("DeduplicateFindings", true)),
+  IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
+   utils::IncludeSorter::IS_LLVM),
+  areDiagsSelfContained()) {
   for (const auto  : IgnoreHeaders) {
 if (!llvm::Regex{Header}.isValid())
   configurationDiag("Invalid ignore headers regex '%0'") << Header;
@@ -71,6 +72,7 @@
 void IncludeCleanerCheck::storeOptions(ClangTidyOptions::OptionMap ) {
   Options.store(Opts, "IgnoreHeaders",
 utils::options::serializeStringList(IgnoreHeaders));

[PATCH] D159263: [clang-tidy] misc-include-cleaner: remove duplicated includes & fixes

2023-08-31 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp:169
+  else
+Unused.push_back();
+  continue;

sammccall wrote:
> If we want this policy, it should be provided at the include-cleaner library 
> level so it applies to all clients, not just the clang-tidy check.
> 
> I think the clearest way is to encapsulate this in include_cleaner::Includes, 
> so that match() never matches a Header requirement against a duplicative 
> Include. This will naturally lead to the directives being marked as unused.
> 
> (In practice, the result will work in clangd, and will respect configuration 
> of headers where analysis should be ignored, keep directives, etc)
I'll leave the policy part to another revision (maybe by others).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159263/new/

https://reviews.llvm.org/D159263

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


[PATCH] D159263: [clang-tidy] misc-include-cleaner: remove duplicated includes & fixes

2023-08-31 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp:227
+  << Inc.SymRef.Target.name();
+  if (!AlreadyInserted.contains(Inc.Missing.resolvedPath())) {
+DB << FixItHint::CreateInsertion(

sammccall wrote:
> This means that if you're looking at individual diagnostics rather than 
> applying all fixes to a file, only the first diagnostic will have any fix 
> available at all.
> 
> I believe the preferred solution is to do this conditionally based on 
> areDiagsSelfContained(). `clang_tidy::utils::IncludeInserter` encapsulates 
> this, but isn't used here.
> 
> I don't know whether we would want to use it here, or how carefully it's 
> already been considered. (It definitely contains a lot of logic that is 
> dubious to apply when the include to insert has already been precisely 
> calculated, but also some things that would be helpful). Will defer to Kadir 
> on that.
Thanks for mentioning the `clang_tidy::utils::IncludeInserter`. I took a 
further look and found that `IncludeInserter` is
more suitable for this checker.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159263/new/

https://reviews.llvm.org/D159263

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


[PATCH] D159263: [clang-tidy] misc-include-cleaner: remove duplicated includes & fixes

2023-08-31 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added reviewers: VitaNuo, kadircet, sammccall.
danix800 added a project: clang-tools-extra.
Herald added subscribers: PiotrZSL, carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

1. Duplicated includes could be removed:

  #include "bar.h"
  #include "bar.h" # could be eliminated



2. FixItHint should not be applied (multiple insertions) for different symbols 
from same header.

  // baz.h
  #pragma once
  #define BAZ 10
  int baz();
  
  // include-cleaner.cpp
  // only one '#include "baz.h"' should be inserted.
  int BazResult = baz();
  int BazResultAgain = BAZ;


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D159263

Files:
  clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
  clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp


Index: clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/misc/include-cleaner.cpp
@@ -1,5 +1,8 @@
 // RUN: %check_clang_tidy %s misc-include-cleaner %t -- -- -I%S/Inputs 
-isystem%S/Inputs/system
 #include "bar.h"
+#include "bar.h"
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header bar.h is not used 
directly [misc-include-cleaner]
+// CHECK-FIXES: {{^}}
 // CHECK-FIXES: {{^}}#include "baz.h"{{$}}
 #include "foo.h"
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header foo.h is not used 
directly [misc-include-cleaner]
@@ -11,6 +14,8 @@
 int BarResult = bar();
 int BazResult = baz();
 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: no header providing "baz" is 
directly included [misc-include-cleaner]
+int BazResultAgain = BAZ; // Header should not be inserted more than once
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: no header providing "BAZ" is 
directly included [misc-include-cleaner]
 std::string HelloString;
 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: no header providing "std::string" 
is directly included [misc-include-cleaner]
 int FooBarResult = foobar();
Index: clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
===
--- clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
+++ clang-tools-extra/test/clang-tidy/checkers/misc/Inputs/baz.h
@@ -1,2 +1,3 @@
 #pragma once
+#define BAZ 10
 int baz();
Index: clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
===
--- clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
@@ -33,6 +33,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
@@ -156,10 +157,18 @@
});
 
   std::vector Unused;
+  llvm::StringSet<> AlreadyIncludedHeaders;
   for (const include_cleaner::Include  :
RecordedPreprocessor.Includes.all()) {
-if (Used.contains() || !I.Resolved)
+if (!I.Resolved)
   continue;
+if (Used.contains()) {
+  if (!AlreadyIncludedHeaders.contains(I.Spelled))
+AlreadyIncludedHeaders.insert(I.Spelled);
+  else
+Unused.push_back();
+  continue;
+}
 if (RecordedPI.shouldKeep(*I.Resolved))
   continue;
 // Check if main file is the public interface for a private header. If so
@@ -199,6 +208,7 @@
 
   tooling::HeaderIncludes HeaderIncludes(getCurrentMainFile(), Code,
  FileStyle->IncludeStyle);
+  llvm::StringSet<> AlreadyInserted;
   for (const auto  : Missing) {
 std::string Spelling = include_cleaner::spellHeader(
 {Inc.Missing, PP->getHeaderSearchInfo(), MainFile});
@@ -209,14 +219,18 @@
 // main file.
 if (auto Replacement =
 HeaderIncludes.insert(llvm::StringRef{Spelling}.trim("\"<>"),
-  Angled, tooling::IncludeDirective::Include))
-  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
-   "no header providing \"%0\" is directly included")
-  << Inc.SymRef.Target.name()
-  << FixItHint::CreateInsertion(
- SM->getComposedLoc(SM->getMainFileID(),
-Replacement->getOffset()),
- Replacement->getReplacementText());
+  Angled, tooling::IncludeDirective::Include)) 
{
+  DiagnosticBuilder DB =
+  diag(SM->getSpellingLoc(Inc.SymRef.RefLocation),
+   "no header providing \"%0\" is directly included")
+  << 

[PATCH] D159163: [analyzer][NFC] Workaround miscompilation on recent MSVC

2023-08-30 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D159163#4627497 , @steakhal wrote:

> Feel free to merge it. Thanks!
> I'd be curious to see if this bug is tracked at Microsoft.

I searched but no result so I submitted it to MS: 
https://developercommunity.visualstudio.com/t/Possible-miscompilation-in-release-mode-/10453172


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D159163/new/

https://reviews.llvm.org/D159163

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


[PATCH] D158948: [clang][ASTImporter] Add import of type-related nodes

2023-08-30 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 554603.
danix800 added a comment.

Pulling local matchers for testcases, since https://reviews.llvm.org/D158872 is 
abandoned.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158948/new/

https://reviews.llvm.org/D158948

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterObjCTest.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -583,6 +583,96 @@
   functionDecl(hasDescendant(typedefDecl(has(atomicType());
 }
 
+TEST_P(ImportType, ImportBitIntType) {
+  const AstTypeMatcher bitIntType;
+  MatchVerifier Verifier;
+  testImport("_BitInt(10) declToImport;", Lang_CXX11, "", Lang_CXX11, Verifier,
+ varDecl(hasType(bitIntType(;
+}
+
+TEST_P(ImportType, ImportDependentBitIntType) {
+  const AstTypeMatcher dependentBitIntType;
+  MatchVerifier Verifier;
+  testImport("template using declToImport = _BitInt(Width);",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typeAliasTemplateDecl(
+ has(typeAliasDecl(hasType(dependentBitIntType());
+}
+
+TEST_P(ImportType, ImportDependentAddressSpaceType) {
+  const AstTypeMatcher dependentAddressSpaceType;
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((address_space(AddrSpace)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentAddressSpaceType());
+}
+
+TEST_P(ImportType, ImportVectorType) {
+  const AstTypeMatcher vectorType;
+  MatchVerifier Verifier;
+  testImport("typedef int __attribute__((vector_size(12))) declToImport;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typedefDecl(hasType(vectorType(;
+}
+
+TEST_P(ImportType, ImportDependentVectorType) {
+  const AstTypeMatcher dependentVectorType;
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((vector_size(Size)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentVectorType());
+}
+
+struct ImportOpenCLPipe : ImportType {
+  std::vector getExtraArgs() const override {
+return {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"};
+  }
+};
+
+TEST_P(ImportOpenCLPipe, ImportPipeType) {
+  const AstTypeMatcher pipeType;
+  MatchVerifier Verifier;
+  testImport("typedef pipe int declToImport;", Lang_OpenCL, "", Lang_OpenCL,
+ Verifier, typedefDecl(hasType(pipeType(;
+}
+
+struct ImportMatrixType : ImportType {
+  std::vector getExtraArgs() const override {
+return {"-fenable-matrix"};
+  }
+};
+
+TEST_P(ImportMatrixType, ImportConstantMatrixType) {
+  const AstTypeMatcher constantMatrixType;
+  MatchVerifier Verifier;
+  testImport("typedef int __attribute__((matrix_type(5, 5))) declToImport;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typedefDecl(hasType(constantMatrixType(;
+}
+
+TEST_P(ImportMatrixType, ImportDependentSizedMatrixType) {
+  const AstTypeMatcher dependentSizedMatrixType;
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((matrix_type(Rows, Cols)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentSizedMatrixType());
+}
+
 TEST_P(ImportType, ImportUsingType) {
   MatchVerifier Verifier;
   testImport("struct C {};"
Index: clang/unittests/AST/ASTImporterObjCTest.cpp
===
--- clang/unittests/AST/ASTImporterObjCTest.cpp
+++ clang/unittests/AST/ASTImporterObjCTest.cpp
@@ -77,6 +77,22 @@
   }
 }
 
+TEST_P(ImportObjCDecl, ImportObjCTypeParamDecl) {
+  Decl *FromTU = getTuDecl(
+  R"(
+@interface X 
+@end
+  )",
+  Lang_OBJCXX, "input.mm");
+  auto *FromInterfaceDecl = FirstDeclMatcher().match(
+  FromTU, namedDecl(hasName("X")));
+  auto *FromTypeParamDecl =
+  FromInterfaceDecl->getTypeParamListAsWritten()->front();
+
+  auto *ToTypeParamDeclImported = Import(FromTypeParamDecl, Lang_OBJCXX);
+  ASSERT_TRUE(ToTypeParamDeclImported);
+}
+
 static const auto ObjCTestArrayForRunOptions =
 std::array, 2>{
 {std::vector{"-fno-objc-arc"},
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -368,58 +368,9 @@
 
 // Importing types
 ExpectedType VisitType(const Type *T);
-ExpectedType VisitAtomicType(const AtomicType *T);
-ExpectedType VisitBuiltinType(const BuiltinType *T);
-ExpectedType VisitDecayedType(const 

[PATCH] D158872: [clang][ASTMatchers] Add a few type-related Matchers

2023-08-30 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158872#4627313 , @PiotrZSL wrote:

> From a mine perspective when it comes to clang-tidy:
>
> - I personally do not care about Objective-C specific matchers - I do not 
> plan to use them.
> - I personally avoid using "Type" based matchers if I can (due to mess with 
> elaborated/wrapped types), it's easier to create custom local matcher for 
> QualType and do there anything is needed. QualType/Type class got very 
> helpful API.
> - There is nothing more annoying than not having a main matcher for specific 
> Stmt, Decl, Expr, TypeLoc (places that actually got SourceLocation) and some 
> basic matchers for traversal into parents/childs.
> - There are lot of local matchers defined in Clang-tidy, those would be a 
> best candidates to push upwards.
> - I'm missing some matchers related to AST traversal: noneOf, 
> equalOrDescendant, hasFirstAncestor(PositiveMatcher, NegativeMatcher), 
> isBeforeInTransationUnit, isInSameScopeAsBoundNode, ...
>
> As for matchers in this change, except maybe hasTypeForDecl, I do not think 
> that I will be using them.

All right, I'll abandon this revison. Thanks for reviewing.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158872/new/

https://reviews.llvm.org/D158872

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


[PATCH] D159163: [analyzer][NFC] Workaround miscompilation on recent MSVC

2023-08-29 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a reviewer: steakhal.
danix800 added a project: clang.
Herald added subscribers: manas, ASDenysPetrov, martong, dkrupp, donat.nagy, 
Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Fixes https://github.com/llvm/llvm-project/issues/62130


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D159163

Files:
  clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp


Index: clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
+++ clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
@@ -91,7 +91,7 @@
 
 ConstraintManager::ProgramStatePair
 ConstraintManager::assumeDual(ProgramStateRef State, DefinedSVal Cond) {
-  auto AssumeFun = [&](bool Assumption) {
+  auto AssumeFun = [&, Cond](bool Assumption) {
 return assumeInternal(State, Cond, Assumption);
   };
   return assumeDualImpl(State, AssumeFun);


Index: clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
===
--- clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
+++ clang/lib/StaticAnalyzer/Core/ConstraintManager.cpp
@@ -91,7 +91,7 @@
 
 ConstraintManager::ProgramStatePair
 ConstraintManager::assumeDual(ProgramStateRef State, DefinedSVal Cond) {
-  auto AssumeFun = [&](bool Assumption) {
+  auto AssumeFun = [&, Cond](bool Assumption) {
 return assumeInternal(State, Cond, Assumption);
   };
   return assumeDualImpl(State, AssumeFun);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158948: [clang][ASTImporter] Add import of type-related nodes

2023-08-29 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

Changes planned for https://reviews.llvm.org/D158872 is still under discussion.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158948/new/

https://reviews.llvm.org/D158948

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


[PATCH] D158948: [clang][ASTImporter] Add import of type-related nodes

2023-08-29 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 554545.
danix800 added a comment.

1. Simplify error handling
2. Remove unnecessary tests


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158948/new/

https://reviews.llvm.org/D158948

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterObjCTest.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -583,6 +583,88 @@
   functionDecl(hasDescendant(typedefDecl(has(atomicType());
 }
 
+TEST_P(ImportType, ImportBitIntType) {
+  MatchVerifier Verifier;
+  testImport("_BitInt(10) declToImport;", Lang_CXX11, "", Lang_CXX11, Verifier,
+ varDecl(hasType(bitIntType(;
+}
+
+TEST_P(ImportType, ImportDependentBitIntType) {
+  MatchVerifier Verifier;
+  testImport("template using declToImport = _BitInt(Width);",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typeAliasTemplateDecl(
+ has(typeAliasDecl(hasType(dependentBitIntType());
+}
+
+TEST_P(ImportType, ImportDependentAddressSpaceType) {
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((address_space(AddrSpace)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentAddressSpaceType());
+}
+
+TEST_P(ImportType, ImportVectorType) {
+  MatchVerifier Verifier;
+  testImport("typedef int __attribute__((vector_size(12))) declToImport;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typedefDecl(hasType(vectorType(;
+}
+
+TEST_P(ImportType, ImportDependentVectorType) {
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((vector_size(Size)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentVectorType());
+}
+
+struct ImportOpenCLPipe : ImportType {
+  std::vector getExtraArgs() const override {
+return {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"};
+  }
+};
+
+TEST_P(ImportOpenCLPipe, ImportPipeType) {
+  MatchVerifier Verifier;
+  testImport("typedef pipe int declToImport;", Lang_OpenCL, "", Lang_OpenCL,
+ Verifier, typedefDecl(hasType(pipeType(;
+}
+
+struct ImportMatrixType : ImportType {
+  std::vector getExtraArgs() const override {
+return {"-fenable-matrix"};
+  }
+};
+
+TEST_P(ImportMatrixType, ImportConstantMatrixType) {
+  MatchVerifier Verifier;
+  testImport("typedef int __attribute__((matrix_type(5, 5))) declToImport;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typedefDecl(hasType(constantMatrixType(;
+}
+
+TEST_P(ImportMatrixType, ImportDependentSizedMatrixType) {
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((matrix_type(Rows, Cols)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentSizedMatrixType());
+}
+
 TEST_P(ImportType, ImportUsingType) {
   MatchVerifier Verifier;
   testImport("struct C {};"
Index: clang/unittests/AST/ASTImporterObjCTest.cpp
===
--- clang/unittests/AST/ASTImporterObjCTest.cpp
+++ clang/unittests/AST/ASTImporterObjCTest.cpp
@@ -77,6 +77,27 @@
   }
 }
 
+TEST_P(ImportObjCDecl, ImportObjCTypeParamDecl) {
+  Decl *FromTU = getTuDecl(
+  R"(
+@interface X 
+@end
+  )",
+  Lang_OBJCXX, "input.mm");
+  auto Pattern = objcTypeParamDecl(hasTypeForDecl(objcTypeParamType()));
+  auto *FromInterfaceDecl = FirstDeclMatcher().match(
+  FromTU, namedDecl(hasName("X")));
+  auto *FromTypeParamDecl =
+  FirstDeclMatcher().match(FromInterfaceDecl, Pattern);
+
+  auto ToTypeParamDeclImported = Import(FromTypeParamDecl, Lang_OBJCXX);
+
+  auto *ToInterfaceDecl = FirstDeclMatcher().match(
+  ToTypeParamDeclImported->getTranslationUnitDecl(),
+  namedDecl(hasName("X")));
+  ASSERT_TRUE(ToTypeParamDeclImported);
+}
+
 static const auto ObjCTestArrayForRunOptions =
 std::array, 2>{
 {std::vector{"-fno-objc-arc"},
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -368,58 +368,9 @@
 
 // Importing types
 ExpectedType VisitType(const Type *T);
-ExpectedType VisitAtomicType(const AtomicType *T);
-ExpectedType VisitBuiltinType(const BuiltinType *T);
-ExpectedType VisitDecayedType(const DecayedType *T);
-ExpectedType VisitComplexType(const ComplexType *T);
-ExpectedType VisitPointerType(const PointerType 

[PATCH] D158872: [clang][ASTMatchers] Add a few type-related Matchers

2023-08-29 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158872#4626272 , @sammccall wrote:

> In D158872#4626095 , @aaron.ballman 
> wrote:
>
>> Out of curiosity, are you testing on Windows with MSVC? My understanding on 
>> build time performance impacts was that it's debug builds with MSVC that get 
>> hit especially hard. (I can test that setup but I could use some help 
>> figuring out how you tested compile times so I can do a similar test instead 
>> of something totally different from what you tried.)
>
> I'm not :-( I don't have a windows machine, and the VM I used to have has 
> bitrotted beyond repair (not sure how useful benchmarks from there would be 
> anyway).
>
> This is with clang on linux, just running `time clang-check-14 
> include/clang/ASTMatchers/ASTMatchers.h` a few times.
> The "deps only" test was `#if 0` ing out all the code in `ASTMatcher.h`, and 
> commenting out the `ASTMatchers/*` includes, and repeating the same.
> For object files I just added a dummy `ASTMatchers.cpp` with only `#include 
> "clang/ASTMatchers/ASTMatchers.h"`.
>
> I guess the equivalent of clang-check would be `/Zs`, not sure the best way 
> to feed it the right flags...

Thanks for the testing. I can do the windows part with MSVC cl.exe.

1. `ASTMatchers.h`: ~3.5s
2. "Deps only": ~3.2s
3. `ASTMatchers.cpp` obj: 8K

  $ uname -a
  MINGW64_NT-10.0-20348 WIN-LH267487PAC 3.3.3-341.x86_64 2022-01-17 11:45 UTC 
x86_64 Msys
  
  $ echo $SHELL
  /usr/bin/bash
  
  $ cat test.ps1
  & "C:\Program Files\Microsoft Visual 
Studio\2022\Community\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64\cl.exe" 
/permissive- /MP /we"4238" /GS /Zc:preprocessor /W4 /wd"4141" /wd"4146" 
/wd"4244" /wd"4267" /wd"4291" /wd"4351" /wd"4456" /wd"4457" /wd"4458" /wd"4459" 
/wd"4503" /wd"4624" /wd"4722" /wd"4100" /wd"4127" /wd"4512" /wd"4505" /wd"4610" 
/wd"4510" /wd"4702" /wd"4245" /wd"4706" /wd"4310" /wd"4701" /wd"4703" /wd"4389" 
/wd"4611" /wd"4805" /wd"4204" /wd"4577" /wd"4091" /wd"4592" /wd"4319" /wd"4709" 
/wd"5105" /wd"4324" /Zc:wchar_t 
/I"C:\Users\Administrator\source\repos\llvm-project\build-main-vs2022\tools\clang\lib\ASTMatchers"
 /I"C:\Users\Administrator\source\repos\llvm-project\clang\lib\ASTMatchers" 
/I"C:\Users\Administrator\source\repos\llvm-project\clang\include" 
/I"C:\Users\Administrator\source\repos\llvm-project\build-main-vs2022\tools\clang\include"
 /I"C:\Users\Administrator\source\repos\llvm-project\build-main-vs2022\include" 
/I"C:\Users\Administrator\source\repos\llvm-project\llvm\include" /Gm- /O2 /Ob2 
/Zc:inline /fp:precise /U"NDEBUG" /D "_UNICODE" /D "UNICODE" /D "WIN32" /D 
"_WINDOWS" /D "_GLIBCXX_ASSERTIONS" /D "_LIBCPP_ENABLE_ASSERTIONS" /D 
"_CRT_SECURE_NO_DEPRECATE" /D "_CRT_SECURE_NO_WARNINGS" /D 
"_CRT_NONSTDC_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_WARNINGS" /D 
"_SCL_SECURE_NO_DEPRECATE" /D "_SCL_SECURE_NO_WARNINGS" /D 
"__STDC_CONSTANT_MACROS" /D "__STDC_FORMAT_MACROS" /D "__STDC_LIMIT_MACROS" /D 
CMAKE_INTDIR=\"Release\" /errorReport:prompt /WX- /Zc:forScope /GR /Gd /Oi /MD 
/std:c++17 /EHsc /nologo 
/Fp"obj.clangASTMatchers.dir\Release\obj.clangASTMatchers.pch" 
/diagnostics:column /Zc:__cplusplus /bigobj -w14062 /Gw /I"C:\Program 
Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\include" 
/I"C:\Program Files\Microsoft Visual 
Studio\2022\Community\VC\Tools\MSVC\14.37.32822\atlmfc\include" /I"C:\Program 
Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include" 
/I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt" 
/I"C:\Program Files\Microsoft Visual 
Studio\2022\Community\VC\Auxiliary\VS\UnitTest\include" /I"C:\Program Files 
(x86)\Windows Kits\10\Include\10.0.22621.0\um" /I"C:\Program Files 
(x86)\Windows Kits\10\Include\10.0.22621.0\shared" /I"C:\Program Files 
(x86)\Windows Kits\10\Include\10.0.22621.0\winrt" /I"C:\Program Files 
(x86)\Windows Kits\10\Include\10.0.22621.0\cppwinrt" /c 
..\clang\include\clang\ASTMatchers\ASTMatchers.h /TP
  
   $ time powershell ./test.ps1
  ASTMatchers.h
  
  real0m3.143s
  user0m0.015s
  sys 0m0.000s


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158872/new/

https://reviews.llvm.org/D158872

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-29 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158707#4621377 , @steakhal wrote:

> In D158707#4621270 , @donat.nagy 
> wrote:
>
>> In D158707#4621135 , @steakhal 
>> wrote:
>>
>>> Oh, so we would canonicalize towards a signed extent type. I see. I think 
>>> I'm okay with that.
>>> However, I think this needs a little bit of polishing and testing when the 
>>> region does not point to the beginning of an array or object, but rather 
>>> inside an object, or like this:
>>>
>>>   int nums[] = {1,2,3};
>>>   char *p = (char*)[1];
>>>   
>>>   clang_analyzer_dumpExtent(p);
>>>   clang_analyzer_dumpElementCount(p);
>>>   ++p;
>>>   clang_analyzer_dumpExtent(p);
>>>   clang_analyzer_dumpElementCount(p);
>>>   ++p;
>>>   int *q = (int*)p;
>>>   clang_analyzer_dumpExtent(q);
>>>   clang_analyzer_dumpElementCount(q);
>>
>> Unfortunately the analyzer engine does not distinguish pointer arithmetic 
>> and element access, and we cannot handle these situations while that 
>> limitation exists. For example, if we have an array `int nums[3];`, then the 
>> element `nums[1]` and the incremented pointer `int *ptr = nums + 1;` are 
>> represented by the same `ElementRegion` object; so we cannot simultaneously 
>> say that (1) `nums[1]` is an int-sized memory region, and (2) it's valid to 
>> access the elements of the array as `ptr[-1]`, `ptr[0]` and `ptr[1]`.
>>
>> The least bad heuristic is probably `RegionRawOffsetV2::computeOffset()` 
>> from ArrayBoundCheckerV2, which strips away all the `ElementRegion` layers, 
>> acting as if they are all coming from pointer arithmetic. This behavior is 
>> incorrect if we want to query the extent/elementcount of a "real" 
>> ElementRegion (e.g. a slice of a multidimensional array or `(char*)[1]` 
>> in your example), but mostly leads to false negatives. On the other hand, if 
>> we process a pointer increment as if it were an element access, we can 
>> easily run into false positive reports -- this is why I had to abandon 
>> D150446 .
>>
>> I'd suggest that we should ignore pointer arithmetic in this commit (or 
>> create a testcase that documents the current insufficient behavior) and 
>> remember this as yet another reason to do through rewrite of the memory 
>> model. This is related to the plan 
>> https://github.com/llvm/llvm-project/issues/42709 suggested by @NoQ, but 
>> perhaps it would be enough to do a less drastic change in that direction.
>
> I'm aware of this, and I didn't mean to ask to fix this here.
> I just want to see how these ExprInspection APIs will be affected in these 
> edge-cases, where previously it returned "unknown", and now will return 
> something else.
> It's useful to demonstrate this if we ever come back to this commit.
> Pinning down some tests and having some FIXMEs there should bring enough 
> visibility.

Thank you all for the above valuable information. It's helpful for me to get 
better understanding of CSA!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-29 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 554383.
danix800 added a comment.

1. Cleanup unnecessary undef/zero checking;
2. Use better defensive API for getting `ConstantArrayType`;
3. Comment on bool argument for readability;
4. Add more test for extent with offset cases.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
  clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
  clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
  clang/test/Analysis/array-bound-v2-constraint-check.c
  clang/test/Analysis/flexible-array-members.c
  clang/test/Analysis/memory-model.cpp

Index: clang/test/Analysis/memory-model.cpp
===
--- clang/test/Analysis/memory-model.cpp
+++ clang/test/Analysis/memory-model.cpp
@@ -66,8 +66,8 @@
 
 void field_ptr(S *a) {
   clang_analyzer_dump(>f); // expected-warning {{Element{SymRegion{reg_$0},0 S64b,struct S}.f}}
-  clang_analyzer_dumpExtent(>f);   // expected-warning {{4 S64b}}
-  clang_analyzer_dumpElementCount(>f); // expected-warning {{1 S64b}}
+  clang_analyzer_dumpExtent(>f);   // expected-warning {{extent_$1{SymRegion{reg_$0
+  clang_analyzer_dumpElementCount(>f); // expected-warning {{(extent_$1{SymRegion{reg_$0}}) / 4U}}
 }
 
 void symbolic_array() {
@@ -90,7 +90,7 @@
 void symbolic_malloc() {
   int *a = (int *)malloc(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
   free(a);
 }
@@ -98,22 +98,22 @@
 void symbolic_alloca() {
   int *a = (int *)alloca(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
 }
 
 void symbolic_complex() {
   int *a = (int *)malloc(4);
-  clang_analyzer_dumpExtent(a);   // expected-warning {{4 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{4 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{1 S64b}}
 
   int *b = (int *)realloc(a, sizeof(int) * 2);
-  clang_analyzer_dumpExtent(b);   // expected-warning {{8 U64b}}
+  clang_analyzer_dumpExtent(b);   // expected-warning {{8 S64b}}
   clang_analyzer_dumpElementCount(b); // expected-warning {{2 S64b}}
   free(b);
 
   int *c = (int *)calloc(3, 4);
-  clang_analyzer_dumpExtent(c);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(c);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(c); // expected-warning {{3 S64b}}
   free(c);
 }
@@ -123,7 +123,7 @@
   char *b = (char *)malloc(13);
 
   clang_analyzer_dump(clang_analyzer_getExtent(a)); // expected-warning {{13 S64b}}
-  clang_analyzer_dump(clang_analyzer_getExtent(b)); // expected-warning {{13 U64b}}
+  clang_analyzer_dump(clang_analyzer_getExtent(b)); // expected-warning {{13 S64b}}
   clang_analyzer_eval(clang_analyzer_getExtent(a) ==
   clang_analyzer_getExtent(b));
   // expected-warning@-2 {{TRUE}}
@@ -155,3 +155,31 @@
 
   operator delete[](a, std::align_val_t(32));
 }
+
+int a[5][0];
+struct T {
+  int x[];
+};
+
+T t[5];
+void zero_sized_element() {
+  clang_analyzer_dumpExtent(a);   // expected-warning {{0 S64b}}
+  clang_analyzer_dumpElementCount(a); // expected-warning {{5 S64b}}
+  clang_analyzer_dumpExtent(t);   // expected-warning {{0 S64b}}
+  clang_analyzer_dumpElementCount(t); // expected-warning {{5 S64b}}
+}
+
+void extent_with_offset() {
+  int nums[] = {1,2,3};
+  char *p = (char*)[1];
+
+  clang_analyzer_dumpExtent(p); // expected-warning {{8 S64b}}
+  clang_analyzer_dumpElementCount(p);   // expected-warning {{8 S64b}}
+  ++p;
+  clang_analyzer_dumpExtent(p); // expected-warning {{7 S64b}}
+  clang_analyzer_dumpElementCount(p);   // expected-warning {{7 S64b}}
+  ++p;
+  int *q = (int*)p;
+  clang_analyzer_dumpExtent(q); // expected-warning {{6 S64b}}
+  clang_analyzer_dumpElementCount(q);   // expected-warning {{1 S64b}}
+}
Index: clang/test/Analysis/flexible-array-members.c
===
--- clang/test/Analysis/flexible-array-members.c
+++ clang/test/Analysis/flexible-array-members.c
@@ -44,20 +44,52 @@
   clang_analyzer_dump(clang_analyzer_getExtent());
   clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
   // expected-warning@-2 {{4 S64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 S64b}}
 
   FAM *p = (FAM *)alloca(sizeof(FAM));
   

[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-29 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp:34
+if (auto SSize =
+SVB.convertToArrayIndex(*Size).getAs())
+  return *SSize;

donat.nagy wrote:
> I think it's a good convention if `getDynamicExtent()` will always return 
> concrete values as `ArrayIndexTy`. (If I didn't miss some very obscure case, 
> then this will be true when this commit is merged.) 
Could you elaborate this a bit more please? Do you mean by 
`nonloc::ConcreteInt` rather than `DefinedOrUnknownSVal`?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158872: [clang][ASTMatchers] Add a few type-related Matchers

2023-08-28 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158872#4622124 , @aaron.ballman 
wrote:

> Are these matchers going to be used in-tree (by clang-tidy, or something 
> else)? We typically do not add new AST matches until there's a need for them 
> because the AST matchers have a pretty big impact on build times of Clang 
> itself.

They are used in `ASTImporter` testcases as shown in 
https://reviews.llvm.org/D158948. Though this might not be a strong reason to
add these matchers and bring on too much bad impact.

ASTImporter is more urgent since we still lack support for some of the AST 
nodes so I considered adding them batchly and started with
type-related nodes. I thought that matchers're OK to use in unittests as 
actually they are used a lot there, but I wasn't aware of the impact
on build of Clang.

If not acceptable, I'm OK with it. We can still test importing with other ways. 
Matchers are not mandatory.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158872/new/

https://reviews.llvm.org/D158872

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


[PATCH] D158953: [analyzer] MmapWriteExecChecker: use getAs instead of castAs

2023-08-27 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 553798.
danix800 added a comment.

Simplify testcase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158953/new/

https://reviews.llvm.org/D158953

Files:
  clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
  clang/test/Analysis/mmap-writeexec.c


Index: clang/test/Analysis/mmap-writeexec.c
===
--- clang/test/Analysis/mmap-writeexec.c
+++ clang/test/Analysis/mmap-writeexec.c
@@ -42,3 +42,9 @@
   int m = mprotect(p, 1024, PROT_WRITE | PROT_EXEC); // expected-warning{{Both 
PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory 
regions, which could be overwritten with malicious code}}
   (void)m;
 }
+
+// gh62285: no crash on non concrete arg 'prot'
+void *gh62285(void *addr, int prot)
+{
+  return mmap(addr, 1, prot, 1, 1, 1);
+}
Index: clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -48,8 +48,10 @@
  CheckerContext ) const {
   if (matchesAny(Call, MmapFn, MprotectFn)) {
 SVal ProtVal = Call.getArgSVal(2);
-auto ProtLoc = ProtVal.castAs();
-int64_t Prot = ProtLoc.getValue().getSExtValue();
+auto ProtLoc = ProtVal.getAs();
+if (!ProtLoc)
+  return;
+int64_t Prot = ProtLoc->getValue().getSExtValue();
 if (ProtExecOv != ProtExec)
   ProtExec = ProtExecOv;
 if (ProtReadOv != ProtRead)


Index: clang/test/Analysis/mmap-writeexec.c
===
--- clang/test/Analysis/mmap-writeexec.c
+++ clang/test/Analysis/mmap-writeexec.c
@@ -42,3 +42,9 @@
   int m = mprotect(p, 1024, PROT_WRITE | PROT_EXEC); // expected-warning{{Both PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory regions, which could be overwritten with malicious code}}
   (void)m;
 }
+
+// gh62285: no crash on non concrete arg 'prot'
+void *gh62285(void *addr, int prot)
+{
+  return mmap(addr, 1, prot, 1, 1, 1);
+}
Index: clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -48,8 +48,10 @@
  CheckerContext ) const {
   if (matchesAny(Call, MmapFn, MprotectFn)) {
 SVal ProtVal = Call.getArgSVal(2);
-auto ProtLoc = ProtVal.castAs();
-int64_t Prot = ProtLoc.getValue().getSExtValue();
+auto ProtLoc = ProtVal.getAs();
+if (!ProtLoc)
+  return;
+int64_t Prot = ProtLoc->getValue().getSExtValue();
 if (ProtExecOv != ProtExec)
   ProtExec = ProtExecOv;
 if (ProtReadOv != ProtRead)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158953: [analyzer] MmapWriteExecChecker: use getAs instead of castAs

2023-08-27 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158953#4620125 , @steakhal wrote:

> Could you please simplify the test case?
> You could basically get rid of everything there, except for forwarding one 
> top level parameter as the proto argument to the mmap call.

No problem!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158953/new/

https://reviews.llvm.org/D158953

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


[PATCH] D158953: [analyzer] MmapWriteExecChecker: use getAs instead of castAs

2023-08-27 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a reviewer: steakhal.
danix800 added a project: clang.
Herald added subscribers: manas, ASDenysPetrov, martong, dkrupp, donat.nagy, 
Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

MmapWriteExecChecker: use getAs instead of castAs

Fixes https://github.com/llvm/llvm-project/issues/62285


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158953

Files:
  clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
  clang/test/Analysis/mmap-writeexec.c


Index: clang/test/Analysis/mmap-writeexec.c
===
--- clang/test/Analysis/mmap-writeexec.c
+++ clang/test/Analysis/mmap-writeexec.c
@@ -42,3 +42,17 @@
   int m = mprotect(p, 1024, PROT_WRITE | PROT_EXEC); // expected-warning{{Both 
PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory 
regions, which could be overwritten with malicious code}}
   (void)m;
 }
+
+// gh62285: no crash on non concrete arg 'prot'
+typedef struct malloc_mmap_2
+{
+  int prot;
+} malloc_mmap_st_2;
+
+int gh62285(int cmd, void *arg2)
+{
+  malloc_mmap_st_2* args2 = arg2;
+  void *buf = ((void*)0);
+  buf = mmap((void*)0, 1, args2->prot, 1, 1, 1);
+  return 0;
+}
Index: clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -48,8 +48,10 @@
  CheckerContext ) const {
   if (matchesAny(Call, MmapFn, MprotectFn)) {
 SVal ProtVal = Call.getArgSVal(2);
-auto ProtLoc = ProtVal.castAs();
-int64_t Prot = ProtLoc.getValue().getSExtValue();
+auto ProtLoc = ProtVal.getAs();
+if (!ProtLoc)
+  return;
+int64_t Prot = ProtLoc->getValue().getSExtValue();
 if (ProtExecOv != ProtExec)
   ProtExec = ProtExecOv;
 if (ProtReadOv != ProtRead)


Index: clang/test/Analysis/mmap-writeexec.c
===
--- clang/test/Analysis/mmap-writeexec.c
+++ clang/test/Analysis/mmap-writeexec.c
@@ -42,3 +42,17 @@
   int m = mprotect(p, 1024, PROT_WRITE | PROT_EXEC); // expected-warning{{Both PROT_WRITE and PROT_EXEC flags are set. This can lead to exploitable memory regions, which could be overwritten with malicious code}}
   (void)m;
 }
+
+// gh62285: no crash on non concrete arg 'prot'
+typedef struct malloc_mmap_2
+{
+  int prot;
+} malloc_mmap_st_2;
+
+int gh62285(int cmd, void *arg2)
+{
+  malloc_mmap_st_2* args2 = arg2;
+  void *buf = ((void*)0);
+  buf = mmap((void*)0, 1, args2->prot, 1, 1, 1);
+  return 0;
+}
Index: clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
@@ -48,8 +48,10 @@
  CheckerContext ) const {
   if (matchesAny(Call, MmapFn, MprotectFn)) {
 SVal ProtVal = Call.getArgSVal(2);
-auto ProtLoc = ProtVal.castAs();
-int64_t Prot = ProtLoc.getValue().getSExtValue();
+auto ProtLoc = ProtVal.getAs();
+if (!ProtLoc)
+  return;
+int64_t Prot = ProtLoc->getValue().getSExtValue();
 if (ProtExecOv != ProtExec)
   ProtExec = ProtExecOv;
 if (ProtReadOv != ProtRead)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158948: [clang][ASTImporter] Add import of type-related nodes

2023-08-26 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a reviewer: balazske.
danix800 added a project: clang.
Herald added a subscriber: martong.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Add import of type-related nodes:

- bitIntType
- constantMatrixType
- dependentAddressSpaceType
- dependentBitIntType
- dependentSizedMatrixType
- dependentVectorType
- hasTypeForDecl
- objcTypeParamDecl
- objcTypeParamType
- pipeType
- vectorType


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158948

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterObjCTest.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -583,6 +583,88 @@
   functionDecl(hasDescendant(typedefDecl(has(atomicType());
 }
 
+TEST_P(ImportType, ImportBitIntType) {
+  MatchVerifier Verifier;
+  testImport("_BitInt(10) declToImport;", Lang_CXX11, "", Lang_CXX11, Verifier,
+ varDecl(hasType(bitIntType(;
+}
+
+TEST_P(ImportType, ImportDependentBitIntType) {
+  MatchVerifier Verifier;
+  testImport("template using declToImport = _BitInt(Width);",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typeAliasTemplateDecl(
+ has(typeAliasDecl(hasType(dependentBitIntType());
+}
+
+TEST_P(ImportType, ImportDependentAddressSpaceType) {
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((address_space(AddrSpace)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentAddressSpaceType());
+}
+
+TEST_P(ImportType, ImportVectorType) {
+  MatchVerifier Verifier;
+  testImport("typedef int __attribute__((vector_size(12))) declToImport;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typedefDecl(hasType(vectorType(;
+}
+
+TEST_P(ImportType, ImportDependentVectorType) {
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((vector_size(Size)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentVectorType());
+}
+
+struct ImportOpenCLPipe : ImportType {
+  std::vector getExtraArgs() const override {
+return {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"};
+  }
+};
+
+TEST_P(ImportOpenCLPipe, ImportPipeType) {
+  MatchVerifier Verifier;
+  testImport("typedef pipe int declToImport;", Lang_OpenCL, "", Lang_OpenCL,
+ Verifier, typedefDecl(hasType(pipeType(;
+}
+
+struct ImportMatrixType : ImportType {
+  std::vector getExtraArgs() const override {
+return {"-fenable-matrix"};
+  }
+};
+
+TEST_P(ImportMatrixType, ImportConstantMatrixType) {
+  MatchVerifier Verifier;
+  testImport("typedef int __attribute__((matrix_type(5, 5))) declToImport;",
+ Lang_CXX11, "", Lang_CXX11, Verifier,
+ typedefDecl(hasType(constantMatrixType(;
+}
+
+TEST_P(ImportMatrixType, ImportDependentSizedMatrixType) {
+  MatchVerifier Verifier;
+  testImport(
+  R"(
+template
+using declToImport = T __attribute__((matrix_type(Rows, Cols)));
+  )",
+  Lang_CXX11, "", Lang_CXX11, Verifier,
+  typeAliasTemplateDecl(
+  has(typeAliasDecl(hasType(dependentSizedMatrixType());
+}
+
 TEST_P(ImportType, ImportUsingType) {
   MatchVerifier Verifier;
   testImport("struct C {};"
Index: clang/unittests/AST/ASTImporterObjCTest.cpp
===
--- clang/unittests/AST/ASTImporterObjCTest.cpp
+++ clang/unittests/AST/ASTImporterObjCTest.cpp
@@ -77,6 +77,31 @@
   }
 }
 
+TEST_P(ImportObjCDecl, ImportObjCTypeParamDecl) {
+  Decl *FromTU = getTuDecl(
+  R"(
+@interface X 
+@end
+  )",
+  Lang_OBJCXX, "input.mm");
+  auto Pattern = objcTypeParamDecl(hasTypeForDecl(objcTypeParamType()));
+  auto *FromInterfaceDecl = FirstDeclMatcher().match(
+  FromTU, namedDecl(hasName("X")));
+  auto *FromTypeParamDecl =
+  FirstDeclMatcher().match(FromInterfaceDecl, Pattern);
+
+  auto ToTypeParamDeclImported = Import(FromTypeParamDecl, Lang_OBJCXX);
+
+  auto *ToInterfaceDecl = FirstDeclMatcher().match(
+  ToTypeParamDeclImported->getTranslationUnitDecl(),
+  namedDecl(hasName("X")));
+  auto *ToTypeParamDeclMatched =
+  FirstDeclMatcher().match(ToInterfaceDecl, Pattern);
+  ASSERT_TRUE(ToTypeParamDeclImported);
+  ASSERT_TRUE(ToTypeParamDeclMatched);
+  ASSERT_TRUE(ToTypeParamDeclImported == ToTypeParamDeclMatched);
+}
+
 static const auto ObjCTestArrayForRunOptions =
 std::array, 2>{
 

[PATCH] D158872: [clang][ASTMatchers] Add a few type-related Matchers

2023-08-26 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 553779.
danix800 added a comment.

Update doc: fix improper naming in objc testcase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158872/new/

https://reviews.llvm.org/D158872

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTest.h

Index: clang/unittests/ASTMatchers/ASTMatchersTest.h
===
--- clang/unittests/ASTMatchers/ASTMatchersTest.h
+++ clang/unittests/ASTMatchers/ASTMatchersTest.h
@@ -284,6 +284,33 @@
   {"-fopenmp=libomp", "-fopenmp-version=51"});
 }
 
+template 
+testing::AssertionResult matchesOpenCL(const Twine , const T ) {
+  return matchesConditionally(Code, AMatcher, true,
+  {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"},
+  FileContentMappings(), "input.cl");
+}
+
+template 
+testing::AssertionResult notMatchesOpenCL(const Twine ,
+  const T ) {
+  return matchesConditionally(Code, AMatcher, false,
+  {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"},
+  FileContentMappings(), "input.cl");
+}
+
+template 
+testing::AssertionResult matchesWithMatrixEnabled(const Twine ,
+  const T ) {
+  return matchesConditionally(Code, AMatcher, true, {"-fenable-matrix"});
+}
+
+template 
+testing::AssertionResult notMatchesWithMatrixEnabled(const Twine ,
+ const T ) {
+  return matchesConditionally(Code, AMatcher, false, {"-fenable-matrix"});
+}
+
 template 
 testing::AssertionResult matchAndVerifyResultConditionally(
 const Twine , const T ,
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1549,6 +1549,89 @@
   EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
 }
 
+TEST_P(ASTMatchersTest, BitIntType) {
+  StringRef code = "_BitInt(10) i;";
+  EXPECT_TRUE(matches(code, varDecl(hasType(bitIntType();
+  EXPECT_TRUE(notMatches(code, varDecl(hasType(builtinType();
+}
+
+TEST_P(ASTMatchersTest, ConstantMatrixType) {
+  StringRef Code = "typedef int __attribute__((matrix_type(5, 5))) X;";
+
+  EXPECT_TRUE(matchesWithMatrixEnabled(
+  Code, typedefDecl(hasType(constantMatrixType();
+  EXPECT_TRUE(
+  notMatchesWithMatrixEnabled(Code, typedefDecl(hasType(vectorType();
+}
+
+TEST_P(ASTMatchersTest, DependentAddressSpaceType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef Code = "template"
+   "class vector {"
+   "  typedef T __attribute__((address_space(AddrSpace))) X;"
+   "};";
+  EXPECT_TRUE(matches(Code, typedefDecl(hasType(dependentAddressSpaceType();
+
+  EXPECT_TRUE(notMatches("int __attribute__((address_space(0))) X;",
+ typedefDecl(hasType(dependentAddressSpaceType();
+}
+
+TEST_P(ASTMatchersTest, DependentBitIntType) {
+  if (!GetParam().isCXX11OrLater())
+return;
+
+  EXPECT_TRUE(matches("template using X = _BitInt(Width);",
+  typeAliasDecl(hasType(dependentBitIntType();
+
+  EXPECT_TRUE(notMatches("typedef _BitInt(10) Int10;",
+ typedefDecl(hasType(dependentBitIntType();
+}
+
+TEST_P(ASTMatchersTest, DependentVectorType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef DepCode = "template"
+  "class vector {"
+  "  typedef T __attribute__((vector_size(Size))) X;"
+  "};";
+  EXPECT_TRUE(matches(DepCode, dependentVectorType()));
+
+  StringRef NonDepCode = "typedef int __attribute__((vector_size(16))) X;";
+  EXPECT_TRUE(notMatches(NonDepCode, dependentVectorType()));
+}
+
+TEST_P(ASTMatchersTest, VectorType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef NonDepCode = "typedef int __attribute__((vector_size(16))) X;";
+  EXPECT_TRUE(matches(NonDepCode, vectorType()));
+
+  StringRef DepCode = "template"
+  "class vector {"
+  "  typedef T __attribute__((vector_size(Size))) X;"
+  "};";
+  EXPECT_TRUE(notMatches(DepCode, vectorType()));
+}
+
+TEST_P(ASTMatchersTest, DependentSizedMatrixType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef DepCode = "template"
+  "class matrix {"
+  "  typedef T 

[PATCH] D158872: [clang][ASTMatchers] Add a few type-related Matchers

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 553697.
danix800 added a comment.

Update docs for `bitIntType` & `dependentBitIntType`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158872/new/

https://reviews.llvm.org/D158872

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTest.h

Index: clang/unittests/ASTMatchers/ASTMatchersTest.h
===
--- clang/unittests/ASTMatchers/ASTMatchersTest.h
+++ clang/unittests/ASTMatchers/ASTMatchersTest.h
@@ -284,6 +284,33 @@
   {"-fopenmp=libomp", "-fopenmp-version=51"});
 }
 
+template 
+testing::AssertionResult matchesOpenCL(const Twine , const T ) {
+  return matchesConditionally(Code, AMatcher, true,
+  {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"},
+  FileContentMappings(), "input.cl");
+}
+
+template 
+testing::AssertionResult notMatchesOpenCL(const Twine ,
+  const T ) {
+  return matchesConditionally(Code, AMatcher, false,
+  {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"},
+  FileContentMappings(), "input.cl");
+}
+
+template 
+testing::AssertionResult matchesWithMatrixEnabled(const Twine ,
+  const T ) {
+  return matchesConditionally(Code, AMatcher, true, {"-fenable-matrix"});
+}
+
+template 
+testing::AssertionResult notMatchesWithMatrixEnabled(const Twine ,
+ const T ) {
+  return matchesConditionally(Code, AMatcher, false, {"-fenable-matrix"});
+}
+
 template 
 testing::AssertionResult matchAndVerifyResultConditionally(
 const Twine , const T ,
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1549,6 +1549,89 @@
   EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
 }
 
+TEST_P(ASTMatchersTest, BitIntType) {
+  StringRef code = "_BitInt(10) i;";
+  EXPECT_TRUE(matches(code, varDecl(hasType(bitIntType();
+  EXPECT_TRUE(notMatches(code, varDecl(hasType(builtinType();
+}
+
+TEST_P(ASTMatchersTest, ConstantMatrixType) {
+  StringRef Code = "typedef int __attribute__((matrix_type(5, 5))) X;";
+
+  EXPECT_TRUE(matchesWithMatrixEnabled(
+  Code, typedefDecl(hasType(constantMatrixType();
+  EXPECT_TRUE(
+  notMatchesWithMatrixEnabled(Code, typedefDecl(hasType(vectorType();
+}
+
+TEST_P(ASTMatchersTest, DependentAddressSpaceType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef Code = "template"
+   "class vector {"
+   "  typedef T __attribute__((address_space(AddrSpace))) X;"
+   "};";
+  EXPECT_TRUE(matches(Code, typedefDecl(hasType(dependentAddressSpaceType();
+
+  EXPECT_TRUE(notMatches("int __attribute__((address_space(0))) X;",
+ typedefDecl(hasType(dependentAddressSpaceType();
+}
+
+TEST_P(ASTMatchersTest, DependentBitIntType) {
+  if (!GetParam().isCXX11OrLater())
+return;
+
+  EXPECT_TRUE(matches("template using X = _BitInt(Width);",
+  typeAliasDecl(hasType(dependentBitIntType();
+
+  EXPECT_TRUE(notMatches("typedef _BitInt(10) Int10;",
+ typedefDecl(hasType(dependentBitIntType();
+}
+
+TEST_P(ASTMatchersTest, DependentVectorType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef DepCode = "template"
+  "class vector {"
+  "  typedef T __attribute__((vector_size(Size))) X;"
+  "};";
+  EXPECT_TRUE(matches(DepCode, dependentVectorType()));
+
+  StringRef NonDepCode = "typedef int __attribute__((vector_size(16))) X;";
+  EXPECT_TRUE(notMatches(NonDepCode, dependentVectorType()));
+}
+
+TEST_P(ASTMatchersTest, VectorType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef NonDepCode = "typedef int __attribute__((vector_size(16))) X;";
+  EXPECT_TRUE(matches(NonDepCode, vectorType()));
+
+  StringRef DepCode = "template"
+  "class vector {"
+  "  typedef T __attribute__((vector_size(Size))) X;"
+  "};";
+  EXPECT_TRUE(notMatches(DepCode, vectorType()));
+}
+
+TEST_P(ASTMatchersTest, DependentSizedMatrixType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef DepCode = "template"
+  "class matrix {"
+  "  typedef T 

[PATCH] D158872: [clang][ASTMatchers] Add a few type-related Matchers

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158872#4618252 , @PiotrZSL wrote:

> LGTM.
> Nothing fancy, looks straight forward.
> You may want to wait for an Aaron Ballman opinion.

Thanks for the reviewing.

Ping @aaron.ballman, could you please take a look at this revision?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158872/new/

https://reviews.llvm.org/D158872

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


[PATCH] D158872: [clang][ASTMatchers] Add a few type-related Matchers

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
Herald added a subscriber: ChuanqiXu.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add a few type-related Matchers

- bitIntType
- constantMatrixType
- dependentAddressSpaceType
- dependentBitIntType
- dependentSizedMatrixType
- dependentVectorType
- hasTypeForDecl
- objcTypeParamDecl
- objcTypeParamType
- pipeType
- vectorType


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158872

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
  clang/unittests/ASTMatchers/ASTMatchersTest.h

Index: clang/unittests/ASTMatchers/ASTMatchersTest.h
===
--- clang/unittests/ASTMatchers/ASTMatchersTest.h
+++ clang/unittests/ASTMatchers/ASTMatchersTest.h
@@ -284,6 +284,33 @@
   {"-fopenmp=libomp", "-fopenmp-version=51"});
 }
 
+template 
+testing::AssertionResult matchesOpenCL(const Twine , const T ) {
+  return matchesConditionally(Code, AMatcher, true,
+  {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"},
+  FileContentMappings(), "input.cl");
+}
+
+template 
+testing::AssertionResult notMatchesOpenCL(const Twine ,
+  const T ) {
+  return matchesConditionally(Code, AMatcher, false,
+  {"-x", "cl", "-cl-no-stdinc", "-cl-std=CL2.0"},
+  FileContentMappings(), "input.cl");
+}
+
+template 
+testing::AssertionResult matchesWithMatrixEnabled(const Twine ,
+  const T ) {
+  return matchesConditionally(Code, AMatcher, true, {"-fenable-matrix"});
+}
+
+template 
+testing::AssertionResult notMatchesWithMatrixEnabled(const Twine ,
+ const T ) {
+  return matchesConditionally(Code, AMatcher, false, {"-fenable-matrix"});
+}
+
 template 
 testing::AssertionResult matchAndVerifyResultConditionally(
 const Twine , const T ,
Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1549,6 +1549,89 @@
   EXPECT_TRUE(matches("struct S {};", qualType().bind("loc")));
 }
 
+TEST_P(ASTMatchersTest, BitIntType) {
+  StringRef code = "_BitInt(10) i;";
+  EXPECT_TRUE(matches(code, varDecl(hasType(bitIntType();
+  EXPECT_TRUE(notMatches(code, varDecl(hasType(builtinType();
+}
+
+TEST_P(ASTMatchersTest, ConstantMatrixType) {
+  StringRef Code = "typedef int __attribute__((matrix_type(5, 5))) X;";
+
+  EXPECT_TRUE(matchesWithMatrixEnabled(
+  Code, typedefDecl(hasType(constantMatrixType();
+  EXPECT_TRUE(
+  notMatchesWithMatrixEnabled(Code, typedefDecl(hasType(vectorType();
+}
+
+TEST_P(ASTMatchersTest, DependentAddressSpaceType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef Code = "template"
+   "class vector {"
+   "  typedef T __attribute__((address_space(AddrSpace))) X;"
+   "};";
+  EXPECT_TRUE(matches(Code, typedefDecl(hasType(dependentAddressSpaceType();
+
+  EXPECT_TRUE(notMatches("int __attribute__((address_space(0))) X;",
+ typedefDecl(hasType(dependentAddressSpaceType();
+}
+
+TEST_P(ASTMatchersTest, DependentBitIntType) {
+  if (!GetParam().isCXX11OrLater())
+return;
+
+  EXPECT_TRUE(matches("template using X = _BitInt(Width);",
+  typeAliasDecl(hasType(dependentBitIntType();
+
+  EXPECT_TRUE(notMatches("typedef _BitInt(10) Int10;",
+ typedefDecl(hasType(dependentBitIntType();
+}
+
+TEST_P(ASTMatchersTest, DependentVectorType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef DepCode = "template"
+  "class vector {"
+  "  typedef T __attribute__((vector_size(Size))) X;"
+  "};";
+  EXPECT_TRUE(matches(DepCode, dependentVectorType()));
+
+  StringRef NonDepCode = "typedef int __attribute__((vector_size(16))) X;";
+  EXPECT_TRUE(notMatches(NonDepCode, dependentVectorType()));
+}
+
+TEST_P(ASTMatchersTest, VectorType) {
+  if (!GetParam().isCXX())
+return;
+
+  StringRef NonDepCode = "typedef int __attribute__((vector_size(16))) X;";
+  EXPECT_TRUE(matches(NonDepCode, vectorType()));
+
+  StringRef DepCode = "template"
+  "class vector {"
+  "  typedef T __attribute__((vector_size(Size))) X;"
+  "};";
+  

[PATCH] D158858: [analyzer] MPIChecker: add defensive checking (check against nullptr)

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158858#4617510 , @steakhal wrote:

> Makes sense.
> Would thus test crash without the early returns? And now they wouldn't?

Yes, the original crash shown in https://godbolt.org/z/39P7W6KPa


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158858/new/

https://reviews.llvm.org/D158858

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp:195
+  const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
+  auto CountReached = SVB.evalBinOp(State, BO_GE, Idx, Count, 
ASTCtx.BoolTy)
+  .getAs();

steakhal wrote:
> In C for example, we might not have a Boot type AFAIK.
> Usually, we use `SVB.getConditionType()` in such cases.
Thanks for this tip.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp:192-198
+SVal Count = CE.getArgSVal(0);
+for (size_t i = 0; i < ArrSize; ++i) {
+  const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
+  auto CountReached = SVB.evalBinOp(State, BO_GE, Idx, Count, 
ASTCtx.BoolTy)
+  .getAs();
+  if (CountReached && State->assume(*CountReached, true))
+break;

steakhal wrote:
> It's suspicious to me to compare stuff in the symbolic domain, such as `Idx 
> >= Count` here.
> And let me elaborate on why I think so.
> 
> I'd assume that the first argument of `MPI_Waitall` is usually just a number 
> literal, thus it's gonna be a ConcreteInt, so now we have `Count`.
> The `Index` you just created, obviously is just a ConcreteInt.
> After this, we could simply unwrap them and do the comparison without doing 
> it in the symbolic domain.
> 
> ---
> 
> As a sidenote, `State->assume(*CountReached, true)` would return a state in 
> two cases:
>  1) We can prove that the assumption holds.
>  2) We cannot disprove the assumption, thus it might hold, so we assume it 
> holds.
> This is probably not what you wanted in the first place, but it's probably 
> irrelelevant anyway.
I'll restrict this checker to handle `ConcreteInt` count only.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/test/Analysis/mpichecker.cpp:286-288
+  for (int i = 0; i < 3; ++i)
+MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+[i]);

steakhal wrote:
> This loop here implicitly depends on the fact that we only unroll loops 4 
> times.
> I'd prefer a simpler test where we don't even have a loop.
I'll unroll this loop.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp:189-190
+ASTCtx.getCharWidth();
+const NonLoc MROffset =
+SVB.makeArrayIndex(MR->getAsOffset().getOffset() / ElemSizeInBits);
 

steakhal wrote:
> What implies that `MR->getAsOffset()` succeeds, and also what implies that 
> the `Offset` within that is not symbolic?
> Also, how can you use this without also using the result region?
> Without using that you don't know what is the anchor point, from which this 
> offset represent anything.
> ATM I believe the code assumes that `MR->getRegion()` equals to 
> `SuperRegion`, which might not be always the case.
> This could materialize a problem when you construct the element region later.
I'll restrict the checker to handle non-symbolic offset only.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp:185-188
+CharUnits ElemSizeInChars = ASTCtx.getTypeSizeInChars(ElemType);
+int64_t ElemSizeInBits =
+(ElemSizeInChars.isZero() ? 1 : ElemSizeInChars.getQuantity()) *
+ASTCtx.getCharWidth();

steakhal wrote:
> How can `ElemSizeInChar` be zero?
> If it can be zero, could you demonstrate it by a test?
Type in the wild does not have to be of non-zero size. MPI vendors might choose 
whatever implementation as they want.
We are doing division so non-zero checking is necessary.

https://reviews.llvm.org/D158707 added a few general testcases for zero-sized 
type processing on dynamic extent.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp:46-48
+if (!ErrorNode)
+  return;
+

steakhal wrote:
> If these hunks are not closely related to the issue you intend to fix in this 
> PR, I'd suggesst submitting it separately. That is a common API, and we 
> wouldn't need tests for such defensive checks, as they rarely trigger.
Moved (together with the extra testcase file) into 
https://reviews.llvm.org/D158858.

Checking `ExplodedNode` against nullptr is a convention in almost all checkers. 
It surely can be null (quite often).

`MPIChecker` is one of the only two checkers that forget to do this checking 
and crashed as reported by #64647


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158813#4616816 , @steakhal wrote:

> Let me try to summarize some of the variables:
>
> So, given an invocation like `MPI_Waitall(C, Requests, Statues)`:
>
> - `MR` is `lval(Requests)`
> - `ElementCount` is the number of elements `Requests` consist of.
> - `ArrSize` is basically `ElementCount` but an APSInt.
> - `MROffset` is the offset and allocated region of the `Requests` region.
> - `Index` is ConcreteInt(0, ..., ArrSize)
> - `Count` is `C`, which is likely a ConcreteInt.
>
> Please note that I have no idea what this checker does.

It's really messy. I tried to refactor and clarify intentions with better 
naming. Thanks for the summary.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

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


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 553514.
danix800 edited the summary of this revision.
danix800 added a comment.

1. Move out complicated computation into separate function;
2. Only check `ConreteInt` request count.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158813/new/

https://reviews.llvm.org/D158813

Files:
  clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
  clang/test/Analysis/mpichecker.cpp

Index: clang/test/Analysis/mpichecker.cpp
===
--- clang/test/Analysis/mpichecker.cpp
+++ clang/test/Analysis/mpichecker.cpp
@@ -272,6 +272,55 @@
   MPI_Wait(, MPI_STATUS_IGNORE);
 } // no error
 
+void nestedRequestWithCount() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  [0]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  [1]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  [2]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(2, rs.req, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // no error
+
+void nestedRequestWithCountMissingNonBlockingWait() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  [0]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  [1]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  [2]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(1, rs.req, MPI_STATUSES_IGNORE);
+  // MPI_Waitall(1, rs.req + 1, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // expected-warning{{Request 'rs.req[1]' has no matching wait.}}
+
 void singleRequestInWaitall() {
   MPI_Request r;
   int rank = 0;
Index: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -143,6 +143,38 @@
   }
 }
 
+static std::optional>
+getRequestRegionOffsetAndCount(const MemRegion *const MR, const CallEvent ) {
+  if (CE.getNumArgs() < 2)
+return std::nullopt;
+
+  ProgramStateRef State = CE.getState();
+  SValBuilder  = State->getStateManager().getSValBuilder();
+  ASTContext  = SVB.getContext();
+
+  QualType RequestTy = CE.getArgExpr(1)->getType()->getPointeeType();
+  auto RequestRegionCount =
+  getDynamicElementCountWithOffset(State, CE.getArgSVal(1), RequestTy)
+  .getAs();
+  if (!RequestRegionCount)
+return std::nullopt;
+
+  CharUnits TypeSizeInChars = ASTCtx.getTypeSizeInChars(RequestTy);
+
+  // MPI_Request as a handle does not have to be of non-zero size.
+  int64_t TypeSizeInBits =
+  (TypeSizeInChars.isZero() ? 1 : TypeSizeInChars.getQuantity()) *
+  ASTCtx.getCharWidth();
+
+  RegionOffset RequestRegionOffset = MR->getAsOffset();
+  if (RequestRegionOffset.hasSymbolicOffset())
+return std::nullopt;
+
+  return std::make_pair(
+  SVB.makeArrayIndex(RequestRegionOffset.getOffset() / TypeSizeInBits),
+  RequestRegionCount->getValue());
+}
+
 void MPIChecker::allRegionsUsedByWait(
 llvm::SmallVector ,
 const MemRegion *const MR, const CallEvent , CheckerContext ) const {
@@ -161,20 +193,34 @@
   return;
 }
 
-DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
-Ctx.getState(), SuperRegion, Ctx.getSValBuilder(),
-CE.getArgExpr(1)->getType()->getPointeeType());
-const llvm::APSInt  =
-ElementCount.castAs().getValue();
+auto RequestRegionOffsetAndCount = getRequestRegionOffsetAndCount(MR, CE);
+if (!RequestRegionOffsetAndCount)
+  return;
+
+auto [RegionOffset, RegionCount] = *RequestRegionOffsetAndCount;
 
-for (size_t i = 0; i < ArrSize; ++i) {
-  const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
+QualType MPIReqTy = CE.getArgExpr(1)->getType()->getPointeeType();
+SValBuilder  = Ctx.getSValBuilder();
 
-  const ElementRegion *const ER = RegionManager.getElementRegion(
-  CE.getArgExpr(1)->getType()->getPointeeType(), Idx, SuperRegion,
-  Ctx.getASTContext());
+auto RequestedCountSVal = CE.getArgSVal(0).getAs();
+if (!RequestedCountSVal)
+  return;
 
-  

[PATCH] D158858: [analyzer] MPIChecker: add defensive checking (check against nullptr)

2023-08-25 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added reviewers: donat.nagy, steakhal.
danix800 added a project: clang.
Herald added subscribers: manas, ASDenysPetrov, martong, dkrupp, Szelethus, 
mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
danix800 requested review of this revision.
Herald added subscribers: cfe-commits, wangpc.

ExplodedNode might be null and shoud be checked conventionally.

Fixes https://github.com/llvm/llvm-project/issues/64647


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158858

Files:
  clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
  clang/test/Analysis/mpichecker.cpp


Index: clang/test/Analysis/mpichecker.cpp
===
--- clang/test/Analysis/mpichecker.cpp
+++ clang/test/Analysis/mpichecker.cpp
@@ -389,3 +389,13 @@
   void callNonblockingExtern(MPI_Request *req);
   callNonblockingExtern();
 }
+
+bool contains();
+void gh64647() {
+  if (contains()) {
+MPI_Request request_item;
+MPI_Wait(_item, MPI_STATUS_IGNORE);
+// expected-warning@-1 {{Request 'request_item' has no matching 
nonblocking call.}}
+  }
+  gh64647();
+}
Index: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -43,6 +43,9 @@
   // double nonblocking detected
   if (Req && Req->CurrentState == Request::State::Nonblocking) {
 ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
+if (!ErrorNode)
+  return;
+
 BReporter.reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode,
   Ctx.getBugReporter());
 Ctx.addTransition(ErrorNode->getState(), ErrorNode);
@@ -83,6 +86,9 @@
 if (!Req) {
   if (!ErrorNode) {
 ErrorNode = Ctx.generateNonFatalErrorNode(State, );
+if (!ErrorNode)
+  break;
+
 State = ErrorNode->getState();
   }
   // A wait has no matching nonblocking call.
@@ -115,6 +121,9 @@
 
 if (!ErrorNode) {
   ErrorNode = Ctx.generateNonFatalErrorNode(State, );
+  if (!ErrorNode)
+break;
+
   State = ErrorNode->getState();
 }
 BReporter.reportMissingWait(Req.second, Req.first, ErrorNode,


Index: clang/test/Analysis/mpichecker.cpp
===
--- clang/test/Analysis/mpichecker.cpp
+++ clang/test/Analysis/mpichecker.cpp
@@ -389,3 +389,13 @@
   void callNonblockingExtern(MPI_Request *req);
   callNonblockingExtern();
 }
+
+bool contains();
+void gh64647() {
+  if (contains()) {
+MPI_Request request_item;
+MPI_Wait(_item, MPI_STATUS_IGNORE);
+// expected-warning@-1 {{Request 'request_item' has no matching nonblocking call.}}
+  }
+  gh64647();
+}
Index: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -43,6 +43,9 @@
   // double nonblocking detected
   if (Req && Req->CurrentState == Request::State::Nonblocking) {
 ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
+if (!ErrorNode)
+  return;
+
 BReporter.reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode,
   Ctx.getBugReporter());
 Ctx.addTransition(ErrorNode->getState(), ErrorNode);
@@ -83,6 +86,9 @@
 if (!Req) {
   if (!ErrorNode) {
 ErrorNode = Ctx.generateNonFatalErrorNode(State, );
+if (!ErrorNode)
+  break;
+
 State = ErrorNode->getState();
   }
   // A wait has no matching nonblocking call.
@@ -115,6 +121,9 @@
 
 if (!ErrorNode) {
   ErrorNode = Ctx.generateNonFatalErrorNode(State, );
+  if (!ErrorNode)
+break;
+
   State = ErrorNode->getState();
 }
 BReporter.reportMissingWait(Req.second, Req.first, ErrorNode,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158813: [analyzer] MPIChecker: MPI_Waitall should respect count arg

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added reviewers: steakhal, donat.nagy, dcoughlin.
danix800 added a project: clang.
Herald added subscribers: manas, ASDenysPetrov, martong, dkrupp, Szelethus, 
mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

1. MPI_Waitall should respect count arg
2. Add more defensive checking, this also:

This also fixes https://github.com/llvm/llvm-project/issues/64647


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158813

Files:
  clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
  clang/test/Analysis/mpichecker-crash-gh64647.cpp
  clang/test/Analysis/mpichecker.cpp

Index: clang/test/Analysis/mpichecker.cpp
===
--- clang/test/Analysis/mpichecker.cpp
+++ clang/test/Analysis/mpichecker.cpp
@@ -272,6 +272,49 @@
   MPI_Wait(, MPI_STATUS_IGNORE);
 } // no error
 
+void nestedRequestWithCount() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  for (int i = 0; i < 3; ++i)
+MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+[i]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(2, rs.req, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // no error
+
+void nestedRequestWithCountMissingNonBlockingWait() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  for (int i = 0; i < 3; ++i)
+MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+[i]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(1, rs.req, MPI_STATUSES_IGNORE);
+  // MPI_Waitall(1, rs.req + 1, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // expected-warning{{Request 'rs.req[1]' has no matching wait.}}
+
 void singleRequestInWaitall() {
   MPI_Request r;
   int rank = 0;
Index: clang/test/Analysis/mpichecker-crash-gh64647.cpp
===
--- /dev/null
+++ clang/test/Analysis/mpichecker-crash-gh64647.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=optin.mpi.MPI-Checker -verify %s
+
+#include "MPIMock.h"
+
+bool contains();
+void do_a() {
+  if (contains()) {
+MPI_Request request_item;
+MPI_Wait(_item, MPI_STATUS_IGNORE);
+// expected-warning@-1 {{Request 'request_item' has no matching nonblocking call.}}
+  }
+  do_a();
+}
Index: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
===
--- clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
@@ -43,6 +43,9 @@
   // double nonblocking detected
   if (Req && Req->CurrentState == Request::State::Nonblocking) {
 ExplodedNode *ErrorNode = Ctx.generateNonFatalErrorNode();
+if (!ErrorNode)
+  return;
+
 BReporter.reportDoubleNonblocking(PreCallEvent, *Req, MR, ErrorNode,
   Ctx.getBugReporter());
 Ctx.addTransition(ErrorNode->getState(), ErrorNode);
@@ -83,6 +86,9 @@
 if (!Req) {
   if (!ErrorNode) {
 ErrorNode = Ctx.generateNonFatalErrorNode(State, );
+if (!ErrorNode)
+  break;
+
 State = ErrorNode->getState();
   }
   // A wait has no matching nonblocking call.
@@ -115,6 +121,9 @@
 
 if (!ErrorNode) {
   ErrorNode = Ctx.generateNonFatalErrorNode(State, );
+  if (!ErrorNode)
+break;
+
   State = ErrorNode->getState();
 }
 BReporter.reportMissingWait(Req.second, Req.first, ErrorNode,
@@ -161,20 +170,41 @@
   return;
 }
 
-DefinedOrUnknownSVal ElementCount = getDynamicElementCount(
-Ctx.getState(), SuperRegion, Ctx.getSValBuilder(),
-CE.getArgExpr(1)->getType()->getPointeeType());
-const llvm::APSInt  =
-ElementCount.castAs().getValue();
+QualType ElemType = CE.getArgExpr(1)->getType()->getPointeeType();
+ProgramStateRef State = Ctx.getState();
+SValBuilder  = Ctx.getSValBuilder();
+ASTContext  = Ctx.getASTContext();
 
-for (size_t i = 0; i < ArrSize; ++i) {
-  const NonLoc Idx = Ctx.getSValBuilder().makeArrayIndex(i);
+auto ElementCount =
+getDynamicElementCountWithOffset(State, CE.getArgSVal(1), ElemType)
+.getAs();
+if (!ElementCount)
+  return;
+const llvm::APSInt  = 

[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 553351.
danix800 edited the summary of this revision.
danix800 added a comment.

`MPIChecker` is not strictly related to this revision. Will be moved into 
another revison.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
  clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
  clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
  clang/test/Analysis/array-bound-v2-constraint-check.c
  clang/test/Analysis/flexible-array-members.c
  clang/test/Analysis/memory-model.cpp

Index: clang/test/Analysis/memory-model.cpp
===
--- clang/test/Analysis/memory-model.cpp
+++ clang/test/Analysis/memory-model.cpp
@@ -66,8 +66,8 @@
 
 void field_ptr(S *a) {
   clang_analyzer_dump(>f); // expected-warning {{Element{SymRegion{reg_$0},0 S64b,struct S}.f}}
-  clang_analyzer_dumpExtent(>f);   // expected-warning {{4 S64b}}
-  clang_analyzer_dumpElementCount(>f); // expected-warning {{1 S64b}}
+  clang_analyzer_dumpExtent(>f);   // expected-warning {{extent_$1{SymRegion{reg_$0
+  clang_analyzer_dumpElementCount(>f); // expected-warning {{(extent_$1{SymRegion{reg_$0}}) / 4U}}
 }
 
 void symbolic_array() {
@@ -90,7 +90,7 @@
 void symbolic_malloc() {
   int *a = (int *)malloc(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
   free(a);
 }
@@ -98,22 +98,22 @@
 void symbolic_alloca() {
   int *a = (int *)alloca(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
 }
 
 void symbolic_complex() {
   int *a = (int *)malloc(4);
-  clang_analyzer_dumpExtent(a);   // expected-warning {{4 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{4 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{1 S64b}}
 
   int *b = (int *)realloc(a, sizeof(int) * 2);
-  clang_analyzer_dumpExtent(b);   // expected-warning {{8 U64b}}
+  clang_analyzer_dumpExtent(b);   // expected-warning {{8 S64b}}
   clang_analyzer_dumpElementCount(b); // expected-warning {{2 S64b}}
   free(b);
 
   int *c = (int *)calloc(3, 4);
-  clang_analyzer_dumpExtent(c);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(c);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(c); // expected-warning {{3 S64b}}
   free(c);
 }
@@ -123,7 +123,7 @@
   char *b = (char *)malloc(13);
 
   clang_analyzer_dump(clang_analyzer_getExtent(a)); // expected-warning {{13 S64b}}
-  clang_analyzer_dump(clang_analyzer_getExtent(b)); // expected-warning {{13 U64b}}
+  clang_analyzer_dump(clang_analyzer_getExtent(b)); // expected-warning {{13 S64b}}
   clang_analyzer_eval(clang_analyzer_getExtent(a) ==
   clang_analyzer_getExtent(b));
   // expected-warning@-2 {{TRUE}}
@@ -155,3 +155,16 @@
 
   operator delete[](a, std::align_val_t(32));
 }
+
+int a[5][0];
+struct T {
+  int x[];
+};
+
+T t[5];
+void zero_sized_element() {
+  clang_analyzer_dumpExtent(a);   // expected-warning {{0 S64b}}
+  clang_analyzer_dumpElementCount(a); // expected-warning {{5 S64b}}
+  clang_analyzer_dumpExtent(t);   // expected-warning {{0 S64b}}
+  clang_analyzer_dumpElementCount(t); // expected-warning {{5 S64b}}
+}
Index: clang/test/Analysis/flexible-array-members.c
===
--- clang/test/Analysis/flexible-array-members.c
+++ clang/test/Analysis/flexible-array-members.c
@@ -44,20 +44,52 @@
   clang_analyzer_dump(clang_analyzer_getExtent());
   clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
   // expected-warning@-2 {{4 S64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 S64b}}
 
   FAM *p = (FAM *)alloca(sizeof(FAM));
   clang_analyzer_dump(clang_analyzer_getExtent(p));
   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
-  // expected-warning@-2 {{4 U64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{4 S64b}}
+  // expected-warning@-2 {{0 S64b}}
 
   FAM *q = (FAM *)malloc(sizeof(FAM));
   clang_analyzer_dump(clang_analyzer_getExtent(q));
   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
-  // expected-warning@-2 {{4 U64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{4 S64b}}
+  // expected-warning@-2 {{0 S64b}}
+  free(q);
+
+  q = (FAM *)malloc(sizeof(FAM) + sizeof(int) 

[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 553335.
danix800 edited the summary of this revision.
danix800 added a comment.

1. `getDynamicExtent()` can return both signed/unsigned results. They are 
converted to signed version as `ArrayIndexType` to keep consistency. All other 
APIs return this version

(even for static type size). Testcases are not affected. `ArrayBoundV2` doesn't 
need explicit `unsigned`-to-`signed` casts to avoid `signed<->unsigned` 
comparison;

2. `getElementExtent()` could be 0, add more defensive checking;
3. `MPIChecker` added more defensive checking, e.g: `ElementCount` doesn't have 
to be `ConcreteInt` so avoid direct 
`ElementCount.castAs()`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
  clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
  clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
  clang/test/Analysis/array-bound-v2-constraint-check.c
  clang/test/Analysis/flexible-array-members.c
  clang/test/Analysis/memory-model.cpp
  clang/test/Analysis/mpichecker.cpp

Index: clang/test/Analysis/mpichecker.cpp
===
--- clang/test/Analysis/mpichecker.cpp
+++ clang/test/Analysis/mpichecker.cpp
@@ -272,6 +272,49 @@
   MPI_Wait(, MPI_STATUS_IGNORE);
 } // no error
 
+void nestedRequestWithCount() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  for (int i = 0; i < 3; ++i)
+MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+[i]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(2, rs.req, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // no error
+
+void nestedRequestWithCountMissingNonBlockingWait() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  for (int i = 0; i < 3; ++i)
+MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+[i]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(1, rs.req, MPI_STATUSES_IGNORE);
+  // MPI_Waitall(1, rs.req + 1, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // expected-warning{{Request 'rs.req[1]' has no matching wait.}}
+
 void singleRequestInWaitall() {
   MPI_Request r;
   int rank = 0;
Index: clang/test/Analysis/memory-model.cpp
===
--- clang/test/Analysis/memory-model.cpp
+++ clang/test/Analysis/memory-model.cpp
@@ -66,8 +66,8 @@
 
 void field_ptr(S *a) {
   clang_analyzer_dump(>f); // expected-warning {{Element{SymRegion{reg_$0},0 S64b,struct S}.f}}
-  clang_analyzer_dumpExtent(>f);   // expected-warning {{4 S64b}}
-  clang_analyzer_dumpElementCount(>f); // expected-warning {{1 S64b}}
+  clang_analyzer_dumpExtent(>f);   // expected-warning {{extent_$1{SymRegion{reg_$0
+  clang_analyzer_dumpElementCount(>f); // expected-warning {{(extent_$1{SymRegion{reg_$0}}) / 4U}}
 }
 
 void symbolic_array() {
@@ -90,7 +90,7 @@
 void symbolic_malloc() {
   int *a = (int *)malloc(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
   free(a);
 }
@@ -98,22 +98,22 @@
 void symbolic_alloca() {
   int *a = (int *)alloca(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
 }
 
 void symbolic_complex() {
   int *a = (int *)malloc(4);
-  clang_analyzer_dumpExtent(a);   // expected-warning {{4 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{4 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{1 S64b}}
 
   int *b = (int *)realloc(a, sizeof(int) * 2);
-  clang_analyzer_dumpExtent(b);   // expected-warning {{8 U64b}}
+  clang_analyzer_dumpExtent(b);   // expected-warning {{8 S64b}}
   clang_analyzer_dumpElementCount(b); // expected-warning {{2 S64b}}
   free(b);
 
   int *c = (int *)calloc(3, 4);
-  clang_analyzer_dumpExtent(c);   // expected-warning 

[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158707#4614100 , @steakhal wrote:

> As a general comment on requiring all extents to be of unsigned APSInts.
> Checkers, like the `MallocChecker`, binds the result of arbitrary 
> expression's values (the argument of malloc, for example) as extents of some 
> regions.
> Usually, that argument is of an `unsigned` static type, thus even if some 
> other expression is there, and implicit cast will turn it into `unsigned`.
> However, in CSA, we don't respect such casts, thus if it was signed, we will 
> bind a signed value as an extent.
>
> Here is an example  demonstrating this:
>
>   int n = conjure();
>   clang_analyzer_dump(n);  // conj
>   clang_analyzer_value(n); // i32
>   
>   char *p = (char*)malloc(n);
>   clang_analyzer_dump(clang_analyzer_getExtent(p));  // conj
>   clang_analyzer_value(clang_analyzer_getExtent(p)); // i32
>
> Consequently, I'm not sure it's possible to turn extents "unsigned", without 
> fixing casts.
> I was sort of expecting this, but I didn't know real world issues 
> materialized by this in the domain of extents.
> Usually, they just happen to work, so I didn't really bother with it.
> This was actually what I intended to deliver with my comment at 
> D158499#4609046 .
>
> By this comment I'm not suggesting that this is a lost cause, or we shouldn't 
> move in this direction. I think something like this would make sense, but I'd 
> need to delve into the change to make sure.

Wow! Really another unexpectation to me!

I think either signedness is ok, the stored data would not be lost. How clients 
use these values are the actual problem.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp:92
+
+  return ElementCount.castAs();
+}

donat.nagy wrote:
> Are you sure that this cannot cause crashes? (E.g. did you check that there 
> is no corner case when `getElementExtent` returns 0?)
> 
> I can accept this cast, especially if you have a clear proof that it's valid, 
> but I'd prefer a more defensive solution that turns `UndefinedVal` into 
> `UnknownVal` either here or preferably in the `assert()` function family that 
> consumes the results from functions like this. 
Wow~ Yeah! This really is a bug with zero-sized types, the original 
`getDynamicElementCount` suffers from this too!
Verified on 13.0.1 & main.

```
void clang_analyzer_dumpElementCount(const void *);

int a[1][0];

void var_simple_ref() {
  clang_analyzer_dumpElementCount(a); // expected-warning {{1 S64b}}
}
```

Dividing by zero gives undefined, casts failed:
```
clang: 
/home/danis/Sources/llvm-project-main/llvm/include/llvm/Support/Casting.h:566: 
decltype(auto) llvm::cast(const From &) [To = 
clang::ento::DefinedOrUnknownSVal, From = clang::ento::SVal]: Assertion 
`isa(Val) && "cast() argument of incompatible type!"' failed.
```

`getDynamicElementCountWithOffset` is the extended offset version of 
`getDynamicElementCount`, same issue.

Nice catch!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/test/Analysis/array-bound-v2-constraint-check.c:1
-// RUN: %clang_analyze_cc1 
-analyzer-checker=core,alpha.security.ArrayBoundV2,debug.ExprInspection \
+// RUN: %clang_analyze_cc1 
-analyzer-checker=core,unix,alpha.security.ArrayBoundV2,debug.ExprInspection \
 // RUN:   -analyzer-config eagerly-assume=false -verify %s

donat.nagy wrote:
> Perhaps only enable `unix.Malloc` to ensure that this test is not affected by 
> changes to other checkers in the `unix` group. (It's enough for the testcase 
> that you added.)
Correct! Thanks for reminding!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp:180-183
+  SVal CountReached =
+  SVB.evalBinOp(State, BO_GE, Idx, Count, ASTCtx.BoolTy);
+  if (!CountReached.isUndef() &&
+  State->assume(*CountReached.getAs(), true))

donat.nagy wrote:
> I think checking the nullness of `getAs()` is more elegant than using a 
> separate `isUndef()` check.
> 
> On a longer term / as a separate improvement, I'd also think about allowing 
> `UndefinedVal` as the argument of the `assert()`-like functions, because the 
> `evalBinOp` -> `assert` combination is very common in checkers and IIRC in 
> most checkers the branch of `UndefinedVal` will produce the same result as 
> `UnknownVal`.
Thanks for the advice!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp:202-203
   // CHECK UPPER BOUND
-  DefinedOrUnknownSVal Size = getDynamicExtent(state, Reg, svalBuilder);
+  SVal Size = svalBuilder.convertToArrayIndex(
+  getDynamicExtent(state, Reg, svalBuilder));
   if (auto KnownSize = Size.getAs()) {

donat.nagy wrote:
> I wonder whether it would be better to move this conversion into the 
> definition of `getDynamicExtent` to ensure that it has a consistent return 
> type. Are there any situations where it's useful that `getDynamicExtent` can 
> return something that's not an `ArrayIndexTy`?
Use consistent return type is necessary. The problem is which version should we 
choose.
I didn't touch this before I can get a clear selection.

At first I tended to think that all extent/count should be unsigned, but 
quickly dropped this idea
since `getDynamicExtentWithOffset` gives reasonable note that extent/offset 
(even count) can
be negative.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158707#4613743 , @donat.nagy 
wrote:

> Thanks for creating this commit, it's a useful improvement!
>
> I added some inline comments on minor implementation details; moreover, note 
> that "Releted checkers:" (instead of "related") is a typo in the commit 
> message.
>
> I also have a less concrete question about the root cause of these bugs. Does 
> this commit fix the "root" of the issue by eliminating some misuse of 
> correctly implemented (but perhaps surprising) `SVal` / `APSInt` arithmetic; 
> or is there an underlying bug in the `SVal` / `APSInt` arithmetic which is 
> just avoided (and not eliminated) by this commit? In the latter case, what 
> obstacles prevent us from fixing the root cause?

For the observed signed compared to unsigned unexpectation from ArrayBoundV2,
the constraint manager does give the CORRECT result.

It's a misuse of the constraint API, mainly caused by unexpected unsigned extent
set by memory modeling. Actually `ArrayBoundV2::getSimplifiedOffsets()` has 
clear
comment that this `signed <-> unsigned` comparison is problematic.

  // TODO: once the constraint manager is smart enough to handle non simplified
  // symbolic expressions remove this function. Note that this can not be used 
in
  // the constraint manager as is, since this does not handle overflows. It is
  // safe to assume, however, that memory offsets will not overflow.
  // NOTE: callers of this function need to be aware of the effects of overflows
  // and signed<->unsigned conversions!
  static std::pair
  getSimplifiedOffsets(NonLoc offset, nonloc::ConcreteInt extent,
   SValBuilder ) {


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158707/new/

https://reviews.llvm.org/D158707

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


[PATCH] D158707: [analyzer] Fix a few size-type signedness inconsistency related to DynamicExtent

2023-08-24 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a project: clang.
Herald added subscribers: steakhal, manas, ASDenysPetrov, martong, dkrupp, 
donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, 
xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Size-type inconsistency (signedness) causes confusion and even bugs.
For example when signed compared to unsigned the result might not
be expected.

Releted checkers:

1. ArrayBoundCheckerV2: signed compared to unsigned
2. MPIChecker: `MPI_Waitall` should respect `count` arg
3. ExprInspection: use more general API to report more results

Fixes https://github.com/llvm/llvm-project/issues/64920


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158707

Files:
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h
  clang/lib/StaticAnalyzer/Checkers/ArrayBoundCheckerV2.cpp
  clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MPI-Checker/MPIChecker.cpp
  clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
  clang/test/Analysis/array-bound-v2-constraint-check.c
  clang/test/Analysis/flexible-array-members.c
  clang/test/Analysis/memory-model.cpp
  clang/test/Analysis/mpichecker.cpp

Index: clang/test/Analysis/mpichecker.cpp
===
--- clang/test/Analysis/mpichecker.cpp
+++ clang/test/Analysis/mpichecker.cpp
@@ -272,6 +272,49 @@
   MPI_Wait(, MPI_STATUS_IGNORE);
 } // no error
 
+void nestedRequestWithCount() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  for (int i = 0; i < 3; ++i)
+MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+[i]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(2, rs.req, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // no error
+
+void nestedRequestWithCountMissingNonBlockingWait() {
+  typedef struct {
+MPI_Request req[3];
+MPI_Request req2;
+  } ReqStruct;
+
+  ReqStruct rs;
+  int rank = 0;
+  double buf = 0;
+  MPI_Comm_rank(MPI_COMM_WORLD, );
+
+  for (int i = 0; i < 3; ++i)
+MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+[i]);
+  MPI_Ireduce(MPI_IN_PLACE, , 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD,
+  );
+  MPI_Waitall(1, rs.req, MPI_STATUSES_IGNORE);
+  // MPI_Waitall(1, rs.req + 1, MPI_STATUSES_IGNORE);
+  MPI_Waitall(1, rs.req + 2, MPI_STATUSES_IGNORE);
+  MPI_Wait(, MPI_STATUS_IGNORE);
+} // expected-warning{{Request 'rs.req[1]' has no matching wait.}}
+
 void singleRequestInWaitall() {
   MPI_Request r;
   int rank = 0;
Index: clang/test/Analysis/memory-model.cpp
===
--- clang/test/Analysis/memory-model.cpp
+++ clang/test/Analysis/memory-model.cpp
@@ -66,8 +66,8 @@
 
 void field_ptr(S *a) {
   clang_analyzer_dump(>f); // expected-warning {{Element{SymRegion{reg_$0},0 S64b,struct S}.f}}
-  clang_analyzer_dumpExtent(>f);   // expected-warning {{4 S64b}}
-  clang_analyzer_dumpElementCount(>f); // expected-warning {{1 S64b}}
+  clang_analyzer_dumpExtent(>f);   // expected-warning {{extent_$1{SymRegion{reg_$0
+  clang_analyzer_dumpElementCount(>f); // expected-warning {{(extent_$1{SymRegion{reg_$0}}) / 4U}}
 }
 
 void symbolic_array() {
@@ -90,7 +90,7 @@
 void symbolic_malloc() {
   int *a = (int *)malloc(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
   free(a);
 }
@@ -98,22 +98,22 @@
 void symbolic_alloca() {
   int *a = (int *)alloca(12);
   clang_analyzer_dump(a); // expected-warning {{Element{HeapSymRegion{conj}}
-  clang_analyzer_dumpExtent(a);   // expected-warning {{12 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{12 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{3 S64b}}
 }
 
 void symbolic_complex() {
   int *a = (int *)malloc(4);
-  clang_analyzer_dumpExtent(a);   // expected-warning {{4 U64b}}
+  clang_analyzer_dumpExtent(a);   // expected-warning {{4 S64b}}
   clang_analyzer_dumpElementCount(a); // expected-warning {{1 S64b}}
 
   int *b = (int *)realloc(a, sizeof(int) * 2);
-  clang_analyzer_dumpExtent(b);   // expected-warning {{8 U64b}}
+  clang_analyzer_dumpExtent(b);   // expected-warning {{8 S64b}}
   clang_analyzer_dumpElementCount(b); // expected-warning {{2 S64b}}
   free(b);
 
   

[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-23 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/AST/ASTImporter.cpp:4105
 
-  T TypeOrDecl = GetCanTypeOrDecl(FD);
-
-  for (const FriendDecl *FoundFriend : RD->friends()) {
+  for (FriendDecl *FoundFriend : RD->friends()) {
 if (FoundFriend == FD) {

balazske wrote:
> It is better if this is `const`.
As API requires this decl cannot be const.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

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


[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-23 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 552678.
danix800 added a comment.

Add `const` qualifier & replace `auto` with explicit type.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -4054,6 +4054,25 @@
  ->lookup(ToRecordOfFriend->getDeclName())
  .empty());
   }
+
+  void testRepeatedFriendImport(const char *Code) {
+Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
+Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
+
+auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
+auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
+auto *FromFriend1 =
+FirstDeclMatcher().match(FromTu, friendDecl());
+auto *FromFriend2 =
+LastDeclMatcher().match(FromTu, friendDecl());
+
+FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
+FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+
+EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
+EXPECT_EQ(ToFriend1, ToImportedFriend1);
+EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  }
 };
 
 TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
@@ -4395,21 +4414,7 @@
 friend class X;
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
-
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
-
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
@@ -4420,21 +4425,31 @@
 friend void f();
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
+  testRepeatedFriendImport(Code);
+}
 
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend void m();
+  template  friend void m();
+};
+  )";
+  testRepeatedFriendImport(Code);
+}
 
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend class X;
+  template  friend class X;
+};
+  )";
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -4079,22 +4079,34 @@
   unsigned int IndexOfDecl;
 };
 
-template 
-static FriendCountAndPosition getFriendCountAndPosition(
-const FriendDecl *FD,
-llvm::function_ref GetCanTypeOrDecl) {
+static bool IsEquivalentFriend(ASTImporter , FriendDecl *FD1,
+   FriendDecl *FD2) {
+  if ((!FD1->getFriendType()) != (!FD2->getFriendType()))
+return false;
+
+  if (const TypeSourceInfo *TSI = FD1->getFriendType())
+return Importer.IsStructurallyEquivalent(
+TSI->getType(), FD2->getFriendType()->getType(), /*Complain=*/false);
+
+  ASTImporter::NonEquivalentDeclSet NonEquivalentDecls;
+  StructuralEquivalenceContext Ctx(
+  FD1->getASTContext(), FD2->getASTContext(), NonEquivalentDecls,
+  StructuralEquivalenceKind::Default,
+  /* StrictTypeSpelling = */ false, /* Complain = */ false);
+  return Ctx.IsEquivalent(FD1, FD2);
+}
+
+static FriendCountAndPosition getFriendCountAndPosition(ASTImporter ,
+FriendDecl 

[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-08-23 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

> I suspected that the wrong cast modeling and how we infer what value ranges 
> are calculated is susceptible to such APSInt signedness issues, but I haven't 
> seen a case in the wild for extents. Thus, I didn't think of fixing it 
> either. But yes, we should.

I think cast is not the problem, size-type inconsistent is. For `ArrayBound`, 
the assumption should be done with correct types to avoid `-Wsign-compare` 
issue.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158499/new/

https://reviews.llvm.org/D158499

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


[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-08-23 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

One of the observable issue with inconsistent size type is

  void clang_analyzer_eval(int);
  
  typedef unsigned long long size_t;
  void *malloc(unsigned long size);
  void free(void *);
  
  void symbolic_longlong_and_int0(long long len) {
char *a = malloc(5);
(void)a[len + 1]; // no-warning
// len: [-1,3]
clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}}
clang_analyzer_eval(0 <= len);  // expected-warning {{UNKNOWN}}
clang_analyzer_eval(len <= 2);  // expected-warning {{UNKNOWN}}
free(a);
  }

which is extracted from `clang/test/Analysis/array-bound-v2-constraint-check.c`,
with `DynamicMemoryModeling` turned on,
the second warning does not hold anymore: `clang_analyzer_eval(0 <= len);`
will be reported as `TRUE` which is not expected.

`DynamicMemoryModeling` will record the extent of allocated memory as `5ULL`,
`ArrayBoundV2` will do `len + 1 < 5ULL` assumption, simplified to `len < 4ULL`,
which casts `len` to unsigned, dropping `-1`, similar to

  void clang_analyzer_eval(int);
  
  void test(int len) {
if (len >= -1 && len <= 4U) { // len is promoted into unsigned, thus can 
never be negative
clang_analyzer_eval(0 <= len);  // TRUE
}
  }


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158499/new/

https://reviews.llvm.org/D158499

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


[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-08-22 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

We have `getDynamicExtentWithOffset` to use, which can handle more general
dynamic memory based cases than this fix.

I'll abandon this one.

There are issues worth clarifying and fixing:

1). Debugging APIs like `clang_analyzer_dumpExtent` in `ExprInspection` might 
be expanded
to use `getDynamicExtentWithOffset` if it's intended to be used on not only 
dynamic allocated
regions but more general ones, and more testcases are needed to demonstrate the 
usage.

2). Fix type-inconsistency of several size-related `SVal`s, e.g.

  FAM fam;
  clang_analyzer_dump(clang_analyzer_getExtent());
  clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
  // expected-warning@-2 {{4 S64b}}  // U64b is more reasonable when used as an 
extent
  // expected-warning@-2 {{0 U64b}}

`ArrayIndexType` might be misused here.

Simple searching results listed here (might not be complete):

1. `getDynamicExtentWithOffset` return value
2. `getElementExtent` return value
3. `ExprEngineCallAndReturn.cpp` when calling `setDynamicExtent` the `Size` arg


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158499/new/

https://reviews.llvm.org/D158499

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


[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-22 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 552372.
danix800 added a comment.

1. Rebase;
2. Replace `auto` with explicit type;
3. Use local var without interrupting `Importer` state.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -4054,6 +4054,25 @@
  ->lookup(ToRecordOfFriend->getDeclName())
  .empty());
   }
+
+  void testRepeatedFriendImport(const char *Code) {
+Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
+Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
+
+auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
+auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
+auto *FromFriend1 =
+FirstDeclMatcher().match(FromTu, friendDecl());
+auto *FromFriend2 =
+LastDeclMatcher().match(FromTu, friendDecl());
+
+FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
+FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+
+EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
+EXPECT_EQ(ToFriend1, ToImportedFriend1);
+EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  }
 };
 
 TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
@@ -4395,21 +4414,7 @@
 friend class X;
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
-
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
-
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
@@ -4420,21 +4425,31 @@
 friend void f();
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
+  testRepeatedFriendImport(Code);
+}
 
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend void m();
+  template  friend void m();
+};
+  )";
+  testRepeatedFriendImport(Code);
+}
 
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend class X;
+  template  friend class X;
+};
+  )";
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -4079,22 +4079,34 @@
   unsigned int IndexOfDecl;
 };
 
-template 
-static FriendCountAndPosition getFriendCountAndPosition(
-const FriendDecl *FD,
-llvm::function_ref GetCanTypeOrDecl) {
+static bool IsEquivalentFriend(ASTImporter , FriendDecl *FD1,
+   FriendDecl *FD2) {
+  if ((!FD1->getFriendType()) != (!FD2->getFriendType()))
+return false;
+
+  if (TypeSourceInfo *TSI = FD1->getFriendType())
+return Importer.IsStructurallyEquivalent(
+TSI->getType(), FD2->getFriendType()->getType(), /*Complain=*/false);
+
+  ASTImporter::NonEquivalentDeclSet NonEquivalentDecls;
+  StructuralEquivalenceContext Ctx(
+  FD1->getASTContext(), FD2->getASTContext(), NonEquivalentDecls,
+  StructuralEquivalenceKind::Default,
+  /* StrictTypeSpelling = */ false, /* Complain = */ false);
+  return Ctx.IsEquivalent(FD1, FD2);
+}
+
+static FriendCountAndPosition getFriendCountAndPosition(ASTImporter ,
+ 

[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-22 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/lib/AST/ASTImporter.cpp:4114
   SmallVector ImportedEquivalentFriends;
-
-  while (ImportedFriend) {
-bool Match = false;
-if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) {
-  Match =
-  IsStructuralMatch(D->getFriendDecl(), 
ImportedFriend->getFriendDecl(),
-/*Complain=*/false);
-} else if (D->getFriendType() && ImportedFriend->getFriendType()) {
-  Match = Importer.IsStructurallyEquivalent(
-  D->getFriendType()->getType(),
-  ImportedFriend->getFriendType()->getType(), /*Complain=*/false);
-}
-if (Match)
+  for (auto *ImportedFriend : RD->friends())
+if (IsEquivalentFriend(Importer, D, ImportedFriend))

balazske wrote:
> `auto` should not be used here, this loop could be replaced by some generic 
> "algorithm" function call (`llvm::copy_if`).
There's no trivial predicate so the result code might be:
```
  llvm::copy_if(RD->friends(), std::back_inserter(ImportedEquivalentFriends),
[&](FriendDecl *ImportedFriend) {
  return IsEquivalentFriend(Importer, D, ImportedFriend);
});
```
which is not that 'intuitive' as the for-range version.

I'll pertain to the original one with `auto` replaced with explicit type. 
Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

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


[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-08-22 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D158499#4606291 , @steakhal wrote:

> Thanks for submitting this.
> A funny thing is that in my free time I was also working on this last week. 
> I'll have a look at this more in depth during the week.
> For the mean time here is my version, committed pretty much a couple days ago 
> to my fork.
> https://github.com/steakhal/llvm-project/commit/986059a146e036ec84db64868a079d3c4a0e5e16
>
> EDIT: fix the link to point to my fork.
>
> Your proposed change looks pretty similar to mine.

Are you going to submit your changes? Which one do you think is more suitable?

Please let me know whether I should continue on this one or wait for yours. 
Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158499/new/

https://reviews.llvm.org/D158499

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


[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-08-22 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 552288.
danix800 added a comment.

Update testcase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158499/new/

https://reviews.llvm.org/D158499

Files:
  clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
  clang/test/Analysis/flexible-array-members.c

Index: clang/test/Analysis/flexible-array-members.c
===
--- clang/test/Analysis/flexible-array-members.c
+++ clang/test/Analysis/flexible-array-members.c
@@ -44,20 +44,52 @@
   clang_analyzer_dump(clang_analyzer_getExtent());
   clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
   // expected-warning@-2 {{4 S64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 U64b}}
 
   FAM *p = (FAM *)alloca(sizeof(FAM));
   clang_analyzer_dump(clang_analyzer_getExtent(p));
   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
   // expected-warning@-2 {{4 U64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 U64b}}
 
   FAM *q = (FAM *)malloc(sizeof(FAM));
   clang_analyzer_dump(clang_analyzer_getExtent(q));
   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
   // expected-warning@-2 {{4 U64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 U64b}}
   free(q);
+
+  q = (FAM *)malloc(sizeof(FAM) + sizeof(int) * 2);
+  clang_analyzer_dump(clang_analyzer_getExtent(q));
+  clang_analyzer_dump(clang_analyzer_getExtent(q->data));
+  // expected-warning@-2 {{12 U64b}}
+  // expected-warning@-2 {{8 U64b}}
+  free(q);
+
+  typedef struct __attribute__((packed)) {
+char c;
+int data[];
+  } PackedFAM;
+
+  PackedFAM *t = (PackedFAM *)malloc(sizeof(PackedFAM) + sizeof(int) * 2);
+  clang_analyzer_dump(clang_analyzer_getExtent(t));
+  clang_analyzer_dump(clang_analyzer_getExtent(t->data));
+  // expected-warning@-2 {{9 U64b}}
+  // expected-warning@-2 {{8 U64b}}
+  free(t);
+}
+
+void test_too_small_base(void) {
+  typedef struct FAM {
+long c;
+int data[];
+  } FAM;
+  short s = 0;
+  FAM *p = (FAM *) 
+  clang_analyzer_dump(clang_analyzer_getExtent(p));
+  clang_analyzer_dump(clang_analyzer_getExtent(p->data));
+  // expected-warning@-2 {{2 S64b}}
+  // expected-warning@-2 {{Unknown}}
 }
 
 void test_zero_length_array_fam(void) {
Index: clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
===
--- clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
+++ clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -25,6 +25,51 @@
 namespace clang {
 namespace ento {
 
+DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
+  const MemRegion *MR, SValBuilder );
+
+static bool isFlexibleArrayMember(const FieldDecl *FD) {
+  const auto *RD = FD->getParent();
+  if (!RD->hasFlexibleArrayMember())
+return false;
+
+  const FieldDecl *LastFD = nullptr;
+  for (const FieldDecl *It : RD->fields())
+LastFD = It;
+
+  return FD == LastFD;
+}
+
+static std::optional
+getFlexibleArrayExtent(ProgramStateRef State, const MemRegion *MR,
+   SValBuilder ) {
+  const auto *FieldMR = dyn_cast(MR);
+  if (nullptr == FieldMR)
+return std::nullopt;
+
+  const FieldDecl *FD = FieldMR->getDecl();
+  if (!isFlexibleArrayMember(FD))
+return std::nullopt;
+
+  const RecordDecl *RD = FD->getParent();
+  const MemRegion *BaseMR = FieldMR->getBaseRegion();
+  auto BaseSize = getDynamicExtent(State, BaseMR, SVB);
+
+  auto  = SVB.getContext();
+  uint64_t RecordSize = C.getTypeSizeInChars(C.getRecordType(RD)).getQuantity();
+  SVal RecordSizeVal = SVB.makeIntVal(RecordSize, C.getSizeType());
+
+  SVal BaseTooSmall =
+  SVB.evalBinOp(State, BO_LT, BaseSize, RecordSizeVal, C.BoolTy);
+  if (!BaseTooSmall.isUndef() &&
+  State->assume(*BaseTooSmall.getAs(), true))
+return std::nullopt;
+
+  SVal FlexibleArrayExtent =
+  SVB.evalBinOp(State, BO_Sub, BaseSize, RecordSizeVal, C.getSizeType());
+  return FlexibleArrayExtent.getAs();
+}
+
 DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
   const MemRegion *MR, SValBuilder ) {
   MR = MR->StripCasts();
@@ -32,6 +77,9 @@
   if (const DefinedOrUnknownSVal *Size = State->get(MR))
 return *Size;
 
+  if (auto FlexibleArrayExtent = getFlexibleArrayExtent(State, MR, SVB))
+return *FlexibleArrayExtent;
+
   return MR->getMemRegionManager().getStaticSize(MR, SVB);
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158499: [analyzer] Compute FAM dynamic size

2023-08-22 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a project: clang.
Herald added subscribers: steakhal, manas, ASDenysPetrov, martong, dkrupp, 
donat.nagy, Szelethus, mikhail.ramalho, a.sidorin, szepet, baloghadamsoftware, 
xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

This commit computes size of FAM which is normally allocated dynamically.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158499

Files:
  clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
  clang/test/Analysis/flexible-array-members.c

Index: clang/test/Analysis/flexible-array-members.c
===
--- clang/test/Analysis/flexible-array-members.c
+++ clang/test/Analysis/flexible-array-members.c
@@ -44,20 +44,52 @@
   clang_analyzer_dump(clang_analyzer_getExtent());
   clang_analyzer_dump(clang_analyzer_getExtent(fam.data));
   // expected-warning@-2 {{4 S64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 U64b}}
 
   FAM *p = (FAM *)alloca(sizeof(FAM));
   clang_analyzer_dump(clang_analyzer_getExtent(p));
   clang_analyzer_dump(clang_analyzer_getExtent(p->data));
   // expected-warning@-2 {{4 U64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 U64b}}
 
   FAM *q = (FAM *)malloc(sizeof(FAM));
   clang_analyzer_dump(clang_analyzer_getExtent(q));
   clang_analyzer_dump(clang_analyzer_getExtent(q->data));
   // expected-warning@-2 {{4 U64b}}
-  // expected-warning@-2 {{Unknown}}
+  // expected-warning@-2 {{0 U64b}}
   free(q);
+
+  q = (FAM *)malloc(sizeof(FAM) + sizeof(int) * 2);
+  clang_analyzer_dump(clang_analyzer_getExtent(q));
+  clang_analyzer_dump(clang_analyzer_getExtent(q->data));
+  // expected-warning@-2 {{12 U64b}}
+  // expected-warning@-2 {{8 U64b}}
+  free(q);
+
+  typedef struct __attribute__((packed)) {
+char c;
+int data[];
+  } PackedFAM;
+
+  PackedFAM *t = (PackedFAM *)malloc(sizeof(PackedFAM) + sizeof(int) * 2);
+  clang_analyzer_dump(clang_analyzer_getExtent(t));
+  clang_analyzer_dump(clang_analyzer_getExtent(t->data));
+  // expected-warning@-2 {{9 U64b}}
+  // expected-warning@-2 {{8 U64b}}
+  free(t);
+}
+
+void test_too_small_base(void) {
+  typedef struct FAM {
+long c;
+int data[0];
+  } FAM;
+  short s = 0;
+  FAM *p = (FAM *) 
+  clang_analyzer_dump(clang_analyzer_getExtent(p));
+  clang_analyzer_dump(clang_analyzer_getExtent(p->data));
+  // expected-warning@-2 {{2 S64b}}
+  // expected-warning@-2 {{Unknown}}
 }
 
 void test_zero_length_array_fam(void) {
Index: clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
===
--- clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
+++ clang/lib/StaticAnalyzer/Core/DynamicExtent.cpp
@@ -25,6 +25,51 @@
 namespace clang {
 namespace ento {
 
+DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
+  const MemRegion *MR, SValBuilder );
+
+static bool isFlexibleArrayMember(const FieldDecl *FD) {
+  const auto *RD = FD->getParent();
+  if (!RD->hasFlexibleArrayMember())
+return false;
+
+  const FieldDecl *LastFD = nullptr;
+  for (const FieldDecl *It : RD->fields())
+LastFD = It;
+
+  return FD == LastFD;
+}
+
+static std::optional
+getFlexibleArrayExtent(ProgramStateRef State, const MemRegion *MR,
+   SValBuilder ) {
+  const auto *FieldMR = dyn_cast(MR);
+  if (nullptr == FieldMR)
+return std::nullopt;
+
+  const FieldDecl *FD = FieldMR->getDecl();
+  if (!isFlexibleArrayMember(FD))
+return std::nullopt;
+
+  const RecordDecl *RD = FD->getParent();
+  const MemRegion *BaseMR = FieldMR->getBaseRegion();
+  auto BaseSize = getDynamicExtent(State, BaseMR, SVB);
+
+  auto  = SVB.getContext();
+  uint64_t RecordSize = C.getTypeSizeInChars(C.getRecordType(RD)).getQuantity();
+  SVal RecordSizeVal = SVB.makeIntVal(RecordSize, C.getSizeType());
+
+  SVal BaseTooSmall =
+  SVB.evalBinOp(State, BO_LT, BaseSize, RecordSizeVal, C.BoolTy);
+  if (!BaseTooSmall.isUndef() &&
+  State->assume(*BaseTooSmall.getAs(), true))
+return std::nullopt;
+
+  SVal FlexibleArrayExtent =
+  SVB.evalBinOp(State, BO_Sub, BaseSize, RecordSizeVal, C.getSizeType());
+  return FlexibleArrayExtent.getAs();
+}
+
 DefinedOrUnknownSVal getDynamicExtent(ProgramStateRef State,
   const MemRegion *MR, SValBuilder ) {
   MR = MR->StripCasts();
@@ -32,6 +77,9 @@
   if (const DefinedOrUnknownSVal *Size = State->get(MR))
 return *Size;
 
+  if (auto FlexibleArrayExtent = getFlexibleArrayExtent(State, MR, SVB))
+return *FlexibleArrayExtent;
+
   return MR->getMemRegionManager().getStaticSize(MR, SVB);
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-22 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

ping~ @balazske @aaron.ballman


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

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


[PATCH] D158302: [clang] Add simple utils to ensure static assert on bit count of DeclContext

2023-08-19 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 551738.
danix800 added a comment.

Apply git-clang-format


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158302/new/

https://reviews.llvm.org/D158302

Files:
  clang/include/clang/AST/DeclBase.h
  clang/include/clang/Support/BitFieldReflection.h
  clang/lib/Serialization/ASTWriterDecl.cpp

Index: clang/lib/Serialization/ASTWriterDecl.cpp
===
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -433,10 +433,6 @@
 }
 
 void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
-  static_assert(DeclContext::NumTagDeclBits == 10,
-"You need to update the serializer after you change the "
-"TagDeclBits");
-
   VisitRedeclarable(D);
   VisitTypeDecl(D);
   Record.push_back(D->getIdentifierNamespace());
@@ -461,10 +457,6 @@
 }
 
 void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
-  static_assert(DeclContext::NumEnumDeclBits == 20,
-"You need to update the serializer after you change the "
-"EnumDeclBits");
-
   VisitTagDecl(D);
   Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo());
   if (!D->getIntegerTypeSourceInfo())
@@ -508,10 +500,6 @@
 }
 
 void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
-  static_assert(DeclContext::NumRecordDeclBits == 41,
-"You need to update the serializer after you change the "
-"RecordDeclBits");
-
   VisitTagDecl(D);
   Record.push_back(D->hasFlexibleArrayMember());
   Record.push_back(D->isAnonymousStructOrUnion());
@@ -580,10 +568,6 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 31,
-"You need to update the serializer after you change the "
-"FunctionDeclBits");
-
   VisitRedeclarable(D);
 
   Record.push_back(D->getTemplatedKind());
@@ -735,10 +719,6 @@
 }
 
 void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
-  static_assert(DeclContext::NumObjCMethodDeclBits == 24,
-"You need to update the serializer after you change the "
-"ObjCMethodDeclBits");
-
   VisitNamedDecl(D);
   // FIXME: convert to LazyStmtPtr?
   // Unlike C/C++, method bodies will never be in header files.
@@ -797,10 +777,6 @@
 }
 
 void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
-  static_assert(DeclContext::NumObjCContainerDeclBits == 51,
-"You need to update the serializer after you change the "
-"ObjCContainerDeclBits");
-
   VisitNamedDecl(D);
   Record.AddSourceLocation(D->getAtStartLoc());
   Record.AddSourceRange(D->getAtEndRange());
@@ -1284,10 +1260,6 @@
 }
 
 void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  static_assert(DeclContext::NumLinkageSpecDeclBits == 4,
-"You need to update the serializer after you change the"
-"LinkageSpecDeclBits");
-
   VisitDecl(D);
   Record.push_back(D->getLanguage());
   Record.AddSourceLocation(D->getExternLoc());
@@ -1495,10 +1467,6 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 20,
-"You need to update the serializer after you change the "
-"CXXConstructorDeclBits");
-
   Record.push_back(D->getTrailingAllocKind());
   addExplicitSpecifier(D->getExplicitSpecifier(), Record);
   if (auto Inherited = D->getInheritedConstructor()) {
@@ -1875,10 +1843,6 @@
 
 /// Emit the DeclContext part of a declaration context decl.
 void ASTDeclWriter::VisitDeclContext(DeclContext *DC) {
-  static_assert(DeclContext::NumDeclContextBits == 13,
-"You need to update the serializer after you change the "
-"DeclContextBits");
-
   Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC));
   Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC));
 }
@@ -1989,10 +1953,6 @@
 }
 
 void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
-  static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 2,
-"You need to update the serializer after you change the "
-"NumOMPDeclareReductionDeclBits");
-
   VisitValueDecl(D);
   Record.AddSourceLocation(D->getBeginLoc());
   Record.AddStmt(D->getCombinerIn());
Index: clang/include/clang/Support/BitFieldReflection.h
===
--- /dev/null
+++ clang/include/clang/Support/BitFieldReflection.h
@@ -0,0 +1,104 @@
+//===--- BitFieldReflection.h - BitField Reflection Utils ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//

[PATCH] D158302: [clang] Add simple utils to ensure static assert on bit count of DeclContext

2023-08-19 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 551737.
danix800 added a comment.

Remove ununsed code.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158302/new/

https://reviews.llvm.org/D158302

Files:
  clang/include/clang/AST/DeclBase.h
  clang/include/clang/Support/BitFieldReflection.h
  clang/lib/Serialization/ASTWriterDecl.cpp

Index: clang/lib/Serialization/ASTWriterDecl.cpp
===
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -433,10 +433,6 @@
 }
 
 void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
-  static_assert(DeclContext::NumTagDeclBits == 10,
-"You need to update the serializer after you change the "
-"TagDeclBits");
-
   VisitRedeclarable(D);
   VisitTypeDecl(D);
   Record.push_back(D->getIdentifierNamespace());
@@ -461,10 +457,6 @@
 }
 
 void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
-  static_assert(DeclContext::NumEnumDeclBits == 20,
-"You need to update the serializer after you change the "
-"EnumDeclBits");
-
   VisitTagDecl(D);
   Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo());
   if (!D->getIntegerTypeSourceInfo())
@@ -508,10 +500,6 @@
 }
 
 void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
-  static_assert(DeclContext::NumRecordDeclBits == 41,
-"You need to update the serializer after you change the "
-"RecordDeclBits");
-
   VisitTagDecl(D);
   Record.push_back(D->hasFlexibleArrayMember());
   Record.push_back(D->isAnonymousStructOrUnion());
@@ -580,10 +568,6 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 31,
-"You need to update the serializer after you change the "
-"FunctionDeclBits");
-
   VisitRedeclarable(D);
 
   Record.push_back(D->getTemplatedKind());
@@ -735,10 +719,6 @@
 }
 
 void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
-  static_assert(DeclContext::NumObjCMethodDeclBits == 24,
-"You need to update the serializer after you change the "
-"ObjCMethodDeclBits");
-
   VisitNamedDecl(D);
   // FIXME: convert to LazyStmtPtr?
   // Unlike C/C++, method bodies will never be in header files.
@@ -797,10 +777,6 @@
 }
 
 void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
-  static_assert(DeclContext::NumObjCContainerDeclBits == 51,
-"You need to update the serializer after you change the "
-"ObjCContainerDeclBits");
-
   VisitNamedDecl(D);
   Record.AddSourceLocation(D->getAtStartLoc());
   Record.AddSourceRange(D->getAtEndRange());
@@ -1284,10 +1260,6 @@
 }
 
 void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  static_assert(DeclContext::NumLinkageSpecDeclBits == 4,
-"You need to update the serializer after you change the"
-"LinkageSpecDeclBits");
-
   VisitDecl(D);
   Record.push_back(D->getLanguage());
   Record.AddSourceLocation(D->getExternLoc());
@@ -1495,10 +1467,6 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 20,
-"You need to update the serializer after you change the "
-"CXXConstructorDeclBits");
-
   Record.push_back(D->getTrailingAllocKind());
   addExplicitSpecifier(D->getExplicitSpecifier(), Record);
   if (auto Inherited = D->getInheritedConstructor()) {
@@ -1875,10 +1843,6 @@
 
 /// Emit the DeclContext part of a declaration context decl.
 void ASTDeclWriter::VisitDeclContext(DeclContext *DC) {
-  static_assert(DeclContext::NumDeclContextBits == 13,
-"You need to update the serializer after you change the "
-"DeclContextBits");
-
   Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC));
   Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC));
 }
@@ -1989,10 +1953,6 @@
 }
 
 void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
-  static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 2,
-"You need to update the serializer after you change the "
-"NumOMPDeclareReductionDeclBits");
-
   VisitValueDecl(D);
   Record.AddSourceLocation(D->getBeginLoc());
   Record.AddStmt(D->getCombinerIn());
Index: clang/include/clang/Support/BitFieldReflection.h
===
--- /dev/null
+++ clang/include/clang/Support/BitFieldReflection.h
@@ -0,0 +1,104 @@
+//===--- BitFieldReflection.h - BitField Reflection Utils ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//

[PATCH] D158302: [clang] Add simple utils to ensure static assert on bit count of DeclContext

2023-08-18 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a reviewer: aaron.ballman.
danix800 added a project: clang.
Herald added a subscriber: kristof.beyls.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Manually counting bits for DeclContext is error-prone. These two are still 
out-dated:

1. `NumObjCMethodDeclBits` (25, not 24)
2. `NumBlockDeclBits` (6, not 5)

Although no harm at this moment but it's still misleading and might cause 
problem
for the future.

Two simple reflection-like utilities `countBits` & `countFields` are added for 
auto-
updating these bits at compile time and static assert on syncing with any 
changes.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158302

Files:
  clang/include/clang/AST/DeclBase.h
  clang/include/clang/Support/BitFieldReflection.h
  clang/lib/Serialization/ASTWriterDecl.cpp

Index: clang/lib/Serialization/ASTWriterDecl.cpp
===
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -433,10 +433,6 @@
 }
 
 void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
-  static_assert(DeclContext::NumTagDeclBits == 10,
-"You need to update the serializer after you change the "
-"TagDeclBits");
-
   VisitRedeclarable(D);
   VisitTypeDecl(D);
   Record.push_back(D->getIdentifierNamespace());
@@ -461,10 +457,6 @@
 }
 
 void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
-  static_assert(DeclContext::NumEnumDeclBits == 20,
-"You need to update the serializer after you change the "
-"EnumDeclBits");
-
   VisitTagDecl(D);
   Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo());
   if (!D->getIntegerTypeSourceInfo())
@@ -508,10 +500,6 @@
 }
 
 void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
-  static_assert(DeclContext::NumRecordDeclBits == 41,
-"You need to update the serializer after you change the "
-"RecordDeclBits");
-
   VisitTagDecl(D);
   Record.push_back(D->hasFlexibleArrayMember());
   Record.push_back(D->isAnonymousStructOrUnion());
@@ -580,10 +568,6 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 31,
-"You need to update the serializer after you change the "
-"FunctionDeclBits");
-
   VisitRedeclarable(D);
 
   Record.push_back(D->getTemplatedKind());
@@ -735,10 +719,6 @@
 }
 
 void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
-  static_assert(DeclContext::NumObjCMethodDeclBits == 24,
-"You need to update the serializer after you change the "
-"ObjCMethodDeclBits");
-
   VisitNamedDecl(D);
   // FIXME: convert to LazyStmtPtr?
   // Unlike C/C++, method bodies will never be in header files.
@@ -797,10 +777,6 @@
 }
 
 void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) {
-  static_assert(DeclContext::NumObjCContainerDeclBits == 51,
-"You need to update the serializer after you change the "
-"ObjCContainerDeclBits");
-
   VisitNamedDecl(D);
   Record.AddSourceLocation(D->getAtStartLoc());
   Record.AddSourceRange(D->getAtEndRange());
@@ -1284,10 +1260,6 @@
 }
 
 void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
-  static_assert(DeclContext::NumLinkageSpecDeclBits == 4,
-"You need to update the serializer after you change the"
-"LinkageSpecDeclBits");
-
   VisitDecl(D);
   Record.push_back(D->getLanguage());
   Record.AddSourceLocation(D->getExternLoc());
@@ -1495,10 +1467,6 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 20,
-"You need to update the serializer after you change the "
-"CXXConstructorDeclBits");
-
   Record.push_back(D->getTrailingAllocKind());
   addExplicitSpecifier(D->getExplicitSpecifier(), Record);
   if (auto Inherited = D->getInheritedConstructor()) {
@@ -1875,10 +1843,6 @@
 
 /// Emit the DeclContext part of a declaration context decl.
 void ASTDeclWriter::VisitDeclContext(DeclContext *DC) {
-  static_assert(DeclContext::NumDeclContextBits == 13,
-"You need to update the serializer after you change the "
-"DeclContextBits");
-
   Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC));
   Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC));
 }
@@ -1989,10 +1953,6 @@
 }
 
 void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
-  static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 2,
-"You need to update the serializer after you change the "
-"NumOMPDeclareReductionDeclBits");
-
   VisitValueDecl(D);
   Record.AddSourceLocation(D->getBeginLoc());
   Record.AddStmt(D->getCombinerIn());
Index: 

[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 551078.
danix800 added a comment.

Remove debug code.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/DeclBase.h
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/unittests/AST/ASTImporterTest.cpp
  clang/unittests/AST/DeclTest.cpp

Index: clang/unittests/AST/DeclTest.cpp
===
--- clang/unittests/AST/DeclTest.cpp
+++ clang/unittests/AST/DeclTest.cpp
@@ -353,6 +353,32 @@
   EXPECT_TRUE(getFooValue->isInlined());
 }
 
+TEST(Decl, FunctionDeclBitsShouldNotOverlapWithCXXConstructorDeclBits) {
+  llvm::Annotations Code(R"(
+struct A {
+  A() : m() {}
+  int m;
+};
+
+A f() { return A(); }
+)");
+
+  auto AST = tooling::buildASTFromCodeWithArgs(Code.code(), {"-std=c++14"});
+  ASTContext  = AST->getASTContext();
+
+  auto HasCtorInit =
+  hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
+  auto ImpMoveCtor =
+  cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit)
+  .bind("MoveCtor");
+
+  auto *ToImpMoveCtor =
+  selectFirst("MoveCtor", match(ImpMoveCtor, Ctx));
+
+  EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+}
+
 TEST(Decl, NoProtoFunctionDeclAttributes) {
   llvm::Annotations Code(R"(
 void f();
Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -7832,6 +7832,47 @@
   CheckAST(ToTU, ToC);
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase,
+   ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+
+A foo() { A a; return a; }
+A bar() { return {}; }
+  )s",
+  Lang_CXX17,
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+A baz() { return {}; }
+  )s",
+  Lang_CXX17, "A");
+
+  auto HasCtorInit =
+  hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
+  auto ImpMoveCtor =
+  cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);
+
+  auto *FromImpMoveCtor = FirstDeclMatcher().match(
+  From, ImpMoveCtor);
+  auto *ToImpMoveCtor = FirstDeclMatcher().match(
+  To, ImpMoveCtor);
+
+  EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+
+  EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+  EXPECT_TRUE(*ToImpMoveCtor->init_begin());
+}
+
 AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher,
   InnerMatcher) {
   return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -580,7 +580,7 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 30,
+  static_assert(DeclContext::NumFunctionDeclBits == 31,
 "You need to update the serializer after you change the "
 "FunctionDeclBits");
 
@@ -1495,7 +1495,7 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 21,
+  static_assert(DeclContext::NumCXXConstructorDeclBits == 20,
 "You need to update the serializer after you change the "
 "CXXConstructorDeclBits");
 
Index: clang/include/clang/AST/DeclBase.h
===
--- clang/include/clang/AST/DeclBase.h
+++ clang/include/clang/AST/DeclBase.h
@@ -1702,7 +1702,7 @@
   };
 
   /// Number of non-inherited bits in FunctionDeclBitfields.
-  enum { NumFunctionDeclBits = 30 };
+  enum { NumFunctionDeclBits = 31 };
 
   /// Stores the bits used by CXXConstructorDecl. If modified
   /// NumCXXConstructorDeclBits and the accessor
@@ -1714,12 +1714,12 @@
 /// For the bits in FunctionDeclBitfields.
 uint64_t : NumFunctionDeclBits;
 
-/// 21 bits to fit in the remaining available space.
+/// 20 bits to fit in the remaining available space.
 /// Note that this makes CXXConstructorDeclBitfields take
 /// exactly 64 bits and thus the width of NumCtorInitializers
 /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
 /// NumFunctionDeclBitfields or 

[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/unittests/AST/DeclTest.cpp:368
+  ASTContext  = AST->getASTContext();
+  Ctx.getTranslationUnitDecl()->dump();
+

balazske wrote:
> This dump is not needed?
Yeah it's for debug only, I'll remove it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

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


[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 551037.
danix800 added a comment.

1. Update ReleaseNotes.rst
2. Fix typos pointed out by @cor3ntin (thanks!)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/AST/DeclBase.h
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/unittests/AST/ASTImporterTest.cpp
  clang/unittests/AST/DeclTest.cpp

Index: clang/unittests/AST/DeclTest.cpp
===
--- clang/unittests/AST/DeclTest.cpp
+++ clang/unittests/AST/DeclTest.cpp
@@ -353,6 +353,33 @@
   EXPECT_TRUE(getFooValue->isInlined());
 }
 
+TEST(Decl, FunctionDeclBitsShouldNotOverlapWithCXXConstructorDeclBits) {
+  llvm::Annotations Code(R"(
+struct A {
+  A() : m() {}
+  int m;
+};
+
+A f() { return A(); }
+)");
+
+  auto AST = tooling::buildASTFromCodeWithArgs(Code.code(), {"-std=c++14"});
+  ASTContext  = AST->getASTContext();
+  Ctx.getTranslationUnitDecl()->dump();
+
+  auto HasCtorInit =
+  hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
+  auto ImpMoveCtor =
+  cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit)
+  .bind("MoveCtor");
+
+  auto *ToImpMoveCtor =
+  selectFirst("MoveCtor", match(ImpMoveCtor, Ctx));
+
+  EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+}
+
 TEST(Decl, NoProtoFunctionDeclAttributes) {
   llvm::Annotations Code(R"(
 void f();
Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -7832,6 +7832,47 @@
   CheckAST(ToTU, ToC);
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase,
+   ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+
+A foo() { A a; return a; }
+A bar() { return {}; }
+  )s",
+  Lang_CXX17,
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+A baz() { return {}; }
+  )s",
+  Lang_CXX17, "A");
+
+  auto HasCtorInit =
+  hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
+  auto ImpMoveCtor =
+  cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);
+
+  auto *FromImpMoveCtor = FirstDeclMatcher().match(
+  From, ImpMoveCtor);
+  auto *ToImpMoveCtor = FirstDeclMatcher().match(
+  To, ImpMoveCtor);
+
+  EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+
+  EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+  EXPECT_TRUE(*ToImpMoveCtor->init_begin());
+}
+
 AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher,
   InnerMatcher) {
   return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -580,7 +580,7 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 30,
+  static_assert(DeclContext::NumFunctionDeclBits == 31,
 "You need to update the serializer after you change the "
 "FunctionDeclBits");
 
@@ -1495,7 +1495,7 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 21,
+  static_assert(DeclContext::NumCXXConstructorDeclBits == 20,
 "You need to update the serializer after you change the "
 "CXXConstructorDeclBits");
 
Index: clang/include/clang/AST/DeclBase.h
===
--- clang/include/clang/AST/DeclBase.h
+++ clang/include/clang/AST/DeclBase.h
@@ -1702,7 +1702,7 @@
   };
 
   /// Number of non-inherited bits in FunctionDeclBitfields.
-  enum { NumFunctionDeclBits = 30 };
+  enum { NumFunctionDeclBits = 31 };
 
   /// Stores the bits used by CXXConstructorDecl. If modified
   /// NumCXXConstructorDeclBits and the accessor
@@ -1714,12 +1714,12 @@
 /// For the bits in FunctionDeclBitfields.
 uint64_t : NumFunctionDeclBits;
 
-/// 21 bits to fit in the remaining available space.
+/// 20 bits to fit in the remaining available space.
 /// Note that this makes CXXConstructorDeclBitfields take
 /// exactly 64 bits and thus the width of NumCtorInitializers
 /// will need to be 

[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/unittests/AST/ASTImporterTest.cpp:7836
+TEST_P(ASTImporterOptionSpecificTestBase,
+ImportFunctionDeclBitShouldNotStampingOnCtorDeclBits) {
+  Decl *From, *To;

cor3ntin wrote:
> danix800 wrote:
> > cor3ntin wrote:
> > > `ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits`
> > I added the case into `DeclTest.cpp` because i think it can cover the root 
> > cause for both testcases.
> > 
> > How about remove the somewhat repeated one in `ASTImporterTest.cpp`?
> Now that you have written it, we can leave both tests i think.
> Afaik one test serialization so they complement each other
OK! :-)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

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


[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

I also investigated whether we could count those bits at compile time and 
statically assert on them,
because a small typo or missed update could spend us a lot of time to dig for 
the cause.

My first step is trying to count number of bits for a single bitfield, this is 
promising based on this 
 but
with a restriction, it only works on `struct` (default public fields), not 
`class` (default to private fields).

If we can implement this `bitsizeof` then we could have:

  enum { NumFunctionDeclBits = offsetof(FunctionDeclBitfields, SClass)
 + offsetof(FunctionDeclBitfields, IsInline)
 + ... };

This can automatically update total number of bits if any of the existing one 
is updated.

The second step is trying to enumerate all bit fields at compile time so that 
we can totally fix this kind
of issue, but it seems not possible.

Any suggestions or advices? Is it even worth it to do it like this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

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


[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/unittests/AST/ASTImporterTest.cpp:7836
+TEST_P(ASTImporterOptionSpecificTestBase,
+ImportFunctionDeclBitShouldNotStampingOnCtorDeclBits) {
+  Decl *From, *To;

cor3ntin wrote:
> `ImportFunctionDeclBitShouldNotOverwriteCtorDeclBits`
I added the case into `DeclTest.cpp` because i think it can cover the root 
cause for both testcases.

How about remove the somewhat repeated one in `ASTImporterTest.cpp`?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

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


[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

> Can you an an entry in `clang/docs/ReleaseNotes.rst` (mentioning the github 
> issue)

No problem!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

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


[PATCH] D156461: [clang][ASTImporter] Merge implicit ctors with definition

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D156461#4583806 , @balazske wrote:

> Normally what should happen is that a new move constructor is imported (with 
> a definition) and linked after the existing one (and the existing is not 
> modified).

Does this violate the constraint that ctor shouldn't be re-declared?

> We get an AST that does not occur after a normal compile, I do not know if 
> this causes problems or if this is the real reason for this patch.

Agreed. The original AST should not be touched.

> What should be done is find the existing constructor and update it with the 
> definition and return it from the import. This can be done with any type of 
> constructor.

So does this mean that importer might be improved on this part?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156461/new/

https://reviews.llvm.org/D156461

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


[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 551016.
danix800 added a comment.

Add alternative testcase.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158145/new/

https://reviews.llvm.org/D158145

Files:
  clang/include/clang/AST/DeclBase.h
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/unittests/AST/ASTImporterTest.cpp
  clang/unittests/AST/DeclTest.cpp

Index: clang/unittests/AST/DeclTest.cpp
===
--- clang/unittests/AST/DeclTest.cpp
+++ clang/unittests/AST/DeclTest.cpp
@@ -353,6 +353,33 @@
   EXPECT_TRUE(getFooValue->isInlined());
 }
 
+TEST(Decl, FunctionDeclBitsShouldNotOverlappningWithCXXConstructorDeclBits) {
+  llvm::Annotations Code(R"(
+struct A {
+  A() : m() {}
+  int m;
+};
+
+A f() { return A(); }
+)");
+
+  auto AST = tooling::buildASTFromCodeWithArgs(Code.code(), {"-std=c++14"});
+  ASTContext  = AST->getASTContext();
+  Ctx.getTranslationUnitDecl()->dump();
+
+  auto HasCtorInit =
+  hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
+  auto ImpMoveCtor =
+  cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit)
+  .bind("MoveCtor");
+
+  auto *ToImpMoveCtor =
+  selectFirst("MoveCtor", match(ImpMoveCtor, Ctx));
+
+  EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+}
+
 TEST(Decl, NoProtoFunctionDeclAttributes) {
   llvm::Annotations Code(R"(
 void f();
Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -7832,6 +7832,47 @@
   CheckAST(ToTU, ToC);
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase,
+ImportFunctionDeclBitShouldNotStampingOnCtorDeclBits) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+
+A foo() { A a; return a; }
+A bar() { return {}; }
+  )s",
+  Lang_CXX17,
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+A baz() { return {}; }
+  )s",
+  Lang_CXX17, "A");
+
+  auto HasCtorInit =
+  hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
+  auto ImpMoveCtor =
+  cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);
+
+  auto *FromImpMoveCtor = FirstDeclMatcher().match(
+  From, ImpMoveCtor);
+  auto *ToImpMoveCtor = FirstDeclMatcher().match(
+  To, ImpMoveCtor);
+
+  EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+
+  EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+  EXPECT_TRUE(*ToImpMoveCtor->init_begin());
+}
+
 AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher,
   InnerMatcher) {
   return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -580,7 +580,7 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 30,
+  static_assert(DeclContext::NumFunctionDeclBits == 31,
 "You need to update the serializer after you change the "
 "FunctionDeclBits");
 
@@ -1495,7 +1495,7 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 21,
+  static_assert(DeclContext::NumCXXConstructorDeclBits == 20,
 "You need to update the serializer after you change the "
 "CXXConstructorDeclBits");
 
Index: clang/include/clang/AST/DeclBase.h
===
--- clang/include/clang/AST/DeclBase.h
+++ clang/include/clang/AST/DeclBase.h
@@ -1702,7 +1702,7 @@
   };
 
   /// Number of non-inherited bits in FunctionDeclBitfields.
-  enum { NumFunctionDeclBits = 30 };
+  enum { NumFunctionDeclBits = 31 };
 
   /// Stores the bits used by CXXConstructorDecl. If modified
   /// NumCXXConstructorDeclBits and the accessor
@@ -1714,12 +1714,12 @@
 /// For the bits in FunctionDeclBitfields.
 uint64_t : NumFunctionDeclBits;
 
-/// 21 bits to fit in the remaining available space.
+/// 20 bits to fit in the remaining available space.
 /// Note that this makes CXXConstructorDeclBitfields take
 /// exactly 64 bits and thus the width of NumCtorInitializers
 /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
 /// 

[PATCH] D156461: [clang][ASTImporter] Merge implicit ctors with definition

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D156461#4583806 , @balazske wrote:

> It looks not good to remove an invalid node from the DeclContext that 
> otherwise remains in the AST. I checked the problem and found that the 
> existing move constructor (originally in the To AST which had no definition) 
> gets a `getNumCtorInitializers` value of 1 but the `init_begin` returns 0. 
> This causes crash even when dumping it. I did not find the cause of this 
> situation (the first time at line 3822 it is already changed, and 
> `ASTImporter` has this single position to change the value). Normally what 
> should happen is that a new move constructor is imported (with a definition) 
> and linked after the existing one (and the existing is not modified). We get 
> an AST that does not occur after a normal compile, I do not know if this 
> causes problems or if this is the real reason for this patch. What should be 
> done is find the existing constructor and update it with the definition and 
> return it from the import. This can be done with any type of constructor.

The root cause might be that `FunctionDeclBitfields.NumFunctionDeclBits` is not 
in syncing with updated `FunctionDeclBitfields.DeductionCandidateKind`. See 
D158145 .


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156461/new/

https://reviews.llvm.org/D156461

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


[PATCH] D158145: [clang] Update NumFunctionDeclBits for FunctionDeclBitfields

2023-08-17 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added reviewers: aaron.ballman, cor3ntin, ychen, balazske.
danix800 added a project: clang.
Herald added a reviewer: shafik.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

`FunctionDeclBitfields.NumFunctionDeclBits` is not updated when 
`DeductionCandidateKind` is incremented.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158145

Files:
  clang/include/clang/AST/DeclBase.h
  clang/lib/Serialization/ASTWriterDecl.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -7832,6 +7832,47 @@
   CheckAST(ToTU, ToC);
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase,
+ImportFunctionDeclBitShouldNotStampingOnCtorDeclBits) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+
+A foo() { A a; return a; }
+A bar() { return {}; }
+  )s",
+  Lang_CXX17,
+  R"s(
+struct A {
+  A() : m() {}
+  int m;
+};
+A baz() { return {}; }
+  )s",
+  Lang_CXX17, "A");
+
+  auto HasCtorInit =
+  hasAnyConstructorInitializer(cxxCtorInitializer(isMemberInitializer()));
+  auto ImpMoveCtor =
+  cxxConstructorDecl(isMoveConstructor(), isImplicit(), HasCtorInit);
+
+  auto *FromImpMoveCtor = FirstDeclMatcher().match(
+  From, ImpMoveCtor);
+  auto *ToImpMoveCtor = FirstDeclMatcher().match(
+  To, ImpMoveCtor);
+
+  EXPECT_TRUE(FromImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(FromImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+
+  EXPECT_TRUE(ToImpMoveCtor->getNumCtorInitializers() == 1);
+  EXPECT_FALSE(ToImpMoveCtor->FriendConstraintRefersToEnclosingTemplate());
+  EXPECT_TRUE(*ToImpMoveCtor->init_begin());
+}
+
 AST_MATCHER_P(UsingShadowDecl, hasIntroducerDecl, internal::Matcher,
   InnerMatcher) {
   return InnerMatcher.matches(*Node.getIntroducer(), Finder, Builder);
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -580,7 +580,7 @@
 }
 
 void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
-  static_assert(DeclContext::NumFunctionDeclBits == 30,
+  static_assert(DeclContext::NumFunctionDeclBits == 31,
 "You need to update the serializer after you change the "
 "FunctionDeclBits");
 
@@ -1495,7 +1495,7 @@
 }
 
 void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
-  static_assert(DeclContext::NumCXXConstructorDeclBits == 21,
+  static_assert(DeclContext::NumCXXConstructorDeclBits == 20,
 "You need to update the serializer after you change the "
 "CXXConstructorDeclBits");
 
Index: clang/include/clang/AST/DeclBase.h
===
--- clang/include/clang/AST/DeclBase.h
+++ clang/include/clang/AST/DeclBase.h
@@ -1702,7 +1702,7 @@
   };
 
   /// Number of non-inherited bits in FunctionDeclBitfields.
-  enum { NumFunctionDeclBits = 30 };
+  enum { NumFunctionDeclBits = 31 };
 
   /// Stores the bits used by CXXConstructorDecl. If modified
   /// NumCXXConstructorDeclBits and the accessor
@@ -1714,12 +1714,12 @@
 /// For the bits in FunctionDeclBitfields.
 uint64_t : NumFunctionDeclBits;
 
-/// 21 bits to fit in the remaining available space.
+/// 20 bits to fit in the remaining available space.
 /// Note that this makes CXXConstructorDeclBitfields take
 /// exactly 64 bits and thus the width of NumCtorInitializers
 /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
 /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
-uint64_t NumCtorInitializers : 18;
+uint64_t NumCtorInitializers : 17;
 uint64_t IsInheritingConstructor : 1;
 
 /// Whether this constructor has a trail-allocated explicit specifier.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157691: [ASTImporter] Remove extranous FunctionTemplateDecl introduced by templated friend

2023-08-15 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 550210.
danix800 added a comment.

1. Remove unnecessary testcase.
2. Format unittest code.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157691/new/

https://reviews.llvm.org/D157691

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -5634,6 +5634,43 @@
   EXPECT_EQ(Imported->getPreviousDecl(), Friend);
 }
 
+TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) 
{
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  template  struct X {
+template  friend void f();
+  };
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromFriend = FirstDeclMatcher().match(From, friendDecl());
+  auto *ToFriend = FirstDeclMatcher().match(To, friendDecl());
+
+  EXPECT_TRUE(FromFriend ==
+  LastDeclMatcher().match(From, friendDecl()));
+  EXPECT_TRUE(ToFriend ==
+  LastDeclMatcher().match(To, friendDecl()));
+
+  auto *FromDecl = FromFriend->getFriendDecl();
+  auto *FromDC = FromFriend->getDeclContext();
+  auto *FromLexicalDC = FromFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(FromDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromDC->containsDecl(FromDecl));
+  EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));
+
+  auto *ToDecl = ToFriend->getFriendDecl();
+  auto *ToDC = ToFriend->getDeclContext();
+  auto *ToLexicalDC = ToFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(ToDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToDC->containsDecl(ToDecl));
+  EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));
+}
+
 struct ASTImporterWithFakeErrors : ASTImporter {
   using ASTImporter::ASTImporter;
   bool returnWithErrorInTest() override { return true; }
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -6447,7 +6447,7 @@
 
   ToFunc->setAccess(D->getAccess());
   ToFunc->setLexicalDeclContext(LexicalDC);
-  LexicalDC->addDeclInternal(ToFunc);
+  addDeclToContexts(D, ToFunc);
 
   ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable();
   if (LT && !OldParamDC.empty()) {


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -5634,6 +5634,43 @@
   EXPECT_EQ(Imported->getPreviousDecl(), Friend);
 }
 
+TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+  template  struct X {
+template  friend void f();
+  };
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromFriend = FirstDeclMatcher().match(From, friendDecl());
+  auto *ToFriend = FirstDeclMatcher().match(To, friendDecl());
+
+  EXPECT_TRUE(FromFriend ==
+  LastDeclMatcher().match(From, friendDecl()));
+  EXPECT_TRUE(ToFriend ==
+  LastDeclMatcher().match(To, friendDecl()));
+
+  auto *FromDecl = FromFriend->getFriendDecl();
+  auto *FromDC = FromFriend->getDeclContext();
+  auto *FromLexicalDC = FromFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(FromDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromDC->containsDecl(FromDecl));
+  EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));
+
+  auto *ToDecl = ToFriend->getFriendDecl();
+  auto *ToDC = ToFriend->getDeclContext();
+  auto *ToLexicalDC = ToFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(ToDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToDC->containsDecl(ToDecl));
+  EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));
+}
+
 struct ASTImporterWithFakeErrors : ASTImporter {
   using ASTImporter::ASTImporter;
   bool returnWithErrorInTest() override { return true; }
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -6447,7 +6447,7 @@
 
   ToFunc->setAccess(D->getAccess());
   ToFunc->setLexicalDeclContext(LexicalDC);
-  LexicalDC->addDeclInternal(ToFunc);
+  addDeclToContexts(D, ToFunc);
 
   ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable();
   if (LT && !OldParamDC.empty()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157691: [ASTImporter] Remove extranous FunctionTemplateDecl introduced by templated friend

2023-08-15 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

In D157691#4587490 , @balazske wrote:

> When committing this patch, the commit message should not contain the whole 
> AST and crash dump (phabricator takes the "summary" text), this looks too 
> much in a commit message. One AST dump from the wrong To AST is enough.




Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157691/new/

https://reviews.llvm.org/D157691

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


[PATCH] D157777: [ASTMatcher] Add matcher for 'MacroQualifiedType'

2023-08-14 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 550178.
danix800 added a comment.

1. Improve matcher description
2. Add a counter-example for test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D15/new/

https://reviews.llvm.org/D15

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1838,6 +1838,20 @@
 namesType(typedefType()));
 }
 
+TEST_P(ASTMatchersTest, MacroQualifiedType) {
+  EXPECT_TRUE(matches(
+  R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  typedefDecl(hasType(pointerType(pointee(macroQualifiedType()));
+  EXPECT_TRUE(notMatches(
+  R"(
+typedef void (__attribute__((cdecl)) *Y)();
+  )",
+  typedefDecl(hasType(pointerType(pointee(macroQualifiedType()));
+}
+
 TEST_P(ASTMatchersTest, TemplateSpecializationType) {
   if (!GetParam().isCXX()) {
 return;
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -485,6 +485,7 @@
   REGISTER_MATCHER(lambdaCapture);
   REGISTER_MATCHER(lambdaExpr);
   REGISTER_MATCHER(linkageSpecDecl);
+  REGISTER_MATCHER(macroQualifiedType);
   REGISTER_MATCHER(materializeTemporaryExpr);
   REGISTER_MATCHER(member);
   REGISTER_MATCHER(memberExpr);
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -1058,6 +1058,7 @@
 const AstTypeMatcher functionProtoType;
 const AstTypeMatcher parenType;
 const AstTypeMatcher blockPointerType;
+const AstTypeMatcher macroQualifiedType;
 const AstTypeMatcher memberPointerType;
 const AstTypeMatcher pointerType;
 const AstTypeMatcher objcObjectPointerType;
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -7258,6 +7258,18 @@
 ///   matches "typedef int X"
 extern const AstTypeMatcher typedefType;
 
+/// Matches qualified types when the qualifier is applied via a macro.
+///
+/// Given
+/// \code
+///   #define CDECL __attribute__((cdecl))
+///   typedef void (CDECL *X)();
+///   typedef void (__attribute__((cdecl)) *Y)();
+/// \endcode
+/// macroQualifiedType()
+///   matches the type of the typedef declaration of \c X but not \c Y.
+extern const AstTypeMatcher macroQualifiedType;
+
 /// Matches enum types.
 ///
 /// Given
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -249,6 +249,7 @@
 
 - Add ``convertVectorExpr``.
 - Add ``dependentSizedExtVectorType``.
+- Add ``macroQualifiedType``.
 
 clang-format
 
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -2648,6 +2648,18 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Type.html;>TypemacroQualifiedTypeMatcherhttps://clang.llvm.org/doxygen/classclang_1_1MacroQualifiedType.html;>MacroQualifiedType...
+Matches qualified types when the qualifier is applied via a macro.
+
+Given
+  #define CDECL __attribute__((cdecl))
+  typedef void (CDECL *X)();
+  typedef void (__attribute__((cdecl)) *Y)();
+macroQualifiedType()
+  matches the type of the typedef declaration of X but not Y.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Type.html;>TypememberPointerTypeMatcherhttps://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html;>MemberPointerType...
 Matches member pointer types.
 Given
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157777: [ASTMatcher] Add matcher for 'MacroQualifiedType'

2023-08-14 Thread Ding Fei via Phabricator via cfe-commits
danix800 added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:7261
 
+/// Matches macro qualified types.
+///

aaron.ballman wrote:
> How about: Matches qualified types when the qualifier is applied via a macro.
> 
> and then a second example like:
> ```
> int * const qual_ptr;
> 
> #define nonnull _Nonnull
> int * const nonnull macro_qual_ptr;
> ```
> where we match `macro_qual_ptr` but not `qual_ptr`.
> How about: Matches qualified types when the qualifier is applied via a macro.

Forgive my broken English!  :-)

> and then a second example like:
> ```
> int * const qual_ptr;
> 
> #define nonnull _Nonnull
> int * const nonnull macro_qual_ptr;
> ```
> where we match `macro_qual_ptr` but not `qual_ptr`.

Thanks for reminding me of the counter-example, it's critical for better test 
coverage.

I'll pertain to the original one but with counter-example appended, because the 
macro
`nonnull` in this case will not generate a `MacroQualifiedType` for 
`macro_qual_ptr`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D15/new/

https://reviews.llvm.org/D15

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


[PATCH] D157691: [ASTImporter] Remove extranous FunctionTemplateDecl introduced by templated friend

2023-08-14 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 550160.
danix800 added a comment.

1. Add unit testcase
2. Use better API


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157691/new/

https://reviews.llvm.org/D157691

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/test/Import/templated-friend/Inputs/T.cpp
  clang/test/Import/templated-friend/test.cpp
  clang/unittests/AST/ASTImporterTest.cpp


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -5634,6 +5634,42 @@
   EXPECT_EQ(Imported->getPreviousDecl(), Friend);
 }
 
+TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) 
{
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(R"(
+  template  struct X {
+template  friend void f();
+  };
+)",
+   Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromFriend = FirstDeclMatcher().match(From, friendDecl());
+  auto *ToFriend = FirstDeclMatcher().match(To, friendDecl());
+
+  EXPECT_TRUE(FromFriend ==
+  LastDeclMatcher().match(From, friendDecl()));
+  EXPECT_TRUE(ToFriend ==
+  LastDeclMatcher().match(To, friendDecl()));
+
+  auto *FromDecl = FromFriend->getFriendDecl();
+  auto *FromDC = FromFriend->getDeclContext();
+  auto *FromLexicalDC = FromFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(FromDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromDC->containsDecl(FromDecl));
+  EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));
+
+  auto *ToDecl = ToFriend->getFriendDecl();
+  auto *ToDC = ToFriend->getDeclContext();
+  auto *ToLexicalDC = ToFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(ToDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToDC->containsDecl(ToDecl));
+  EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));
+}
+
 struct ASTImporterWithFakeErrors : ASTImporter {
   using ASTImporter::ASTImporter;
   bool returnWithErrorInTest() override { return true; }
Index: clang/test/Import/templated-friend/test.cpp
===
--- /dev/null
+++ clang/test/Import/templated-friend/test.cpp
@@ -0,0 +1,5 @@
+// RUN: clang-import-test -import %S/Inputs/T.cpp -expression %s
+
+void expr() {
+  A a;
+}
Index: clang/test/Import/templated-friend/Inputs/T.cpp
===
--- /dev/null
+++ clang/test/Import/templated-friend/Inputs/T.cpp
@@ -0,0 +1,3 @@
+template  struct A {
+  template  friend void f();
+};
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -6447,7 +6447,7 @@
 
   ToFunc->setAccess(D->getAccess());
   ToFunc->setLexicalDeclContext(LexicalDC);
-  LexicalDC->addDeclInternal(ToFunc);
+  addDeclToContexts(D, ToFunc);
 
   ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable();
   if (LT && !OldParamDC.empty()) {


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -5634,6 +5634,42 @@
   EXPECT_EQ(Imported->getPreviousDecl(), Friend);
 }
 
+TEST_P(ImportFriendFunctionTemplates, ImportFriendFunctionInsideClassTemplate) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(R"(
+  template  struct X {
+template  friend void f();
+  };
+)",
+   Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromFriend = FirstDeclMatcher().match(From, friendDecl());
+  auto *ToFriend = FirstDeclMatcher().match(To, friendDecl());
+
+  EXPECT_TRUE(FromFriend ==
+  LastDeclMatcher().match(From, friendDecl()));
+  EXPECT_TRUE(ToFriend ==
+  LastDeclMatcher().match(To, friendDecl()));
+
+  auto *FromDecl = FromFriend->getFriendDecl();
+  auto *FromDC = FromFriend->getDeclContext();
+  auto *FromLexicalDC = FromFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(FromDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromDC->containsDecl(FromDecl));
+  EXPECT_TRUE(FromLexicalDC->containsDecl(FromFriend));
+  EXPECT_FALSE(FromLexicalDC->containsDecl(FromDecl));
+
+  auto *ToDecl = ToFriend->getFriendDecl();
+  auto *ToDC = ToFriend->getDeclContext();
+  auto *ToLexicalDC = ToFriend->getLexicalDeclContext();
+
+  EXPECT_TRUE(ToDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToDC->containsDecl(ToDecl));
+  EXPECT_TRUE(ToLexicalDC->containsDecl(ToFriend));
+  EXPECT_FALSE(ToLexicalDC->containsDecl(ToDecl));
+}
+
 struct ASTImporterWithFakeErrors : ASTImporter {
   using ASTImporter::ASTImporter;
   bool returnWithErrorInTest() override { return true; }
Index: 

[PATCH] D157780: [ASTImporter] Add import of MacroQualifiedType

2023-08-12 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 549609.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157780/new/

https://reviews.llvm.org/D157780

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -8638,6 +8638,24 @@
   EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromTy =
+  FirstDeclMatcher().match(From, macroQualifiedType());
+  auto *ToTy =
+  FirstDeclMatcher().match(To, macroQualifiedType());
+
+  EXPECT_TRUE(isa(FromTy->getUnderlyingType()));
+  EXPECT_TRUE(isa(ToTy->getUnderlyingType()));
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
   constexpr auto TestCode = R"(
   template 
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -419,6 +419,7 @@
 ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T);
 ExpectedType VisitObjCObjectType(const ObjCObjectType *T);
 ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+ExpectedType VisitMacroQualifiedType(const MacroQualifiedType *T);
 
 // Importing declarations
 Error ImportDeclParts(NamedDecl *D, DeclarationName , NamedDecl *,
@@ -1701,6 +1702,17 @@
   return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
 }
 
+ExpectedType
+ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
+  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+  if (!ToUnderlyingTypeOrErr)
+return ToUnderlyingTypeOrErr.takeError();
+
+  IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier());
+  return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr,
+   ToIdentifier);
+}
+
 //
 // Import Declarations
 //


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -8638,6 +8638,24 @@
   EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromTy =
+  FirstDeclMatcher().match(From, macroQualifiedType());
+  auto *ToTy =
+  FirstDeclMatcher().match(To, macroQualifiedType());
+
+  EXPECT_TRUE(isa(FromTy->getUnderlyingType()));
+  EXPECT_TRUE(isa(ToTy->getUnderlyingType()));
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
   constexpr auto TestCode = R"(
   template 
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -419,6 +419,7 @@
 ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T);
 ExpectedType VisitObjCObjectType(const ObjCObjectType *T);
 ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+ExpectedType VisitMacroQualifiedType(const MacroQualifiedType *T);
 
 // Importing declarations
 Error ImportDeclParts(NamedDecl *D, DeclarationName , NamedDecl *,
@@ -1701,6 +1702,17 @@
   return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
 }
 
+ExpectedType
+ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
+  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+  if (!ToUnderlyingTypeOrErr)
+return ToUnderlyingTypeOrErr.takeError();
+
+  IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier());
+  return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr,
+   ToIdentifier);
+}
+
 //
 // Import Declarations
 //
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D157780: [ASTImporter] Add import of MacroQualifiedType

2023-08-12 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a project: clang.
Herald added a subscriber: martong.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Add import of MacroQualifiedType.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157780

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -8638,6 +8638,24 @@
   EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromTy =
+  FirstDeclMatcher().match(From, macroQualifiedType());
+  auto *ToTy =
+  FirstDeclMatcher().match(To, macroQualifiedType());
+
+  EXPECT_TRUE(isa(FromTy->getUnderlyingType()));
+  EXPECT_TRUE(isa(ToTy->getUnderlyingType()));
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
   constexpr auto TestCode = R"(
   template 
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -419,6 +419,7 @@
 ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T);
 ExpectedType VisitObjCObjectType(const ObjCObjectType *T);
 ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+ExpectedType VisitMacroQualifiedType(const MacroQualifiedType *T);
 
 // Importing declarations
 Error ImportDeclParts(NamedDecl *D, DeclarationName , NamedDecl *,
@@ -1701,6 +1702,17 @@
   return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
 }
 
+ExpectedType
+ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
+  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+  if (!ToUnderlyingTypeOrErr)
+return ToUnderlyingTypeOrErr.takeError();
+
+  IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier());
+  return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr,
+   ToIdentifier);
+}
+
 //
 // Import Declarations
 //


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -8638,6 +8638,24 @@
   EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromTy =
+  FirstDeclMatcher().match(From, macroQualifiedType());
+  auto *ToTy =
+  FirstDeclMatcher().match(To, macroQualifiedType());
+
+  EXPECT_TRUE(isa(FromTy->getUnderlyingType()));
+  EXPECT_TRUE(isa(ToTy->getUnderlyingType()));
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
   constexpr auto TestCode = R"(
   template 
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -419,6 +419,7 @@
 ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T);
 ExpectedType VisitObjCObjectType(const ObjCObjectType *T);
 ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+ExpectedType VisitMacroQualifiedType(const MacroQualifiedType *T);
 
 // Importing declarations
 Error ImportDeclParts(NamedDecl *D, DeclarationName , NamedDecl *,
@@ -1701,6 +1702,17 @@
   return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
 }
 
+ExpectedType
+ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
+  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+  if (!ToUnderlyingTypeOrErr)
+return ToUnderlyingTypeOrErr.takeError();
+
+  IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier());
+  return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr,
+   ToIdentifier);
+}
+
 //
 // Import Declarations
 

[PATCH] D157777: [ASTMatcher] Add matcher for 'MacroQualifiedType'

2023-08-12 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 549607.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D15/new/

https://reviews.llvm.org/D15

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp


Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1838,6 +1838,15 @@
 namesType(typedefType()));
 }
 
+TEST_P(ASTMatchersTest, MacroQualifiedType) {
+  EXPECT_TRUE(matches(R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  typedefDecl(hasName("X"), hasType(pointerType(pointee(
+macroQualifiedType()));
+}
+
 TEST_P(ASTMatchersTest, TemplateSpecializationType) {
   if (!GetParam().isCXX()) {
 return;
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -485,6 +485,7 @@
   REGISTER_MATCHER(lambdaCapture);
   REGISTER_MATCHER(lambdaExpr);
   REGISTER_MATCHER(linkageSpecDecl);
+  REGISTER_MATCHER(macroQualifiedType);
   REGISTER_MATCHER(materializeTemporaryExpr);
   REGISTER_MATCHER(member);
   REGISTER_MATCHER(memberExpr);
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -1058,6 +1058,7 @@
 const AstTypeMatcher functionProtoType;
 const AstTypeMatcher parenType;
 const AstTypeMatcher blockPointerType;
+const AstTypeMatcher macroQualifiedType;
 const AstTypeMatcher memberPointerType;
 const AstTypeMatcher pointerType;
 const AstTypeMatcher objcObjectPointerType;
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -7258,6 +7258,17 @@
 ///   matches "typedef int X"
 extern const AstTypeMatcher typedefType;
 
+/// Matches macro qualified types.
+///
+/// Given
+/// \code
+///   #define CDECL __attribute__((cdecl))
+///   typedef void (CDECL *X)();
+/// \endcode
+/// macroQualifiedType()
+///   matches the type of the typedef declaration of \c X.
+extern const AstTypeMatcher macroQualifiedType;
+
 /// Matches enum types.
 ///
 /// Given
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -244,6 +244,7 @@
 
 - Add ``convertVectorExpr``.
 - Add ``dependentSizedExtVectorType``.
+- Add ``macroQualifiedType``.
 
 clang-format
 
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -2648,6 +2648,17 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Type.html;>TypemacroQualifiedTypeMatcherhttps://clang.llvm.org/doxygen/classclang_1_1MacroQualifiedType.html;>MacroQualifiedType...
+Matches macro 
qualified types.
+
+Given
+  #define CDECL __attribute__((cdecl))
+  typedef void (CDECL *X)();
+macroQualifiedType()
+  matches the type of the typedef declaration of X.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Type.html;>TypememberPointerTypeMatcherhttps://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html;>MemberPointerType...
 Matches member 
pointer types.
 Given


Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1838,6 +1838,15 @@
 namesType(typedefType()));
 }
 
+TEST_P(ASTMatchersTest, MacroQualifiedType) {
+  EXPECT_TRUE(matches(R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  typedefDecl(hasName("X"), hasType(pointerType(pointee(
+macroQualifiedType()));
+}
+
 TEST_P(ASTMatchersTest, TemplateSpecializationType) {
   if (!GetParam().isCXX()) {
 return;
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- 

[PATCH] D157777: [ASTMatcher] Add matcher for 'MacroQualifiedType'

2023-08-12 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 549605.
danix800 added a comment.
Herald added a subscriber: martong.
Herald added a reviewer: shafik.

Add import of MacroQualifiedType.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D15/new/

https://reviews.llvm.org/D15

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -8638,6 +8638,24 @@
   EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromTy =
+  FirstDeclMatcher().match(From, macroQualifiedType());
+  auto *ToTy =
+  FirstDeclMatcher().match(To, macroQualifiedType());
+
+  EXPECT_TRUE(isa(FromTy->getUnderlyingType()));
+  EXPECT_TRUE(isa(ToTy->getUnderlyingType()));
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
   constexpr auto TestCode = R"(
   template 
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -419,6 +419,7 @@
 ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T);
 ExpectedType VisitObjCObjectType(const ObjCObjectType *T);
 ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+ExpectedType VisitMacroQualifiedType(const MacroQualifiedType *T);
 
 // Importing declarations
 Error ImportDeclParts(NamedDecl *D, DeclarationName , NamedDecl *,
@@ -1701,6 +1702,17 @@
   return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
 }
 
+ExpectedType
+ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
+  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+  if (!ToUnderlyingTypeOrErr)
+return ToUnderlyingTypeOrErr.takeError();
+
+  IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier());
+  return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr,
+   ToIdentifier);
+}
+
 //
 // Import Declarations
 //


Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -8638,6 +8638,24 @@
   EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar));
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, ImportMacroQualifiedType) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(
+  R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  Lang_CXX03, "", Lang_CXX03, "X");
+
+  auto *FromTy =
+  FirstDeclMatcher().match(From, macroQualifiedType());
+  auto *ToTy =
+  FirstDeclMatcher().match(To, macroQualifiedType());
+
+  EXPECT_TRUE(isa(FromTy->getUnderlyingType()));
+  EXPECT_TRUE(isa(ToTy->getUnderlyingType()));
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, ImportCorrectTemplateName) {
   constexpr auto TestCode = R"(
   template 
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -419,6 +419,7 @@
 ExpectedType VisitObjCInterfaceType(const ObjCInterfaceType *T);
 ExpectedType VisitObjCObjectType(const ObjCObjectType *T);
 ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T);
+ExpectedType VisitMacroQualifiedType(const MacroQualifiedType *T);
 
 // Importing declarations
 Error ImportDeclParts(NamedDecl *D, DeclarationName , NamedDecl *,
@@ -1701,6 +1702,17 @@
   return Importer.getToContext().getObjCObjectPointerType(*ToPointeeTypeOrErr);
 }
 
+ExpectedType
+ASTNodeImporter::VisitMacroQualifiedType(const MacroQualifiedType *T) {
+  ExpectedType ToUnderlyingTypeOrErr = import(T->getUnderlyingType());
+  if (!ToUnderlyingTypeOrErr)
+return ToUnderlyingTypeOrErr.takeError();
+
+  IdentifierInfo *ToIdentifier = Importer.Import(T->getMacroIdentifier());
+  return Importer.getToContext().getMacroQualifiedType(*ToUnderlyingTypeOrErr,
+   ToIdentifier);
+}
+
 //
 // Import Declarations
 //

[PATCH] D157777: [ASTMatcher] Add matcher for 'MacroQualifiedType'

2023-08-12 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a project: clang.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Add matcher for 'MacroQualifiedType'


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D15

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/ReleaseNotes.rst
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp


Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1838,6 +1838,15 @@
 namesType(typedefType()));
 }
 
+TEST_P(ASTMatchersTest, MacroQualifiedType) {
+  EXPECT_TRUE(matches(R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  typedefDecl(hasName("X"), hasType(pointerType(pointee(
+macroQualifiedType()));
+}
+
 TEST_P(ASTMatchersTest, TemplateSpecializationType) {
   if (!GetParam().isCXX()) {
 return;
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -485,6 +485,7 @@
   REGISTER_MATCHER(lambdaCapture);
   REGISTER_MATCHER(lambdaExpr);
   REGISTER_MATCHER(linkageSpecDecl);
+  REGISTER_MATCHER(macroQualifiedType);
   REGISTER_MATCHER(materializeTemporaryExpr);
   REGISTER_MATCHER(member);
   REGISTER_MATCHER(memberExpr);
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -1058,6 +1058,7 @@
 const AstTypeMatcher functionProtoType;
 const AstTypeMatcher parenType;
 const AstTypeMatcher blockPointerType;
+const AstTypeMatcher macroQualifiedType;
 const AstTypeMatcher memberPointerType;
 const AstTypeMatcher pointerType;
 const AstTypeMatcher objcObjectPointerType;
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -7258,6 +7258,17 @@
 ///   matches "typedef int X"
 extern const AstTypeMatcher typedefType;
 
+/// Matches macro qualified types.
+///
+/// Given
+/// \code
+///   #define CDECL __attribute__((cdecl))
+///   typedef void (CDECL *X)();
+/// \endcode
+/// macroQualifiedType()
+///   matches the type of the typedef declaration of \c X.
+extern const AstTypeMatcher macroQualifiedType;
+
 /// Matches enum types.
 ///
 /// Given
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -244,6 +244,7 @@
 
 - Add ``convertVectorExpr``.
 - Add ``dependentSizedExtVectorType``.
+- Add ``macroQualifiedType``.
 
 clang-format
 
Index: clang/docs/LibASTMatchersReference.html
===
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -2648,6 +2648,17 @@
 
 
 
+Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Type.html;>TypemacroQualifiedTypeMatcherhttps://clang.llvm.org/doxygen/classclang_1_1MacroQualifiedType.html;>MacroQualifiedType...
+Matches macro 
qualified types.
+
+Given
+  #define CDECL __attribute__((cdecl))
+  typedef void (CDECL *X)();
+macroQualifiedType()
+  matches the type of the typedef declaration of X.
+
+
+
 Matcherhttps://clang.llvm.org/doxygen/classclang_1_1Type.html;>TypememberPointerTypeMatcherhttps://clang.llvm.org/doxygen/classclang_1_1MemberPointerType.html;>MemberPointerType...
 Matches member 
pointer types.
 Given


Index: clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1838,6 +1838,15 @@
 namesType(typedefType()));
 }
 
+TEST_P(ASTMatchersTest, MacroQualifiedType) {
+  EXPECT_TRUE(matches(R"(
+#define CDECL __attribute__((cdecl))
+typedef void (CDECL *X)();
+  )",
+  typedefDecl(hasName("X"), hasType(pointerType(pointee(
+macroQualifiedType()));
+}
+
 TEST_P(ASTMatchersTest, TemplateSpecializationType) {
   if (!GetParam().isCXX()) {
 return;
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp

[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-11 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 549436.
danix800 added a comment.

Turn off `Complain` mode on `IsEquivalentFriend` checking.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -4054,6 +4054,25 @@
  ->lookup(ToRecordOfFriend->getDeclName())
  .empty());
   }
+
+  void testRepeatedFriendImport(const char *Code) {
+Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
+Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
+
+auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
+auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
+auto *FromFriend1 =
+FirstDeclMatcher().match(FromTu, friendDecl());
+auto *FromFriend2 =
+LastDeclMatcher().match(FromTu, friendDecl());
+
+FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
+FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+
+EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
+EXPECT_EQ(ToFriend1, ToImportedFriend1);
+EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  }
 };
 
 TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
@@ -4343,21 +4362,7 @@
 friend class X;
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
-
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
-
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
@@ -4368,21 +4373,31 @@
 friend void f();
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
+  testRepeatedFriendImport(Code);
+}
 
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend void m();
+  template  friend void m();
+};
+  )";
+  testRepeatedFriendImport(Code);
+}
 
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend class X;
+  template  friend class X;
+};
+  )";
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -4064,22 +4064,33 @@
   unsigned int IndexOfDecl;
 };
 
-template 
-static FriendCountAndPosition getFriendCountAndPosition(
-const FriendDecl *FD,
-llvm::function_ref GetCanTypeOrDecl) {
+static bool IsEquivalentFriend(ASTImporter , FriendDecl *FD1,
+   FriendDecl *FD2) {
+  if ((!FD1->getFriendType()) != (!FD2->getFriendType()))
+return false;
+
+  if (auto *TSI = FD1->getFriendType())
+return Importer.IsStructurallyEquivalent(
+TSI->getType(), FD2->getFriendType()->getType(), /*Complain=*/false);
+
+  StructuralEquivalenceContext Ctx(
+  FD1->getASTContext(), FD2->getASTContext(),
+  Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer),
+  /* StrictTypeSpelling = */ false, /* Complain = */ false);
+  return Ctx.IsEquivalent(FD1, FD2);
+}
+
+static FriendCountAndPosition getFriendCountAndPosition(ASTImporter ,
+FriendDecl *FD) {
   unsigned int FriendCount = 0;
   std::optional 

[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-11 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 549376.
danix800 added a comment.

Apply git-clang-format.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/unittests/AST/ASTImporterTest.cpp

Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -4054,6 +4054,25 @@
  ->lookup(ToRecordOfFriend->getDeclName())
  .empty());
   }
+
+  void testRepeatedFriendImport(const char *Code) {
+Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
+Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
+
+auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
+auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
+auto *FromFriend1 =
+FirstDeclMatcher().match(FromTu, friendDecl());
+auto *FromFriend2 =
+LastDeclMatcher().match(FromTu, friendDecl());
+
+FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
+FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+
+EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
+EXPECT_EQ(ToFriend1, ToImportedFriend1);
+EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  }
 };
 
 TEST_P(ImportFriendClasses, ImportOfFriendRecordDoesNotMergeDefinition) {
@@ -4343,21 +4362,7 @@
 friend class X;
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
-
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
-
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ImportFriendClasses, ImportOfRepeatedFriendDecl) {
@@ -4368,21 +4373,31 @@
 friend void f();
   };
   )";
-  Decl *ToTu = getToTuDecl(Code, Lang_CXX03);
-  Decl *FromTu = getTuDecl(Code, Lang_CXX03, "from.cc");
-
-  auto *ToFriend1 = FirstDeclMatcher().match(ToTu, friendDecl());
-  auto *ToFriend2 = LastDeclMatcher().match(ToTu, friendDecl());
-  auto *FromFriend1 =
-  FirstDeclMatcher().match(FromTu, friendDecl());
-  auto *FromFriend2 = LastDeclMatcher().match(FromTu, friendDecl());
+  testRepeatedFriendImport(Code);
+}
 
-  FriendDecl *ToImportedFriend1 = Import(FromFriend1, Lang_CXX03);
-  FriendDecl *ToImportedFriend2 = Import(FromFriend2, Lang_CXX03);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendFunctionTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend void m();
+  template  friend void m();
+};
+  )";
+  testRepeatedFriendImport(Code);
+}
 
-  EXPECT_NE(ToImportedFriend1, ToImportedFriend2);
-  EXPECT_EQ(ToFriend1, ToImportedFriend1);
-  EXPECT_EQ(ToFriend2, ToImportedFriend2);
+TEST_P(ImportFriendClasses, ImportOfRepeatedFriendClassTemplateDecl) {
+  const char *Code =
+  R"(
+template 
+class Container {
+  template  friend class X;
+  template  friend class X;
+};
+  )";
+  testRepeatedFriendImport(Code);
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
Index: clang/lib/AST/ASTImporter.cpp
===
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -4064,22 +4064,32 @@
   unsigned int IndexOfDecl;
 };
 
-template 
-static FriendCountAndPosition getFriendCountAndPosition(
-const FriendDecl *FD,
-llvm::function_ref GetCanTypeOrDecl) {
+static bool IsEquivalentFriend(ASTImporter , FriendDecl *FD1,
+   FriendDecl *FD2) {
+  if ((!FD1->getFriendType()) != (!FD2->getFriendType()))
+return false;
+
+  if (auto *TSI = FD1->getFriendType())
+return Importer.IsStructurallyEquivalent(
+TSI->getType(), FD2->getFriendType()->getType(), /*Complain=*/false);
+
+  StructuralEquivalenceContext Ctx(
+  Importer.getFromContext(), Importer.getToContext(),
+  Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer));
+  return Ctx.IsEquivalent(FD1, FD2);
+}
+
+static FriendCountAndPosition getFriendCountAndPosition(ASTImporter ,
+FriendDecl *FD) {
   unsigned int FriendCount = 0;
   std::optional FriendPosition;
   const auto *RD = cast(FD->getLexicalDeclContext());
 
-  T TypeOrDecl = 

[PATCH] D157691: [ASTImporter] Remove extranous FunctionTemplateDecl introduced by templated friend

2023-08-11 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added reviewers: balazske, aaron.ballman.
danix800 added a project: clang.
Herald added subscribers: pengfei, martong, kristof.beyls.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

An extranous `FunctionTemplateDecl` is introduced in the following testcase:

  template  struct A {
template  friend void f();
  };

`From`:

  ClassTemplateDecl 0x55dae7001500  col:30 A
  |-TemplateTypeParmDecl 0x55dae70013b0  col:20 typename depth 
0 index 0 T
  `-CXXRecordDecl 0x55dae7001470  col:30 struct A definition
|-DefinitionData empty aggregate standard_layout trivially_copyable pod 
trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| |-DefaultConstructor exists trivial constexpr needs_implicit 
defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveConstructor exists simple trivial needs_implicit
| |-CopyAssignment simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial needs_implicit
|-CXXRecordDecl 0x55dae7001750  col:30 implicit struct A
`-FriendDecl 0x55dae7001a68  col:69
  `-FunctionTemplateDecl 0x55dae70019a0 parent 0x55dae6f97e28  col:69 f
|-TemplateTypeParmDecl 0x55dae70017e0  col:54 typename 
depth 1 index 0 U
`-FunctionDecl 0x55dae70018e8 parent 0x55dae6f97e28  
col:69 f 'void ()'

`To`:

  ClassTemplateDecl 0x55dae7116618  col:30 A
  |-TemplateTypeParmDecl 0x55dae7116490  col:20 typename depth 
0 index 0 T
  `-CXXRecordDecl 0x55dae7116550  col:30 struct A definition
|-DefinitionData empty aggregate standard_layout trivially_copyable pod 
trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| |-DefaultConstructor exists trivial constexpr needs_implicit 
defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveConstructor exists simple trivial needs_implicit
| |-CopyAssignment simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial needs_implicit
|-FunctionTemplateDecl 0x55dae7116a38 parent 0x55dae6fa2b68  col:69 f// extranous node
| |-TemplateTypeParmDecl 0x55dae7116860  col:54 typename 
depth 1 index 0 U
| `-FunctionDecl 0x55dae7116968 parent 0x55dae6fa2b68  
col:69 f 'void ()'
|-FriendDecl 0x55dae7116aa0  col:69
| `-FunctionTemplateDecl 0x55dae7116a38 parent 0x55dae6fa2b68  col:69 f
|   |-TemplateTypeParmDecl 0x55dae7116860  col:54 typename 
depth 1 index 0 U
|   `-FunctionDecl 0x55dae7116968 parent 0x55dae6fa2b68  
col:69 f 'void ()'
`-CXXRecordDecl 0x55dae7116ae0  col:30 implicit struct A

`clang-import-test` would crash on this case:

  clang-import-test: 
/home/x/Sources/llvm-project-main/clang/lib/AST/ExternalASTMerger.cpp:533: 
auto clang::ExternalASTMerger::FindExternalLexicalDecls(const 
clang::DeclContext *, llvm::function_ref, 
SmallVectorImpl &)::(anonymous 
class)::operator()(clang::ASTImporter &, clang::ASTImporter &, Source) const: Assertion `!(*ImportedDeclOrErr) || 
IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC)' failed.
  f #0 0x7fec39df812a llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) 
/home/x/Sources/llvm-project-main/llvm/lib/Support/Unix/Signals.inc:602:11
   #1 0x7fec39df82db PrintStackTraceSignalHandler(void*) 
/home/x/Sources/llvm-project-main/llvm/lib/Support/Unix/Signals.inc:675:1
   #2 0x7fec39df6846 llvm::sys::RunSignalHandlers() 
/home/x/Sources/llvm-project-main/llvm/lib/Support/Signals.cpp:104:5
   #3 0x7fec39df8af5 SignalHandler(int) 
/home/x/Sources/llvm-project-main/llvm/lib/Support/Unix/Signals.inc:413:1
   #4 0x7fec3985afd0 (/lib/x86_64-linux-gnu/libc.so.6+0x3bfd0)
   #5 0x7fec398a9d3c __pthread_kill_implementation 
./nptl/pthread_kill.c:44:76
   #6 0x7fec3985af32 raise ./signal/../sysdeps/posix/raise.c:27:6
   #7 0x7fec39845472 abort ./stdlib/abort.c:81:7
   #8 0x7fec39845395 _nl_load_domain ./intl/loadmsgcat.c:1177:9
   #9 0x7fec39853e32 (/lib/x86_64-linux-gnu/libc.so.6+0x34e32)
  #10 0x7fec3c90c203 
clang::ExternalASTMerger::FindExternalLexicalDecls(clang::DeclContext const*, 
llvm::function_ref, 
llvm::SmallVectorImpl&)::$_5::operator()(clang::ASTImporter&, 
clang::ASTImporter&, (anonymous namespace)::Source) 
const 
/home/x/Sources/llvm-project-main/clang/lib/AST/ExternalASTMerger.cpp:532:11
  #11 0x7fec3c9094a7 void 
clang::ExternalASTMerger::ForEachMatchingDC, 
llvm::SmallVectorImpl&)::$_5>(clang::DeclContext const*, 

[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-11 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

By `FromContext` dump it's easy to observe that there're two different 
`FunctionTemplateDecl` (`0x5590cff48048` and `0x5590cff481f8`):

  |-FriendDecl 0x5590cff48048  col:42
  | `-FunctionTemplateDecl 0x5590cff47f80 parent 0x5590cfefeda8  col:42 m
  |   |-...
  `-FriendDecl 0x5590cff48260  col:42
`-FunctionTemplateDecl 0x5590cff481f8 parent 0x5590cfefeda8  col:42 m
  |-...


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157684/new/

https://reviews.llvm.org/D157684

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


[PATCH] D157684: [clang][ASTImporter] Repeated friend templates are partially imported

2023-08-11 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added reviewers: balazske, aaron.ballman.
danix800 added a project: clang.
Herald added subscribers: pengfei, martong, kristof.beyls.
Herald added a reviewer: a.sidorin.
Herald added a reviewer: shafik.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

1. Repeated friends of template class/function in template class are partially 
imported:

  template 
  class Container {
template  friend void m();
template  friend void m();
  };

Only one `m` can be imported,

`FromTu`:

  ClassTemplateDecl 0x5590cff47ae0  line:3:15 Container
  |-TemplateTypeParmDecl 0x5590cff47990  col:25 class depth 
0 index 0 T
  `-CXXRecordDecl 0x5590cff47a50  line:3:15 class Container 
definition
|-DefinitionData empty aggregate standard_layout trivially_copyable pod 
trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| |-DefaultConstructor exists trivial constexpr needs_implicit 
defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveConstructor exists simple trivial needs_implicit
| |-CopyAssignment simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial needs_implicit
|-CXXRecordDecl 0x5590cff47d30  col:15 implicit class 
Container
|-FriendDecl 0x5590cff48048  col:42
| `-FunctionTemplateDecl 0x5590cff47f80 parent 0x5590cfefeda8  col:42 m
|   |-TemplateTypeParmDecl 0x5590cff47dc0  col:27 class 
depth 1 index 0 U
|   `-FunctionDecl 0x5590cff47ec8 parent 0x5590cfefeda8  
col:42 m 'void ()'
`-FriendDecl 0x5590cff48260  col:42
  `-FunctionTemplateDecl 0x5590cff481f8 parent 0x5590cfefeda8  col:42 m
|-TemplateTypeParmDecl 0x5590cff48088  col:27 class 
depth 1 index 0 U
`-FunctionDecl 0x5590cff48140 parent 0x5590cfefeda8  
col:42 m 'void ()'

`ToTu`:

  ClassTemplateDecl 0x5590cffe3ad8  line:3:15 Container
  |-TemplateTypeParmDecl 0x5590cffe3950  col:25 class depth 
0 index 0 T
  `-CXXRecordDecl 0x5590cffe3a10  line:3:15 class Container 
definition
|-DefinitionData empty aggregate standard_layout trivially_copyable pod 
trivial literal has_constexpr_non_copy_move_ctor can_const_default_init
| |-DefaultConstructor exists trivial constexpr needs_implicit 
defaulted_is_constexpr
| |-CopyConstructor simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveConstructor exists simple trivial needs_implicit
| |-CopyAssignment simple trivial has_const_param needs_implicit 
implicit_has_const_param
| |-MoveAssignment exists simple trivial needs_implicit
| `-Destructor simple irrelevant trivial needs_implicit
|-FunctionTemplateDecl 0x5590cffe3ef8 parent 0x5590cff9b128  col:42 m // extranous node
| |-TemplateTypeParmDecl 0x5590cffe3d20  col:27 class depth 
1 index 0 U
| `-FunctionDecl 0x5590cffe3e28 parent 0x5590cff9b128  
col:42 m 'void ()'
|-FriendDecl 0x5590cffe3f60  col:42
| `-FunctionTemplateDecl 0x5590cffe3ef8 parent 0x5590cff9b128  col:42 m
|   |-TemplateTypeParmDecl 0x5590cffe3d20  col:27 class 
depth 1 index 0 U
|   `-FunctionDecl 0x5590cffe3e28 parent 0x5590cff9b128  
col:42 m 'void ()'
`-CXXRecordDecl 0x5590cffe3fa0  col:15 implicit class 
Container

Also note that an extranous `FunctionTemplateDecl 0x5590cffe3ef8` is added into 
this `ClassTemplateDecl 0x5590cffe3ad8` lexical context, which
renders it NOT identical to the original DeclContext, even after the second 
friend is successfully imported, this extra node would crash 
`clang-import-test`.
Plan to fix it in another revision.

2. Import single friend node `m` into existing context would crash with an 
assertion failure:

  ./build/tools/clang/unittests/AST/ASTTests 
--gtest_filter="*ImportFriendClasses.ImportOfRepeatedFriendFunctionTemplateDecl*"
 |& sed 's/danis/x/'
  Note: Google Test filter = 
*ImportFriendClasses.ImportOfRepeatedFriendFunctionTemplateDecl*
  [==] Running 4 tests from 1 test suite.
  [--] Global test environment set-up.
  [--] 4 tests from ParameterizedTests/ImportFriendClasses
  [ RUN  ] 
ParameterizedTests/ImportFriendClasses.ImportOfRepeatedFriendFunctionTemplateDecl/0
  ASTTests: 
/home/x/Sources/llvm-project-main/clang/lib/AST/ASTImporter.cpp:4139: 
clang::ExpectedDecl clang::ASTNodeImporter::VisitFriendDecl(clang::FriendDecl 
*): Assertion `ImportedEquivalentFriends.size() <= CountAndPosition.TotalCount 
&& "Class with non-matching friends is imported, ODR check wrong?"' failed.
   #0 0x7f1f53bf812a llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) 
/home/x/Sources/llvm-project-main/llvm/lib/Support/Unix/Signals.inc:602:11
   #1 0x7f1f53bf82db PrintStackTraceSignalHandler(void*) 

[PATCH] D157637: [ASTImporter][NFC] Fix typo in testcase

2023-08-10 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a reviewer: balazske.
Herald added a subscriber: martong.
Herald added a reviewer: a.sidorin.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Fix typo in testcase.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157637

Files:
  clang/unittests/AST/StructuralEquivalenceTest.cpp


Index: clang/unittests/AST/StructuralEquivalenceTest.cpp
===
--- clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -992,8 +992,8 @@
 
 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineTopLevel) {
   auto Decls =
-  makeNamedDecls("inline namespace A { class X; } }",
- "inline namespace B { class X; } }", Lang_CXX17, "X");
+  makeNamedDecls("inline namespace A { class X; }",
+ "inline namespace B { class X; }", Lang_CXX17, "X");
   EXPECT_TRUE(testStructuralMatch(Decls));
 }
 


Index: clang/unittests/AST/StructuralEquivalenceTest.cpp
===
--- clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -992,8 +992,8 @@
 
 TEST_F(StructuralEquivalenceRecordContextTest, NamespaceInlineTopLevel) {
   auto Decls =
-  makeNamedDecls("inline namespace A { class X; } }",
- "inline namespace B { class X; } }", Lang_CXX17, "X");
+  makeNamedDecls("inline namespace A { class X; }",
+ "inline namespace B { class X; }", Lang_CXX17, "X");
   EXPECT_TRUE(testStructuralMatch(Decls));
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157114: [clang][ASTImporter] Improve StructuralEquivalence algorithm on repeated friends

2023-08-10 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 549059.
danix800 added a comment.

`CXXRecordDecl::friend_iterator` is actually a reversed iterator. Deduplication 
with
different iterator direction produces different result. ASTImporter uses 
forward iterator
so structural equivalence checking should be in consistent with that.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157114/new/

https://reviews.llvm.org/D157114

Files:
  clang/lib/AST/ASTImporter.cpp
  clang/lib/AST/ASTStructuralEquivalence.cpp
  clang/unittests/AST/ASTImporterTest.cpp
  clang/unittests/AST/StructuralEquivalenceTest.cpp

Index: clang/unittests/AST/StructuralEquivalenceTest.cpp
===
--- clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -833,7 +833,18 @@
   auto t = makeNamedDecls("struct foo { friend class X; };",
   "struct foo { friend class X; friend class X; };",
   Lang_CXX11);
-  EXPECT_FALSE(testStructuralMatch(t));
+  EXPECT_TRUE(testStructuralMatch(t));
+}
+
+TEST_F(StructuralEquivalenceRecordTest,
+   SameFriendMultipleTimesForwardIteratorDirection) {
+  // Deduplication with forward iterator produces the same 'foo', but reverse
+  // iterator doesn't.
+  auto t = makeNamedDecls(
+  "struct foo { friend class X; friend class Y;};",
+  "struct foo { friend class X; friend class Y; friend class X; };",
+  Lang_CXX11);
+  EXPECT_TRUE(testStructuralMatch(t));
 }
 
 TEST_F(StructuralEquivalenceRecordTest, SameFriendsDifferentOrder) {
Index: clang/unittests/AST/ASTImporterTest.cpp
===
--- clang/unittests/AST/ASTImporterTest.cpp
+++ clang/unittests/AST/ASTImporterTest.cpp
@@ -10,6 +10,7 @@
 //
 //===--===//
 
+#include "clang/AST/ASTStructuralEquivalence.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "llvm/ADT/StringMap.h"
@@ -4385,6 +4386,44 @@
   EXPECT_EQ(ToFriend2, ToImportedFriend2);
 }
 
+TEST_P(ASTImporterOptionSpecificTestBase, ImportRepeatedFriendDeclIntoEmptyDC) {
+  Decl *From, *To;
+  std::tie(From, To) = getImportedDecl(R"(
+  template 
+  class A {
+  public:
+template  friend A ();
+template  friend A ();
+  };
+  )",
+   Lang_CXX17, "", Lang_CXX17, "A");
+
+  auto *FromFriend1 = FirstDeclMatcher().match(From, friendDecl());
+  auto *FromFriend2 = LastDeclMatcher().match(From, friendDecl());
+  auto *ToFriend1 = FirstDeclMatcher().match(To, friendDecl());
+  auto *ToFriend2 = LastDeclMatcher().match(To, friendDecl());
+
+  // Two different FriendDecls in From context.
+  EXPECT_TRUE(FromFriend1 != FromFriend2);
+  // Only one is imported into empty DC.
+  EXPECT_TRUE(ToFriend1 == ToFriend2);
+
+  // 'A' is imported into empty DC, keeping structure equivalence.
+  llvm::DenseSet> NonEquivalentDecls01;
+  llvm::DenseSet> NonEquivalentDecls10;
+  StructuralEquivalenceContext Ctx01(
+  From->getASTContext(), To->getASTContext(), NonEquivalentDecls01,
+  StructuralEquivalenceKind::Default, false, false);
+  StructuralEquivalenceContext Ctx10(
+  To->getASTContext(), From->getASTContext(), NonEquivalentDecls10,
+  StructuralEquivalenceKind::Default, false, false);
+
+  bool Eq01 = Ctx01.IsEquivalent(From, To);
+  bool Eq10 = Ctx10.IsEquivalent(To, From);
+  EXPECT_EQ(Eq01, Eq10);
+  EXPECT_TRUE(Eq01);
+}
+
 TEST_P(ASTImporterOptionSpecificTestBase, FriendFunInClassTemplate) {
   auto *Code = R"(
   template 
Index: clang/lib/AST/ASTStructuralEquivalence.cpp
===
--- clang/lib/AST/ASTStructuralEquivalence.cpp
+++ clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1464,6 +1464,165 @@
   return IsStructurallyEquivalent(GetName(D1), GetName(D2));
 }
 
+static bool
+IsCXXRecordBaseStructurallyEquivalent(StructuralEquivalenceContext ,
+  RecordDecl *D1, RecordDecl *D2) {
+  auto *D1CXX = cast(D1);
+  auto *D2CXX = cast(D2);
+
+  if (D1CXX->getNumBases() != D2CXX->getNumBases()) {
+if (Context.Complain) {
+  Context.Diag2(D2->getLocation(), Context.getApplicableDiagnostic(
+   diag::err_odr_tag_type_inconsistent))
+  << Context.ToCtx.getTypeDeclType(D2);
+  Context.Diag2(D2->getLocation(), diag::note_odr_number_of_bases)
+  << D2CXX->getNumBases();
+  Context.Diag1(D1->getLocation(), diag::note_odr_number_of_bases)
+  << D1CXX->getNumBases();
+}
+return false;
+  }
+
+  for (CXXRecordDecl::base_class_iterator Base1 = D1CXX->bases_begin(),
+  BaseEnd1 = D1CXX->bases_end(),
+  Base2 = 

[PATCH] D157584: [clang][Sema] Skip access check on arrays of zero-length element

2023-08-10 Thread Ding Fei via Phabricator via cfe-commits
danix800 created this revision.
danix800 added a project: clang.
Herald added a project: All.
danix800 requested review of this revision.
Herald added a subscriber: cfe-commits.

Bound check on array of zero-sized element isn't meaningful.

Fixes https://github.com/llvm/llvm-project/issues/64564


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157584

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaChecking.cpp
  clang/test/Sema/array-bounds-zero-length-elem-gh64564.c


Index: clang/test/Sema/array-bounds-zero-length-elem-gh64564.c
===
--- /dev/null
+++ clang/test/Sema/array-bounds-zero-length-elem-gh64564.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple i686-apple-darwin -verify %s
+
+int a[][0]; // expected-warning {{tentative array definition assumed to have 
one element}}
+void gh64564_1(void) {
+  int b = a[0x1][0];
+}
+
+typedef struct {} S;
+S s[]; // expected-warning {{tentative array definition assumed to have one 
element}}
+void gh64564_2(void) {
+  S t = s[0x1];
+}
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -17146,7 +17146,7 @@
   ASTC.getTypeSizeInCharsIfKnown(EffectiveType);
   // PR50741 - If EffectiveType has unknown size (e.g., if it's a void
   // pointer) bounds-checking isn't meaningful.
-  if (!ElemCharUnits)
+  if (!ElemCharUnits || ElemCharUnits->isZero())
 return;
   llvm::APInt ElemBytes(index.getBitWidth(), ElemCharUnits->getQuantity());
   // If index has more active bits than address space, we already know
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -181,6 +181,8 @@
   terminated. Clang should now also recover better when an @end is missing
   between blocks.
   `Issue 64065 `_
+- Fixed a crash when check array access on zero-length element.
+  `Issue 64564 `_
 
 Target Specific Changes
 ---


Index: clang/test/Sema/array-bounds-zero-length-elem-gh64564.c
===
--- /dev/null
+++ clang/test/Sema/array-bounds-zero-length-elem-gh64564.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple i686-apple-darwin -verify %s
+
+int a[][0]; // expected-warning {{tentative array definition assumed to have one element}}
+void gh64564_1(void) {
+  int b = a[0x1][0];
+}
+
+typedef struct {} S;
+S s[]; // expected-warning {{tentative array definition assumed to have one element}}
+void gh64564_2(void) {
+  S t = s[0x1];
+}
Index: clang/lib/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -17146,7 +17146,7 @@
   ASTC.getTypeSizeInCharsIfKnown(EffectiveType);
   // PR50741 - If EffectiveType has unknown size (e.g., if it's a void
   // pointer) bounds-checking isn't meaningful.
-  if (!ElemCharUnits)
+  if (!ElemCharUnits || ElemCharUnits->isZero())
 return;
   llvm::APInt ElemBytes(index.getBitWidth(), ElemCharUnits->getQuantity());
   // If index has more active bits than address space, we already know
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -181,6 +181,8 @@
   terminated. Clang should now also recover better when an @end is missing
   between blocks.
   `Issue 64065 `_
+- Fixed a crash when check array access on zero-length element.
+  `Issue 64564 `_
 
 Target Specific Changes
 ---
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157296: [AST][Coroutine] Fix CoyieldExpr missing end loc

2023-08-08 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

I'll finish this patch when CI build succeeds.

For future improvement I might start with the idea
of marking those generated inner exprs as implicit,
this seems to be easier.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157296/new/

https://reviews.llvm.org/D157296

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


[PATCH] D157296: [AST][Coroutine] Fix CoyieldExpr missing end loc

2023-08-08 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 548434.
danix800 edited the summary of this revision.
danix800 added a comment.

Cleanup duplicated boilerplate testcase code. Append a few extra child nodes of 
`CoyieldExpr` dumped in testcase.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157296/new/

https://reviews.llvm.org/D157296

Files:
  clang/lib/Sema/SemaCoroutine.cpp
  clang/test/AST/Inputs/std-coroutine.h
  clang/test/AST/coroutine-co_yield-source-range.cpp


Index: clang/test/AST/coroutine-co_yield-source-range.cpp
===
--- /dev/null
+++ clang/test/AST/coroutine-co_yield-source-range.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 \
+// RUN:-fsyntax-only -ast-dump | FileCheck %s
+
+#include "Inputs/std-coroutine.h"
+
+using namespace std;
+
+struct Chat {
+  struct promise_type {
+std::suspend_always initial_suspend() { return {}; }
+Chat get_return_object() {
+  return std::coroutine_handle::from_promise(*this);
+}
+std::suspend_always yield_value(int m) { return {}; }
+std::suspend_always final_suspend() noexcept { return {}; }
+std::suspend_always return_value(int) { return {}; }
+void unhandled_exception() {}
+
+auto await_transform(int s) {
+  struct awaiter {
+promise_type *promise;
+bool await_ready() { return true; }
+int await_resume() { return promise->message; }
+void await_suspend(std::coroutine_handle<>) {}
+  };
+
+  return awaiter{this};
+}
+int message;
+  };
+
+  Chat(std::coroutine_handle promise);
+
+  std::coroutine_handle handle;
+};
+
+Chat f(int s)  {
+  // CHECK:  CoyieldExpr {{.*}} 
+  // CHECK-NEXT:   CXXMemberCallExpr {{.*}}  {{.*}}
+  // CHECK-NEXT: MemberExpr {{.*}}  {{.*}}
+  // CHECK-NEXT:   DeclRefExpr {{.*}}  {{.*}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}}  {{.*}}
+  // CHECK-NEXT:   DeclRefExpr {{.*}}  {{.*}}
+  co_yield s;
+  // CHECK:  CoreturnStmt {{.*}} 
+  co_return s;
+  // CHECK:  CoawaitExpr {{.*}}  'int'
+  co_await s;
+}
Index: clang/test/AST/Inputs/std-coroutine.h
===
--- clang/test/AST/Inputs/std-coroutine.h
+++ clang/test/AST/Inputs/std-coroutine.h
@@ -55,9 +55,9 @@
 };
 
 struct suspend_always {
-  bool await_ready() { return false; }
-  void await_suspend(coroutine_handle<>) {}
-  void await_resume() {}
+  bool await_ready() noexcept { return false; }
+  void await_suspend(coroutine_handle<>) noexcept {}
+  void await_resume() noexcept {}
 };
 
 struct suspend_never {
Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -318,7 +318,8 @@
 return ExprError();
   }
 
-  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
+  auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
+  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
 }
 
 // See if return type is coroutine-handle and if so, invoke builtin coro-resume


Index: clang/test/AST/coroutine-co_yield-source-range.cpp
===
--- /dev/null
+++ clang/test/AST/coroutine-co_yield-source-range.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 \
+// RUN:-fsyntax-only -ast-dump | FileCheck %s
+
+#include "Inputs/std-coroutine.h"
+
+using namespace std;
+
+struct Chat {
+  struct promise_type {
+std::suspend_always initial_suspend() { return {}; }
+Chat get_return_object() {
+  return std::coroutine_handle::from_promise(*this);
+}
+std::suspend_always yield_value(int m) { return {}; }
+std::suspend_always final_suspend() noexcept { return {}; }
+std::suspend_always return_value(int) { return {}; }
+void unhandled_exception() {}
+
+auto await_transform(int s) {
+  struct awaiter {
+promise_type *promise;
+bool await_ready() { return true; }
+int await_resume() { return promise->message; }
+void await_suspend(std::coroutine_handle<>) {}
+  };
+
+  return awaiter{this};
+}
+int message;
+  };
+
+  Chat(std::coroutine_handle promise);
+
+  std::coroutine_handle handle;
+};
+
+Chat f(int s)  {
+  // CHECK:  CoyieldExpr {{.*}} 
+  // CHECK-NEXT:   CXXMemberCallExpr {{.*}}  {{.*}}
+  // CHECK-NEXT: MemberExpr {{.*}}  {{.*}}
+  // CHECK-NEXT:   DeclRefExpr {{.*}}  {{.*}}
+  // CHECK-NEXT: ImplicitCastExpr {{.*}}  {{.*}}
+  // CHECK-NEXT:   DeclRefExpr {{.*}}  {{.*}}
+  co_yield s;
+  // CHECK:  CoreturnStmt {{.*}} 
+  co_return s;
+  // CHECK:  CoawaitExpr {{.*}}  'int'
+  co_await s;
+}
Index: clang/test/AST/Inputs/std-coroutine.h
===
--- 

[PATCH] D157296: [AST][Coroutine] Fix CoyieldExpr missing end loc

2023-08-07 Thread Ding Fei via Phabricator via cfe-commits
danix800 added a comment.

1. Use invalid loc: `SourceLocation()`

  ExprWithCleanups 0x55d1067162c8  'void'
  `-CoyieldExpr 0x55d106716280  'void'
|-CXXMemberCallExpr 0x55d106715ed8  
'std::suspend_always':'std::suspend_always'
| |-MemberExpr 0x55d106715ea8  '' 
.yield_value 0x55d10670b220
| | `-DeclRefExpr 0x55d106715e88  'std::coroutine_traits::promise_type':'Chat::promise_type' lvalue Var 0x55d106714218 '__promise' 
'std::coroutine_traits::promise_type':'Chat::promise_type'
| `-ImplicitCastExpr 0x55d106715f00  'int' 
|   `-DeclRefExpr 0x55d1067118e8  'int' lvalue ParmVar 
0x55d1067116c0 'sss' 'int'
|-MaterializeTemporaryExpr 0x55d106715f58  
'std::suspend_always':'std::suspend_always' lvalue
| `-CXXMemberCallExpr 0x55d106715ed8  
'std::suspend_always':'std::suspend_always'
|   |-MemberExpr 0x55d106715ea8  '' 
.yield_value 0x55d10670b220
|   | `-DeclRefExpr 0x55d106715e88  'std::coroutine_traits::promise_type':'Chat::promise_type' lvalue Var 0x55d106714218 '__promise' 
'std::coroutine_traits::promise_type':'Chat::promise_type'
|   `-ImplicitCastExpr 0x55d106715f00  'int' 
| `-DeclRefExpr 0x55d1067118e8  'int' lvalue ParmVar 
0x55d1067116c0 'sss' 'int'
|-ExprWithCleanups 0x55d106715fd8 > 'bool'
| `-CXXMemberCallExpr 0x55d106715fb8 > 'bool'
|   `-MemberExpr 0x55d106715f88  '' 
.await_ready 0x55d106708858
| `-OpaqueValueExpr 0x55d106715f70  
'std::suspend_always':'std::suspend_always' lvalue
|   `-MaterializeTemporaryExpr 0x55d106715f58  
'std::suspend_always':'std::suspend_always' lvalue
| `-CXXMemberCallExpr 0x55d106715ed8  
'std::suspend_always':'std::suspend_always'
|   |-MemberExpr 0x55d106715ea8  '' .yield_value 0x55d10670b220
|   | `-DeclRefExpr 0x55d106715e88  
'std::coroutine_traits::promise_type':'Chat::promise_type' lvalue 
Var 0x55d106714218 '__promise' 'std::coroutine_traits::promise_type':'Chat::promise_type'
|   `-ImplicitCastExpr 0x55d106715f00  'int' 

| `-DeclRefExpr 0x55d1067118e8  'int' lvalue ParmVar 
0x55d1067116c0 'sss' 'int'
|-CXXMemberCallExpr 0x55d106716160  'void'
| |-MemberExpr 0x55d106716130  '' 
.await_suspend 0x55d106708ad8
| | `-OpaqueValueExpr 0x55d106715f70  
'std::suspend_always':'std::suspend_always' lvalue
| |   `-MaterializeTemporaryExpr 0x55d106715f58  
'std::suspend_always':'std::suspend_always' lvalue
| | `-CXXMemberCallExpr 0x55d106715ed8  
'std::suspend_always':'std::suspend_always'
| |   |-MemberExpr 0x55d106715ea8  '' .yield_value 0x55d10670b220
| |   | `-DeclRefExpr 0x55d106715e88  
'std::coroutine_traits::promise_type':'Chat::promise_type' lvalue 
Var 0x55d106714218 '__promise' 'std::coroutine_traits::promise_type':'Chat::promise_type'
| |   `-ImplicitCastExpr 0x55d106715f00  'int' 
| | `-DeclRefExpr 0x55d1067118e8  'int' lvalue ParmVar 
0x55d1067116c0 'sss' 'int'
| `-ImplicitCastExpr 0x55d106716218  
'coroutine_handle<>':'std::coroutine_handle' 
|   `-CXXConstructExpr 0x55d1067161e8  
'coroutine_handle<>':'std::coroutine_handle' 'void 
(coroutine_handle) noexcept'
| `-CallExpr 0x55d1067160d0  
'coroutine_handle':'std::coroutine_handle'
|   |-ImplicitCastExpr 0x55d1067160b8  
'coroutine_handle (*)(void *) noexcept' 
|   | `-DeclRefExpr 0x55d106716098  
'coroutine_handle (void *) noexcept' lvalue CXXMethod 
0x55d10670dd98 'from_address' 'coroutine_handle (void *) noexcept'
|   `-CallExpr 0x55d106716078  'void *'
| `-ImplicitCastExpr 0x55d106716060  'void *(*)() noexcept' 

|   `-DeclRefExpr 0x55d106716040  'void *() noexcept' lvalue 
Function 0x55d106714c88 '__builtin_coro_frame' 'void *() noexcept'
`-CXXMemberCallExpr 0x55d106716260 > 'void'
  `-MemberExpr 0x55d106716230  '' 
.await_resume 0x55d106708bf8
`-OpaqueValueExpr 0x55d106715f70  
'std::suspend_always':'std::suspend_always' lvalue
  `-MaterializeTemporaryExpr 0x55d106715f58  
'std::suspend_always':'std::suspend_always' lvalue
`-CXXMemberCallExpr 0x55d106715ed8  
'std::suspend_always':'std::suspend_always'
  |-MemberExpr 0x55d106715ea8  '' .yield_value 0x55d10670b220
  | `-DeclRefExpr 0x55d106715e88  
'std::coroutine_traits::promise_type':'Chat::promise_type' lvalue 
Var 0x55d106714218 '__promise' 'std::coroutine_traits::promise_type':'Chat::promise_type'
  `-ImplicitCastExpr 0x55d106715f00  'int' 
`-DeclRefExpr 0x55d1067118e8  'int' lvalue ParmVar 
0x55d1067116c0 'sss' 'int'

Note that `CXXMemberCallExpr 0x55d106716260 >` relies on 
`RParenLoc` directly. Coroutine is implemented as member call so I think 
`RParen` is intended and should exist and be correct.

2. Use last arg's end loc if exists:  `auto EndLoc = Args.empty() ? Loc : 
Args.back()->getEndLoc();`

  ExprWithCleanups 0x55dcfa09f2c8  'void'
  `-CoyieldExpr 0x55dcfa09f280  'void'

[PATCH] D157296: [AST][Coroutine] Fix CoyieldExpr missing end loc

2023-08-07 Thread Ding Fei via Phabricator via cfe-commits
danix800 updated this revision to Diff 547843.
danix800 added a comment.

Use `getEndLoc()` instead of `getBeginLoc()`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D157296/new/

https://reviews.llvm.org/D157296

Files:
  clang/lib/Sema/SemaCoroutine.cpp
  clang/test/AST/coroutine-co_yield-source-range.cpp


Index: clang/test/AST/coroutine-co_yield-source-range.cpp
===
--- /dev/null
+++ clang/test/AST/coroutine-co_yield-source-range.cpp
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 \
+// RUN:-fsyntax-only -ast-dump | FileCheck %s
+
+namespace std {
+template 
+struct coroutine_traits { using promise_type = typename Ret::promise_type; };
+
+template 
+struct coroutine_handle {
+  static coroutine_handle from_address(void *) noexcept;
+  static coroutine_handle from_promise(Promise );
+  constexpr void* address() const noexcept;
+};
+template <>
+struct coroutine_handle {
+  template 
+  coroutine_handle(coroutine_handle) noexcept;
+  static coroutine_handle from_address(void *);
+  constexpr void* address() const noexcept;
+};
+
+struct suspend_always {
+  bool await_ready() noexcept { return false; }
+  void await_suspend(coroutine_handle<>) noexcept {}
+  void await_resume() noexcept {}
+};
+
+struct suspend_never {
+  bool await_ready() noexcept { return true; }
+  void await_suspend(coroutine_handle<>) noexcept {}
+  void await_resume() noexcept {}
+};
+} // namespace std
+
+struct Chat {
+  struct promise_type {
+std::suspend_always initial_suspend() { return {}; }
+Chat get_return_object() {
+  return std::coroutine_handle::from_promise(*this);
+}
+std::suspend_always yield_value(int m) {
+  return {};
+}
+std::suspend_always final_suspend() noexcept { return {}; }
+std::suspend_always return_value(int) noexcept { return {}; }
+void unhandled_exception() noexcept {}
+
+auto await_transform(int s) noexcept {
+  struct awaiter {
+promise_type *promise;
+bool await_ready() const {
+  return true;
+}
+int await_resume() const {
+  return promise->message;
+}
+void await_suspend(std::coroutine_handle<>) {
+}
+  };
+  return awaiter{this};
+}
+int message;
+  };
+
+  Chat(std::coroutine_handle promise);
+
+  std::coroutine_handle handle;
+};
+
+Chat f(int s) {
+  // CHECK: CoyieldExpr {{.*}} 
+  co_yield s;
+  // CHECK: CoreturnStmt {{.*}} 
+  co_return s;
+  // CHECK: CoawaitExpr {{.*}} 
+  co_await s;
+}
Index: clang/lib/Sema/SemaCoroutine.cpp
===
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -318,7 +318,8 @@
 return ExprError();
   }
 
-  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, Loc, nullptr);
+  auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
+  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
 }
 
 // See if return type is coroutine-handle and if so, invoke builtin coro-resume


Index: clang/test/AST/coroutine-co_yield-source-range.cpp
===
--- /dev/null
+++ clang/test/AST/coroutine-co_yield-source-range.cpp
@@ -0,0 +1,77 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++20 \
+// RUN:-fsyntax-only -ast-dump | FileCheck %s
+
+namespace std {
+template 
+struct coroutine_traits { using promise_type = typename Ret::promise_type; };
+
+template 
+struct coroutine_handle {
+  static coroutine_handle from_address(void *) noexcept;
+  static coroutine_handle from_promise(Promise );
+  constexpr void* address() const noexcept;
+};
+template <>
+struct coroutine_handle {
+  template 
+  coroutine_handle(coroutine_handle) noexcept;
+  static coroutine_handle from_address(void *);
+  constexpr void* address() const noexcept;
+};
+
+struct suspend_always {
+  bool await_ready() noexcept { return false; }
+  void await_suspend(coroutine_handle<>) noexcept {}
+  void await_resume() noexcept {}
+};
+
+struct suspend_never {
+  bool await_ready() noexcept { return true; }
+  void await_suspend(coroutine_handle<>) noexcept {}
+  void await_resume() noexcept {}
+};
+} // namespace std
+
+struct Chat {
+  struct promise_type {
+std::suspend_always initial_suspend() { return {}; }
+Chat get_return_object() {
+  return std::coroutine_handle::from_promise(*this);
+}
+std::suspend_always yield_value(int m) {
+  return {};
+}
+std::suspend_always final_suspend() noexcept { return {}; }
+std::suspend_always return_value(int) noexcept { return {}; }
+void unhandled_exception() noexcept {}
+
+auto await_transform(int s) noexcept {
+  struct awaiter {
+promise_type *promise;
+bool await_ready() const {
+  return true;
+}
+int 

  1   2   >