[PATCH] D155858: Add a concept AST node.

2023-08-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a subscriber: aaron.ballman.
hokein added a comment.

adding @aaron.ballman, who might have opinion on this.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155858

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


[PATCH] D157434: [include-cleaner] Add a simple heuristic to handle token-pasting symbols.

2023-08-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang-tools-extra.

include-cleaner didn't report the usage of token-pasting symbols, as
these symbols are spelled in a "scratch space" file which is not a real
file, thus we have some false postives of unused includes for these
symbols (e.g. ABSL_FLAG).

This patch adds a simple heuristic to handle this case, we use the
expansion location as a "proxy" reference location, this should work
well on token-pasting formed from macro arguemtns.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D157434

Files:
  clang-tools-extra/include-cleaner/lib/Analysis.cpp
  clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -197,6 +197,31 @@
   Pair(Code.point("4"), UnorderedElementsAre(MainFile;
 }
 
+TEST_F(WalkUsedTest, TokenPasting) {
+  llvm::Annotations Code(R"cpp(
+#define DEFINE_FLAG(name) int FLAG_##name = 0;
+#define MY_FLAG(name) DEFINE_FLAG(MY_##name)
+
+#define PASTED_TOKEN X##2
+
+$1^DEFINE_FLAG(abc);
+$2^MY_FLAG(abc);
+
+int $3^TPASTED_TOKEN = 3;
+  )cpp");
+  Inputs.Code = Code.code();
+
+  TestAST AST(Inputs);
+  auto  = AST.sourceManager();
+  auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID()));
+
+  EXPECT_THAT(offsetToProviders(AST, SM),
+  UnorderedElementsAre(
+  Pair(Code.point("1"), UnorderedElementsAre(MainFile)),
+  Pair(Code.point("2"), UnorderedElementsAre(MainFile)),
+  Pair(Code.point("3"), UnorderedElementsAre(MainFile;
+}
+
 class AnalyzeTest : public testing::Test {
 protected:
   TestInputs Inputs;
Index: clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
===
--- clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
+++ clang-tools-extra/include-cleaner/lib/HTMLReport.cpp
@@ -519,6 +519,9 @@
   const auto& SM = Ctx.getSourceManager();
   for (Decl *Root : Roots)
 walkAST(*Root, [&](SourceLocation Loc, const NamedDecl , RefType T) {
+  if (SM.isWrittenInScratchSpace( SM.getSpellingLoc(Loc)))
+Loc = SM.getExpansionLoc(Loc);
+
   if(!SM.isWrittenInMainFile(SM.getSpellingLoc(Loc)))
 return;
   R.addRef(SymbolReference{D, Loc, T});
Index: clang-tools-extra/include-cleaner/lib/Analysis.cpp
===
--- clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -40,6 +40,15 @@
   tooling::stdlib::Recognizer Recognizer;
   for (auto *Root : ASTRoots) {
 walkAST(*Root, [&](SourceLocation Loc, NamedDecl , RefType RT) {
+  // If the symbol is spelled as a token paste, it spelling location points
+  // to  file which is not a real file. We fallback to use
+  // the expansion location, this herustic is based on the assumption that
+  // most of token pastings are formed with the macro arguement, and it can
+  // allow us to detect uses of symbol defined by the common macro like
+  // `ABSL_FLAG`.
+  if (SM.isWrittenInScratchSpace(SM.getSpellingLoc(Loc)))
+Loc = SM.getExpansionLoc(Loc);
+
   auto FID = SM.getFileID(SM.getSpellingLoc(Loc));
   if (FID != SM.getMainFileID() && FID != SM.getPreambleFileID())
 return;


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -197,6 +197,31 @@
   Pair(Code.point("4"), UnorderedElementsAre(MainFile;
 }
 
+TEST_F(WalkUsedTest, TokenPasting) {
+  llvm::Annotations Code(R"cpp(
+#define DEFINE_FLAG(name) int FLAG_##name = 0;
+#define MY_FLAG(name) DEFINE_FLAG(MY_##name)
+
+#define PASTED_TOKEN X##2
+
+$1^DEFINE_FLAG(abc);
+$2^MY_FLAG(abc);
+
+int $3^TPASTED_TOKEN = 3;
+  )cpp");
+  Inputs.Code = Code.code();
+
+  TestAST AST(Inputs);
+  auto  = AST.sourceManager();
+  auto MainFile = Header(SM.getFileEntryForID(SM.getMainFileID()));
+
+  EXPECT_THAT(offsetToProviders(AST, SM),
+  UnorderedElementsAre(
+  Pair(Code.point("1"), UnorderedElementsAre(MainFile)),
+  Pair(Code.point("2"), UnorderedElementsAre(MainFile)),
+  Pair(Code.point("3"), UnorderedElementsAre(MainFile;
+}
+
 class AnalyzeTest : public testing::Test {
 protected:
   TestInputs Inputs;
Index: 

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

2023-08-08 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/Sema/SemaCoroutine.cpp:322
+  auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
+  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
 }

aaron.ballman wrote:
> hokein wrote:
> > aaron.ballman wrote:
> > > hokein wrote:
> > > > Thanks for the fast fix.
> > > > 
> > > > Reading the source code here, I'm not sure this is a correct fix (and 
> > > > put the heuristic here). I assume the `Loc` points the the `co_yield` 
> > > > token here, passing the `Loc` to the `LParenLoc` and `RParenLoc` 
> > > > parameters seems wrong to me, there is no `(` and `)` written in the 
> > > > source code here (because the member call expression is an implicit 
> > > > generated node in the clang AST), we should pass an invalid source 
> > > > location (`SourceLocation()`).
> > > > 
> > > > The `CallExpr::getEndLoc()` has implemented similar 
> > > > [heuristic](https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/Expr.cpp#L1662-L1664)
> > > >  to handle the case where the RParenLoc is invalid.
> > > >  passing the Loc to the LParenLoc and RParenLoc parameters seems wrong 
> > > > to me
> > > 
> > > FWIW, I thought so as well, but I thought we have the same behavior for 
> > > `CoreturnExpr` and `CoawaitExpr`. These statements are not really call 
> > > expressions as far as the AST is concerned, so it's a bit hard to say 
> > > whether there is a right or wrong answer for where the l- and r-paren 
> > > locations are for the call.
> > Agree, the coroutine is a hard case. I was concerned about the 
> > `MemberCallExpr::getRParenLoc()` API, it returns a valid source location 
> > but the token it points to is not a `)`, this could lead to subtle bugs in 
> > tooling.
> > 
> > since this change is an improvement, I'm fine with the current change.
> > Agree, the coroutine is a hard case. I was concerned about the 
> > MemberCallExpr::getRParenLoc() API, it returns a valid source location but 
> > the token it points to is not a ), this could lead to subtle bugs in 
> > tooling.
> 
> Yeah, that was actually my concern as well -- I'm glad we're both on the same 
> page. :-)
> 
> I eventually convinced myself that folks are generally interested in the 
> right paren location because they want to know when the argument list is 
> complete, not because they specifically want the right paren token itself. 
> But the reason they want to do that is because they want to insert a 
> qualifier, a semi-colon, an attribute, etc (something that follows the 
> closing paren) and in all of those cases, they'll be surprised here. Perhaps 
> we should be marking this call expression as an implicit AST node so that 
> it's more clear to users "this wasn't from source, don't expect fix-its to be 
> a good idea?"
> I eventually convinced myself that folks are generally interested in the 
> right paren location because they want to know when the argument list is 
> complete, not because they specifically want the right paren token itself. 
> But the reason they want to do that is because they want to insert a 
> qualifier, a semi-colon, an attribute, etc (something that follows the 
> closing paren) and in all of those cases, they'll be surprised here.

Yes, exactly.

> Perhaps we should be marking this call expression as an implicit AST node so 
> that it's more clear to users "this wasn't from source, don't expect fix-its 
> to be a good idea?"

Possibly.  My understanding of this expression is that it represents the 
written `operand` of the `co_yield` expression to some degree (see 
https://github.com/llvm/llvm-project/blob/main/clang/include/clang/AST/RecursiveASTVisitor.h#L2901).
 If we marked it implicit, then there is no "visible" expression in the 
`CoyieldExpr`, which means the operand will not be visited.

Overall, it looks like the current AST node for `co_yield`, `co_await`, 
`co_await` expressions are mostly modeling the language semantics, thus they 
are complicated, I guess this is the reason why it feels hard to improve the 
support for the syntactic. Probably, we can borrow the idea from 
`InitListExpr`, there are two forms, one is for semantic, the other one is for 
syntactic, having these two split can make everything easier.



Repository:
  rG LLVM Github Monorepo

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 Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks for exploring all the options.

For case 1)

> 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.

Yeah, I think this is because we don't have argument, so the getEndLoc 
heuristic 
 
failed, and it returned the RParenLoc which is invalid. This could be fixed by 
adjusting the heuristic there (we fallback to getBeginLoc if the endLoc is 
invalid), but no sure whether it will has any side effect.

for case 2) and 3)

> Note that CXXMemberCallExpr 0x55dcfa09f260  cannot get end loc because 
> no arg exists (but covered by its base).



> This is better, but CXXMemberCallExpr 0x565000382160  'void' still 
> cannot get proper end loc, its base spans , arg also exists 
> but this arg is irrevelant.

Looks like the source range of the `MemberExpr` is not correct in both case 2) 
and 3), I guess this is the culprit, but I think it is a different bug in 
`MemberExpr::getEndLoc` .

  `-MemberExpr 0x55dcfa09f230  '' 
.await_resume 0x55dcfa091bf8
   `-OpaqueValueExpr 0x55dcfa09ef70  
'std::suspend_always':'std::suspend_always' lvalue




Comment at: clang/lib/Sema/SemaCoroutine.cpp:322
+  auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
+  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
 }

aaron.ballman wrote:
> hokein wrote:
> > Thanks for the fast fix.
> > 
> > Reading the source code here, I'm not sure this is a correct fix (and put 
> > the heuristic here). I assume the `Loc` points the the `co_yield` token 
> > here, passing the `Loc` to the `LParenLoc` and `RParenLoc` parameters seems 
> > wrong to me, there is no `(` and `)` written in the source code here 
> > (because the member call expression is an implicit generated node in the 
> > clang AST), we should pass an invalid source location (`SourceLocation()`).
> > 
> > The `CallExpr::getEndLoc()` has implemented similar 
> > [heuristic](https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/Expr.cpp#L1662-L1664)
> >  to handle the case where the RParenLoc is invalid.
> >  passing the Loc to the LParenLoc and RParenLoc parameters seems wrong to me
> 
> FWIW, I thought so as well, but I thought we have the same behavior for 
> `CoreturnExpr` and `CoawaitExpr`. These statements are not really call 
> expressions as far as the AST is concerned, so it's a bit hard to say whether 
> there is a right or wrong answer for where the l- and r-paren locations are 
> for the call.
Agree, the coroutine is a hard case. I was concerned about the 
`MemberCallExpr::getRParenLoc()` API, it returns a valid source location but 
the token it points to is not a `)`, this could lead to subtle bugs in tooling.

since this change is an improvement, I'm fine with the current change.



Comment at: clang/test/AST/coroutine-co_yield-source-range.cpp:4
+
+namespace std {
+template 

nit: use the `test/AST/Inputs/std-coroutine.h` header to avoid repeating the 
boilerplate code. 


Repository:
  rG LLVM Github Monorepo

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-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/Sema/SemaCoroutine.cpp:322
+  auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();
+  return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);
 }

Thanks for the fast fix.

Reading the source code here, I'm not sure this is a correct fix (and put the 
heuristic here). I assume the `Loc` points the the `co_yield` token here, 
passing the `Loc` to the `LParenLoc` and `RParenLoc` parameters seems wrong to 
me, there is no `(` and `)` written in the source code here (because the member 
call expression is an implicit generated node in the clang AST), we should pass 
an invalid source location (`SourceLocation()`).

The `CallExpr::getEndLoc()` has implemented similar 
[heuristic](https://github.com/llvm/llvm-project/blob/main/clang/lib/AST/Expr.cpp#L1662-L1664)
 to handle the case where the RParenLoc is invalid.


Repository:
  rG LLVM Github Monorepo

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] D157195: [Clang] Fix the do while statement disappearing in AST when an error occurs in the conditional expression of the do while statement

2023-08-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

thanks, looks good.




Comment at: clang/test/SemaCXX/constexpr-function-recovery-crash.cpp:81
 
+constexpr int test13() { do {} while (a < 10); return 0; }   // expected-error 
{{use of undeclared identifier}}
+static_assert(test13());  // expected-error {{static assertion expression is 
not an integral constant expression}}

nit: it is better to use the below `TEST_EVALUATE` macro for the test, 
`TEST_EVALUATE(DoWhile2, do {} while (undefined < 10); )`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157195

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


[PATCH] D156650: [clangd] Respect IWYU keep pragma for standard headers.

2023-07-31 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D156650#4545867 , @kadircet wrote:

> also we should get this cherry-picked too. `keep` pragmas on includes are not 
> common, but people do have export pragmas often enough to cause some 
> annoyance here.

Filed https://github.com/llvm/llvm-project/issues/64260.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156650

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


[PATCH] D156648: [Tooling/Inclusion] Add std::range symbols in the mapping.

2023-07-31 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D156648#4545863 , @kadircet wrote:

> can you also create a cherry-pick request for this patch once it lands?

Filed https://github.com/llvm/llvm-project/issues/64261.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156648

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


[PATCH] D156650: [clangd] Respect IWYU keep pragma for standard headers.

2023-07-31 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGdcb28244faa8: [clangd] Respect IWYU keep pragma for standard 
headers. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156650

Files:
  clang-tools-extra/clangd/IncludeCleaner.cpp
  clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp


Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -78,6 +78,8 @@
   auto TU = TestTU::withCode(R"cpp(
 #include 
 #include 
+#include  // IWYU pragma: keep
+#include  // IWYU pragma: export
 std::list x;
   )cpp");
   // Layout of std library impl is not relevant.
@@ -86,10 +88,13 @@
 namespace std {
   template  class list {};
   template  class queue {};
+  template  class vector {};
 }
   )cpp";
   TU.AdditionalFiles["list"] = "#include ";
   TU.AdditionalFiles["queue"] = "#include ";
+  TU.AdditionalFiles["vector"] = "#include ";
+  TU.AdditionalFiles["string"] = "#include ";
   TU.ExtraArgs = {"-isystem", testRoot()};
   auto AST = TU.build();
   IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST);
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -71,6 +71,8 @@
 bool mayConsiderUnused(
 const Inclusion , ParsedAST ,
 const include_cleaner::PragmaIncludes *PI) {
+  if (PI && PI->shouldKeep(Inc.HashLine + 1))
+  return false;
   // FIXME(kirillbobyrev): We currently do not support the umbrella headers.
   // System headers are likely to be standard library headers.
   // Until we have good support for umbrella headers, don't warn about them.
@@ -82,8 +84,6 @@
   AST.getIncludeStructure().getRealPath(HID));
   assert(FE);
   if (PI) {
-if (PI->shouldKeep(Inc.HashLine + 1))
-  return false;
 // Check if main file is the public interface for a private header. If so 
we
 // shouldn't diagnose it as unused.
 if (auto PHeader = PI->getPublic(*FE); !PHeader.empty()) {


Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -78,6 +78,8 @@
   auto TU = TestTU::withCode(R"cpp(
 #include 
 #include 
+#include  // IWYU pragma: keep
+#include  // IWYU pragma: export
 std::list x;
   )cpp");
   // Layout of std library impl is not relevant.
@@ -86,10 +88,13 @@
 namespace std {
   template  class list {};
   template  class queue {};
+  template  class vector {};
 }
   )cpp";
   TU.AdditionalFiles["list"] = "#include ";
   TU.AdditionalFiles["queue"] = "#include ";
+  TU.AdditionalFiles["vector"] = "#include ";
+  TU.AdditionalFiles["string"] = "#include ";
   TU.ExtraArgs = {"-isystem", testRoot()};
   auto AST = TU.build();
   IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST);
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -71,6 +71,8 @@
 bool mayConsiderUnused(
 const Inclusion , ParsedAST ,
 const include_cleaner::PragmaIncludes *PI) {
+  if (PI && PI->shouldKeep(Inc.HashLine + 1))
+  return false;
   // FIXME(kirillbobyrev): We currently do not support the umbrella headers.
   // System headers are likely to be standard library headers.
   // Until we have good support for umbrella headers, don't warn about them.
@@ -82,8 +84,6 @@
   AST.getIncludeStructure().getRealPath(HID));
   assert(FE);
   if (PI) {
-if (PI->shouldKeep(Inc.HashLine + 1))
-  return false;
 // Check if main file is the public interface for a private header. If so we
 // shouldn't diagnose it as unused.
 if (auto PHeader = PI->getPublic(*FE); !PHeader.empty()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156650: [clangd] Respect IWYU keep pragma for standard headers.

2023-07-31 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 545589.
hokein marked an inline comment as done.
hokein added a comment.

address review comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156650

Files:
  clang-tools-extra/clangd/IncludeCleaner.cpp
  clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp


Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -78,6 +78,8 @@
   auto TU = TestTU::withCode(R"cpp(
 #include 
 #include 
+#include  // IWYU pragma: keep
+#include  // IWYU pragma: export
 std::list x;
   )cpp");
   // Layout of std library impl is not relevant.
@@ -86,10 +88,13 @@
 namespace std {
   template  class list {};
   template  class queue {};
+  template  class vector {};
 }
   )cpp";
   TU.AdditionalFiles["list"] = "#include ";
   TU.AdditionalFiles["queue"] = "#include ";
+  TU.AdditionalFiles["vector"] = "#include ";
+  TU.AdditionalFiles["string"] = "#include ";
   TU.ExtraArgs = {"-isystem", testRoot()};
   auto AST = TU.build();
   IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST);
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -71,6 +71,8 @@
 bool mayConsiderUnused(
 const Inclusion , ParsedAST ,
 const include_cleaner::PragmaIncludes *PI) {
+  if (PI && PI->shouldKeep(Inc.HashLine + 1))
+  return false;
   // FIXME(kirillbobyrev): We currently do not support the umbrella headers.
   // System headers are likely to be standard library headers.
   // Until we have good support for umbrella headers, don't warn about them.
@@ -82,8 +84,6 @@
   AST.getIncludeStructure().getRealPath(HID));
   assert(FE);
   if (PI) {
-if (PI->shouldKeep(Inc.HashLine + 1))
-  return false;
 // Check if main file is the public interface for a private header. If so 
we
 // shouldn't diagnose it as unused.
 if (auto PHeader = PI->getPublic(*FE); !PHeader.empty()) {


Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -78,6 +78,8 @@
   auto TU = TestTU::withCode(R"cpp(
 #include 
 #include 
+#include  // IWYU pragma: keep
+#include  // IWYU pragma: export
 std::list x;
   )cpp");
   // Layout of std library impl is not relevant.
@@ -86,10 +88,13 @@
 namespace std {
   template  class list {};
   template  class queue {};
+  template  class vector {};
 }
   )cpp";
   TU.AdditionalFiles["list"] = "#include ";
   TU.AdditionalFiles["queue"] = "#include ";
+  TU.AdditionalFiles["vector"] = "#include ";
+  TU.AdditionalFiles["string"] = "#include ";
   TU.ExtraArgs = {"-isystem", testRoot()};
   auto AST = TU.build();
   IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST);
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -71,6 +71,8 @@
 bool mayConsiderUnused(
 const Inclusion , ParsedAST ,
 const include_cleaner::PragmaIncludes *PI) {
+  if (PI && PI->shouldKeep(Inc.HashLine + 1))
+  return false;
   // FIXME(kirillbobyrev): We currently do not support the umbrella headers.
   // System headers are likely to be standard library headers.
   // Until we have good support for umbrella headers, don't warn about them.
@@ -82,8 +84,6 @@
   AST.getIncludeStructure().getRealPath(HID));
   assert(FE);
   if (PI) {
-if (PI->shouldKeep(Inc.HashLine + 1))
-  return false;
 // Check if main file is the public interface for a private header. If so we
 // shouldn't diagnose it as unused.
 if (auto PHeader = PI->getPublic(*FE); !PHeader.empty()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156648: [Tooling/Inclusion] Add std::range symbols in the mapping.

2023-07-31 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG171868dc2cd6: [Tooling/Inclusion] Add std::range symbols in 
the mapping. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156648

Files:
  clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
  clang/tools/include-mapping/gen_std.py


Index: clang/tools/include-mapping/gen_std.py
===
--- clang/tools/include-mapping/gen_std.py
+++ clang/tools/include-mapping/gen_std.py
@@ -242,6 +242,11 @@
 (symbol_index_root, "filesystem.html", "std::filesystem::"),
 (symbol_index_root, "pmr.html", "std::pmr::"),
 (symbol_index_root, "ranges.html", "std::ranges::"),
+
+(symbol_index_root, "views.html", "std::ranges::views::"),
+# std::ranges::views can be accessed as std::views.
+(symbol_index_root, "views.html", "std::views::"),
+
 (symbol_index_root, "regex_constants.html", 
"std::regex_constants::"),
 (symbol_index_root, "this_thread.html", "std::this_thread::"),
 # Zombie symbols that were available from the Standard Library, 
but are
Index: clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
===
--- clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
+++ clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
@@ -3773,6 +3773,33 @@
 SYMBOL(wistream_view, std::ranges::, )
 SYMBOL(zip_transform_view, std::ranges::, )
 SYMBOL(zip_view, std::ranges::, )
+SYMBOL(all, std::ranges::views::, )
+SYMBOL(all_t, std::ranges::views::, )
+SYMBOL(as_const, std::ranges::views::, )
+SYMBOL(as_rvalue, std::ranges::views::, )
+SYMBOL(common, std::ranges::views::, )
+SYMBOL(counted, std::ranges::views::, )
+SYMBOL(drop, std::ranges::views::, )
+SYMBOL(drop_while, std::ranges::views::, )
+SYMBOL(elements, std::ranges::views::, )
+SYMBOL(empty, std::ranges::views::, )
+SYMBOL(filter, std::ranges::views::, )
+SYMBOL(iota, std::ranges::views::, )
+SYMBOL(istream, std::ranges::views::, )
+SYMBOL(istream, std::ranges::views::, )
+SYMBOL(join, std::ranges::views::, )
+SYMBOL(join_with, std::ranges::views::, )
+SYMBOL(keys, std::ranges::views::, )
+SYMBOL(lazy_split, std::ranges::views::, )
+SYMBOL(reverse, std::ranges::views::, )
+SYMBOL(single, std::ranges::views::, )
+SYMBOL(split, std::ranges::views::, )
+SYMBOL(take, std::ranges::views::, )
+SYMBOL(take_while, std::ranges::views::, )
+SYMBOL(transform, std::ranges::views::, )
+SYMBOL(values, std::ranges::views::, )
+SYMBOL(zip, std::ranges::views::, )
+SYMBOL(zip_transform, std::ranges::views::, )
 SYMBOL(ECMAScript, std::regex_constants::, )
 SYMBOL(awk, std::regex_constants::, )
 SYMBOL(basic, std::regex_constants::, )
@@ -3817,3 +3844,30 @@
 SYMBOL(sleep_for, std::this_thread::, )
 SYMBOL(sleep_until, std::this_thread::, )
 SYMBOL(yield, std::this_thread::, )
+SYMBOL(all, std::views::, )
+SYMBOL(all_t, std::views::, )
+SYMBOL(as_const, std::views::, )
+SYMBOL(as_rvalue, std::views::, )
+SYMBOL(common, std::views::, )
+SYMBOL(counted, std::views::, )
+SYMBOL(drop, std::views::, )
+SYMBOL(drop_while, std::views::, )
+SYMBOL(elements, std::views::, )
+SYMBOL(empty, std::views::, )
+SYMBOL(filter, std::views::, )
+SYMBOL(iota, std::views::, )
+SYMBOL(istream, std::views::, )
+SYMBOL(istream, std::views::, )
+SYMBOL(join, std::views::, )
+SYMBOL(join_with, std::views::, )
+SYMBOL(keys, std::views::, )
+SYMBOL(lazy_split, std::views::, )
+SYMBOL(reverse, std::views::, )
+SYMBOL(single, std::views::, )
+SYMBOL(split, std::views::, )
+SYMBOL(take, std::views::, )
+SYMBOL(take_while, std::views::, )
+SYMBOL(transform, std::views::, )
+SYMBOL(values, std::views::, )
+SYMBOL(zip, std::views::, )
+SYMBOL(zip_transform, std::views::, )


Index: clang/tools/include-mapping/gen_std.py
===
--- clang/tools/include-mapping/gen_std.py
+++ clang/tools/include-mapping/gen_std.py
@@ -242,6 +242,11 @@
 (symbol_index_root, "filesystem.html", "std::filesystem::"),
 (symbol_index_root, "pmr.html", "std::pmr::"),
 (symbol_index_root, "ranges.html", "std::ranges::"),
+
+(symbol_index_root, "views.html", "std::ranges::views::"),
+# std::ranges::views can be accessed as std::views.
+(symbol_index_root, "views.html", "std::views::"),
+
 (symbol_index_root, "regex_constants.html", "std::regex_constants::"),
 (symbol_index_root, "this_thread.html", "std::this_thread::"),
 # Zombie symbols that were available from the Standard Library, but are
Index: clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
===

[PATCH] D156650: [clangd] Respect IWYU keep pragma for standard headers.

2023-07-31 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

see the issue https://github.com/llvm/llvm-project/issues/64191


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156650

Files:
  clang-tools-extra/clangd/IncludeCleaner.cpp
  clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp


Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -76,6 +76,8 @@
   auto TU = TestTU::withCode(R"cpp(
 #include 
 #include 
+#include  // IWYU pragma: keep
+#include  // IWYU pragma: export
 std::list x;
   )cpp");
   // Layout of std library impl is not relevant.
@@ -84,10 +86,13 @@
 namespace std {
   template  class list {};
   template  class queue {};
+  template  class vector {};
 }
   )cpp";
   TU.AdditionalFiles["list"] = "#include ";
   TU.AdditionalFiles["queue"] = "#include ";
+  TU.AdditionalFiles["vector"] = "#include ";
+  TU.AdditionalFiles["string"] = "#include ";
   TU.ExtraArgs = {"-isystem", testRoot()};
   auto AST = TU.build();
   IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST);
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -74,7 +74,8 @@
   // System headers are likely to be standard library headers.
   // Until we have good support for umbrella headers, don't warn about them.
   if (Inc.Written.front() == '<')
-return tooling::stdlib::Header::named(Inc.Written).has_value();
+return tooling::stdlib::Header::named(Inc.Written).has_value() &&
+   !(PI && PI->shouldKeep(Inc.HashLine + 1));
   assert(Inc.HeaderID);
   auto HID = static_cast(*Inc.HeaderID);
   auto FE = AST.getSourceManager().getFileManager().getFileRef(


Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -76,6 +76,8 @@
   auto TU = TestTU::withCode(R"cpp(
 #include 
 #include 
+#include  // IWYU pragma: keep
+#include  // IWYU pragma: export
 std::list x;
   )cpp");
   // Layout of std library impl is not relevant.
@@ -84,10 +86,13 @@
 namespace std {
   template  class list {};
   template  class queue {};
+  template  class vector {};
 }
   )cpp";
   TU.AdditionalFiles["list"] = "#include ";
   TU.AdditionalFiles["queue"] = "#include ";
+  TU.AdditionalFiles["vector"] = "#include ";
+  TU.AdditionalFiles["string"] = "#include ";
   TU.ExtraArgs = {"-isystem", testRoot()};
   auto AST = TU.build();
   IncludeCleanerFindings Findings = computeIncludeCleanerFindings(AST);
Index: clang-tools-extra/clangd/IncludeCleaner.cpp
===
--- clang-tools-extra/clangd/IncludeCleaner.cpp
+++ clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -74,7 +74,8 @@
   // System headers are likely to be standard library headers.
   // Until we have good support for umbrella headers, don't warn about them.
   if (Inc.Written.front() == '<')
-return tooling::stdlib::Header::named(Inc.Written).has_value();
+return tooling::stdlib::Header::named(Inc.Written).has_value() &&
+   !(PI && PI->shouldKeep(Inc.HashLine + 1));
   assert(Inc.HeaderID);
   auto HID = static_cast(*Inc.HeaderID);
   auto FE = AST.getSourceManager().getFileManager().getFileRef(
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156648: [Tooling/Inclusion] Add std::range symbols in the mapping.

2023-07-31 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156648

Files:
  clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
  clang/tools/include-mapping/gen_std.py


Index: clang/tools/include-mapping/gen_std.py
===
--- clang/tools/include-mapping/gen_std.py
+++ clang/tools/include-mapping/gen_std.py
@@ -242,6 +242,11 @@
 (symbol_index_root, "filesystem.html", "std::filesystem::"),
 (symbol_index_root, "pmr.html", "std::pmr::"),
 (symbol_index_root, "ranges.html", "std::ranges::"),
+
+(symbol_index_root, "views.html", "std::ranges::views::"),
+# std::ranges::views can be accessed as std::views.
+(symbol_index_root, "views.html", "std::views::"),
+
 (symbol_index_root, "regex_constants.html", 
"std::regex_constants::"),
 (symbol_index_root, "this_thread.html", "std::this_thread::"),
 # Zombie symbols that were available from the Standard Library, 
but are
Index: clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
===
--- clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
+++ clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
@@ -3773,6 +3773,33 @@
 SYMBOL(wistream_view, std::ranges::, )
 SYMBOL(zip_transform_view, std::ranges::, )
 SYMBOL(zip_view, std::ranges::, )
+SYMBOL(all, std::ranges::views::, )
+SYMBOL(all_t, std::ranges::views::, )
+SYMBOL(as_const, std::ranges::views::, )
+SYMBOL(as_rvalue, std::ranges::views::, )
+SYMBOL(common, std::ranges::views::, )
+SYMBOL(counted, std::ranges::views::, )
+SYMBOL(drop, std::ranges::views::, )
+SYMBOL(drop_while, std::ranges::views::, )
+SYMBOL(elements, std::ranges::views::, )
+SYMBOL(empty, std::ranges::views::, )
+SYMBOL(filter, std::ranges::views::, )
+SYMBOL(iota, std::ranges::views::, )
+SYMBOL(istream, std::ranges::views::, )
+SYMBOL(istream, std::ranges::views::, )
+SYMBOL(join, std::ranges::views::, )
+SYMBOL(join_with, std::ranges::views::, )
+SYMBOL(keys, std::ranges::views::, )
+SYMBOL(lazy_split, std::ranges::views::, )
+SYMBOL(reverse, std::ranges::views::, )
+SYMBOL(single, std::ranges::views::, )
+SYMBOL(split, std::ranges::views::, )
+SYMBOL(take, std::ranges::views::, )
+SYMBOL(take_while, std::ranges::views::, )
+SYMBOL(transform, std::ranges::views::, )
+SYMBOL(values, std::ranges::views::, )
+SYMBOL(zip, std::ranges::views::, )
+SYMBOL(zip_transform, std::ranges::views::, )
 SYMBOL(ECMAScript, std::regex_constants::, )
 SYMBOL(awk, std::regex_constants::, )
 SYMBOL(basic, std::regex_constants::, )
@@ -3817,3 +3844,30 @@
 SYMBOL(sleep_for, std::this_thread::, )
 SYMBOL(sleep_until, std::this_thread::, )
 SYMBOL(yield, std::this_thread::, )
+SYMBOL(all, std::views::, )
+SYMBOL(all_t, std::views::, )
+SYMBOL(as_const, std::views::, )
+SYMBOL(as_rvalue, std::views::, )
+SYMBOL(common, std::views::, )
+SYMBOL(counted, std::views::, )
+SYMBOL(drop, std::views::, )
+SYMBOL(drop_while, std::views::, )
+SYMBOL(elements, std::views::, )
+SYMBOL(empty, std::views::, )
+SYMBOL(filter, std::views::, )
+SYMBOL(iota, std::views::, )
+SYMBOL(istream, std::views::, )
+SYMBOL(istream, std::views::, )
+SYMBOL(join, std::views::, )
+SYMBOL(join_with, std::views::, )
+SYMBOL(keys, std::views::, )
+SYMBOL(lazy_split, std::views::, )
+SYMBOL(reverse, std::views::, )
+SYMBOL(single, std::views::, )
+SYMBOL(split, std::views::, )
+SYMBOL(take, std::views::, )
+SYMBOL(take_while, std::views::, )
+SYMBOL(transform, std::views::, )
+SYMBOL(values, std::views::, )
+SYMBOL(zip, std::views::, )
+SYMBOL(zip_transform, std::views::, )


Index: clang/tools/include-mapping/gen_std.py
===
--- clang/tools/include-mapping/gen_std.py
+++ clang/tools/include-mapping/gen_std.py
@@ -242,6 +242,11 @@
 (symbol_index_root, "filesystem.html", "std::filesystem::"),
 (symbol_index_root, "pmr.html", "std::pmr::"),
 (symbol_index_root, "ranges.html", "std::ranges::"),
+
+(symbol_index_root, "views.html", "std::ranges::views::"),
+# std::ranges::views can be accessed as std::views.
+(symbol_index_root, "views.html", "std::views::"),
+
 (symbol_index_root, "regex_constants.html", "std::regex_constants::"),
 (symbol_index_root, "this_thread.html", "std::this_thread::"),
 # Zombie symbols that were available from the Standard Library, but are
Index: clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
===
--- clang/lib/Tooling/Inclusions/Stdlib/StdSymbolMap.inc
+++ 

[PATCH] D155816: [Tooling/Inclusion] Make the Recognizer work for C99 code.

2023-07-25 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe93cbd18c112: [Tooling/Inclusion] Make the Recognizer work 
for C99 code. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155816

Files:
  clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
  clang/unittests/Tooling/StandardLibraryTest.cpp


Index: clang/unittests/Tooling/StandardLibraryTest.cpp
===
--- clang/unittests/Tooling/StandardLibraryTest.cpp
+++ clang/unittests/Tooling/StandardLibraryTest.cpp
@@ -174,6 +174,17 @@
   EXPECT_EQ(Recognizer(Sec), std::nullopt);
 }
 
+TEST(StdlibTest, RecognizerForC99) {
+  TestInputs Input("typedef char uint8_t;");
+  Input.Language = TestLanguage::Lang_C99;
+  TestAST AST(Input);
+
+  auto  = lookup(AST, "uint8_t");
+  stdlib::Recognizer Recognizer;
+  EXPECT_EQ(Recognizer(),
+stdlib::Symbol::named("", "uint8_t", stdlib::Lang::C));
+}
+
 } // namespace
 } // namespace tooling
 } // namespace clang
Index: clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
===
--- clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -247,13 +247,12 @@
 
 std::optional Recognizer::operator()(const Decl *D) {
   Lang L;
-  if (D->getLangOpts().CPlusPlus) {
+  if (D->getLangOpts().CPlusPlus)
 L = Lang::CXX;
-  } else if (D->getLangOpts().C11) {
+  else if (D->getLangOpts().C99)
 L = Lang::C;
-  } else {
+  else
 return std::nullopt; // not a supported language.
-  }
 
   // If D is std::vector::iterator, `vector` is the outer symbol to look up.
   // We keep all the candidate DCs as some may turn out to be anon enums.


Index: clang/unittests/Tooling/StandardLibraryTest.cpp
===
--- clang/unittests/Tooling/StandardLibraryTest.cpp
+++ clang/unittests/Tooling/StandardLibraryTest.cpp
@@ -174,6 +174,17 @@
   EXPECT_EQ(Recognizer(Sec), std::nullopt);
 }
 
+TEST(StdlibTest, RecognizerForC99) {
+  TestInputs Input("typedef char uint8_t;");
+  Input.Language = TestLanguage::Lang_C99;
+  TestAST AST(Input);
+
+  auto  = lookup(AST, "uint8_t");
+  stdlib::Recognizer Recognizer;
+  EXPECT_EQ(Recognizer(),
+stdlib::Symbol::named("", "uint8_t", stdlib::Lang::C));
+}
+
 } // namespace
 } // namespace tooling
 } // namespace clang
Index: clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
===
--- clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -247,13 +247,12 @@
 
 std::optional Recognizer::operator()(const Decl *D) {
   Lang L;
-  if (D->getLangOpts().CPlusPlus) {
+  if (D->getLangOpts().CPlusPlus)
 L = Lang::CXX;
-  } else if (D->getLangOpts().C11) {
+  else if (D->getLangOpts().C99)
 L = Lang::C;
-  } else {
+  else
 return std::nullopt; // not a supported language.
-  }
 
   // If D is std::vector::iterator, `vector` is the outer symbol to look up.
   // We keep all the candidate DCs as some may turn out to be anon enums.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155984: [Sema][ObjC] Invalidate BlockDecl with invalid ParmVarDecl

2023-07-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

thanks, the fix looks reasonable to me




Comment at: clang/test/AST/ast-dump-recovery.m:22
+// CHECK-NEXT:   `-BlockDecl {{.*}} invalid
+int (^a)(int, int) = ^(int, undefine b) {
+   return 1;

nit: a => `gh64005`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155984

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


[PATCH] D155985: [clang][ASTDumper] Remove redundant dump of BlockDecl's ParmVarDecl

2023-07-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

thanks for the fix.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155985

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


[PATCH] D155396: [Sema][ObjC] Invalidate BlockDecl with invalid return expr & its parent BlockExpr

2023-07-24 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

thanks, looks good to me.




Comment at: clang/test/AST/ast-dump-recovery.m:24
+// CHECK-NEXT: | `-BlockDecl {{.*}} invalid
+int (^a)() = ^() {
+  return c;

nit: it'd be nice to encode the github issue number to the testcase here, for 
example (renaming the `a` to `gh63863` etc).



Comment at: clang/test/AST/ast-dump-recovery.m:25
+int (^a)() = ^() {
+  return c;
+};

nit: use a more descriptive name `return undef;`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155396

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


[PATCH] D155396: [Sema][ObjC] Propagating value-dependent errors into BlockExpr

2023-07-21 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

thanks!




Comment at: clang/lib/Sema/SemaStmt.cpp:3736
+BlockDecl *BD = CurBlock->TheDecl;
+if (!BD->isInvalidDecl() && RetValExp && RetValExp->containsErrors())
+  BD->setInvalidDecl();

nit: the `isInvalidDecl` check is not need, we can inline the `RetValExpr` to 
the above if as well.

```
if (auto *CurBlock = dyn_cast(CurCap); CurBlock && 
CurCap->HasImplicitReturnType && RetValExp && RetValExp->containsErrors()) 
  CurBlock->TheDecl->setInvalidDecl();
```



Comment at: clang/test/SemaObjC/crash-on-val-dep-block-expr.m:1
+// RUN: %clang_cc1 -fblocks -fsyntax-only -verify %s
+// no crash

can you move these tests to `llvm-project/clang/test/AST/ast-dump-recovery.c`?


Repository:
  rZORG LLVM Github Zorg

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

https://reviews.llvm.org/D155396

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


[PATCH] D154471: [clang] Add serialization support for the DynamicAllocLValue variant of APValue::LValueBase::Ptr

2023-07-21 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

Thanks, looks good to me.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154471

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


[PATCH] D155421: [clangd] Add BlockEnd comments for control flow statements

2023-07-21 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

Thanks, this looks like in a good shape. I left comments with some thoughts and 
nits, but they're not blockers, feel free to land it.




Comment at: clang-tools-extra/clangd/InlayHints.cpp:252
+// This is used to summarize e.g. the condition of a while loop.
+std::string summarizeExpr(const Expr *E) {
+  struct Namer : ConstStmtVisitor {

This looks like a complicated implementation to get an abbreviated-form of cond 
expression for the inlay label text.


A different idea would be if the user can just click the inlay label text, then 
the editor jumps to the corresponding for statement (looks like it is supported 
with the 
[InlayHintLabelPart::Location](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#inlayHintLabelPart))
 with that we probably don't need to emit an abbreviated-form text (`// for` 
should be clear enough).



Comment at: clang-tools-extra/clangd/InlayHints.cpp:578
+  //   } else if (cond2) {
+  //   } // mark as "cond1" or "cond2"?
+  // For now, the answer is neither, just mark as "if".

my opinion for this case would be (the marking result is also consistent with 
the brackets)

```
if (cond1) {
} // mark as cond1
else if (cond2) {
} // mark as cond2.
```



Comment at: clang-tools-extra/clangd/InlayHints.cpp:599
+llvm::StringRef Name = "") {
+if (const auto *CS = llvm::dyn_cast_or_null(Body))
+  addBlockEndHint(CS->getSourceRange(), Label, Name, "");

it looks like we will mark the block end for single-statement `CompoundStmt` 
without `{}`, it doesn't seem to add much value to this case (the body is short 
enough to spot the for statement).

```
for (int i = 0; i < 10; ++i)
  foo();
```



Comment at: clang-tools-extra/clangd/unittests/InlayHintTests.cpp:1786
+
+   if (auto X = cond) {
+   $init[[}]]

nit: add a case `if (int i = 0; i > 10) { ... }`.



Comment at: clang-tools-extra/clangd/unittests/InlayHintTests.cpp:1859
+  ExpectedHint{" // while \"foo\"", "string"},
+  ExpectedHint{" // while \"...\"", "string_long"},
+  ExpectedHint{" // while true", "boolean"},

nit: I guess showing `foo...` is better.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155421

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


[PATCH] D155816: [Tooling/Inclusion] Make the Recognizer work for C99 code.

2023-07-20 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang.

C99 is the the earliest C version provided by the language opt.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155816

Files:
  clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
  clang/unittests/Tooling/StandardLibraryTest.cpp


Index: clang/unittests/Tooling/StandardLibraryTest.cpp
===
--- clang/unittests/Tooling/StandardLibraryTest.cpp
+++ clang/unittests/Tooling/StandardLibraryTest.cpp
@@ -174,6 +174,17 @@
   EXPECT_EQ(Recognizer(Sec), std::nullopt);
 }
 
+TEST(StdlibTest, RecognizerForC99) {
+  TestInputs Input("typedef char uint8_t;");
+  Input.Language = TestLanguage::Lang_C99;
+  TestAST AST(Input);
+
+  auto  = lookup(AST, "uint8_t");
+  stdlib::Recognizer Recognizer;
+  EXPECT_EQ(Recognizer(),
+stdlib::Symbol::named("", "uint8_t", stdlib::Lang::C));
+}
+
 } // namespace
 } // namespace tooling
 } // namespace clang
Index: clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
===
--- clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -247,13 +247,12 @@
 
 std::optional Recognizer::operator()(const Decl *D) {
   Lang L;
-  if (D->getLangOpts().CPlusPlus) {
+  if (D->getLangOpts().CPlusPlus)
 L = Lang::CXX;
-  } else if (D->getLangOpts().C11) {
+  else if (D->getLangOpts().C99)
 L = Lang::C;
-  } else {
+  else
 return std::nullopt; // not a supported language.
-  }
 
   // If D is std::vector::iterator, `vector` is the outer symbol to look up.
   // We keep all the candidate DCs as some may turn out to be anon enums.


Index: clang/unittests/Tooling/StandardLibraryTest.cpp
===
--- clang/unittests/Tooling/StandardLibraryTest.cpp
+++ clang/unittests/Tooling/StandardLibraryTest.cpp
@@ -174,6 +174,17 @@
   EXPECT_EQ(Recognizer(Sec), std::nullopt);
 }
 
+TEST(StdlibTest, RecognizerForC99) {
+  TestInputs Input("typedef char uint8_t;");
+  Input.Language = TestLanguage::Lang_C99;
+  TestAST AST(Input);
+
+  auto  = lookup(AST, "uint8_t");
+  stdlib::Recognizer Recognizer;
+  EXPECT_EQ(Recognizer(),
+stdlib::Symbol::named("", "uint8_t", stdlib::Lang::C));
+}
+
 } // namespace
 } // namespace tooling
 } // namespace clang
Index: clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
===
--- clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
+++ clang/lib/Tooling/Inclusions/Stdlib/StandardLibrary.cpp
@@ -247,13 +247,12 @@
 
 std::optional Recognizer::operator()(const Decl *D) {
   Lang L;
-  if (D->getLangOpts().CPlusPlus) {
+  if (D->getLangOpts().CPlusPlus)
 L = Lang::CXX;
-  } else if (D->getLangOpts().C11) {
+  else if (D->getLangOpts().C99)
 L = Lang::C;
-  } else {
+  else
 return std::nullopt; // not a supported language.
-  }
 
   // If D is std::vector::iterator, `vector` is the outer symbol to look up.
   // We keep all the candidate DCs as some may turn out to be anon enums.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155396: [Sema][ObjC] Propagating value-dependent errors into BlockExpr

2023-07-19 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.






Comment at: clang/lib/Sema/SemaExpr.cpp:16749-16753
+  bool ContainsError = llvm::any_of(BSI->Returns, [](const ReturnStmt *Return) 
{
+const auto *RetValExpr = Return->getRetValue();
+return RetValExpr && RetValExpr->containsErrors();
+  });
+  BlockExpr *Result = new (Context) BlockExpr(BD, BlockTy, ContainsError);

aaron.ballman wrote:
> Hmmm -- is the block *expression* what contains the errors in this case  or 
> is it the block declaration? I would have expected this to be an issue for 
> the block declaration created for the block expression. CC @rjmccall 
I think a reasonable model is to follow how we handle `FunctionDecl`, as 
`BlockDecl` and `FunctionDecl` are similar function-decl concepts.

For the crash case like `int (^a)() = ^() { return undefined; }`, we should:

- invalidate the `BlockDecl` as its returned type can not be deduced because of 
the error return stmt (similar to `FunctionDecl`, we invalidate it for `auto 
func() { return undefined; }`)
- for an invalid `BlockDecl`, we should not build a `BlockExpr` that refers to 
it (we don't build `DeclRefExpr` for invalid `FunctionDecl`). For error 
recovery, we should use `RecoveryExpr`.

So I think the reasonable fix is to invalidate the BlockDecl (calling 
`Decl->setInvalidDecl()`) if its body has any error stmt, and return 
`ExprError()` if the BlockDecl is invalid.



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155396

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


[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-18 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf4f6c229bde8: [clangd] Refine the workflow for diagnostic 
Fixits. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -962,16 +962,6 @@
 };
 llvm::json::Value toJSON(const Diagnostic &);
 
-/// A LSP-specific comparator used to find diagnostic in a container like
-/// std:map.
-/// We only use the required fields of Diagnostic to do the comparison to avoid
-/// any regression issues from LSP clients (e.g. VScode), see
-/// https://git.io/vbr29
-struct LSPDiagnosticCompare {
-  bool operator()(const Diagnostic , const Diagnostic ) const {
-return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
-  }
-};
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,49 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Ref to the clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+bool operator<(const DiagRef ) const {
+  return std::tie(Range, Message) < std::tie(Other.Range, Other.Message);
+}
+  };
+
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  struct CodeActionResult {
+std::string Version;
+struct QuickFix {
+  DiagRef Diag;
+  Fix F;
+};
+std::vector QuickFixes;
+std::vector TweakRefs;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,11 +52,16 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
 namespace {
 
+// Tracks number of times a tweak has been offered.
+static constexpr trace::Metric TweakAvailable(
+"tweak_available", trace::Metric::Counter, "tweak_id");
+
 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
 struct UpdateIndexCallbacks : public ParsingCallbacks {
   UpdateIndexCallbacks(FileIndex *FIndex,
@@ -643,12 +648,65 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback CB) {
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+CodeActionResult Result;
+Result.Version = InpAST->AST.version().str();
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatchedFixes =
+  [](const DiagRef ) -> llvm::ArrayRef {
+for (const auto  : 

[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-18 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 541546.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -962,16 +962,6 @@
 };
 llvm::json::Value toJSON(const Diagnostic &);
 
-/// A LSP-specific comparator used to find diagnostic in a container like
-/// std:map.
-/// We only use the required fields of Diagnostic to do the comparison to avoid
-/// any regression issues from LSP clients (e.g. VScode), see
-/// https://git.io/vbr29
-struct LSPDiagnosticCompare {
-  bool operator()(const Diagnostic , const Diagnostic ) const {
-return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
-  }
-};
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,49 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Ref to the clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+bool operator<(const DiagRef ) const {
+  return std::tie(Range, Message) < std::tie(Other.Range, Other.Message);
+}
+  };
+
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  struct CodeActionResult {
+std::string Version;
+struct QuickFix {
+  DiagRef Diag;
+  Fix F;
+};
+std::vector QuickFixes;
+std::vector TweakRefs;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,11 +52,16 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
 namespace {
 
+// Tracks number of times a tweak has been offered.
+static constexpr trace::Metric TweakAvailable(
+"tweak_available", trace::Metric::Counter, "tweak_id");
+
 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
 struct UpdateIndexCallbacks : public ParsingCallbacks {
   UpdateIndexCallbacks(FileIndex *FIndex,
@@ -643,12 +648,65 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback CB) {
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+CodeActionResult Result;
+Result.Version = InpAST->AST.version().str();
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatchedFixes =
+  [](const DiagRef ) -> llvm::ArrayRef {
+for (const auto  : InpAST->AST.getDiagnostics())
+  if (Diag.Range == DR.Range && Diag.Message == DR.Message)
+return 

[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-18 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 541481.
hokein added a comment.

more cleanup


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -962,16 +962,6 @@
 };
 llvm::json::Value toJSON(const Diagnostic &);
 
-/// A LSP-specific comparator used to find diagnostic in a container like
-/// std:map.
-/// We only use the required fields of Diagnostic to do the comparison to avoid
-/// any regression issues from LSP clients (e.g. VScode), see
-/// https://git.io/vbr29
-struct LSPDiagnosticCompare {
-  bool operator()(const Diagnostic , const Diagnostic ) const {
-return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
-  }
-};
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,49 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Ref to the clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+bool operator<(const DiagRef ) const {
+  return std::tie(Range, Message) < std::tie(Other.Range, Other.Message);
+}
+  };
+
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  struct CodeActionResult {
+std::string Version;
+struct QuickFix {
+  DiagRef Diag;
+  Fix F;
+};
+std::vector QuickFixes;
+std::vector TweakRefs;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,11 +52,16 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
 namespace {
 
+// Tracks number of times a tweak has been offered.
+static constexpr trace::Metric TweakAvailable(
+"tweak_available", trace::Metric::Counter, "tweak_id");
+
 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
 struct UpdateIndexCallbacks : public ParsingCallbacks {
   UpdateIndexCallbacks(FileIndex *FIndex,
@@ -643,12 +648,66 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback CB) {
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+CodeActionResult Result;
+Result.Version = InpAST->AST.version().str();
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatched = [](const DiagRef ) -> const clangd::Diag * {
+for (const auto  : InpAST->AST.getDiagnostics())
+  if (Diag.Range == DR.Range && Diag.Message == DR.Message)
+return 
+return nullptr;
+  };
+  for (const auto  : 

[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-18 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 541480.
hokein marked an inline comment as done.
hokein added a comment.

address comments

- introduce `DiagKey` for the caching map
- get rid of extra index conversion


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -962,16 +962,6 @@
 };
 llvm::json::Value toJSON(const Diagnostic &);
 
-/// A LSP-specific comparator used to find diagnostic in a container like
-/// std:map.
-/// We only use the required fields of Diagnostic to do the comparison to avoid
-/// any regression issues from LSP clients (e.g. VScode), see
-/// https://git.io/vbr29
-struct LSPDiagnosticCompare {
-  bool operator()(const Diagnostic , const Diagnostic ) const {
-return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
-  }
-};
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,49 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Ref to the clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+bool operator<(const DiagRef ) const {
+  return std::tie(Range, Message) < std::tie(Other.Range, Other.Message);
+}
+  };
+
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  struct CodeActionResult {
+std::string Version;
+struct QuickFix {
+  DiagRef Diag;
+  Fix F;
+};
+std::vector QuickFixes;
+std::vector TweakRefs;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,11 +52,16 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
 namespace {
 
+// Tracks number of times a tweak has been offered.
+static constexpr trace::Metric TweakAvailable(
+"tweak_available", trace::Metric::Counter, "tweak_id");
+
 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
 struct UpdateIndexCallbacks : public ParsingCallbacks {
   UpdateIndexCallbacks(FileIndex *FIndex,
@@ -643,12 +648,66 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback CB) {
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+CodeActionResult Result;
+Result.Version = InpAST->AST.version().str();
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatched = [](const DiagRef ) -> const clangd::Diag * {
+for (const auto  : InpAST->AST.getDiagnostics())
+  if (Diag.Range == 

[PATCH] D155195: [include-cleaner] Avoid a caching issue when running --edit mode on multiple files.

2023-07-18 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGbe861b64d941: [include-cleaner] Avoid a caching issue when 
running --edit mode on multiple… (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D155195?vs=539988=541449#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155195

Files:
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
@@ -270,12 +271,24 @@
   }
 }
   }
+
+  clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
+ OptionsParser->getSourcePathList());
+  std::vector> Buffers;
+  for (const auto  : OptionsParser->getSourcePathList()) {
+auto Content = llvm::MemoryBuffer::getFile(File);
+if (!Content) {
+  llvm::errs() << "Error: can't read file '" << File
+   << "': " << Content.getError().message() << "\n";
+  return 1;
+}
+Buffers.push_back(std::move(Content.get()));
+Tool.mapVirtualFile(File, Buffers.back()->getBuffer());
+  }
+
   auto HeaderFilter = headerFilter();
   if (!HeaderFilter)
 return 1; // error already reported.
   ActionFactory Factory(HeaderFilter);
-  return clang::tooling::ClangTool(OptionsParser->getCompilations(),
-   OptionsParser->getSourcePathList())
- .run() ||
- Errors != 0;
+  return Tool.run() || Errors != 0;
 }


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
@@ -270,12 +271,24 @@
   }
 }
   }
+
+  clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
+ OptionsParser->getSourcePathList());
+  std::vector> Buffers;
+  for (const auto  : OptionsParser->getSourcePathList()) {
+auto Content = llvm::MemoryBuffer::getFile(File);
+if (!Content) {
+  llvm::errs() << "Error: can't read file '" << File
+   << "': " << Content.getError().message() << "\n";
+  return 1;
+}
+Buffers.push_back(std::move(Content.get()));
+Tool.mapVirtualFile(File, Buffers.back()->getBuffer());
+  }
+
   auto HeaderFilter = headerFilter();
   if (!HeaderFilter)
 return 1; // error already reported.
   ActionFactory Factory(HeaderFilter);
-  return clang::tooling::ClangTool(OptionsParser->getCompilations(),
-   OptionsParser->getSourcePathList())
- .run() ||
- Errors != 0;
+  return Tool.run() || Errors != 0;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-18 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 541391.
hokein added a comment.

cleanup


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h

Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,49 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Ref to the clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+bool operator<(const DiagRef ) const {
+  return std::tie(Range, Message) < std::tie(Other.Range, Other.Message);
+}
+  };
+
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  struct CodeActionResult {
+std::string Version;
+struct QuickFix {
+  DiagRef Diag;
+  Fix F;
+};
+std::vector QuickFixes;
+std::vector TweakRefs;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,11 +52,16 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
 namespace {
 
+// Tracks number of times a tweak has been offered.
+static constexpr trace::Metric TweakAvailable(
+"tweak_available", trace::Metric::Counter, "tweak_id");
+
 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
 struct UpdateIndexCallbacks : public ParsingCallbacks {
   UpdateIndexCallbacks(FileIndex *FIndex,
@@ -643,12 +648,66 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback CB) {
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+CodeActionResult Result;
+Result.Version = InpAST->AST.version().str();
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatched = [](const DiagRef ) -> const clangd::Diag * {
+for (const auto  : InpAST->AST.getDiagnostics())
+  if (Diag.Range == DR.Range && Diag.Message == DR.Message)
+return 
+return nullptr;
+  };
+  for (const auto  : Params.Diagnostics) {
+if (const auto *Match = FindMatched(Diag))
+  for (const auto  : Match->Fixes)
+Result.QuickFixes.push_back({Diag, Fix});
+  }
+}
+
+// Collect Tweaks
+auto Selections = tweakSelection(Params.Selection, *InpAST, /*FS=*/nullptr);
+if (!Selections)
+  return CB(Selections.takeError());
+// Don't allow a tweak to fire more than once across ambiguous selections.
+llvm::DenseSet PreparedTweaks;
+auto DeduplicatingFilter = [&](const Tweak ) {
+  return KindAllowed(T.kind()) && Params.TweakFilter(T) &&
+ !PreparedTweaks.count(T.id());
+};
+for (const auto  : *Selections) {
+  for (auto  : prepareTweaks(*Sel, DeduplicatingFilter, FeatureModules)) {
+Result.TweakRefs.push_back(TweakRef{T->id(), T->title(), T->kind()});
+PreparedTweaks.insert(T->id());
+

[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-18 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 541389.
hokein marked 2 inline comments as done.
hokein added a comment.

add LSPServer cache back and repurpose for lsp <=> naive diagnostic mapping, 
per offline discussion.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -972,6 +972,7 @@
 return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
   }
 };
+
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,49 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Ref to the clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+bool operator<(const DiagRef ) const {
+  return std::tie(Range, Message) < std::tie(Other.Range, Other.Message);
+}
+  };
+
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  struct CodeActionResult {
+std::string Version;
+struct QuickFix {
+  DiagRef Diag;
+  Fix F;
+};
+std::vector QuickFixes;
+std::vector TweakRefs;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,11 +52,16 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
 namespace {
 
+// Tracks number of times a tweak has been offered.
+static constexpr trace::Metric TweakAvailable(
+"tweak_available", trace::Metric::Counter, "tweak_id");
+
 // Update the FileIndex with new ASTs and plumb the diagnostics responses.
 struct UpdateIndexCallbacks : public ParsingCallbacks {
   UpdateIndexCallbacks(FileIndex *FIndex,
@@ -643,12 +648,66 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback CB) {
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+CodeActionResult Result;
+Result.Version = InpAST->AST.version().str();
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatched = [](const DiagRef ) -> const clangd::Diag * {
+for (const auto  : InpAST->AST.getDiagnostics())
+  if (Diag.Range == DR.Range && Diag.Message == DR.Message)
+return 
+return nullptr;
+  };
+  for (const auto  : Params.Diagnostics) {
+if (const auto *Match = FindMatched(Diag))
+  for (const auto  : Match->Fixes)
+Result.QuickFixes.push_back({Diag, Fix});
+  }
+}
+
+// Collect Tweaks
+auto Selections = tweakSelection(Params.Selection, *InpAST, 

[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-17 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/ClangdServer.cpp:671
+  // FIMXE: this is tricky
+  llvm::StringRef(LSPDiag.Message)
+  .starts_with_insensitive(Diag.Message))

hokein wrote:
> kadircet wrote:
> > this is tricky indeed and conceptually really hard to achieve inside 
> > ClangdServer layer.
> > 
> > what about keeping the cache in ClangdLSPServer, but changing the format? 
> > Similar to `TweakRef`, we now have a `DiagRef`, which is 
> > ClangdServer-native. So we can keep a cache from `(FilePath, 
> > clangd::Diagnostic)` to `clangd::DiagRef`, and pass those `DiagRef`s to 
> > `ClangdServer` and make sure we're doing the search for sure on the right 
> > domain here?
> > 
> > this also gives us the flexibility to change the definition of a `DiagRef` 
> > in the future.
> I'm not a fan of keeping a cache in `ClangdLSPServer`, I'd like to remove it 
> entirely. 
> 
> What do you think about this alternative? 
> 
> - pull out and exposed the `mainMessage` API from the `toLSPDiags`
> - we add the `ClangdDiagnosticOptions` to the `CodeActionInputs`.
> - when searching a diagnostic in `ClangdServer.cpp`, we check the equality by 
> checking `mainMessage(ClangdServerDiagnostic.message, Inputs.DiagOpts) == 
> DiagRef.Message`
> 
> The downside here is that we have to pay `O(N * cost of mainMessage)` to find 
> a matched diagnostic.
>  
I updated the patch with the `mainMessage` approach, please take a look.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

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


[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-17 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 541129.
hokein added a comment.

Use the mainMessage to find the corresponding ClangdServer diagnostics.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Diagnostics.cpp
  clang-tools-extra/clangd/Diagnostics.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -962,16 +962,6 @@
 };
 llvm::json::Value toJSON(const Diagnostic &);
 
-/// A LSP-specific comparator used to find diagnostic in a container like
-/// std:map.
-/// We only use the required fields of Diagnostic to do the comparison to avoid
-/// any regression issues from LSP clients (e.g. VScode), see
-/// https://git.io/vbr29
-struct LSPDiagnosticCompare {
-  bool operator()(const Diagnostic , const Diagnostic ) const {
-return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
-  }
-};
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/Diagnostics.h
===
--- clang-tools-extra/clangd/Diagnostics.h
+++ clang-tools-extra/clangd/Diagnostics.h
@@ -124,6 +124,18 @@
 const Diag , const URIForFile , const ClangdDiagnosticOptions ,
 llvm::function_ref)> OutFn);
 
+/// Returns a message sent to LSP for the main diagnostic in \p D.
+/// This message may include notes, if they're not emitted in some other way.
+/// Example output:
+///
+/// no matching function for call to 'foo'
+///
+/// main.cpp:3:5: note: candidate function not viable: requires 2 arguments
+///
+/// dir1/dir2/dir3/../../dir4/header.h:12:23
+/// note: candidate function not viable: requires 3 arguments
+std::string mainMessage(const Diag , const ClangdDiagnosticOptions );
+
 /// Convert from clang diagnostic level to LSP severity.
 int getSeverity(DiagnosticsEngine::Level L);
 
Index: clang-tools-extra/clangd/Diagnostics.cpp
===
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -297,32 +297,6 @@
   return Message;
 }
 
-/// Returns a message sent to LSP for the main diagnostic in \p D.
-/// This message may include notes, if they're not emitted in some other way.
-/// Example output:
-///
-/// no matching function for call to 'foo'
-///
-/// main.cpp:3:5: note: candidate function not viable: requires 2 arguments
-///
-/// dir1/dir2/dir3/../../dir4/header.h:12:23
-/// note: candidate function not viable: requires 3 arguments
-std::string mainMessage(const Diag , const ClangdDiagnosticOptions ) {
-  std::string Result;
-  llvm::raw_string_ostream OS(Result);
-  OS << D.Message;
-  if (Opts.DisplayFixesCount && !D.Fixes.empty())
-OS << " (" << (D.Fixes.size() > 1 ? "fixes" : "fix") << " available)";
-  // If notes aren't emitted as structured info, add them to the message.
-  if (!Opts.EmitRelatedLocations)
-for (auto  : D.Notes) {
-  OS << "\n\n";
-  printDiag(OS, Note);
-}
-  OS.flush();
-  return capitalize(std::move(Result));
-}
-
 /// Returns a message sent to LSP for the note of the main diagnostic.
 std::string noteMessage(const Diag , const DiagBase ,
 const ClangdDiagnosticOptions ) {
@@ -554,6 +528,23 @@
 }
 }
 
+std::string mainMessage(const Diag , const ClangdDiagnosticOptions ) {
+  std::string Result;
+  llvm::raw_string_ostream OS(Result);
+  OS << D.Message;
+  if (Opts.DisplayFixesCount && !D.Fixes.empty())
+OS << " (" << (D.Fixes.size() > 1 ? "fixes" : "fix") << " available)";
+  // If notes aren't emitted as structured info, add them to the message.
+  if (!Opts.EmitRelatedLocations)
+for (auto  : D.Notes) {
+  OS << "\n\n";
+  printDiag(OS, Note);
+}
+  OS.flush();
+  return capitalize(std::move(Result));
+}
+
+
 int getSeverity(DiagnosticsEngine::Level L) {
   switch (L) {
   case DiagnosticsEngine::Remark:
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,48 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Contains fields (LSP-form) to identify corresponding clangd::Diag.
+  struct DiagRef {
+

[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-17 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/clangd/ClangdServer.cpp:671
+  // FIMXE: this is tricky
+  llvm::StringRef(LSPDiag.Message)
+  .starts_with_insensitive(Diag.Message))

kadircet wrote:
> this is tricky indeed and conceptually really hard to achieve inside 
> ClangdServer layer.
> 
> what about keeping the cache in ClangdLSPServer, but changing the format? 
> Similar to `TweakRef`, we now have a `DiagRef`, which is ClangdServer-native. 
> So we can keep a cache from `(FilePath, clangd::Diagnostic)` to 
> `clangd::DiagRef`, and pass those `DiagRef`s to `ClangdServer` and make sure 
> we're doing the search for sure on the right domain here?
> 
> this also gives us the flexibility to change the definition of a `DiagRef` in 
> the future.
I'm not a fan of keeping a cache in `ClangdLSPServer`, I'd like to remove it 
entirely. 

What do you think about this alternative? 

- pull out and exposed the `mainMessage` API from the `toLSPDiags`
- we add the `ClangdDiagnosticOptions` to the `CodeActionInputs`.
- when searching a diagnostic in `ClangdServer.cpp`, we check the equality by 
checking `mainMessage(ClangdServerDiagnostic.message, Inputs.DiagOpts) == 
DiagRef.Message`

The downside here is that we have to pay `O(N * cost of mainMessage)` to find a 
matched diagnostic.
 



Comment at: clang-tools-extra/clangd/ClangdServer.cpp:683
+  // Return immediately if this is a quick-fix-only codeAction request.
+  if (Params.RequestedActionKinds.size() == 1)
+return CB(std::move(Results));

kadircet wrote:
> we can have quick fix kind tweaks too (e.g. populate switch)
oops, I weren't aware of that, removed.



Comment at: clang-tools-extra/clangd/ClangdServer.cpp:714-715
   // Tracks number of times a tweak has been offered.
   static constexpr trace::Metric TweakAvailable(
   "tweak_available", trace::Metric::Counter, "tweak_id");
   auto Action = [Sel, CB = std::move(CB), Filter = std::move(Filter),

kadircet wrote:
> can you also move this counter to global scope and use it in `::codeAction` 
> too?
I added a similar local counter in `codeAction` method, since this method is 
being deprecated, and removed eventually (it doesn't seem too make much sense 
to use a shared counter)



Comment at: clang-tools-extra/clangd/ClangdServer.h:387
+  void codeAction(const CodeActionInputs ,
+  Callback> CB);
+

kadircet wrote:
> maybe a more structured output can be useful here:
> ```
> struct CodeActionResult {
>   std::string Version; // Version of content results belong to.
>   struct QuickFix {
>   DiagRef D; // Diagnostic being addressed by the fix.
>   Fix F;
>   };
>   std::vector QuickFixes;
>   std::vector TweakRefs;
> };
> ```
good idea, also keep symmetry with the `CodeActionInputs`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

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


[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-17 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 541009.
hokein marked an inline comment as done.
hokein added a comment.

address review comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -962,16 +962,6 @@
 };
 llvm::json::Value toJSON(const Diagnostic &);
 
-/// A LSP-specific comparator used to find diagnostic in a container like
-/// std:map.
-/// We only use the required fields of Diagnostic to do the comparison to avoid
-/// any regression issues from LSP clients (e.g. VScode), see
-/// https://git.io/vbr29
-struct LSPDiagnosticCompare {
-  bool operator()(const Diagnostic , const Diagnostic ) const {
-return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
-  }
-};
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,7 @@
 #include 
 #include 
 #include 
-#include 
-#include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +350,45 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Contains fields (LSP-form) to identify corresponding clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef& Other ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+  };
+
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  struct CodeActionResult {
+std::string Version;
+struct QuickFix {
+  DiagRef Diag;
+  Fix F;
+};
+std::vector QuickFixes;
+std::vector TweakRefs;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,6 +52,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
@@ -643,6 +644,70 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback CB) {
+  static constexpr trace::Metric TweakAvailable(
+  "code_action_tweak_available", trace::Metric::Counter, "tweak_id");
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+CodeActionResult Result;
+Result.Version = InpAST->AST.version().str();
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatched =
+  [](const DiagRef ) -> const clangd::Diag * {
+for (const auto  : InpAST->AST.getDiagnostics()) {
+  if (Diag.Range == LSPDiag.Range &&
+  // FIMXE: this is tricky
+  llvm::StringRef(LSPDiag.Message)
+  .starts_with_insensitive(Diag.Message))
+return 
+}
+return nullptr;
+  };
+  for (const auto  : Params.Diagnostics) {
+if (const auto *Match = FindMatched(Diag))
+  for (const auto  : Match->Fixes)

[PATCH] D153617: [clangd] Fix an assertion failure in NamedDecl::getName during the prepareRename

2023-07-14 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5649b24c48ab: [clangd] Fix an assertion failure in 
NamedDecl::getName during the prepareRename (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153617

Files:
  clang-tools-extra/clangd/refactor/Rename.cpp
  clang-tools-extra/clangd/unittests/RenameTests.cpp


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -1129,6 +1129,15 @@
 using ns::^foo;
   )cpp",
"there are multiple symbols at the given location", !HeaderFile},
+
+  {R"cpp(
+void test() {
+  // no crash
+  using namespace std;
+  int [[V^ar]];
+}
+  )cpp",
+nullptr, !HeaderFile},
   };
 
   for (const auto& Case : Cases) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -332,7 +332,8 @@
   return nullptr;
 for (const auto  : DS->getDeclGroup())
   if (const auto *ND = dyn_cast(Child))
-if (ND !=  && ND->getName() == Name)
+if (ND !=  && ND->getDeclName().isIdentifier() &&
+ND->getName() == Name)
   return ND;
 return nullptr;
   };


Index: clang-tools-extra/clangd/unittests/RenameTests.cpp
===
--- clang-tools-extra/clangd/unittests/RenameTests.cpp
+++ clang-tools-extra/clangd/unittests/RenameTests.cpp
@@ -1129,6 +1129,15 @@
 using ns::^foo;
   )cpp",
"there are multiple symbols at the given location", !HeaderFile},
+
+  {R"cpp(
+void test() {
+  // no crash
+  using namespace std;
+  int [[V^ar]];
+}
+  )cpp",
+nullptr, !HeaderFile},
   };
 
   for (const auto& Case : Cases) {
Index: clang-tools-extra/clangd/refactor/Rename.cpp
===
--- clang-tools-extra/clangd/refactor/Rename.cpp
+++ clang-tools-extra/clangd/refactor/Rename.cpp
@@ -332,7 +332,8 @@
   return nullptr;
 for (const auto  : DS->getDeclGroup())
   if (const auto *ND = dyn_cast(Child))
-if (ND !=  && ND->getName() == Name)
+if (ND !=  && ND->getDeclName().isIdentifier() &&
+ND->getName() == Name)
   return ND;
 return nullptr;
   };
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155195: [include-cleaner] Avoid a caching issue when running --edit mode on multiple files.

2023-07-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang-tools-extra.

Snapshot all analysing files before running the tool, this makes sure
that we analyse all files statelessly and avoid the FileManager caching issue
when running `-edit` on multiple files.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155195

Files:
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
@@ -270,10 +271,22 @@
   }
 }
   }
+
+  clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
+ OptionsParser->getSourcePathList());
+  std::vector> Buffers;
+  for (const auto  : OptionsParser->getSourcePathList()) {
+auto Content = llvm::MemoryBuffer::getFile(File);
+if (!Content) {
+  llvm::errs() << "Error: can't read file '" << File
+   << "': " << Content.getError().message() << "\n";
+  return 1;
+}
+Buffers.push_back(std::move(Content.get()));
+Tool.mapVirtualFile(File, Buffers.back()->getBuffer());
+  }
+
   auto HeaderFilter = headerFilter();
   ActionFactory Factory(HeaderFilter);
-  return clang::tooling::ClangTool(OptionsParser->getCompilations(),
-   OptionsParser->getSourcePathList())
- .run() ||
- Errors != 0;
+  return Tool.run() || Errors != 0;
 }


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
@@ -270,10 +271,22 @@
   }
 }
   }
+
+  clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
+ OptionsParser->getSourcePathList());
+  std::vector> Buffers;
+  for (const auto  : OptionsParser->getSourcePathList()) {
+auto Content = llvm::MemoryBuffer::getFile(File);
+if (!Content) {
+  llvm::errs() << "Error: can't read file '" << File
+   << "': " << Content.getError().message() << "\n";
+  return 1;
+}
+Buffers.push_back(std::move(Content.get()));
+Tool.mapVirtualFile(File, Buffers.back()->getBuffer());
+  }
+
   auto HeaderFilter = headerFilter();
   ActionFactory Factory(HeaderFilter);
-  return clang::tooling::ClangTool(OptionsParser->getCompilations(),
-   OptionsParser->getSourcePathList())
- .run() ||
- Errors != 0;
+  return Tool.run() || Errors != 0;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155173: [clangd] Refine the workflow for diagnostic Fixits.

2023-07-13 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

- Remove the diagnostic fixits map from the clangdLSPServer
- When propagating the fixit via the code action, we use the Diag information 
stored in the ParsedAST (in clangdServer.cpp)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155173

Files:
  clang-tools-extra/clangd/ClangdLSPServer.cpp
  clang-tools-extra/clangd/ClangdLSPServer.h
  clang-tools-extra/clangd/ClangdServer.cpp
  clang-tools-extra/clangd/ClangdServer.h
  clang-tools-extra/clangd/Protocol.h

Index: clang-tools-extra/clangd/Protocol.h
===
--- clang-tools-extra/clangd/Protocol.h
+++ clang-tools-extra/clangd/Protocol.h
@@ -962,16 +962,6 @@
 };
 llvm::json::Value toJSON(const Diagnostic &);
 
-/// A LSP-specific comparator used to find diagnostic in a container like
-/// std:map.
-/// We only use the required fields of Diagnostic to do the comparison to avoid
-/// any regression issues from LSP clients (e.g. VScode), see
-/// https://git.io/vbr29
-struct LSPDiagnosticCompare {
-  bool operator()(const Diagnostic , const Diagnostic ) const {
-return std::tie(LHS.range, LHS.message) < std::tie(RHS.range, RHS.message);
-  }
-};
 bool fromJSON(const llvm::json::Value &, Diagnostic &, llvm::json::Path);
 llvm::raw_ostream <<(llvm::raw_ostream &, const Diagnostic &);
 
Index: clang-tools-extra/clangd/ClangdServer.h
===
--- clang-tools-extra/clangd/ClangdServer.h
+++ clang-tools-extra/clangd/ClangdServer.h
@@ -37,8 +37,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 
 namespace clang {
@@ -351,8 +353,42 @@
 std::string Title; /// A single-line message to show in the UI.
 llvm::StringLiteral Kind;
   };
+
+  // Contains fields (LSP-form) to identify corresponding clangd::Diag.
+  struct DiagRef {
+Range Range;
+std::string Message;
+bool operator==(const DiagRef& Other ) const {
+  return std::tie(Range, Message) == std::tie(Other.Range, Other.Message);
+}
+  };
+  struct DiagFix {
+DiagRef Diag;
+Fix F;
+std::string Version;
+  };
+
+  using CodeActionFix = std::variant;
+  struct CodeActionInputs {
+std::string File;
+Range Selection;
+/// Requested kind of actions to return.
+std::vector RequestedActionKinds;
+
+/// Diagnostics attached to the code action request.
+std::vector Diagnostics;
+
+/// Tweaks where Filter returns false will not be checked or included.
+std::function TweakFilter;
+  };
+  /// Surface code actions (quick-fixes for diagnostics, or available code
+  /// tweaks) for a given range in a file.
+  void codeAction(const CodeActionInputs ,
+  Callback> CB);
+
   /// Enumerate the code tweaks available to the user at a specified point.
   /// Tweaks where Filter returns false will not be checked or included.
+  /// Deprecated, use codeAction instead.
   void enumerateTweaks(PathRef File, Range Sel,
llvm::unique_function Filter,
Callback> CB);
Index: clang-tools-extra/clangd/ClangdServer.cpp
===
--- clang-tools-extra/clangd/ClangdServer.cpp
+++ clang-tools-extra/clangd/ClangdServer.cpp
@@ -52,6 +52,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 namespace clangd {
@@ -643,6 +644,69 @@
   return std::move(Result);
 }
 
+void ClangdServer::codeAction(const CodeActionInputs ,
+  Callback> CB) {
+  auto Action = [Params, CB = std::move(CB),
+ FeatureModules(this->FeatureModules)](
+Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+auto KindAllowed =
+[Only(Params.RequestedActionKinds)](llvm::StringRef Kind) {
+  if (Only.empty())
+return true;
+  return llvm::any_of(Only, [&](llvm::StringRef Base) {
+return Kind.consume_front(Base) &&
+   (Kind.empty() || Kind.startswith("."));
+  });
+};
+
+std::vector Results;
+if (KindAllowed(CodeAction::QUICKFIX_KIND)) {
+  auto FindMatched =
+  [](const DiagRef ) -> const clangd::Diag * {
+for (const auto  : InpAST->AST.getDiagnostics()) {
+  if (Diag.Range == LSPDiag.Range &&
+  // FIMXE: this is tricky
+  llvm::StringRef(LSPDiag.Message)
+  .starts_with_insensitive(Diag.Message))
+return 
+}
+return nullptr;
+  };
+  for (const auto  : Params.Diagnostics) {
+if (const auto *Match = FindMatched(Diag))
+  for (const 

[PATCH] D154963: [Format][Tooling] Fix HeaderIncludes::insert not respect the main-file header.

2023-07-13 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
hokein marked an inline comment as done.
Closed by commit rG85c6d57eb304: [Format][Tooling] Fix HeaderIncludes::insert 
not respect the main-file header. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154963

Files:
  clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -143,6 +143,19 @@
   EXPECT_NE(Expected, insert(Code, "")) << "Not main header";
 }
 
+TEST_F(HeaderIncludesTest, InsertMainHeader) {
+  Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+  .IncludeStyle;
+  FileName = "fix.cpp";
+  EXPECT_EQ(R"cpp(#include "fix.h"
+#include "a.h")cpp", insert("#include \"a.h\"", "\"fix.h\""));
+
+  // Respect the original main-file header.
+  EXPECT_EQ(R"cpp(#include "z/fix.h"
+#include "a/fix.h"
+)cpp", insert("#include \"z/fix.h\"", "\"a/fix.h\""));
+}
+
 TEST_F(HeaderIncludesTest, InsertBeforeSystemHeaderLLVM) {
   std::string Code = "#include \n"
  "\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -276,6 +276,7 @@
   MaxInsertOffset(MinInsertOffset +
   getMaxHeaderInsertionOffset(
   FileName, Code.drop_front(MinInsertOffset), Style)),
+  MainIncludeFound(false),
   Categories(Style, FileName) {
   // Add 0 for main header and INT_MAX for headers that are not in any
   // category.
@@ -335,7 +336,9 @@
   // Only record the offset of current #include if we can insert after it.
   if (CurInclude.R.getOffset() <= MaxInsertOffset) {
 int Priority = Categories.getIncludePriority(
-CurInclude.Name, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+CurInclude.Name, /*CheckMainHeader=*/!MainIncludeFound);
+if (Priority == 0)
+  MainIncludeFound = true;
 CategoryEndOffsets[Priority] = NextLineOffset;
 IncludesByPriority[Priority].push_back();
 if (FirstIncludeOffset < 0)
@@ -362,7 +365,7 @@
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
   int Priority = Categories.getIncludePriority(
-  QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+  QuotedName, /*CheckMainHeader=*/!MainIncludeFound);
   auto CatOffset = CategoryEndOffsets.find(Priority);
   assert(CatOffset != CategoryEndOffsets.end());
   unsigned InsertOffset = CatOffset->second; // Fall back offset
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -128,6 +128,8 @@
   // inserting new #includes into the actual code section (e.g. after a
   // declaration).
   unsigned MaxInsertOffset;
+  // True if we find the main-file header in the Code.
+  bool MainIncludeFound;
   IncludeCategoryManager Categories;
   // Record the offset of the end of the last include in each category.
   std::unordered_map CategoryEndOffsets;
Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -311,12 +311,9 @@
   Results = {};
   Results.Missing.push_back("\"d.h\"");
   Code = R"cpp(#include "a.h")cpp";
-  // FIXME: this isn't correct, the main-file header d.h should be added before
-  // a.h.
   EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
-R"cpp(#include "a.h"
-#include "d.h"
-)cpp");
+R"cpp(#include "d.h"
+#include "a.h")cpp");
 }
 
 MATCHER_P3(expandedAt, FileID, Offset, SM, "") {
Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -214,7 +214,7 @@
 })cpp");
 
   TestTU TU;
-  TU.Filename = "foo.cpp";
+  TU.Filename = "main.cpp";
   TU.AdditionalFiles["a.h"] = guard("#include \"b.h\"");
   TU.AdditionalFiles["b.h"] = guard("void b();");
 

[PATCH] D154963: [Format][Tooling] Fix HeaderIncludes::insert not respect the main-file header.

2023-07-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked an inline comment as done.
hokein added inline comments.



Comment at: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp:369-370
+  QuotedName, /*CheckMainHeader=*/!MainIncludeFound);
+  if (Priority == 0)
+MainIncludeFound = true;
   auto CatOffset = CategoryEndOffsets.find(Priority);

kadircet wrote:
> sorry if I was unclear in the previous comment. but i was trying to say we 
> should only consider includes we've encountered during the initial scan.
> 
> getting different results depending on the order of insertions being 
> performed is likely gonna cause confusion elsewhere (e.g. depending on the 
> first diagnostic you've in clangd, you'll get different order of includes). 
> hence, let's keep this function stateless (which also gets rid of the 
> concerns around mutable)
sorry for misunderstanding your comment. Make it stateless looks like a good 
idea.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154963

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


[PATCH] D154963: [Format][Tooling] Fix HeaderIncludes::insert not respect the main-file header.

2023-07-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 539506.
hokein added a comment.

Make the MainFileFound stateless.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154963

Files:
  clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -143,6 +143,19 @@
   EXPECT_NE(Expected, insert(Code, "")) << "Not main header";
 }
 
+TEST_F(HeaderIncludesTest, InsertMainHeader) {
+  Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+  .IncludeStyle;
+  FileName = "fix.cpp";
+  EXPECT_EQ(R"cpp(#include "fix.h"
+#include "a.h")cpp", insert("#include \"a.h\"", "\"fix.h\""));
+
+  // Respect the original main-file header.
+  EXPECT_EQ(R"cpp(#include "z/fix.h"
+#include "a/fix.h"
+)cpp", insert("#include \"z/fix.h\"", "\"a/fix.h\""));
+}
+
 TEST_F(HeaderIncludesTest, InsertBeforeSystemHeaderLLVM) {
   std::string Code = "#include \n"
  "\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -276,6 +276,7 @@
   MaxInsertOffset(MinInsertOffset +
   getMaxHeaderInsertionOffset(
   FileName, Code.drop_front(MinInsertOffset), Style)),
+  MainIncludeFound(false),
   Categories(Style, FileName) {
   // Add 0 for main header and INT_MAX for headers that are not in any
   // category.
@@ -335,7 +336,9 @@
   // Only record the offset of current #include if we can insert after it.
   if (CurInclude.R.getOffset() <= MaxInsertOffset) {
 int Priority = Categories.getIncludePriority(
-CurInclude.Name, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+CurInclude.Name, /*CheckMainHeader=*/!MainIncludeFound);
+if (Priority == 0)
+  MainIncludeFound = true;
 CategoryEndOffsets[Priority] = NextLineOffset;
 IncludesByPriority[Priority].push_back();
 if (FirstIncludeOffset < 0)
@@ -362,7 +365,7 @@
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
   int Priority = Categories.getIncludePriority(
-  QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+  QuotedName, /*CheckMainHeader=*/!MainIncludeFound);
   auto CatOffset = CategoryEndOffsets.find(Priority);
   assert(CatOffset != CategoryEndOffsets.end());
   unsigned InsertOffset = CatOffset->second; // Fall back offset
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -128,6 +128,8 @@
   // inserting new #includes into the actual code section (e.g. after a
   // declaration).
   unsigned MaxInsertOffset;
+  // True if we find the main-file header in the Code.
+  bool MainIncludeFound;
   IncludeCategoryManager Categories;
   // Record the offset of the end of the last include in each category.
   std::unordered_map CategoryEndOffsets;
Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -311,12 +311,9 @@
   Results = {};
   Results.Missing.push_back("\"d.h\"");
   Code = R"cpp(#include "a.h")cpp";
-  // FIXME: this isn't correct, the main-file header d.h should be added before
-  // a.h.
   EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
-R"cpp(#include "a.h"
-#include "d.h"
-)cpp");
+R"cpp(#include "d.h"
+#include "a.h")cpp");
 }
 
 MATCHER_P3(expandedAt, FileID, Offset, SM, "") {
Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -214,7 +214,7 @@
 })cpp");
 
   TestTU TU;
-  TU.Filename = "foo.cpp";
+  TU.Filename = "main.cpp";
   TU.AdditionalFiles["a.h"] = guard("#include \"b.h\"");
   TU.AdditionalFiles["b.h"] = guard("void b();");
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154963: [Format][Tooling] Fix HeaderIncludes::insert not respect the main-file header.

2023-07-12 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 539481.
hokein marked 2 inline comments as done.
hokein added a comment.
Herald added a subscriber: arphaman.

address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154963

Files:
  clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
  clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp

Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -143,6 +143,19 @@
   EXPECT_NE(Expected, insert(Code, "")) << "Not main header";
 }
 
+TEST_F(HeaderIncludesTest, InsertMainHeader) {
+  Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+  .IncludeStyle;
+  FileName = "fix.cpp";
+  EXPECT_EQ(R"cpp(#include "fix.h"
+#include "a.h")cpp", insert("#include \"a.h\"", "\"fix.h\""));
+
+  // Respect the original main-file header.
+  EXPECT_EQ(R"cpp(#include "z/fix.h"
+#include "a/fix.h"
+)cpp", insert("#include \"z/fix.h\"", "\"a/fix.h\""));
+}
+
 TEST_F(HeaderIncludesTest, InsertBeforeSystemHeaderLLVM) {
   std::string Code = "#include \n"
  "\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -276,6 +276,7 @@
   MaxInsertOffset(MinInsertOffset +
   getMaxHeaderInsertionOffset(
   FileName, Code.drop_front(MinInsertOffset), Style)),
+  MainIncludeFound(false),
   Categories(Style, FileName) {
   // Add 0 for main header and INT_MAX for headers that are not in any
   // category.
@@ -335,7 +336,9 @@
   // Only record the offset of current #include if we can insert after it.
   if (CurInclude.R.getOffset() <= MaxInsertOffset) {
 int Priority = Categories.getIncludePriority(
-CurInclude.Name, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+CurInclude.Name, /*CheckMainHeader=*/!MainIncludeFound);
+if (Priority == 0)
+  MainIncludeFound = true;
 CategoryEndOffsets[Priority] = NextLineOffset;
 IncludesByPriority[Priority].push_back();
 if (FirstIncludeOffset < 0)
@@ -362,7 +365,9 @@
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
   int Priority = Categories.getIncludePriority(
-  QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+  QuotedName, /*CheckMainHeader=*/!MainIncludeFound);
+  if (Priority == 0)
+MainIncludeFound = true;
   auto CatOffset = CategoryEndOffsets.find(Priority);
   assert(CatOffset != CategoryEndOffsets.end());
   unsigned InsertOffset = CatOffset->second; // Fall back offset
Index: clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
===
--- clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
+++ clang/include/clang/Tooling/Inclusions/HeaderIncludes.h
@@ -128,6 +128,7 @@
   // inserting new #includes into the actual code section (e.g. after a
   // declaration).
   unsigned MaxInsertOffset;
+  mutable bool MainIncludeFound;
   IncludeCategoryManager Categories;
   // Record the offset of the end of the last include in each category.
   std::unordered_map CategoryEndOffsets;
Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -311,12 +311,9 @@
   Results = {};
   Results.Missing.push_back("\"d.h\"");
   Code = R"cpp(#include "a.h")cpp";
-  // FIXME: this isn't correct, the main-file header d.h should be added before
-  // a.h.
   EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
-R"cpp(#include "a.h"
-#include "d.h"
-)cpp");
+R"cpp(#include "d.h"
+#include "a.h")cpp");
 }
 
 MATCHER_P3(expandedAt, FileID, Offset, SM, "") {
Index: clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
===
--- clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
+++ clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp
@@ -214,7 +214,7 @@
 })cpp");
 
   TestTU TU;
-  TU.Filename = "foo.cpp";
+  TU.Filename = "main.cpp";
   TU.AdditionalFiles["a.h"] = guard("#include \"b.h\"");
   TU.AdditionalFiles["b.h"] = guard("void b();");
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org

[PATCH] D154963: [Format][Tooling] Fix HeaderIncludes::insert not respect the main-file header.

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added reviewers: sammccall, kadircet.
Herald added a project: All.
hokein requested review of this revision.
Herald added projects: clang, clang-tools-extra.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154963

Files:
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
  clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
  clang/unittests/Tooling/HeaderIncludesTest.cpp


Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -143,6 +143,17 @@
   EXPECT_NE(Expected, insert(Code, "")) << "Not main header";
 }
 
+TEST_F(HeaderIncludesTest, InsertMainHeader) {
+  std::string Code = R"cpp(#include "a.h")cpp";
+  std::string Expected = R"cpp(#include "fix.h"
+#include "a.h")cpp";
+
+  Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+  .IncludeStyle;
+  FileName = "fix.cpp";
+  EXPECT_EQ(Expected, insert(Code, "\"fix.h\""));
+}
+
 TEST_F(HeaderIncludesTest, InsertBeforeSystemHeaderLLVM) {
   std::string Code = "#include \n"
  "\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -335,7 +335,7 @@
   // Only record the offset of current #include if we can insert after it.
   if (CurInclude.R.getOffset() <= MaxInsertOffset) {
 int Priority = Categories.getIncludePriority(
-CurInclude.Name, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+CurInclude.Name, /*CheckMainHeader=*/true);
 CategoryEndOffsets[Priority] = NextLineOffset;
 IncludesByPriority[Priority].push_back();
 if (FirstIncludeOffset < 0)
@@ -362,7 +362,7 @@
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
   int Priority = Categories.getIncludePriority(
-  QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+  QuotedName, /*CheckMainHeader=*/true);
   auto CatOffset = CategoryEndOffsets.find(Priority);
   assert(CatOffset != CategoryEndOffsets.end());
   unsigned InsertOffset = CatOffset->second; // Fall back offset
Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -311,12 +311,9 @@
   Results = {};
   Results.Missing.push_back("\"d.h\"");
   Code = R"cpp(#include "a.h")cpp";
-  // FIXME: this isn't correct, the main-file header d.h should be added before
-  // a.h.
   EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
-R"cpp(#include "a.h"
-#include "d.h"
-)cpp");
+R"cpp(#include "d.h"
+#include "a.h")cpp");
 }
 
 MATCHER_P3(expandedAt, FileID, Offset, SM, "") {


Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -143,6 +143,17 @@
   EXPECT_NE(Expected, insert(Code, "")) << "Not main header";
 }
 
+TEST_F(HeaderIncludesTest, InsertMainHeader) {
+  std::string Code = R"cpp(#include "a.h")cpp";
+  std::string Expected = R"cpp(#include "fix.h"
+#include "a.h")cpp";
+
+  Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+  .IncludeStyle;
+  FileName = "fix.cpp";
+  EXPECT_EQ(Expected, insert(Code, "\"fix.h\""));
+}
+
 TEST_F(HeaderIncludesTest, InsertBeforeSystemHeaderLLVM) {
   std::string Code = "#include \n"
  "\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -335,7 +335,7 @@
   // Only record the offset of current #include if we can insert after it.
   if (CurInclude.R.getOffset() <= MaxInsertOffset) {
 int Priority = Categories.getIncludePriority(
-CurInclude.Name, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+CurInclude.Name, /*CheckMainHeader=*/true);
 CategoryEndOffsets[Priority] = NextLineOffset;
 IncludesByPriority[Priority].push_back();
 if (FirstIncludeOffset < 0)
@@ -362,7 +362,7 @@
   std::string(llvm::formatv(IsAngled ? "<{0}>" : "\"{0}\"", IncludeName));
   StringRef QuotedName = Quoted;
   int Priority = Categories.getIncludePriority(
-  QuotedName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
+  QuotedName, /*CheckMainHeader=*/true);
   auto CatOffset = CategoryEndOffsets.find(Priority);
   assert(CatOffset != CategoryEndOffsets.end());
   unsigned InsertOffset = 

[PATCH] D154950: [include-cleaner] Fix the `fixIncludes` API not respect main-file header.

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7f3d2cd7ec25: [include-cleaner] Fix the `fixIncludes` API 
not respect main-file header. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154950

Files:
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
  clang-tools-extra/include-cleaner/lib/Analysis.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -274,7 +274,7 @@
 }
 
 TEST(FixIncludes, Basic) {
-  llvm::StringRef Code = R"cpp(
+  llvm::StringRef Code = R"cpp(#include "d.h"
 #include "a.h"
 #include "b.h"
 #include 
@@ -300,11 +300,22 @@
   Results.Unused.push_back(Inc.atLine(3));
   Results.Unused.push_back(Inc.atLine(4));
 
-  EXPECT_EQ(fixIncludes(Results, Code, format::getLLVMStyle()), R"cpp(
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
+R"cpp(#include "d.h"
 #include "a.h"
 #include "aa.h"
 #include "ab.h"
 #include 
+)cpp");
+
+  Results = {};
+  Results.Missing.push_back("\"d.h\"");
+  Code = R"cpp(#include "a.h")cpp";
+  // FIXME: this isn't correct, the main-file header d.h should be added before
+  // a.h.
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
+R"cpp(#include "a.h"
+#include "d.h"
 )cpp");
 }
 
Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -164,7 +164,7 @@
   Results.Missing.clear();
 if (!Remove)
   Results.Unused.clear();
-std::string Final = fixIncludes(Results, Code, getStyle(Path));
+std::string Final = fixIncludes(Results, Path, Code, getStyle(Path));
 
 if (Print.getNumOccurrences()) {
   switch (Print) {
Index: clang-tools-extra/include-cleaner/lib/Analysis.cpp
===
--- clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -112,15 +112,16 @@
   return Results;
 }
 
-std::string fixIncludes(const AnalysisResults , llvm::StringRef Code,
+std::string fixIncludes(const AnalysisResults ,
+llvm::StringRef FileName, llvm::StringRef Code,
 const format::FormatStyle ) {
   assert(Style.isCpp() && "Only C++ style supports include insertions!");
   tooling::Replacements R;
   // Encode insertions/deletions in the magic way clang-format understands.
   for (const Include *I : Results.Unused)
-cantFail(R.add(tooling::Replacement("input", UINT_MAX, 1, I->quote(;
+cantFail(R.add(tooling::Replacement(FileName, UINT_MAX, 1, I->quote(;
   for (llvm::StringRef Spelled : Results.Missing)
-cantFail(R.add(tooling::Replacement("input", UINT_MAX, 0,
+cantFail(R.add(tooling::Replacement(FileName, UINT_MAX, 0,
 ("#include " + Spelled).str(;
   // "cleanup" actually turns the UINT_MAX replacements into concrete edits.
   auto Positioned = cantFail(format::cleanupAroundReplacements(Code, R, 
Style));
Index: 
clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
===
--- clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
+++ clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
@@ -79,7 +79,8 @@
 /// Removes unused includes and inserts missing ones in the main file.
 /// Returns the modified main-file code.
 /// The FormatStyle must be C++ or ObjC (to support include ordering).
-std::string fixIncludes(const AnalysisResults , llvm::StringRef Code,
+std::string fixIncludes(const AnalysisResults ,
+llvm::StringRef FileName, llvm::StringRef Code,
 const format::FormatStyle );
 
 /// Gets all the providers for a symbol by traversing each location.


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -274,7 +274,7 @@
 }
 
 TEST(FixIncludes, Basic) {
-  llvm::StringRef Code = R"cpp(
+  llvm::StringRef Code = R"cpp(#include "d.h"
 #include "a.h"
 #include "b.h"
 #include 
@@ -300,11 +300,22 @@
   

[PATCH] D154950: [include-cleaner] Fix the `fixIncludes` API not respect main-file header.

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp:303
 
-  EXPECT_EQ(fixIncludes(Results, Code, format::getLLVMStyle()), R"cpp(
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
+R"cpp(#include "d.h"

kadircet wrote:
> can you also have a test in which we insert "d.h" and it gets put into the 
> right place?
added a test with a FIXME -- unfortunately, this case doesn't work yet (I 
believe this is a bug in the `tooling::HeaderIncludes`, I plan to fix it 
afterwards.)




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154950

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


[PATCH] D154950: [include-cleaner] Fix the `fixIncludes` API not respect main-file header.

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 539045.
hokein added a comment.

add a testcase.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154950

Files:
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
  clang-tools-extra/include-cleaner/lib/Analysis.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -274,7 +274,7 @@
 }
 
 TEST(FixIncludes, Basic) {
-  llvm::StringRef Code = R"cpp(
+  llvm::StringRef Code = R"cpp(#include "d.h"
 #include "a.h"
 #include "b.h"
 #include 
@@ -300,11 +300,22 @@
   Results.Unused.push_back(Inc.atLine(3));
   Results.Unused.push_back(Inc.atLine(4));
 
-  EXPECT_EQ(fixIncludes(Results, Code, format::getLLVMStyle()), R"cpp(
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
+R"cpp(#include "d.h"
 #include "a.h"
 #include "aa.h"
 #include "ab.h"
 #include 
+)cpp");
+
+  Results = {};
+  Results.Missing.push_back("\"d.h\"");
+  Code = R"cpp(#include "a.h")cpp";
+  // FIXME: this isn't correct, the main-file header d.h should be added before
+  // a.h.
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
+R"cpp(#include "a.h"
+#include "d.h"
 )cpp");
 }
 
Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -164,7 +164,7 @@
   Results.Missing.clear();
 if (!Remove)
   Results.Unused.clear();
-std::string Final = fixIncludes(Results, Code, getStyle(Path));
+std::string Final = fixIncludes(Results, Path, Code, getStyle(Path));
 
 if (Print.getNumOccurrences()) {
   switch (Print) {
Index: clang-tools-extra/include-cleaner/lib/Analysis.cpp
===
--- clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -112,15 +112,16 @@
   return Results;
 }
 
-std::string fixIncludes(const AnalysisResults , llvm::StringRef Code,
+std::string fixIncludes(const AnalysisResults ,
+llvm::StringRef FileName, llvm::StringRef Code,
 const format::FormatStyle ) {
   assert(Style.isCpp() && "Only C++ style supports include insertions!");
   tooling::Replacements R;
   // Encode insertions/deletions in the magic way clang-format understands.
   for (const Include *I : Results.Unused)
-cantFail(R.add(tooling::Replacement("input", UINT_MAX, 1, I->quote(;
+cantFail(R.add(tooling::Replacement(FileName, UINT_MAX, 1, I->quote(;
   for (llvm::StringRef Spelled : Results.Missing)
-cantFail(R.add(tooling::Replacement("input", UINT_MAX, 0,
+cantFail(R.add(tooling::Replacement(FileName, UINT_MAX, 0,
 ("#include " + Spelled).str(;
   // "cleanup" actually turns the UINT_MAX replacements into concrete edits.
   auto Positioned = cantFail(format::cleanupAroundReplacements(Code, R, 
Style));
Index: 
clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
===
--- clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
+++ clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
@@ -79,7 +79,8 @@
 /// Removes unused includes and inserts missing ones in the main file.
 /// Returns the modified main-file code.
 /// The FormatStyle must be C++ or ObjC (to support include ordering).
-std::string fixIncludes(const AnalysisResults , llvm::StringRef Code,
+std::string fixIncludes(const AnalysisResults ,
+llvm::StringRef FileName, llvm::StringRef Code,
 const format::FormatStyle );
 
 /// Gets all the providers for a symbol by traversing each location.


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -274,7 +274,7 @@
 }
 
 TEST(FixIncludes, Basic) {
-  llvm::StringRef Code = R"cpp(
+  llvm::StringRef Code = R"cpp(#include "d.h"
 #include "a.h"
 #include "b.h"
 #include 
@@ -300,11 +300,22 @@
   Results.Unused.push_back(Inc.atLine(3));
   Results.Unused.push_back(Inc.atLine(4));
 
-  EXPECT_EQ(fixIncludes(Results, Code, format::getLLVMStyle()), R"cpp(
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, 

[PATCH] D154950: [include-cleaner] Fix the `fixIncludes` API not respect main-file header.

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang-tools-extra.

The fixIncludes was using the `input` as the main file path, this will
results in inserting header at wrong places.

We need the main file path to so that we can get the real main-file
header.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154950

Files:
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
  clang-tools-extra/include-cleaner/lib/Analysis.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
  clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -274,7 +274,7 @@
 }
 
 TEST(FixIncludes, Basic) {
-  llvm::StringRef Code = R"cpp(
+  llvm::StringRef Code = R"cpp(#include "d.h"
 #include "a.h"
 #include "b.h"
 #include 
@@ -300,7 +300,8 @@
   Results.Unused.push_back(Inc.atLine(3));
   Results.Unused.push_back(Inc.atLine(4));
 
-  EXPECT_EQ(fixIncludes(Results, Code, format::getLLVMStyle()), R"cpp(
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
+R"cpp(#include "d.h"
 #include "a.h"
 #include "aa.h"
 #include "ab.h"
Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -164,7 +164,7 @@
   Results.Missing.clear();
 if (!Remove)
   Results.Unused.clear();
-std::string Final = fixIncludes(Results, Code, getStyle(Path));
+std::string Final = fixIncludes(Results, Path, Code, getStyle(Path));
 
 if (Print.getNumOccurrences()) {
   switch (Print) {
Index: clang-tools-extra/include-cleaner/lib/Analysis.cpp
===
--- clang-tools-extra/include-cleaner/lib/Analysis.cpp
+++ clang-tools-extra/include-cleaner/lib/Analysis.cpp
@@ -112,15 +112,16 @@
   return Results;
 }
 
-std::string fixIncludes(const AnalysisResults , llvm::StringRef Code,
+std::string fixIncludes(const AnalysisResults ,
+llvm::StringRef FileName, llvm::StringRef Code,
 const format::FormatStyle ) {
   assert(Style.isCpp() && "Only C++ style supports include insertions!");
   tooling::Replacements R;
   // Encode insertions/deletions in the magic way clang-format understands.
   for (const Include *I : Results.Unused)
-cantFail(R.add(tooling::Replacement("input", UINT_MAX, 1, I->quote(;
+cantFail(R.add(tooling::Replacement(FileName, UINT_MAX, 1, I->quote(;
   for (llvm::StringRef Spelled : Results.Missing)
-cantFail(R.add(tooling::Replacement("input", UINT_MAX, 0,
+cantFail(R.add(tooling::Replacement(FileName, UINT_MAX, 0,
 ("#include " + Spelled).str(;
   // "cleanup" actually turns the UINT_MAX replacements into concrete edits.
   auto Positioned = cantFail(format::cleanupAroundReplacements(Code, R, 
Style));
Index: 
clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
===
--- clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
+++ clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
@@ -79,7 +79,8 @@
 /// Removes unused includes and inserts missing ones in the main file.
 /// Returns the modified main-file code.
 /// The FormatStyle must be C++ or ObjC (to support include ordering).
-std::string fixIncludes(const AnalysisResults , llvm::StringRef Code,
+std::string fixIncludes(const AnalysisResults ,
+llvm::StringRef FileName, llvm::StringRef Code,
 const format::FormatStyle );
 
 /// Gets all the providers for a symbol by traversing each location.


Index: clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
===
--- clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
+++ clang-tools-extra/include-cleaner/unittests/AnalysisTest.cpp
@@ -274,7 +274,7 @@
 }
 
 TEST(FixIncludes, Basic) {
-  llvm::StringRef Code = R"cpp(
+  llvm::StringRef Code = R"cpp(#include "d.h"
 #include "a.h"
 #include "b.h"
 #include 
@@ -300,7 +300,8 @@
   Results.Unused.push_back(Inc.atLine(3));
   Results.Unused.push_back(Inc.atLine(4));
 
-  EXPECT_EQ(fixIncludes(Results, Code, format::getLLVMStyle()), R"cpp(
+  EXPECT_EQ(fixIncludes(Results, "d.cc", Code, format::getLLVMStyle()),
+R"cpp(#include "d.h"
 #include "a.h"
 #include "aa.h"
 #include "ab.h"
Index: 

[PATCH] D154471: [clang] Add serialization support for the DynamicAllocLValue variant of APValue::LValueBase::Ptr

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

I gave it a try, here is a testcase that triggers the crash

  // clang -cc1 -emit-pch -o /tmp/t.pch /tmp/t.cpp
  #ifndef HEADER
  #define HEADER
  
  struct A {  int *p; };
  const A  = A{ new int(10) };
  
  #endif


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154471

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


[PATCH] D154471: [clang] Add serialization support for the DynamicAllocLValue variant of APValue::LValueBase::Ptr

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

I believe the fix is correct.

Though the fix has been verified by a real-world example, I think it would be 
nice to get a reproducible testcase. Looking at the stacktrace:

- the crash occurs during the pch deserialization
- and we miss handling the case where LValue base is a `DynamicAllocLValue`

so it looks like we can construct a `DynamicAllocLValue` case, and try to 
deserialize it (e.g. emitting a pch), and it should reproduce the crash.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154471

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


[PATCH] D154861: [clang][AST] Propagate the contains-errors bit to DeclRefExpr from VarDecl's initializer.

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9ca395b5ade1: [clang][AST] Propagate the contains-errors bit 
to DeclRefExpr from VarDecls… (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D154861?vs=538929=538931#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154861

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ComputeDependence.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/SemaCXX/cxx11-crashes.cpp


Index: clang/test/SemaCXX/cxx11-crashes.cpp
===
--- clang/test/SemaCXX/cxx11-crashes.cpp
+++ clang/test/SemaCXX/cxx11-crashes.cpp
@@ -65,7 +65,7 @@
   struct S {}; // expected-note 3{{candidate}}
   void f() {
 S s(1, 2, 3); // expected-error {{no matching}}
-for (auto x : s) { // expected-error {{invalid range expression of}}
+for (auto x : s) {
   // We used to attempt to evaluate the initializer of this variable,
   // and crash because it has an undeduced type.
   const int (x);
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -126,3 +126,25 @@
   // CHECK-NEXT:   `-RecoveryExpr {{.*}} ''
   sizeof array / sizeof foo(undef);
 }
+
+// No crash on DeclRefExpr that refers to ValueDecl with invalid initializers.
+void test7() {
+  int b[] = {""()};
+
+  // CHECK:  CStyleCastExpr {{.*}} 'unsigned int' contains-errors
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[]' contains-errors
+  (unsigned) b; // GH50236
+
+  // CHECK:  BinaryOperator {{.*}} '' contains-errors '+'
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int[]' contains-errors
+  // CHECK-NEXT: `-IntegerLiteral {{.*}}
+  b + 1; // GH50243
+
+  // CHECK:  CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int ()' Function
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int[]' contains-errors
+  return c(b); // GH48636
+}
+int test8_GH50320_b[] = {""()};
+// CHECK: ArraySubscriptExpr {{.*}} 'int' contains-errors lvalue
+int test8 = test_8GH50320_b[0];
Index: clang/lib/AST/ComputeDependence.cpp
===
--- clang/lib/AST/ComputeDependence.cpp
+++ clang/lib/AST/ComputeDependence.cpp
@@ -489,7 +489,7 @@
   // more bullets here that we handle by treating the declaration as having a
   // dependent type if they involve a placeholder type that can't be deduced.]
   if (Type->isDependentType())
-return Deps | ExprDependence::TypeValueInstantiation;
+Deps |= ExprDependence::TypeValueInstantiation;
   else if (Type->isInstantiationDependentType())
 Deps |= ExprDependence::Instantiation;
 
@@ -525,13 +525,13 @@
   //   - it names a potentially-constant variable that is initialized with an
   // expression that is value-dependent
   if (const auto *Var = dyn_cast(Decl)) {
-if (Var->mightBeUsableInConstantExpressions(Ctx)) {
-  if (const Expr *Init = Var->getAnyInitializer()) {
-if (Init->isValueDependent())
-  Deps |= ExprDependence::ValueInstantiation;
-if (Init->containsErrors())
-  Deps |= ExprDependence::Error;
-  }
+if (const Expr *Init = Var->getAnyInitializer()) {
+  if (Init->containsErrors())
+Deps |= ExprDependence::Error;
+
+  if (Var->mightBeUsableInConstantExpressions(Ctx) &&
+  Init->isValueDependent())
+Deps |= ExprDependence::ValueInstantiation;
 }
 
 // - it names a static data member that is a dependent member of the
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -576,6 +576,12 @@
 - Fixed false positive error diagnostic when pack expansion appears in template
   parameters of a member expression.
   (`#48731 `_)
+- Fix the contains-errors bit not being set for DeclRefExpr that refers to a
+  VarDecl with invalid initializer. This fixes:
+  (`#50236 `_),
+  (`#50243 `_),
+  (`#48636 `_),
+  (`#50320 `_).
 
 Bug Fixes to Compiler Builtins
 ^^


Index: clang/test/SemaCXX/cxx11-crashes.cpp
===
--- clang/test/SemaCXX/cxx11-crashes.cpp
+++ clang/test/SemaCXX/cxx11-crashes.cpp
@@ -65,7 +65,7 @@
   struct S {}; // expected-note 3{{candidate}}
   void f() {
 S s(1, 2, 3); // expected-error {{no matching}}
-for (auto x : s) { // expected-error 

[PATCH] D154861: [clang][AST] Propagate the contains-errors bit to DeclRefExpr from VarDecl's initializer.

2023-07-11 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 538929.
hokein marked 2 inline comments as done.
hokein added a comment.

address comments and add release note.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154861

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ComputeDependence.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/SemaCXX/cxx11-crashes.cpp


Index: clang/test/SemaCXX/cxx11-crashes.cpp
===
--- clang/test/SemaCXX/cxx11-crashes.cpp
+++ clang/test/SemaCXX/cxx11-crashes.cpp
@@ -65,7 +65,7 @@
   struct S {}; // expected-note 3{{candidate}}
   void f() {
 S s(1, 2, 3); // expected-error {{no matching}}
-for (auto x : s) { // expected-error {{invalid range expression of}}
+for (auto x : s) {
   // We used to attempt to evaluate the initializer of this variable,
   // and crash because it has an undeduced type.
   const int (x);
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -126,3 +126,25 @@
   // CHECK-NEXT:   `-RecoveryExpr {{.*}} ''
   sizeof array / sizeof foo(undef);
 }
+
+// No crash on DeclRefExpr that refers to ValueDecl with invalid initializers.
+void test7() {
+  int b[] = {""()};
+
+  // CHECK:  CStyleCastExpr {{.*}} 'unsigned int' contains-errors
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[]' contains-errors
+  (unsigned) b; // GH50236
+
+  // CHECK:  BinaryOperator {{.*}} '' contains-errors '+'
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int[]' contains-errors
+  // CHECK-NEXT: `-IntegerLiteral {{.*}}
+  b + 1; // GH50243
+
+  // CHECK:  CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int ()' Function
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int[]' contains-errors
+  return c(b); // GH48636
+}
+int test8_GH50320_b[] = {""()};
+// CHECK: ArraySubscriptExpr {{.*}} 'int' contains-errors lvalue
+int test8 = test_8GH50320_b[0];
Index: clang/lib/AST/ComputeDependence.cpp
===
--- clang/lib/AST/ComputeDependence.cpp
+++ clang/lib/AST/ComputeDependence.cpp
@@ -489,7 +489,7 @@
   // more bullets here that we handle by treating the declaration as having a
   // dependent type if they involve a placeholder type that can't be deduced.]
   if (Type->isDependentType())
-return Deps | ExprDependence::TypeValueInstantiation;
+Deps |= ExprDependence::TypeValueInstantiation;
   else if (Type->isInstantiationDependentType())
 Deps |= ExprDependence::Instantiation;
 
@@ -525,13 +525,13 @@
   //   - it names a potentially-constant variable that is initialized with an
   // expression that is value-dependent
   if (const auto *Var = dyn_cast(Decl)) {
-if (Var->mightBeUsableInConstantExpressions(Ctx)) {
-  if (const Expr *Init = Var->getAnyInitializer()) {
-if (Init->isValueDependent())
-  Deps |= ExprDependence::ValueInstantiation;
-if (Init->containsErrors())
-  Deps |= ExprDependence::Error;
-  }
+if (const Expr *Init = Var->getAnyInitializer()) {
+  if (Init->containsErrors())
+Deps |= ExprDependence::Error;
+
+  if (Var->mightBeUsableInConstantExpressions(Ctx) &&
+  Init->isValueDependent())
+Deps |= ExprDependence::ValueInstantiation;
 }
 
 // - it names a static data member that is a dependent member of the
Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -573,6 +573,12 @@
 - Stop evaluating a constant expression if the condition expression which in
   switch statement contains errors.
   (`#63453 _`)
+- Fix the contains-errors bit not being set for DeclRefExpr that refers to a
+  VarDecl with invalid initializer. This fixes:
+  (`#50236 `_),
+  (`#50243 `_),
+  (`#48636 `_),
+  (`#50320 `_).
 
 Bug Fixes to Compiler Builtins
 ^^


Index: clang/test/SemaCXX/cxx11-crashes.cpp
===
--- clang/test/SemaCXX/cxx11-crashes.cpp
+++ clang/test/SemaCXX/cxx11-crashes.cpp
@@ -65,7 +65,7 @@
   struct S {}; // expected-note 3{{candidate}}
   void f() {
 S s(1, 2, 3); // expected-error {{no matching}}
-for (auto x : s) { // expected-error {{invalid range expression of}}
+for (auto x : s) {
   // We used to attempt to evaluate the initializer of this variable,
   // and crash because it has an undeduced type.
   const int 

[PATCH] D154861: [clang][AST] Propagate the contains-errors bit to DeclRefExpr from VarDecl's initializer.

2023-07-10 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added reviewers: aaron.ballman, shafik, sammccall.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang.

Similar to the https://reviews.llvm.org/D86048 (it only sets the bit for C++
code), we propagate the contains-errors bit for C-code path.

Fixes https://github.com/llvm/llvm-project/issues/50236
Fixes https://github.com/llvm/llvm-project/issues/50243
Fixes https://github.com/llvm/llvm-project/issues/48636
Fixes https://github.com/llvm/llvm-project/issues/50320


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154861

Files:
  clang/lib/AST/ComputeDependence.cpp
  clang/test/AST/ast-dump-recovery.c
  clang/test/SemaCXX/cxx11-crashes.cpp


Index: clang/test/SemaCXX/cxx11-crashes.cpp
===
--- clang/test/SemaCXX/cxx11-crashes.cpp
+++ clang/test/SemaCXX/cxx11-crashes.cpp
@@ -65,7 +65,7 @@
   struct S {}; // expected-note 3{{candidate}}
   void f() {
 S s(1, 2, 3); // expected-error {{no matching}}
-for (auto x : s) { // expected-error {{invalid range expression of}}
+for (auto x : s) {
   // We used to attempt to evaluate the initializer of this variable,
   // and crash because it has an undeduced type.
   const int (x);
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -126,3 +126,25 @@
   // CHECK-NEXT:   `-RecoveryExpr {{.*}} ''
   sizeof array / sizeof foo(undef);
 }
+
+// No crash on DeclRefExpr that refers to ValueDecl with invalid initializers.
+void test7() {
+  int b[] = {""()};
+
+  // CHECK:  CStyleCastExpr {{.*}} 'unsigned int' contains-errors
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[]' contains-errors
+  (unsigned) b; // GH50236
+
+  // CHECK:  BinaryOperator {{.*}} '' contains-errors '+'
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int[]' contains-errors
+  // CHECK-NEXT: `-IntegerLiteral {{.*}}
+  b + 1; // GH50243
+
+  // CHECK:  CallExpr {{.*}} '' contains-errors
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int ()' Function
+  // CHECK-NEXT: `-DeclRefExpr {{.*}} 'int[]' contains-errors
+  return c(b); // GH48636
+}
+int test8_GH50320_b[] = {""()};
+// CHECK: ArraySubscriptExpr {{.*}} 'int' contains-errors lvalue
+int test8 = test_8GH50320_b[0];
\ No newline at end of file
Index: clang/lib/AST/ComputeDependence.cpp
===
--- clang/lib/AST/ComputeDependence.cpp
+++ clang/lib/AST/ComputeDependence.cpp
@@ -489,7 +489,7 @@
   // more bullets here that we handle by treating the declaration as having a
   // dependent type if they involve a placeholder type that can't be deduced.]
   if (Type->isDependentType())
-return Deps | ExprDependence::TypeValueInstantiation;
+Deps |= ExprDependence::TypeValueInstantiation;
   else if (Type->isInstantiationDependentType())
 Deps |= ExprDependence::Instantiation;
 
@@ -525,12 +525,14 @@
   //   - it names a potentially-constant variable that is initialized with an
   // expression that is value-dependent
   if (const auto *Var = dyn_cast(Decl)) {
+if (const Expr *Init = Var->getAnyInitializer();
+Init && Init->containsErrors())
+  Deps |= ExprDependence::Error;
+
 if (Var->mightBeUsableInConstantExpressions(Ctx)) {
   if (const Expr *Init = Var->getAnyInitializer()) {
 if (Init->isValueDependent())
   Deps |= ExprDependence::ValueInstantiation;
-if (Init->containsErrors())
-  Deps |= ExprDependence::Error;
   }
 }
 


Index: clang/test/SemaCXX/cxx11-crashes.cpp
===
--- clang/test/SemaCXX/cxx11-crashes.cpp
+++ clang/test/SemaCXX/cxx11-crashes.cpp
@@ -65,7 +65,7 @@
   struct S {}; // expected-note 3{{candidate}}
   void f() {
 S s(1, 2, 3); // expected-error {{no matching}}
-for (auto x : s) { // expected-error {{invalid range expression of}}
+for (auto x : s) {
   // We used to attempt to evaluate the initializer of this variable,
   // and crash because it has an undeduced type.
   const int (x);
Index: clang/test/AST/ast-dump-recovery.c
===
--- clang/test/AST/ast-dump-recovery.c
+++ clang/test/AST/ast-dump-recovery.c
@@ -126,3 +126,25 @@
   // CHECK-NEXT:   `-RecoveryExpr {{.*}} ''
   sizeof array / sizeof foo(undef);
 }
+
+// No crash on DeclRefExpr that refers to ValueDecl with invalid initializers.
+void test7() {
+  int b[] = {""()};
+
+  // CHECK:  CStyleCastExpr {{.*}} 'unsigned int' contains-errors
+  // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'int[]' contains-errors
+  (unsigned) b; // GH50236
+
+  // CHECK:  BinaryOperator {{.*}} '' contains-errors '+'
+  // CHECK-NEXT: |-DeclRefExpr {{.*}} 'int[]' contains-errors
+  // 

[PATCH] D153296: [AST] Stop evaluate constant expression if the condition expression which in switch statement contains errors

2023-07-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D153296#4480141 , @yronglin wrote:

> In D153296#4479718 , @hokein wrote:
>
>> Thanks, this looks good.
>
> Thanks for your review! I don't know why the reversion status still `Needs 
> Review`, and the `libcxx ci` often fails to start.

I guess the `Needs Review` is probably caused by the previous "Requested 
Changes" by Aaron.
The `libcxx ci` failure doesn't seem to be relevant. I think we're all on the 
same page about the fix, it is fine to land it assuming that the `ninja 
check-clang` passes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153296

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


[PATCH] D153296: [AST] Stop evaluate constant expression if the condition expression which in switch statement contains errors

2023-07-07 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.

Thanks, this looks good.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153296

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


[PATCH] D153740: [llvm][Support] Deprecate llvm::writeFileAtomically API

2023-07-06 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
hokein marked an inline comment as done.
Closed by commit rG7aafea001282: [llvm][Support] Deprecate 
llvm::writeFileAtomically API (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153740

Files:
  llvm/include/llvm/Support/FileUtilities.h
  llvm/lib/Support/FileUtilities.cpp
  llvm/unittests/Support/CMakeLists.txt
  llvm/unittests/Support/FileUtilitiesTest.cpp

Index: llvm/unittests/Support/FileUtilitiesTest.cpp
===
--- llvm/unittests/Support/FileUtilitiesTest.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- llvm/unittest/Support/FileUtilitiesTest.cpp - unit tests ---===//
-//
-// 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
-//
-//===--===//
-
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Testing/Support/SupportHelpers.h"
-#include "gtest/gtest.h"
-#include 
-
-using namespace llvm;
-using namespace llvm::sys;
-
-using llvm::unittest::TempDir;
-
-#define ASSERT_NO_ERROR(x) \
-  if (std::error_code ASSERT_NO_ERROR_ec = x) {\
-SmallString<128> MessageStorage;   \
-raw_svector_ostream Message(MessageStorage);   \
-Message << #x ": did not return errc::success.\n"  \
-<< "error number: " << ASSERT_NO_ERROR_ec.value() << "\n"  \
-<< "error message: " << ASSERT_NO_ERROR_ec.message() << "\n";  \
-GTEST_FATAL_FAILURE_(MessageStorage.c_str());  \
-  } else { \
-  }
-
-namespace {
-TEST(writeFileAtomicallyTest, Test) {
-  // Create unique temporary directory for these tests
-  TempDir RootTestDirectory("writeFileAtomicallyTest", /*Unique*/ true);
-
-  SmallString<128> FinalTestfilePath(RootTestDirectory.path());
-  sys::path::append(FinalTestfilePath, "foo.txt");
-  const std::string TempUniqTestFileModel =
-  std::string(FinalTestfilePath) + "-";
-  const std::string TestfileContent = "fooFOOfoo";
-
-  llvm::Error Err = llvm::writeFileAtomically(TempUniqTestFileModel, FinalTestfilePath, TestfileContent);
-  ASSERT_FALSE(static_cast(Err));
-
-  std::ifstream FinalFileStream(std::string(FinalTestfilePath.str()));
-  std::string FinalFileContent;
-  FinalFileStream >> FinalFileContent;
-  ASSERT_EQ(FinalFileContent, TestfileContent);
-}
-} // anonymous namespace
Index: llvm/unittests/Support/CMakeLists.txt
===
--- llvm/unittests/Support/CMakeLists.txt
+++ llvm/unittests/Support/CMakeLists.txt
@@ -41,7 +41,6 @@
   ExtensibleRTTITest.cpp
   FileCollectorTest.cpp
   FileOutputBufferTest.cpp
-  FileUtilitiesTest.cpp
   FormatVariadicTest.cpp
   FSUniqueIDTest.cpp
   GlobPatternTest.cpp
Index: llvm/lib/Support/FileUtilities.cpp
===
--- llvm/lib/Support/FileUtilities.cpp
+++ llvm/lib/Support/FileUtilities.cpp
@@ -267,64 +267,6 @@
   return CompareFailed;
 }
 
-void llvm::AtomicFileWriteError::log(raw_ostream ) const {
-  OS << "atomic_write_error: ";
-  switch (Error) {
-  case atomic_write_error::failed_to_create_uniq_file:
-OS << "failed_to_create_uniq_file";
-return;
-  case atomic_write_error::output_stream_error:
-OS << "output_stream_error";
-return;
-  case atomic_write_error::failed_to_rename_temp_file:
-OS << "failed_to_rename_temp_file";
-return;
-  }
-  llvm_unreachable("unknown atomic_write_error value in "
-   "failed_to_rename_temp_file::log()");
-}
-
-llvm::Error llvm::writeFileAtomically(StringRef TempPathModel,
-  StringRef FinalPath, StringRef Buffer) {
-  return writeFileAtomically(TempPathModel, FinalPath,
- [](llvm::raw_ostream ) {
-   OS.write(Buffer.data(), Buffer.size());
-   return llvm::Error::success();
- });
-}
-
-llvm::Error llvm::writeFileAtomically(
-StringRef TempPathModel, StringRef FinalPath,
-std::function Writer) {
-  SmallString<128> GeneratedUniqPath;
-  int TempFD;
-  if (sys::fs::createUniqueFile(TempPathModel, TempFD, 

[PATCH] D153340: [include-cleaner] Add an IgnoreHeaders flag to the command-line tool.

2023-07-06 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG507d766d76d8: [include-cleaner] Add an IgnoreHeaders flag to 
the command-line tool. (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D153340?vs=537631=537634#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153340

Files:
  clang-tools-extra/clangd/IncludeCleaner.cpp
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h
  clang-tools-extra/include-cleaner/lib/Analysis.cpp
  clang-tools-extra/include-cleaner/lib/Types.cpp
  clang-tools-extra/include-cleaner/test/tool.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp

Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -14,10 +14,19 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Regex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+#include 
+#include 
+#include 
 
 namespace clang {
 namespace include_cleaner {
@@ -47,6 +56,14 @@
 cl::cat(IncludeCleaner),
 };
 
+cl::opt IgnoreHeaders{
+"ignore-headers",
+cl::desc("A comma-separated list of regexes to match against suffix of a "
+ "header, and disable analysis if matched."),
+cl::init(""),
+cl::cat(IncludeCleaner),
+};
+
 enum class PrintStyle { Changes, Final };
 cl::opt Print{
 "print",
@@ -91,9 +108,15 @@
 }
 
 class Action : public clang::ASTFrontendAction {
+public:
+  Action(llvm::function_ref HeaderFilter)
+  : HeaderFilter(HeaderFilter){};
+
+private:
   RecordedAST AST;
   RecordedPP PP;
   PragmaIncludes PI;
+  llvm::function_ref HeaderFilter;
 
   bool BeginInvocation(CompilerInstance ) override {
 // We only perform include-cleaner analysis. So we disable diagnostics that
@@ -135,8 +158,8 @@
 assert(!Path.empty() && "Main file path not known?");
 llvm::StringRef Code = SM.getBufferData(SM.getMainFileID());
 
-auto Results =
-analyze(AST.Roots, PP.MacroReferences, PP.Includes, , SM, HS);
+auto Results = analyze(AST.Roots, PP.MacroReferences, PP.Includes, , SM,
+   HS, HeaderFilter);
 if (!Insert)
   Results.Missing.clear();
 if (!Remove)
@@ -185,6 +208,43 @@
 getCompilerInstance().getPreprocessor().getHeaderSearchInfo(), , OS);
   }
 };
+class ActionFactory : public tooling::FrontendActionFactory {
+public:
+  ActionFactory(llvm::function_ref HeaderFilter)
+  : HeaderFilter(HeaderFilter) {}
+
+  std::unique_ptr create() override {
+return std::make_unique(HeaderFilter);
+  }
+
+private:
+  llvm::function_ref HeaderFilter;
+};
+
+std::function headerFilter() {
+  auto FilterRegs = std::make_shared>();
+
+  llvm::SmallVector Headers;
+  llvm::StringRef(IgnoreHeaders).split(Headers, ',', -1, /*KeepEmpty=*/false);
+  for (auto HeaderPattern : Headers) {
+std::string AnchoredPattern = "(" + HeaderPattern.str() + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  llvm::errs() << llvm::formatv("Invalid regular expression '{0}': {1}\n",
+HeaderPattern, RegexError);
+  return nullptr;
+}
+FilterRegs->push_back(std::move(CompiledRegex));
+  }
+  return [FilterRegs](llvm::StringRef Path) {
+for (const auto  : *FilterRegs) {
+  if (F.match(Path))
+return true;
+}
+return false;
+  };
+}
 
 } // namespace
 } // namespace include_cleaner
@@ -210,9 +270,10 @@
   }
 }
   }
-  auto Factory = clang::tooling::newFrontendActionFactory();
+  auto HeaderFilter = headerFilter();
+  ActionFactory Factory(HeaderFilter);
   return clang::tooling::ClangTool(OptionsParser->getCompilations(),
OptionsParser->getSourcePathList())
- .run(Factory.get()) ||
+ .run() ||
  Errors != 0;
 }
Index: clang-tools-extra/include-cleaner/test/tool.cpp
===
--- clang-tools-extra/include-cleaner/test/tool.cpp
+++ clang-tools-extra/include-cleaner/test/tool.cpp
@@ -14,6 +14,14 @@
 //  REMOVE: - "foobar.h"
 //  REMOVE-NOT: + "foo.h"
 
+//RUN: clang-include-cleaner -print=changes %s 

[PATCH] D153340: [include-cleaner] Add an IgnoreHeaders flag to the command-line tool.

2023-07-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp:231
+  }
+  return [FilterRegs](llvm::StringRef Path) {
+llvm::errs() << "Path: " << Path << "\n";

kadircet wrote:
> `FilterRegs=std::move(FilterRegs)` and drop the `shared_ptr`?
This was my first attempt, it didn't work, we're returning a lamdba function, 
which invokes a delete constructor of `llvm::Regex`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153340

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


[PATCH] D153340: [include-cleaner] Add an IgnoreHeaders flag to the command-line tool.

2023-07-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 537631.
hokein marked 5 inline comments as done.
hokein added a comment.

address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153340

Files:
  clang-tools-extra/clangd/IncludeCleaner.cpp
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h
  clang-tools-extra/include-cleaner/lib/Analysis.cpp
  clang-tools-extra/include-cleaner/lib/Types.cpp
  clang-tools-extra/include-cleaner/test/tool.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp

Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -14,10 +14,19 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Regex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+#include 
+#include 
+#include 
 
 namespace clang {
 namespace include_cleaner {
@@ -47,6 +56,14 @@
 cl::cat(IncludeCleaner),
 };
 
+cl::opt IgnoreHeaders{
+"ignore-headers",
+cl::desc("A comma-separated list of regexes to match against suffix of a "
+ "header, and disable analysis if matched."),
+cl::init(""),
+cl::cat(IncludeCleaner),
+};
+
 enum class PrintStyle { Changes, Final };
 cl::opt Print{
 "print",
@@ -91,9 +108,15 @@
 }
 
 class Action : public clang::ASTFrontendAction {
+public:
+  Action(llvm::function_ref HeaderFilter)
+  : HeaderFilter(HeaderFilter){};
+
+private:
   RecordedAST AST;
   RecordedPP PP;
   PragmaIncludes PI;
+  llvm::function_ref HeaderFilter;
 
   bool BeginInvocation(CompilerInstance ) override {
 // We only perform include-cleaner analysis. So we disable diagnostics that
@@ -135,8 +158,8 @@
 assert(!Path.empty() && "Main file path not known?");
 llvm::StringRef Code = SM.getBufferData(SM.getMainFileID());
 
-auto Results =
-analyze(AST.Roots, PP.MacroReferences, PP.Includes, , SM, HS);
+auto Results = analyze(AST.Roots, PP.MacroReferences, PP.Includes, , SM,
+   HS, HeaderFilter);
 if (!Insert)
   Results.Missing.clear();
 if (!Remove)
@@ -185,6 +208,43 @@
 getCompilerInstance().getPreprocessor().getHeaderSearchInfo(), , OS);
   }
 };
+class ActionFactory : public tooling::FrontendActionFactory {
+public:
+  ActionFactory(llvm::function_ref HeaderFilter)
+  : HeaderFilter(HeaderFilter) {}
+
+  std::unique_ptr create() override {
+return std::make_unique(HeaderFilter);
+  }
+
+private:
+  llvm::function_ref HeaderFilter;
+};
+
+std::function headerFilter() {
+  auto FilterRegs = std::make_shared>();
+
+  llvm::SmallVector Headers;
+  llvm::StringRef(IgnoreHeaders).split(Headers, ',', -1, /*KeepEmpty=*/false);
+  for (auto HeaderPattern : Headers) {
+std::string AnchoredPattern = "(" + HeaderPattern.str() + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  llvm::errs() << llvm::formatv("Invalid regular expression '{0}': {1}\n",
+HeaderPattern, RegexError);
+  return nullptr;
+}
+FilterRegs->push_back(std::move(CompiledRegex));
+  }
+  return [FilterRegs](llvm::StringRef Path) {
+for (const auto  : *FilterRegs) {
+  if (F.match(Path))
+return true;
+}
+return false;
+  };
+}
 
 } // namespace
 } // namespace include_cleaner
@@ -200,7 +260,6 @@
 llvm::errs() << toString(OptionsParser.takeError());
 return 1;
   }
-
   if (OptionsParser->getSourcePathList().size() != 1) {
 std::vector IncompatibleFlags = {, };
 for (const auto *Flag : IncompatibleFlags) {
@@ -210,9 +269,10 @@
   }
 }
   }
-  auto Factory = clang::tooling::newFrontendActionFactory();
+  auto HeaderFilter = headerFilter();
+  ActionFactory Factory(HeaderFilter);
   return clang::tooling::ClangTool(OptionsParser->getCompilations(),
OptionsParser->getSourcePathList())
- .run(Factory.get()) ||
+ .run() ||
  Errors != 0;
 }
Index: clang-tools-extra/include-cleaner/test/tool.cpp
===
--- clang-tools-extra/include-cleaner/test/tool.cpp
+++ clang-tools-extra/include-cleaner/test/tool.cpp
@@ -14,6 +14,14 @@
 //  REMOVE: - "foobar.h"
 //  REMOVE-NOT: + "foo.h"
 
+//RUN: clang-include-cleaner 

[PATCH] D153296: [AST] Stop evaluate constant expression if the condition expression which in switch statement contains errors

2023-07-06 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:4921
+  // value is.
+  if (isa(E))
+return false;

aaron.ballman wrote:
> hokein wrote:
> > hokein wrote:
> > > hokein wrote:
> > > > yronglin wrote:
> > > > > yronglin wrote:
> > > > > > aaron.ballman wrote:
> > > > > > > yronglin wrote:
> > > > > > > > hokein wrote:
> > > > > > > > > The constant evaluator is not aware of the "error" concept, 
> > > > > > > > > it is only aware of value-dependent -- the general idea 
> > > > > > > > > behind is that we treat the dependent-on-error and 
> > > > > > > > > dependent-on-template-parameters cases the same, they are 
> > > > > > > > > potentially constant (if we see an expression contains 
> > > > > > > > > errors, it could be constant depending on how the error is 
> > > > > > > > > resolved), this will give us nice recovery and avoid bogus 
> > > > > > > > > following diagnostics.
> > > > > > > > > 
> > > > > > > > > So, a `RecoveryExpr` should not result in failure when 
> > > > > > > > > checking for a potential constant expression.
> > > > > > > > > 
> > > > > > > > > I think the right fix is to remove the conditional check `if 
> > > > > > > > > (!EvaluateDependentExpr(SS->getCond(), Info))` in 
> > > > > > > > > `EvaluateSwitch`, and return `ESR_Failed` unconditionally (we 
> > > > > > > > > don't know its value, any switch-case anwser will be wrong in 
> > > > > > > > > some cases). We already do this for return-statment, 
> > > > > > > > > do-statement etc.
> > > > > > > > > 
> > > > > > > > > 
> > > > > > > > Do you mean?
> > > > > > > > ```
> > > > > > > > if (SS->getCond()->isValueDependent()) {
> > > > > > > > EvaluateDependentExpr(SS->getCond(), Info);
> > > > > > > > return ESR_Failed;
> > > > > > > > }
> > > > > > > > ```
> > > > > > > > the general idea behind is that we treat the dependent-on-error 
> > > > > > > > and dependent-on-template-parameters cases the same, they are 
> > > > > > > > potentially constant (if we see an expression contains errors, 
> > > > > > > > it could be constant depending on how the error is resolved), 
> > > > > > > > this will give us nice recovery and avoid bogus following 
> > > > > > > > diagnostics.
> > > > > > > 
> > > > > > > I could use some further education on why this is the correct 
> > > > > > > approach. For a dependent-on-template-parameters case, this makes 
> > > > > > > sense -- either the template will be instantiated (at which point 
> > > > > > > we'll know if it's a constant expression) or it won't be (at 
> > > > > > > which point it's constant expression-ness doesn't matter). But 
> > > > > > > for error recovery, we will *never* get a valid constant 
> > > > > > > expression.
> > > > > > > 
> > > > > > > I worry about the performance overhead of continuing on with 
> > > > > > > constant expression evaluation in the error case. We use these 
> > > > > > > code paths not only to get a value but to say "is this a constant 
> > > > > > > expression at all?".
> > > > > > > 
> > > > > > > I don't see why the fix should be localized to just the switch 
> > > > > > > statement condition; it seems like *any* attempt to get a 
> > > > > > > dependent value from an error recovery expression is a point at 
> > > > > > > which we can definitively say "this is not a constant expression" 
> > > > > > > and move on.
> > > > > > I understand that continuing to perform constant evaluation when an 
> > > > > > error occurs can bring more additional diagnostic information (such 
> > > > > > as jumping to the default branch to continue calculation when the 
> > > > > > condition expression evaluation of switch-statement fails), but the 
> > > > > > additional diagnostic message that is emitted is in some cases 
> > > > > > doesn't usually useful, and as Aaron said may affect performance of 
> > > > > > clang. I don't have enough experience to make a tradeoff between 
> > > > > > the two. BTW 
> > > > > > https://github.com/llvm/llvm-project/blob/843ff7581408a02e852c0f1f7ebf176cabbc7527/clang/lib/Parse/ParseStmt.cpp#L1894-L1909
> > > > > >  I don't quite understand why a RecoveryExpr is not created here, 
> > > > > > which caused to the whole do statement disappears on the 
> > > > > > AST(https://godbolt.org/z/PsPb31YKP), should we fix this? 
> > > > > Thanks a lot for your comments! @aaron.ballman 
> > > > > But for error recovery, we will *never* get a valid constant 
> > > > > expression.
> > > > 
> > > > Yeah, this is true, and we don't evaluate these error-dependent 
> > > > expressions.
> > > > 
> > > > I think the question here is that when we encounter an error-dependent 
> > > > expression during a constant expression evaluation, do we want to 
> > > > bailout the whole evaluation immediately, or just ignore the evaluation 
> > > > of this error-dependent expression and continue to proceed when 
> > > > possible?
> > > > 
> > > > We choose 2) -- this was based on the discussion 

[PATCH] D154349: [include-cleaner] Add a signal to down-rank exporting headers

2023-07-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added a comment.
This revision is now accepted and ready to land.

Thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154349

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


[PATCH] D154477: [include-cleaner] Ignore the layering-violation errors for the standalone tool

2023-07-05 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG67e94c9dc8ff: [include-cleaner] Ignore the 
layering-violation errors for the standalone tool (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D154477?vs=537240=537292#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154477

Files:
  clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
  clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
  clang-tools-extra/include-cleaner/test/module.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -95,6 +95,15 @@
   RecordedPP PP;
   PragmaIncludes PI;
 
+  bool BeginInvocation(CompilerInstance ) override {
+// We only perform include-cleaner analysis. So we disable diagnostics that
+// won't affect our analysis to make the tool more robust against
+// in-development code.
+CI.getLangOpts().ModulesDeclUse = false;
+CI.getLangOpts().ModulesStrictDeclUse = false;
+return true;
+  }
+
   void ExecuteAction() override {
 auto  = getCompilerInstance().getPreprocessor();
 P.addPPCallbacks(PP.record(P));
Index: clang-tools-extra/include-cleaner/test/module.cpp
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/module.cpp
@@ -0,0 +1,7 @@
+// RUN: cp %s %t.cpp
+// RUN: clang-include-cleaner -edit %t.cpp -- -I%S/Inputs/modules 
-fimplicit-module-maps -fmodules-strict-decluse -fmodule-name=XA
+// RUN: FileCheck --match-full-lines --check-prefix=EDIT %s < %t.cpp
+
+// Verify the tool still works on compilable-but-layering-violation code.
+#include "a.h"
+// EDIT-NOT: {{^}}#include "a.h"{{$}}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
@@ -0,0 +1,2 @@
+module XA {
+}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
@@ -0,0 +1,2 @@
+#pragma once
+class A {};


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -95,6 +95,15 @@
   RecordedPP PP;
   PragmaIncludes PI;
 
+  bool BeginInvocation(CompilerInstance ) override {
+// We only perform include-cleaner analysis. So we disable diagnostics that
+// won't affect our analysis to make the tool more robust against
+// in-development code.
+CI.getLangOpts().ModulesDeclUse = false;
+CI.getLangOpts().ModulesStrictDeclUse = false;
+return true;
+  }
+
   void ExecuteAction() override {
 auto  = getCompilerInstance().getPreprocessor();
 P.addPPCallbacks(PP.record(P));
Index: clang-tools-extra/include-cleaner/test/module.cpp
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/module.cpp
@@ -0,0 +1,7 @@
+// RUN: cp %s %t.cpp
+// RUN: clang-include-cleaner -edit %t.cpp -- -I%S/Inputs/modules -fimplicit-module-maps -fmodules-strict-decluse -fmodule-name=XA
+// RUN: FileCheck --match-full-lines --check-prefix=EDIT %s < %t.cpp
+
+// Verify the tool still works on compilable-but-layering-violation code.
+#include "a.h"
+// EDIT-NOT: {{^}}#include "a.h"{{$}}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
@@ -0,0 +1,2 @@
+module XA {
+}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
@@ -0,0 +1,2 @@
+#pragma once
+class A {};
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153296: [AST] Stop evaluate constant expression if the condition expression which in switch statement contains errors

2023-07-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:4921
+  // value is.
+  if (isa(E))
+return false;

yronglin wrote:
> yronglin wrote:
> > aaron.ballman wrote:
> > > yronglin wrote:
> > > > hokein wrote:
> > > > > The constant evaluator is not aware of the "error" concept, it is 
> > > > > only aware of value-dependent -- the general idea behind is that we 
> > > > > treat the dependent-on-error and dependent-on-template-parameters 
> > > > > cases the same, they are potentially constant (if we see an 
> > > > > expression contains errors, it could be constant depending on how the 
> > > > > error is resolved), this will give us nice recovery and avoid bogus 
> > > > > following diagnostics.
> > > > > 
> > > > > So, a `RecoveryExpr` should not result in failure when checking for a 
> > > > > potential constant expression.
> > > > > 
> > > > > I think the right fix is to remove the conditional check `if 
> > > > > (!EvaluateDependentExpr(SS->getCond(), Info))` in `EvaluateSwitch`, 
> > > > > and return `ESR_Failed` unconditionally (we don't know its value, any 
> > > > > switch-case anwser will be wrong in some cases). We already do this 
> > > > > for return-statment, do-statement etc.
> > > > > 
> > > > > 
> > > > Do you mean?
> > > > ```
> > > > if (SS->getCond()->isValueDependent()) {
> > > > EvaluateDependentExpr(SS->getCond(), Info);
> > > > return ESR_Failed;
> > > > }
> > > > ```
> > > > the general idea behind is that we treat the dependent-on-error and 
> > > > dependent-on-template-parameters cases the same, they are potentially 
> > > > constant (if we see an expression contains errors, it could be constant 
> > > > depending on how the error is resolved), this will give us nice 
> > > > recovery and avoid bogus following diagnostics.
> > > 
> > > I could use some further education on why this is the correct approach. 
> > > For a dependent-on-template-parameters case, this makes sense -- either 
> > > the template will be instantiated (at which point we'll know if it's a 
> > > constant expression) or it won't be (at which point it's constant 
> > > expression-ness doesn't matter). But for error recovery, we will *never* 
> > > get a valid constant expression.
> > > 
> > > I worry about the performance overhead of continuing on with constant 
> > > expression evaluation in the error case. We use these code paths not only 
> > > to get a value but to say "is this a constant expression at all?".
> > > 
> > > I don't see why the fix should be localized to just the switch statement 
> > > condition; it seems like *any* attempt to get a dependent value from an 
> > > error recovery expression is a point at which we can definitively say 
> > > "this is not a constant expression" and move on.
> > I understand that continuing to perform constant evaluation when an error 
> > occurs can bring more additional diagnostic information (such as jumping to 
> > the default branch to continue calculation when the condition expression 
> > evaluation of switch-statement fails), but the additional diagnostic 
> > message that is emitted is in some cases doesn't usually useful, and as 
> > Aaron said may affect performance of clang. I don't have enough experience 
> > to make a tradeoff between the two. BTW 
> > https://github.com/llvm/llvm-project/blob/843ff7581408a02e852c0f1f7ebf176cabbc7527/clang/lib/Parse/ParseStmt.cpp#L1894-L1909
> >  I don't quite understand why a RecoveryExpr is not created here, which 
> > caused to the whole do statement disappears on the 
> > AST(https://godbolt.org/z/PsPb31YKP), should we fix this? 
> Thanks a lot for your comments! @aaron.ballman 
> But for error recovery, we will *never* get a valid constant expression.

Yeah, this is true, and we don't evaluate these error-dependent expressions.

I think the question here is that when we encounter an error-dependent 
expression during a constant expression evaluation, do we want to bailout the 
whole evaluation immediately, or just ignore the evaluation of this 
error-dependent expression and continue to proceed when possible?

We choose 2) -- this was based on the discussion with @rsmith. This will likely 
give us decent error-recovery and useful followup diagnostics.

Some concrete examples,

```
int abc();
constexpr int f() { 
  error(); 
  // We emit a diagnostic "Constexpr function never produces a constant 
expression, because abc() cannot be used in a constant expression"
  return abc(); 
}
```

```
// We prefer to treat the function f as a constexpr function even though it has 
an error expression. We will preserve more information in the AST, e.g. 
clangd's hover on the function call `f()` can give you the return value 1.

constexpr int f() {
   error();
   return 1;
}
```

> I worry about the performance overhead of continuing on with constant 
> expression evaluation in the error case. We use these code paths not only to 
> get a value but to say "is 

[PATCH] D154477: [include-cleaner] Ignore the layering-violation errors for the standalone tool

2023-07-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang-tools-extra.

If the source code is compilable-but-layzering-violation, we still want
the tool to be functional on it (rather than bailing out).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154477

Files:
  clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
  clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
  clang-tools-extra/include-cleaner/test/module.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -95,6 +95,15 @@
   RecordedPP PP;
   PragmaIncludes PI;
 
+  bool BeginInvocation(CompilerInstance ) override {
+// Disable the clang-module-based layering-violation checks.
+// These checks emit errors for a compilable source code. We want the tool
+// continue to be functional even on a layering-violation code.
+CI.getLangOpts().ModulesDeclUse = false;
+CI.getLangOpts().ModulesStrictDeclUse = false;
+return true;
+  }
+
   void ExecuteAction() override {
 auto  = getCompilerInstance().getPreprocessor();
 P.addPPCallbacks(PP.record(P));
Index: clang-tools-extra/include-cleaner/test/module.cpp
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/module.cpp
@@ -0,0 +1,7 @@
+// RUN: cp %s %t.cpp
+// RUN: clang-include-cleaner -edit %t.cpp -- -I%S/Inputs/modules 
-fimplicit-module-maps -fmodules-strict-decluse -fmodule-name=XA
+// RUN: FileCheck --match-full-lines --check-prefix=EDIT %s < %t.cpp
+
+// Verify the tool still works on compilable-but-layering-violation code.
+#include "a.h"
+// EDIT-NOT: {{^}}#include "a.h"{{$}}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
@@ -0,0 +1,2 @@
+module XA {
+}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
@@ -0,0 +1,2 @@
+#pragma once
+class A {};


Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -95,6 +95,15 @@
   RecordedPP PP;
   PragmaIncludes PI;
 
+  bool BeginInvocation(CompilerInstance ) override {
+// Disable the clang-module-based layering-violation checks.
+// These checks emit errors for a compilable source code. We want the tool
+// continue to be functional even on a layering-violation code.
+CI.getLangOpts().ModulesDeclUse = false;
+CI.getLangOpts().ModulesStrictDeclUse = false;
+return true;
+  }
+
   void ExecuteAction() override {
 auto  = getCompilerInstance().getPreprocessor();
 P.addPPCallbacks(PP.record(P));
Index: clang-tools-extra/include-cleaner/test/module.cpp
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/module.cpp
@@ -0,0 +1,7 @@
+// RUN: cp %s %t.cpp
+// RUN: clang-include-cleaner -edit %t.cpp -- -I%S/Inputs/modules -fimplicit-module-maps -fmodules-strict-decluse -fmodule-name=XA
+// RUN: FileCheck --match-full-lines --check-prefix=EDIT %s < %t.cpp
+
+// Verify the tool still works on compilable-but-layering-violation code.
+#include "a.h"
+// EDIT-NOT: {{^}}#include "a.h"{{$}}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/module.map
@@ -0,0 +1,2 @@
+module XA {
+}
Index: clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
===
--- /dev/null
+++ clang-tools-extra/include-cleaner/test/Inputs/modules/a.h
@@ -0,0 +1,2 @@
+#pragma once
+class A {};
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154473: [clang][Tooling] Add mapping for make_error_code

2023-07-05 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/lib/Tooling/Inclusions/Stdlib/StdSpecialSymbolMap.inc:353
+// type.
+SYMBOL(make_error_code, std::, /*no headers*/)
 

nit: maybe add `make_error_condition` as well.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154473

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


[PATCH] D154434: [clang-tidy] Don't emit the whole spelling include header in include-cleaner diagnostic message

2023-07-04 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2444fb96435e: [clang-tidy] Dont emit the whole 
spelling include header in include-cleaner… (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154434

Files:
  clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
  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
@@ -2,11 +2,11 @@
 #include "bar.h"
 // 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]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header foo.h is not used 
directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 // CHECK-FIXES: {{^}}#include {{$}}
 #include 
-// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header  is not 
used directly [misc-include-cleaner]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header vector.h is not 
used directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 int BarResult = bar();
 int BazResult = 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
@@ -34,6 +34,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
 #include 
 #include 
@@ -171,7 +172,8 @@
 
   for (const auto *Inc : Unused) {
 diag(Inc->HashLocation, "included header %0 is not used directly")
-<< Inc->quote()
+<< llvm::sys::path::filename(Inc->Spelled,
+ llvm::sys::path::Style::posix)
 << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));


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
@@ -2,11 +2,11 @@
 #include "bar.h"
 // 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]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header foo.h is not used directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 // CHECK-FIXES: {{^}}#include {{$}}
 #include 
-// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header  is not used directly [misc-include-cleaner]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header vector.h is not used directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 int BarResult = bar();
 int BazResult = 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
@@ -34,6 +34,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
 #include 
 #include 
@@ -171,7 +172,8 @@
 
   for (const auto *Inc : Unused) {
 diag(Inc->HashLocation, "included header %0 is not used directly")
-<< Inc->quote()
+<< llvm::sys::path::filename(Inc->Spelled,
+ llvm::sys::path::Style::posix)
 << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154434: [clang-tidy] Don't emit the whole spelling include header in include-cleaner diagnostic message

2023-07-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: kadircet.
Herald added subscribers: PiotrZSL, carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
hokein requested review of this revision.
Herald added a subscriber: ilya-biryukov.
Herald added a project: clang-tools-extra.

To keep the message short and consistent with clangd, and the diagnostics are
attached to the #include line, users have enough context to understand the 
whole #include.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154434

Files:
  clang-tools-extra/clang-tidy/misc/IncludeCleanerCheck.cpp
  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
@@ -2,11 +2,11 @@
 #include "bar.h"
 // 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]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header foo.h is not used 
directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 // CHECK-FIXES: {{^}}#include {{$}}
 #include 
-// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header  is not 
used directly [misc-include-cleaner]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header vector.h is not 
used directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 int BarResult = bar();
 int BazResult = 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
@@ -34,6 +34,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
 #include 
 #include 
@@ -171,7 +172,8 @@
 
   for (const auto *Inc : Unused) {
 diag(Inc->HashLocation, "included header %0 is not used directly")
-<< Inc->quote()
+<< llvm::sys::path::filename(Inc->Spelled,
+ llvm::sys::path::Style::posix)
 << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));


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
@@ -2,11 +2,11 @@
 #include "bar.h"
 // 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]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header foo.h is not used directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 // CHECK-FIXES: {{^}}#include {{$}}
 #include 
-// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header  is not used directly [misc-include-cleaner]
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: included header vector.h is not used directly [misc-include-cleaner]
 // CHECK-FIXES: {{^}}
 int BarResult = bar();
 int BazResult = 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
@@ -34,6 +34,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Path.h"
 #include "llvm/Support/Regex.h"
 #include 
 #include 
@@ -171,7 +172,8 @@
 
   for (const auto *Inc : Unused) {
 diag(Inc->HashLocation, "included header %0 is not used directly")
-<< Inc->quote()
+<< llvm::sys::path::filename(Inc->Spelled,
+ llvm::sys::path::Style::posix)
 << FixItHint::CreateRemoval(CharSourceRange::getCharRange(
SM->translateLineCol(SM->getMainFileID(), Inc->Line, 1),
SM->translateLineCol(SM->getMainFileID(), Inc->Line + 1, 1)));
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153340: [include-cleaner] Add an IgnoreHeaders flag to the command-line tool.

2023-07-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: clang-tools-extra/include-cleaner/test/tool.cpp:17
 
+//RUN: clang-include-cleaner -print=changes %s 
--ignore-headers="foobar\.h,foo\.h" -- -I%S/Inputs/ | FileCheck 
--match-full-lines --allow-empty --check-prefix=IGNORE %s
+// IGNORE-NOT: - "foobar.h"

kadircet wrote:
> can you ignore one but keep other?
> 
> it'd be useful to also test the regex behaviour
this tests aims to test filtering logic for both missing-includes and 
unused-includes cases.

added a new test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153340

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


[PATCH] D153340: [include-cleaner] Add an IgnoreHeaders flag to the command-line tool.

2023-07-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 536998.
hokein marked 10 inline comments as done.
hokein added a comment.

address review comments.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153340

Files:
  clang-tools-extra/clangd/IncludeCleaner.cpp
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Analysis.h
  clang-tools-extra/include-cleaner/include/clang-include-cleaner/Types.h
  clang-tools-extra/include-cleaner/lib/Analysis.cpp
  clang-tools-extra/include-cleaner/lib/Types.cpp
  clang-tools-extra/include-cleaner/test/tool.cpp
  clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp

Index: clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
===
--- clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
+++ clang-tools-extra/include-cleaner/tool/IncludeCleaner.cpp
@@ -14,10 +14,19 @@
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Tooling/CommonOptionsParser.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Regex.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
+#include 
+#include 
+#include 
+#include 
+#include 
 
 namespace clang {
 namespace include_cleaner {
@@ -47,6 +56,14 @@
 cl::cat(IncludeCleaner),
 };
 
+cl::opt IgnoreHeaders{
+"ignore-headers",
+cl::desc("A comma-separated list of regexes to match against suffix of a "
+ "header, and disable analysis if matched."),
+cl::init(""),
+cl::cat(IncludeCleaner),
+};
+
 enum class PrintStyle { Changes, Final };
 cl::opt Print{
 "print",
@@ -91,9 +108,15 @@
 }
 
 class Action : public clang::ASTFrontendAction {
+public:
+  Action(llvm::function_ref HeaderFilter)
+  : HeaderFilter(HeaderFilter){};
+
+private:
   RecordedAST AST;
   RecordedPP PP;
   PragmaIncludes PI;
+  llvm::function_ref HeaderFilter;
 
   void ExecuteAction() override {
 auto  = getCompilerInstance().getPreprocessor();
@@ -126,8 +149,8 @@
 assert(!Path.empty() && "Main file path not known?");
 llvm::StringRef Code = SM.getBufferData(SM.getMainFileID());
 
-auto Results =
-analyze(AST.Roots, PP.MacroReferences, PP.Includes, , SM, HS);
+auto Results = analyze(AST.Roots, PP.MacroReferences, PP.Includes, , SM,
+   HS, HeaderFilter);
 if (!Insert)
   Results.Missing.clear();
 if (!Remove)
@@ -176,6 +199,44 @@
 getCompilerInstance().getPreprocessor().getHeaderSearchInfo(), , OS);
   }
 };
+class ActionFactory : public tooling::FrontendActionFactory {
+public:
+  ActionFactory(llvm::function_ref HeaderFilter)
+  : HeaderFilter(HeaderFilter) {}
+
+  std::unique_ptr create() override {
+return std::make_unique(HeaderFilter);
+  }
+
+private:
+  llvm::function_ref HeaderFilter;
+};
+
+std::function headerFilter() {
+  auto FilterRegs = std::make_shared>();
+
+  llvm::SmallVector Headers;
+  llvm::StringRef(IgnoreHeaders).split(Headers, ',', -1, /*KeepEmpty=*/false);
+  for (auto HeaderPattern : Headers) {
+std::string AnchoredPattern = "(" + HeaderPattern.str() + ")$";
+llvm::Regex CompiledRegex(AnchoredPattern);
+std::string RegexError;
+if (!CompiledRegex.isValid(RegexError)) {
+  llvm::errs() << llvm::formatv("Invalid regular expression '{0}': {1}\n",
+HeaderPattern, RegexError);
+  return nullptr;
+}
+FilterRegs->push_back(std::move(CompiledRegex));
+  }
+  return [FilterRegs](llvm::StringRef Path) {
+llvm::errs() << "Path: " << Path << "\n";
+for (const auto  : *FilterRegs) {
+  if (F.match(Path))
+return true;
+}
+return false;
+  };
+}
 
 } // namespace
 } // namespace include_cleaner
@@ -191,19 +252,10 @@
 llvm::errs() << toString(OptionsParser.takeError());
 return 1;
   }
-
-  if (OptionsParser->getSourcePathList().size() != 1) {
-std::vector IncompatibleFlags = {, };
-for (const auto *Flag : IncompatibleFlags) {
-  if (Flag->getNumOccurrences()) {
-llvm::errs() << "-" << Flag->ArgStr << " requires a single input file";
-return 1;
-  }
-}
-  }
-  auto Factory = clang::tooling::newFrontendActionFactory();
+  auto HeaderFilter = headerFilter();
+  ActionFactory Factory(HeaderFilter);
   return clang::tooling::ClangTool(OptionsParser->getCompilations(),
OptionsParser->getSourcePathList())
- .run(Factory.get()) ||
+ .run() ||
  Errors != 0;
 }
Index: clang-tools-extra/include-cleaner/test/tool.cpp
===
--- clang-tools-extra/include-cleaner/test/tool.cpp
+++ 

[PATCH] D153296: [AST] Stop evaluate constant expression if the condition expression which in switch statement contains errors

2023-07-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks for the fix. Sorry for being late (I was looking through the emails and 
found this patch).




Comment at: clang/lib/AST/ExprConstant.cpp:4921
+  // value is.
+  if (isa(E))
+return false;

The constant evaluator is not aware of the "error" concept, it is only aware of 
value-dependent -- the general idea behind is that we treat the 
dependent-on-error and dependent-on-template-parameters cases the same, they 
are potentially constant (if we see an expression contains errors, it could be 
constant depending on how the error is resolved), this will give us nice 
recovery and avoid bogus following diagnostics.

So, a `RecoveryExpr` should not result in failure when checking for a potential 
constant expression.

I think the right fix is to remove the conditional check `if 
(!EvaluateDependentExpr(SS->getCond(), Info))` in `EvaluateSwitch`, and return 
`ESR_Failed` unconditionally (we don't know its value, any switch-case anwser 
will be wrong in some cases). We already do this for return-statment, 
do-statement etc.





Comment at: clang/test/SemaCXX/constexpr-function-recovery-crash.cpp:91
+
+static_assert(test13(), "should not crash"); // expected-error {{static 
assertion expression is not an integral constant expression}}
+

nit: we can simplify it with the `TEST_EVALUATE` macro:

```
TEST_EVALUATE(SwitchErrorCond, switch(undef) { case 0: return 7; default: 
break;})
```



Comment at: clang/test/SemaCXX/constexpr-function-recovery-crash.cpp:93
+
+constexpr int test14() {
+int sum = 0;

Is this a new crash (and the tests below)?

They don't look like new crashes, I think the current constant evaluator should 
be able to handle them well. IIUC the only crash we have is the case where we 
have a error-dependent condition in `switch`?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153296

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


[PATCH] D154329: [lldb] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-07-04 Thread Haojian Wu via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2a579db32a7a: [lldb] Replace llvm::writeFileAtomically with 
llvm::writeToOutput API. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154329

Files:
  lldb/tools/lldb-server/lldb-platform.cpp


Index: lldb/tools/lldb-server/lldb-platform.cpp
===
--- lldb/tools/lldb-server/lldb-platform.cpp
+++ lldb/tools/lldb-server/lldb-platform.cpp
@@ -22,7 +22,6 @@
 #include 
 
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -103,38 +102,15 @@
 return Status("Failed to create directory %s: %s",
   temp_file_spec.GetPath().c_str(), error.AsCString());
 
-  llvm::SmallString<64> temp_file_path;
-  temp_file_spec.AppendPathComponent("port-file.%%");
-  temp_file_path = temp_file_spec.GetPath();
-
   Status status;
-  if (auto Err =
-  handleErrors(llvm::writeFileAtomically(
-   temp_file_path, file_spec.GetPath(), socket_id),
-   [, _spec](const AtomicFileWriteError ) {
- std::string ErrorMsgBuffer;
- llvm::raw_string_ostream S(ErrorMsgBuffer);
- E.log(S);
-
- switch (E.Error) {
- case atomic_write_error::failed_to_create_uniq_file:
-   status = Status("Failed to create temp file: %s",
-   ErrorMsgBuffer.c_str());
-   break;
- case atomic_write_error::output_stream_error:
-   status = Status("Failed to write to port file.");
-   break;
- case atomic_write_error::failed_to_rename_temp_file:
-   status = Status("Failed to rename file %s to %s: 
%s",
-   ErrorMsgBuffer.c_str(),
-   file_spec.GetPath().c_str(),
-   ErrorMsgBuffer.c_str());
-   break;
- }
-   })) {
-return Status("Failed to atomically write file %s",
-  file_spec.GetPath().c_str());
-  }
+  if (auto Err = llvm::writeToOutput(file_spec.GetPath(),
+ [_id](llvm::raw_ostream ) {
+   OS << socket_id;
+   return llvm::Error::success();
+ }))
+return Status("Failed to atomically write file %s: %s",
+  file_spec.GetPath().c_str(),
+  llvm::toString(std::move(Err)).c_str());
   return status;
 }
 


Index: lldb/tools/lldb-server/lldb-platform.cpp
===
--- lldb/tools/lldb-server/lldb-platform.cpp
+++ lldb/tools/lldb-server/lldb-platform.cpp
@@ -22,7 +22,6 @@
 #include 
 
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -103,38 +102,15 @@
 return Status("Failed to create directory %s: %s",
   temp_file_spec.GetPath().c_str(), error.AsCString());
 
-  llvm::SmallString<64> temp_file_path;
-  temp_file_spec.AppendPathComponent("port-file.%%");
-  temp_file_path = temp_file_spec.GetPath();
-
   Status status;
-  if (auto Err =
-  handleErrors(llvm::writeFileAtomically(
-   temp_file_path, file_spec.GetPath(), socket_id),
-   [, _spec](const AtomicFileWriteError ) {
- std::string ErrorMsgBuffer;
- llvm::raw_string_ostream S(ErrorMsgBuffer);
- E.log(S);
-
- switch (E.Error) {
- case atomic_write_error::failed_to_create_uniq_file:
-   status = Status("Failed to create temp file: %s",
-   ErrorMsgBuffer.c_str());
-   break;
- case atomic_write_error::output_stream_error:
-   status = Status("Failed to write to port file.");
-   break;
- case atomic_write_error::failed_to_rename_temp_file:
-   status = Status("Failed to rename file %s to %s: %s",
-   ErrorMsgBuffer.c_str(),
-   file_spec.GetPath().c_str(),
-   ErrorMsgBuffer.c_str());
-  

[PATCH] D154329: [lldb] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-07-04 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

thanks for the review!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154329

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


[PATCH] D154329: [lldb] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: lldb/tools/lldb-server/lldb-platform.cpp:112
 return Status("Failed to atomically write file %s",
   file_spec.GetPath().c_str());
   return status;

avl wrote:
> probably, it would be better to add error text here?
> 
> ```
> return Status("Failed to atomically write file %s: %s",
>   file_spec.GetPath().c_str(), 
> toString(std::move(Err)).c_str());
> ```
good idea.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154329

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


[PATCH] D154329: [lldb] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 536735.
hokein marked an inline comment as done.
hokein added a comment.

address a comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154329

Files:
  lldb/tools/lldb-server/lldb-platform.cpp


Index: lldb/tools/lldb-server/lldb-platform.cpp
===
--- lldb/tools/lldb-server/lldb-platform.cpp
+++ lldb/tools/lldb-server/lldb-platform.cpp
@@ -22,7 +22,6 @@
 #include 
 
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -103,38 +102,15 @@
 return Status("Failed to create directory %s: %s",
   temp_file_spec.GetPath().c_str(), error.AsCString());
 
-  llvm::SmallString<64> temp_file_path;
-  temp_file_spec.AppendPathComponent("port-file.%%");
-  temp_file_path = temp_file_spec.GetPath();
-
   Status status;
-  if (auto Err =
-  handleErrors(llvm::writeFileAtomically(
-   temp_file_path, file_spec.GetPath(), socket_id),
-   [, _spec](const AtomicFileWriteError ) {
- std::string ErrorMsgBuffer;
- llvm::raw_string_ostream S(ErrorMsgBuffer);
- E.log(S);
-
- switch (E.Error) {
- case atomic_write_error::failed_to_create_uniq_file:
-   status = Status("Failed to create temp file: %s",
-   ErrorMsgBuffer.c_str());
-   break;
- case atomic_write_error::output_stream_error:
-   status = Status("Failed to write to port file.");
-   break;
- case atomic_write_error::failed_to_rename_temp_file:
-   status = Status("Failed to rename file %s to %s: 
%s",
-   ErrorMsgBuffer.c_str(),
-   file_spec.GetPath().c_str(),
-   ErrorMsgBuffer.c_str());
-   break;
- }
-   })) {
-return Status("Failed to atomically write file %s",
-  file_spec.GetPath().c_str());
-  }
+  if (auto Err = llvm::writeToOutput(file_spec.GetPath(),
+ [_id](llvm::raw_ostream ) {
+   OS << socket_id;
+   return llvm::Error::success();
+ }))
+return Status("Failed to atomically write file %s: %s",
+  file_spec.GetPath().c_str(),
+  llvm::toString(std::move(Err)).c_str());
   return status;
 }
 


Index: lldb/tools/lldb-server/lldb-platform.cpp
===
--- lldb/tools/lldb-server/lldb-platform.cpp
+++ lldb/tools/lldb-server/lldb-platform.cpp
@@ -22,7 +22,6 @@
 #include 
 
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -103,38 +102,15 @@
 return Status("Failed to create directory %s: %s",
   temp_file_spec.GetPath().c_str(), error.AsCString());
 
-  llvm::SmallString<64> temp_file_path;
-  temp_file_spec.AppendPathComponent("port-file.%%");
-  temp_file_path = temp_file_spec.GetPath();
-
   Status status;
-  if (auto Err =
-  handleErrors(llvm::writeFileAtomically(
-   temp_file_path, file_spec.GetPath(), socket_id),
-   [, _spec](const AtomicFileWriteError ) {
- std::string ErrorMsgBuffer;
- llvm::raw_string_ostream S(ErrorMsgBuffer);
- E.log(S);
-
- switch (E.Error) {
- case atomic_write_error::failed_to_create_uniq_file:
-   status = Status("Failed to create temp file: %s",
-   ErrorMsgBuffer.c_str());
-   break;
- case atomic_write_error::output_stream_error:
-   status = Status("Failed to write to port file.");
-   break;
- case atomic_write_error::failed_to_rename_temp_file:
-   status = Status("Failed to rename file %s to %s: %s",
-   ErrorMsgBuffer.c_str(),
-   file_spec.GetPath().c_str(),
-   ErrorMsgBuffer.c_str());
-   break;
- }
- 

[PATCH] D153740: [llvm][Support] Deprecate llvm::writeFileAtomically API

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked an inline comment as done.
hokein added a comment.

Now this patch only contains the removal part of the API (I have cleaned all 
usages of `writeFileAtomically` API, except a remaining one in lldb 
https://reviews.llvm.org/D154329).




Comment at: lldb/tools/lldb-server/lldb-platform.cpp:107
   Status status;
-  if (auto Err =
-  handleErrors(llvm::writeFileAtomically(
-   temp_file_path, file_spec.GetPath(), socket_id),
-   [, _spec](const AtomicFileWriteError ) {
- std::string ErrorMsgBuffer;
- llvm::raw_string_ostream S(ErrorMsgBuffer);
- E.log(S);
-
- switch (E.Error) {
- case atomic_write_error::failed_to_create_uniq_file:
-   status = Status("Failed to create temp file: %s",
-   ErrorMsgBuffer.c_str());
-   break;
- case atomic_write_error::output_stream_error:
-   status = Status("Failed to write to port file.");
-   break;
- case atomic_write_error::failed_to_rename_temp_file:
-   status = Status("Failed to rename file %s to %s: 
%s",
-   ErrorMsgBuffer.c_str(),
-   file_spec.GetPath().c_str(),
-   ErrorMsgBuffer.c_str());
-   break;
- }
-   })) {
+  if (auto Err = handleErrors(file_spec.GetPath(),
+  [_id](llvm::raw_ostream ) {

avl wrote:
> the call to llvm::writeToOutput is probably missed here.
oops, good catch, the `handleError` should be `writeToOutput`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153740

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


[PATCH] D153740: [llvm][Support] Deprecate llvm::writeFileAtomically API

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 536698.
hokein added a comment.

Restrict the patch to only remove the writeFileAtomically API


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153740

Files:
  llvm/include/llvm/Support/FileUtilities.h
  llvm/lib/Support/FileUtilities.cpp
  llvm/unittests/Support/CMakeLists.txt
  llvm/unittests/Support/FileUtilitiesTest.cpp

Index: llvm/unittests/Support/FileUtilitiesTest.cpp
===
--- llvm/unittests/Support/FileUtilitiesTest.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- llvm/unittest/Support/FileUtilitiesTest.cpp - unit tests ---===//
-//
-// 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
-//
-//===--===//
-
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Testing/Support/SupportHelpers.h"
-#include "gtest/gtest.h"
-#include 
-
-using namespace llvm;
-using namespace llvm::sys;
-
-using llvm::unittest::TempDir;
-
-#define ASSERT_NO_ERROR(x) \
-  if (std::error_code ASSERT_NO_ERROR_ec = x) {\
-SmallString<128> MessageStorage;   \
-raw_svector_ostream Message(MessageStorage);   \
-Message << #x ": did not return errc::success.\n"  \
-<< "error number: " << ASSERT_NO_ERROR_ec.value() << "\n"  \
-<< "error message: " << ASSERT_NO_ERROR_ec.message() << "\n";  \
-GTEST_FATAL_FAILURE_(MessageStorage.c_str());  \
-  } else { \
-  }
-
-namespace {
-TEST(writeFileAtomicallyTest, Test) {
-  // Create unique temporary directory for these tests
-  TempDir RootTestDirectory("writeFileAtomicallyTest", /*Unique*/ true);
-
-  SmallString<128> FinalTestfilePath(RootTestDirectory.path());
-  sys::path::append(FinalTestfilePath, "foo.txt");
-  const std::string TempUniqTestFileModel =
-  std::string(FinalTestfilePath) + "-";
-  const std::string TestfileContent = "fooFOOfoo";
-
-  llvm::Error Err = llvm::writeFileAtomically(TempUniqTestFileModel, FinalTestfilePath, TestfileContent);
-  ASSERT_FALSE(static_cast(Err));
-
-  std::ifstream FinalFileStream(std::string(FinalTestfilePath.str()));
-  std::string FinalFileContent;
-  FinalFileStream >> FinalFileContent;
-  ASSERT_EQ(FinalFileContent, TestfileContent);
-}
-} // anonymous namespace
Index: llvm/unittests/Support/CMakeLists.txt
===
--- llvm/unittests/Support/CMakeLists.txt
+++ llvm/unittests/Support/CMakeLists.txt
@@ -41,7 +41,6 @@
   ExtensibleRTTITest.cpp
   FileCollectorTest.cpp
   FileOutputBufferTest.cpp
-  FileUtilitiesTest.cpp
   FormatVariadicTest.cpp
   FSUniqueIDTest.cpp
   GlobPatternTest.cpp
Index: llvm/lib/Support/FileUtilities.cpp
===
--- llvm/lib/Support/FileUtilities.cpp
+++ llvm/lib/Support/FileUtilities.cpp
@@ -267,64 +267,6 @@
   return CompareFailed;
 }
 
-void llvm::AtomicFileWriteError::log(raw_ostream ) const {
-  OS << "atomic_write_error: ";
-  switch (Error) {
-  case atomic_write_error::failed_to_create_uniq_file:
-OS << "failed_to_create_uniq_file";
-return;
-  case atomic_write_error::output_stream_error:
-OS << "output_stream_error";
-return;
-  case atomic_write_error::failed_to_rename_temp_file:
-OS << "failed_to_rename_temp_file";
-return;
-  }
-  llvm_unreachable("unknown atomic_write_error value in "
-   "failed_to_rename_temp_file::log()");
-}
-
-llvm::Error llvm::writeFileAtomically(StringRef TempPathModel,
-  StringRef FinalPath, StringRef Buffer) {
-  return writeFileAtomically(TempPathModel, FinalPath,
- [](llvm::raw_ostream ) {
-   OS.write(Buffer.data(), Buffer.size());
-   return llvm::Error::success();
- });
-}
-
-llvm::Error llvm::writeFileAtomically(
-StringRef TempPathModel, StringRef FinalPath,
-std::function Writer) {
-  SmallString<128> GeneratedUniqPath;
-  int TempFD;
-  if (sys::fs::createUniqueFile(TempPathModel, TempFD, GeneratedUniqPath)) {
-return llvm::make_error(
-atomic_write_error::failed_to_create_uniq_file);
-  }
-  llvm::FileRemover 

[PATCH] D154329: [lldb] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added reviewers: avl, JDevlieghere.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154329

Files:
  lldb/tools/lldb-server/lldb-platform.cpp


Index: lldb/tools/lldb-server/lldb-platform.cpp
===
--- lldb/tools/lldb-server/lldb-platform.cpp
+++ lldb/tools/lldb-server/lldb-platform.cpp
@@ -22,7 +22,6 @@
 #include 
 
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -103,38 +102,14 @@
 return Status("Failed to create directory %s: %s",
   temp_file_spec.GetPath().c_str(), error.AsCString());
 
-  llvm::SmallString<64> temp_file_path;
-  temp_file_spec.AppendPathComponent("port-file.%%");
-  temp_file_path = temp_file_spec.GetPath();
-
   Status status;
-  if (auto Err =
-  handleErrors(llvm::writeFileAtomically(
-   temp_file_path, file_spec.GetPath(), socket_id),
-   [, _spec](const AtomicFileWriteError ) {
- std::string ErrorMsgBuffer;
- llvm::raw_string_ostream S(ErrorMsgBuffer);
- E.log(S);
-
- switch (E.Error) {
- case atomic_write_error::failed_to_create_uniq_file:
-   status = Status("Failed to create temp file: %s",
-   ErrorMsgBuffer.c_str());
-   break;
- case atomic_write_error::output_stream_error:
-   status = Status("Failed to write to port file.");
-   break;
- case atomic_write_error::failed_to_rename_temp_file:
-   status = Status("Failed to rename file %s to %s: 
%s",
-   ErrorMsgBuffer.c_str(),
-   file_spec.GetPath().c_str(),
-   ErrorMsgBuffer.c_str());
-   break;
- }
-   })) {
+  if (auto Err = llvm::writeToOutput(file_spec.GetPath(),
+ [_id](llvm::raw_ostream ) {
+   OS << socket_id;
+   return llvm::Error::success();
+ }))
 return Status("Failed to atomically write file %s",
   file_spec.GetPath().c_str());
-  }
   return status;
 }
 


Index: lldb/tools/lldb-server/lldb-platform.cpp
===
--- lldb/tools/lldb-server/lldb-platform.cpp
+++ lldb/tools/lldb-server/lldb-platform.cpp
@@ -22,7 +22,6 @@
 #include 
 
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -103,38 +102,14 @@
 return Status("Failed to create directory %s: %s",
   temp_file_spec.GetPath().c_str(), error.AsCString());
 
-  llvm::SmallString<64> temp_file_path;
-  temp_file_spec.AppendPathComponent("port-file.%%");
-  temp_file_path = temp_file_spec.GetPath();
-
   Status status;
-  if (auto Err =
-  handleErrors(llvm::writeFileAtomically(
-   temp_file_path, file_spec.GetPath(), socket_id),
-   [, _spec](const AtomicFileWriteError ) {
- std::string ErrorMsgBuffer;
- llvm::raw_string_ostream S(ErrorMsgBuffer);
- E.log(S);
-
- switch (E.Error) {
- case atomic_write_error::failed_to_create_uniq_file:
-   status = Status("Failed to create temp file: %s",
-   ErrorMsgBuffer.c_str());
-   break;
- case atomic_write_error::output_stream_error:
-   status = Status("Failed to write to port file.");
-   break;
- case atomic_write_error::failed_to_rename_temp_file:
-   status = Status("Failed to rename file %s to %s: %s",
-   ErrorMsgBuffer.c_str(),
-   file_spec.GetPath().c_str(),
-   ErrorMsgBuffer.c_str());
-   break;
- }
-   })) {
+  if (auto Err = llvm::writeToOutput(file_spec.GetPath(),
+ [_id](llvm::raw_ostream ) {
+  

[PATCH] D153741: [Tooling][Rewriter] Remove the redundant AtomicallyMovedFile Implementation.

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG653920cb158b: [Tooling][Rewriter] Remove the redundant 
AtomicallyMovedFile Implementation. (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153741

Files:
  clang/lib/Rewrite/Rewriter.cpp

Index: clang/lib/Rewrite/Rewriter.cpp
===
--- clang/lib/Rewrite/Rewriter.cpp
+++ clang/lib/Rewrite/Rewriter.cpp
@@ -14,22 +14,18 @@
 #include "clang/Rewrite/Core/Rewriter.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticIDs.h"
-#include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Rewrite/Core/RewriteBuffer.h"
 #include "clang/Rewrite/Core/RewriteRope.h"
-#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 
 using namespace clang;
@@ -410,68 +406,21 @@
   return false;
 }
 
-namespace {
-
-// A wrapper for a file stream that atomically overwrites the target.
-//
-// Creates a file output stream for a temporary file in the constructor,
-// which is later accessible via getStream() if ok() return true.
-// Flushes the stream and moves the temporary file to the target location
-// in the destructor.
-class AtomicallyMovedFile {
-public:
-  AtomicallyMovedFile(DiagnosticsEngine , StringRef Filename,
-  bool )
-  : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
-TempFilename = Filename;
-TempFilename += "-";
-int FD;
-if (llvm::sys::fs::createUniqueFile(TempFilename, FD, TempFilename)) {
-  AllWritten = false;
-  Diagnostics.Report(clang::diag::err_unable_to_make_temp)
-<< TempFilename;
-} else {
-  FileStream.reset(new llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
-}
-  }
-
-  ~AtomicallyMovedFile() {
-if (!ok()) return;
-
-// Close (will also flush) theFileStream.
-FileStream->close();
-if (std::error_code ec = llvm::sys::fs::rename(TempFilename, Filename)) {
-  AllWritten = false;
-  Diagnostics.Report(clang::diag::err_unable_to_rename_temp)
-<< TempFilename << Filename << ec.message();
-  // If the remove fails, there's not a lot we can do - this is already an
-  // error.
-  llvm::sys::fs::remove(TempFilename);
-}
-  }
-
-  bool ok() { return (bool)FileStream; }
-  raw_ostream () { return *FileStream; }
-
-private:
-  DiagnosticsEngine 
-  StringRef Filename;
-  SmallString<128> TempFilename;
-  std::unique_ptr FileStream;
-  bool 
-};
-
-} // namespace
-
 bool Rewriter::overwriteChangedFiles() {
   bool AllWritten = true;
+  auto& Diag = getSourceMgr().getDiagnostics();
+  unsigned OverwriteFailure = Diag.getCustomDiagID(
+  DiagnosticsEngine::Error, "unable to overwrite file %0: %1");
   for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
-const FileEntry *Entry =
-getSourceMgr().getFileEntryForID(I->first);
-AtomicallyMovedFile File(getSourceMgr().getDiagnostics(), Entry->getName(),
- AllWritten);
-if (File.ok()) {
-  I->second.write(File.getStream());
+const FileEntry *Entry = getSourceMgr().getFileEntryForID(I->first);
+if (auto Error =
+llvm::writeToOutput(Entry->getName(), [&](llvm::raw_ostream ) {
+  I->second.write(OS);
+  return llvm::Error::success();
+})) {
+  Diag.Report(OverwriteFailure)
+  << Entry->getName() << llvm::toString(std::move(Error));
+  AllWritten = false;
 }
   }
   return !AllWritten;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153741: [Tooling][Rewriter] Remove the redundant AtomicallyMovedFile Implementation.

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks for the review!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153741

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


[PATCH] D153741: [Tooling][Rewriter] Remove the redundant AtomicallyMovedFile Implementation.

2023-07-03 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 536679.
hokein added a comment.

rebase and update.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153741

Files:
  clang/lib/Rewrite/Rewriter.cpp

Index: clang/lib/Rewrite/Rewriter.cpp
===
--- clang/lib/Rewrite/Rewriter.cpp
+++ clang/lib/Rewrite/Rewriter.cpp
@@ -14,22 +14,18 @@
 #include "clang/Rewrite/Core/Rewriter.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticIDs.h"
-#include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Rewrite/Core/RewriteBuffer.h"
 #include "clang/Rewrite/Core/RewriteRope.h"
-#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 
 using namespace clang;
@@ -410,68 +406,21 @@
   return false;
 }
 
-namespace {
-
-// A wrapper for a file stream that atomically overwrites the target.
-//
-// Creates a file output stream for a temporary file in the constructor,
-// which is later accessible via getStream() if ok() return true.
-// Flushes the stream and moves the temporary file to the target location
-// in the destructor.
-class AtomicallyMovedFile {
-public:
-  AtomicallyMovedFile(DiagnosticsEngine , StringRef Filename,
-  bool )
-  : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
-TempFilename = Filename;
-TempFilename += "-";
-int FD;
-if (llvm::sys::fs::createUniqueFile(TempFilename, FD, TempFilename)) {
-  AllWritten = false;
-  Diagnostics.Report(clang::diag::err_unable_to_make_temp)
-<< TempFilename;
-} else {
-  FileStream.reset(new llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
-}
-  }
-
-  ~AtomicallyMovedFile() {
-if (!ok()) return;
-
-// Close (will also flush) theFileStream.
-FileStream->close();
-if (std::error_code ec = llvm::sys::fs::rename(TempFilename, Filename)) {
-  AllWritten = false;
-  Diagnostics.Report(clang::diag::err_unable_to_rename_temp)
-<< TempFilename << Filename << ec.message();
-  // If the remove fails, there's not a lot we can do - this is already an
-  // error.
-  llvm::sys::fs::remove(TempFilename);
-}
-  }
-
-  bool ok() { return (bool)FileStream; }
-  raw_ostream () { return *FileStream; }
-
-private:
-  DiagnosticsEngine 
-  StringRef Filename;
-  SmallString<128> TempFilename;
-  std::unique_ptr FileStream;
-  bool 
-};
-
-} // namespace
-
 bool Rewriter::overwriteChangedFiles() {
   bool AllWritten = true;
+  auto& Diag = getSourceMgr().getDiagnostics();
+  unsigned OverwriteFailure = Diag.getCustomDiagID(
+  DiagnosticsEngine::Error, "unable to overwrite file %0: %1");
   for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
-const FileEntry *Entry =
-getSourceMgr().getFileEntryForID(I->first);
-AtomicallyMovedFile File(getSourceMgr().getDiagnostics(), Entry->getName(),
- AllWritten);
-if (File.ok()) {
-  I->second.write(File.getStream());
+const FileEntry *Entry = getSourceMgr().getFileEntryForID(I->first);
+if (auto Error =
+llvm::writeToOutput(Entry->getName(), [&](llvm::raw_ostream ) {
+  I->second.write(OS);
+  return llvm::Error::success();
+})) {
+  Diag.Report(OverwriteFailure)
+  << Entry->getName() << llvm::toString(std::move(Error));
+  AllWritten = false;
 }
   }
   return !AllWritten;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154191: [LTO] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-07-01 Thread Haojian Wu via Phabricator via cfe-commits
hokein closed this revision.
hokein added a comment.

committed in 6ecc6b1250b253816703cbca18af432b95fb4089 
 and 
dc6c8b8d1e357acf6440824afaf6b6547b34aeeb 
.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154191

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


[PATCH] D154191: [LTO] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-07-01 Thread Haojian Wu via Phabricator via cfe-commits
hokein marked an inline comment as done.
hokein added a comment.

Thanks for the review.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154191

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


[PATCH] D154191: [LTO] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-06-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

This is a patch split out from https://reviews.llvm.org/D153740.




Comment at: llvm/lib/LTO/ThinLTOCodeGenerator.cpp:433
-  if (E.Error ==
-  llvm::atomic_write_error::failed_to_create_uniq_file) {
-errs() << "Error: " << ErrorMsgBuffer << "\n";

this is not a completely-none-functional change (in case of error), but I think 
it should be fine. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154191

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


[PATCH] D154191: [LTO] Replace llvm::writeFileAtomically with llvm::writeToOutput API.

2023-06-30 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added reviewers: jkorous, avl.
Herald added subscribers: ormris, steven_wu, hiraditya, inglorion.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154191

Files:
  llvm/lib/LTO/ThinLTOCodeGenerator.cpp


Index: llvm/lib/LTO/ThinLTOCodeGenerator.cpp
===
--- llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -44,13 +44,14 @@
 #include "llvm/Support/CachePruning.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
-#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SHA1.h"
 #include "llvm/Support/SmallVectorMemoryBuffer.h"
 #include "llvm/Support/ThreadPool.h"
 #include "llvm/Support/Threading.h"
 #include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/Transforms/IPO/FunctionAttrs.h"
@@ -415,29 +416,14 @@
 if (EntryPath.empty())
   return;
 
-// Write to a temporary to avoid race condition
-SmallString<128> TempFilename;
-SmallString<128> CachePath(EntryPath);
-llvm::sys::path::remove_filename(CachePath);
-sys::path::append(TempFilename, CachePath, "Thin-%%.tmp.o");
-
-if (auto Err = handleErrors(
-llvm::writeFileAtomically(TempFilename, EntryPath,
-  OutputBuffer.getBuffer()),
-[](const llvm::AtomicFileWriteError ) {
-  std::string ErrorMsgBuffer;
-  llvm::raw_string_ostream S(ErrorMsgBuffer);
-  E.log(S);
-
-  if (E.Error ==
-  llvm::atomic_write_error::failed_to_create_uniq_file) {
-errs() << "Error: " << ErrorMsgBuffer << "\n";
-report_fatal_error("ThinLTO: Can't get a temporary file");
-  }
-})) {
-  // FIXME
-  consumeError(std::move(Err));
-}
+if (auto Err = handleErrors(llvm::writeToOutput(
+EntryPath, [](llvm::raw_ostream ) -> llvm::Error {
+  OS << OutputBuffer.getBuffer();
+  return llvm::Error::success();
+})))
+  report_fatal_error(llvm::formatv("ThinLTO: Can't write file {0}: {1}",
+   EntryPath,
+   toString(std::move(Err)).c_str()));
   }
 };
 


Index: llvm/lib/LTO/ThinLTOCodeGenerator.cpp
===
--- llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -44,13 +44,14 @@
 #include "llvm/Support/CachePruning.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
-#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SHA1.h"
 #include "llvm/Support/SmallVectorMemoryBuffer.h"
 #include "llvm/Support/ThreadPool.h"
 #include "llvm/Support/Threading.h"
 #include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/Transforms/IPO/FunctionAttrs.h"
@@ -415,29 +416,14 @@
 if (EntryPath.empty())
   return;
 
-// Write to a temporary to avoid race condition
-SmallString<128> TempFilename;
-SmallString<128> CachePath(EntryPath);
-llvm::sys::path::remove_filename(CachePath);
-sys::path::append(TempFilename, CachePath, "Thin-%%.tmp.o");
-
-if (auto Err = handleErrors(
-llvm::writeFileAtomically(TempFilename, EntryPath,
-  OutputBuffer.getBuffer()),
-[](const llvm::AtomicFileWriteError ) {
-  std::string ErrorMsgBuffer;
-  llvm::raw_string_ostream S(ErrorMsgBuffer);
-  E.log(S);
-
-  if (E.Error ==
-  llvm::atomic_write_error::failed_to_create_uniq_file) {
-errs() << "Error: " << ErrorMsgBuffer << "\n";
-report_fatal_error("ThinLTO: Can't get a temporary file");
-  }
-})) {
-  // FIXME
-  consumeError(std::move(Err));
-}
+if (auto Err = handleErrors(llvm::writeToOutput(
+EntryPath, [](llvm::raw_ostream ) -> llvm::Error {
+  OS << OutputBuffer.getBuffer();
+  return llvm::Error::success();
+})))
+  report_fatal_error(llvm::formatv("ThinLTO: Can't write file {0}: {1}",
+   EntryPath,
+   toString(std::move(Err)).c_str()));
   }
 };
 
___
cfe-commits mailing 

[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-30 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG1233e2e66831: [Support] Dont set all_exe 
mode by default for file written by llvm… (authored by hokein).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

Files:
  llvm/lib/Support/raw_ostream.cpp
  llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
  llvm/unittests/Support/raw_ostream_test.cpp

Index: llvm/unittests/Support/raw_ostream_test.cpp
===
--- llvm/unittests/Support/raw_ostream_test.cpp
+++ llvm/unittests/Support/raw_ostream_test.cpp
@@ -504,6 +504,31 @@
   checkFileData(Path, "HelloWorld");
 }
 
+#ifndef _WIN32
+TEST(raw_ostreamTest, filePermissions) {
+  // Set umask to be permissive of all permissions.
+  unsigned OldMask = ::umask(0);
+
+  llvm::unittest::TempDir RootTestDirectory("writToOutput", /*Unique*/ true);
+  SmallString<128> Path(RootTestDirectory.path());
+  sys::path::append(Path, "test.txt");
+
+  ASSERT_THAT_ERROR(writeToOutput(Path,
+  [](raw_ostream ) -> Error {
+Out << "HelloWorld";
+return Error::success();
+  }),
+Succeeded());
+
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(Perms) << "should be able to get permissions";
+  // Verify the permission bits set by writeToOutput are read and write only.
+  EXPECT_EQ(Perms.get(), llvm::sys::fs::all_read | llvm::sys::fs::all_write);
+
+  ::umask(OldMask);
+}
+#endif
+
 TEST(raw_ostreamTest, writeToNonexistingPath) {
   StringRef FileName = "/_bad/_path";
   std::string ErrorMessage = toString(createFileError(
Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
===
--- /dev/null
+++ llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
@@ -0,0 +1,51 @@
+## The Unix version of this test must use umask(1) because
+## llvm-dwarfutil respects the umask in setting output permissions.
+## Setting the umask to 0 ensures deterministic permissions across
+## test environments.
+# UNSUPPORTED: system-windows
+# REQUIRES: shell
+
+# RUN: touch %t
+# RUN: chmod 0777 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0777
+# RUN: chmod 0666 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0666
+# RUN: chmod 0640 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0640
+
+## Set umask to be permissive of all permissions,
+## only test mirroring of permissions.
+# RUN: umask 0
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: chmod 0777 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0777
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0777
+
+# RUN: chmod 0666 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0666
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0666
+
+# RUN: chmod 0640 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0640
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0640
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:ELFDATA2LSB
+  Type:ET_EXEC
+  Machine: EM_X86_64
Index: llvm/lib/Support/raw_ostream.cpp
===
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -1007,7 +1007,7 @@
 return Write(Out);
   }
 
-  unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
   Expected Temp =
   sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%", Mode);
   if (!Temp)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D153652#4459489 , @jhenderson 
wrote:

> The new test LGTM, albeit with one query: I assume `umask` sets some global 
> state. When the lit unit tests are running, do the tests within the same 
> process run sequentially, or are they in parallel at all? If the latter, 
> there could be some thread-safety issue, although I suspect the tests are run 
> sequentially.

Good question. For each lit test, `llvm-lit` will run it on a separate worker 
process 
, 
so we should be safe here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

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


[PATCH] D154068: [clangd] Don't show header for namespace decl in Hover

2023-06-29 Thread Haojian Wu via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG21b6da35f1d5: [clangd] Dont show header for namespace 
decl in Hover (authored by hokein).

Changed prior to commit:
  https://reviews.llvm.org/D154068?vs=535732=535809#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154068

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -3059,7 +3059,13 @@
   }
   ns::F^oo d;
 )cpp",
-[](HoverInfo ) { HI.Provider = "\"foo.h\""; }}};
+[](HoverInfo ) { HI.Provider = "\"foo.h\""; }},
+{R"cpp(
+  namespace foo {};
+  using namespace fo^o;
+)cpp",
+[](HoverInfo ) { HI.Provider = ""; }},
+};
 
   for (const auto  : Cases) {
 Annotations Code{Case.Code};
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1374,7 +1374,10 @@
 if (!HI->Value)
   HI->Value = printExprValue(N, AST.getASTContext()).PrintedValue;
 maybeAddCalleeArgInfo(N, *HI, PP);
-maybeAddSymbolProviders(AST, *HI, include_cleaner::Symbol{*DeclToUse});
+
+if (!isa(DeclToUse))
+  maybeAddSymbolProviders(AST, *HI,
+  include_cleaner::Symbol{*DeclToUse});
   } else if (const Expr *E = N->ASTNode.get()) {
 HoverCountMetric.record(1, "expr");
 HI = getHoverContents(N, E, AST, PP, Index);


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -3059,7 +3059,13 @@
   }
   ns::F^oo d;
 )cpp",
-[](HoverInfo ) { HI.Provider = "\"foo.h\""; }}};
+[](HoverInfo ) { HI.Provider = "\"foo.h\""; }},
+{R"cpp(
+  namespace foo {};
+  using namespace fo^o;
+)cpp",
+[](HoverInfo ) { HI.Provider = ""; }},
+};
 
   for (const auto  : Cases) {
 Annotations Code{Case.Code};
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1374,7 +1374,10 @@
 if (!HI->Value)
   HI->Value = printExprValue(N, AST.getASTContext()).PrintedValue;
 maybeAddCalleeArgInfo(N, *HI, PP);
-maybeAddSymbolProviders(AST, *HI, include_cleaner::Symbol{*DeclToUse});
+
+if (!isa(DeclToUse))
+  maybeAddSymbolProviders(AST, *HI,
+  include_cleaner::Symbol{*DeclToUse});
   } else if (const Expr *E = N->ASTNode.get()) {
 HoverCountMetric.record(1, "expr");
 HI = getHoverContents(N, E, AST, PP, Index);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154068: [clangd] Don't show header for namespace decl in Hover

2023-06-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: VitaNuo.
Herald added subscribers: kadircet, arphaman.
Herald added a project: All.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

The header for namespace symbol is barely useful.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154068

Files:
  clang-tools-extra/clangd/Hover.cpp
  clang-tools-extra/clangd/unittests/HoverTests.cpp


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -3059,7 +3059,13 @@
   }
   ns::F^oo d;
 )cpp",
-[](HoverInfo ) { HI.Provider = "\"foo.h\""; }}};
+[](HoverInfo ) { HI.Provider = "\"foo.h\""; }},
+{R"cpp(
+  namespace foo {};
+  using namespace fo^o;
+)cpp",
+[](HoverInfo ) { HI.Provider = ""; }},
+};
 
   for (const auto  : Cases) {
 Annotations Code{Case.Code};
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1374,7 +1374,10 @@
 if (!HI->Value)
   HI->Value = printExprValue(N, AST.getASTContext()).PrintedValue;
 maybeAddCalleeArgInfo(N, *HI, PP);
-maybeAddSymbolProviders(AST, *HI, include_cleaner::Symbol{*DeclToUse});
+
+if (!isa(DeclToUse))
+  maybeAddSymbolProviders(AST, *HI,
+  include_cleaner::Symbol{*DeclToUse});
   } else if (const Expr *E = N->ASTNode.get()) {
 HoverCountMetric.record(1, "expr");
 HI = getHoverContents(N, E, AST, PP, Index);


Index: clang-tools-extra/clangd/unittests/HoverTests.cpp
===
--- clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -3059,7 +3059,13 @@
   }
   ns::F^oo d;
 )cpp",
-[](HoverInfo ) { HI.Provider = "\"foo.h\""; }}};
+[](HoverInfo ) { HI.Provider = "\"foo.h\""; }},
+{R"cpp(
+  namespace foo {};
+  using namespace fo^o;
+)cpp",
+[](HoverInfo ) { HI.Provider = ""; }},
+};
 
   for (const auto  : Cases) {
 Annotations Code{Case.Code};
Index: clang-tools-extra/clangd/Hover.cpp
===
--- clang-tools-extra/clangd/Hover.cpp
+++ clang-tools-extra/clangd/Hover.cpp
@@ -1374,7 +1374,10 @@
 if (!HI->Value)
   HI->Value = printExprValue(N, AST.getASTContext()).PrintedValue;
 maybeAddCalleeArgInfo(N, *HI, PP);
-maybeAddSymbolProviders(AST, *HI, include_cleaner::Symbol{*DeclToUse});
+
+if (!isa(DeclToUse))
+  maybeAddSymbolProviders(AST, *HI,
+  include_cleaner::Symbol{*DeclToUse});
   } else if (const Expr *E = N->ASTNode.get()) {
 HoverCountMetric.record(1, "expr");
 HI = getHoverContents(N, E, AST, PP, Index);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: llvm/unittests/Support/raw_ostream_test.cpp:525
+  ASSERT_TRUE(Perms) << "should be able to get permissions";
+  // Verify that writeToOutput doesn't set exe bit.
+  EXPECT_EQ(Perms.get(), llvm::sys::fs::all_read | llvm::sys::fs::all_write);

avl wrote:
> nit: comment looks a bit inconsistent as we check for read bits.
refined the comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

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


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-29 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 535712.
hokein marked an inline comment as done.
hokein added a comment.

address the comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

Files:
  llvm/lib/Support/raw_ostream.cpp
  llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
  llvm/unittests/Support/raw_ostream_test.cpp

Index: llvm/unittests/Support/raw_ostream_test.cpp
===
--- llvm/unittests/Support/raw_ostream_test.cpp
+++ llvm/unittests/Support/raw_ostream_test.cpp
@@ -504,6 +504,31 @@
   checkFileData(Path, "HelloWorld");
 }
 
+#ifndef _WIN32
+TEST(raw_ostreamTest, filePermissions) {
+  // Set umask to be permissive of all permissions.
+  unsigned OldMask = ::umask(0);
+
+  llvm::unittest::TempDir RootTestDirectory("writToOutput", /*Unique*/ true);
+  SmallString<128> Path(RootTestDirectory.path());
+  sys::path::append(Path, "test.txt");
+
+  ASSERT_THAT_ERROR(writeToOutput(Path,
+  [](raw_ostream ) -> Error {
+Out << "HelloWorld";
+return Error::success();
+  }),
+Succeeded());
+
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(Perms) << "should be able to get permissions";
+  // Verify the permission bits set by writeToOutput are read and write only.
+  EXPECT_EQ(Perms.get(), llvm::sys::fs::all_read | llvm::sys::fs::all_write);
+
+  ::umask(OldMask);
+}
+#endif
+
 TEST(raw_ostreamTest, writeToNonexistingPath) {
   StringRef FileName = "/_bad/_path";
   std::string ErrorMessage = toString(createFileError(
Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
===
--- /dev/null
+++ llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
@@ -0,0 +1,51 @@
+## The Unix version of this test must use umask(1) because
+## llvm-dwarfutil respects the umask in setting output permissions.
+## Setting the umask to 0 ensures deterministic permissions across
+## test environments.
+# UNSUPPORTED: system-windows
+# REQUIRES: shell
+
+# RUN: touch %t
+# RUN: chmod 0777 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0777
+# RUN: chmod 0666 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0666
+# RUN: chmod 0640 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0640
+
+## Set umask to be permissive of all permissions,
+## only test mirroring of permissions.
+# RUN: umask 0
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: chmod 0777 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0777
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0777
+
+# RUN: chmod 0666 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0666
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0666
+
+# RUN: chmod 0640 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0640
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0640
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:ELFDATA2LSB
+  Type:ET_EXEC
+  Machine: EM_X86_64
Index: llvm/lib/Support/raw_ostream.cpp
===
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -1007,7 +1007,7 @@
 return Write(Out);
   }
 
-  unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
   Expected Temp =
   sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%", Mode);
   if (!Temp)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-28 Thread Haojian Wu via Phabricator via cfe-commits
hokein added inline comments.



Comment at: llvm/unittests/Support/raw_ostream_test.cpp:500
+  ASSERT_TRUE(!!Perms);
+  EXPECT_EQ(0, *Perms & llvm::sys::fs::all_exe);
+

jhenderson wrote:
> hokein wrote:
> > jhenderson wrote:
> > > Here and below, rather than just checking the all_exe bit, let's check 
> > > the permissions are exactly what are expected (e.g. does it have the 
> > > read/write perms?). 
> > checking all existing bits is a bit tricky here (I tried it, then gave up):
> > 
> > - createTemporaryFile() creates a file with `owner_read | owner_write`
> > - writeToOutput() sets the written file to `all_read | all_write`
> > 
> > Both API don't provide a way to customize these bits, and they're internal 
> > details. We could test against them, but testing the implementation details 
> > seems subtle. And here we aim to verify the exe-bit not set by the 
> > `writeToOutput`, so I think just testing the exe-bit is not set should be 
> > enough. 
> This argument doesn't make much sense to me. Why are the `all_read` and 
> `all_write` bits implementation details that shouldn't be tested when the 
> lack of `all_exe` is?
> 
> This test is for testing `writeToOutput`. Part of `writeToOutput`'s behaviour 
> appears to be to create a file with the `all_read` and `all_write` bits set. 
> Therefore, we should be testing that behaviour. As there was already one 
> issue with the permission bits of the file this method creates, and you are 
> directly modifiyng a test to add permissions testing, I think it's justified 
> to request testing of the other bits.
OK, I changed the test to verify the all_read and all_write bits, please take 
another look.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

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


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-28 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 535309.
hokein added a comment.

compare the file-permission bits in unittest


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

Files:
  llvm/lib/Support/raw_ostream.cpp
  llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
  llvm/unittests/Support/raw_ostream_test.cpp

Index: llvm/unittests/Support/raw_ostream_test.cpp
===
--- llvm/unittests/Support/raw_ostream_test.cpp
+++ llvm/unittests/Support/raw_ostream_test.cpp
@@ -504,6 +504,31 @@
   checkFileData(Path, "HelloWorld");
 }
 
+#ifndef _WIN32
+TEST(raw_ostreamTest, filePermissions) {
+  // Set umask to be permissive of all permissions.
+  unsigned OldMask = ::umask(0);
+
+  llvm::unittest::TempDir RootTestDirectory("writToOutput", /*Unique*/ true);
+  SmallString<128> Path(RootTestDirectory.path());
+  sys::path::append(Path, "test.txt");
+
+  ASSERT_THAT_ERROR(writeToOutput(Path,
+  [](raw_ostream ) -> Error {
+Out << "HelloWorld";
+return Error::success();
+  }),
+Succeeded());
+
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(Perms) << "should be able to get permissions";
+  // Verify that writeToOutput doesn't set exe bit.
+  EXPECT_EQ(Perms.get(), llvm::sys::fs::all_read | llvm::sys::fs::all_write);
+
+  ::umask(OldMask);
+}
+#endif
+
 TEST(raw_ostreamTest, writeToNonexistingPath) {
   StringRef FileName = "/_bad/_path";
   std::string ErrorMessage = toString(createFileError(
Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
===
--- /dev/null
+++ llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
@@ -0,0 +1,51 @@
+## The Unix version of this test must use umask(1) because
+## llvm-dwarfutil respects the umask in setting output permissions.
+## Setting the umask to 0 ensures deterministic permissions across
+## test environments.
+# UNSUPPORTED: system-windows
+# REQUIRES: shell
+
+# RUN: touch %t
+# RUN: chmod 0777 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0777
+# RUN: chmod 0666 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0666
+# RUN: chmod 0640 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0640
+
+## Set umask to be permissive of all permissions,
+## only test mirroring of permissions.
+# RUN: umask 0
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: chmod 0777 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0777
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0777
+
+# RUN: chmod 0666 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0666
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0666
+
+# RUN: chmod 0640 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0640
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0640
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:ELFDATA2LSB
+  Type:ET_EXEC
+  Machine: EM_X86_64
Index: llvm/lib/Support/raw_ostream.cpp
===
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -1007,7 +1007,7 @@
 return Write(Out);
   }
 
-  unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
   Expected Temp =
   sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%", Mode);
   if (!Temp)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153882: [clangd] Always allow diagnostics from stale preambles

2023-06-28 Thread Haojian Wu via Phabricator via cfe-commits
hokein accepted this revision.
hokein added inline comments.
This revision is now accepted and ready to land.



Comment at: clang-tools-extra/clangd/ConfigYAML.cpp:137
 Dict.handle("ClangTidy", [&](Node ) { parse(F.ClangTidy, N); });
-Dict.handle("AllowStalePreamble", [&](Node ) {
-  F.AllowStalePreamble = boolValue(N, "AllowStalePreamble");

I wonder whether it is worth keeping this flag, but no-op (just emitting an 
warning message, this flag is no-op).

Probably not worth, since this flag was introduced recently, and it is not in 
any release.



Comment at: clang-tools-extra/clangd/ParsedAST.h:157
   std::vector Marks;
   // Data, stored after parsing. std::nullopt if AST was built with a stale
   // preamble.

nit: update the comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153882

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


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-27 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D153652#4451292 , @jhenderson 
wrote:

> The updated unit test is failing on Windows in the pre-merge checks. Please 
> investigate and fix as appropriate.

Good catch, thanks. I have restricted the unittest to linux only, I think it 
should be fine -- the behavior on windows is a bit different, the exe bit is 
set even you only set `read|write` bits, the `unittests/Support/Path.cpp` 
verifies that behavior.




Comment at: llvm/unittests/Support/raw_ostream_test.cpp:499
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(!!Perms);
+  EXPECT_EQ(0, *Perms & llvm::sys::fs::all_exe);

avl wrote:
> !!  looks a bit unclear. Probably check it in more explicit way?
> 
> EXPECT_TRUE(Perms && !(*Perms & llvm::sys::fs::all_exe)); 
sure, done.



Comment at: llvm/unittests/Support/raw_ostream_test.cpp:500
+  ASSERT_TRUE(!!Perms);
+  EXPECT_EQ(0, *Perms & llvm::sys::fs::all_exe);
+

jhenderson wrote:
> Here and below, rather than just checking the all_exe bit, let's check the 
> permissions are exactly what are expected (e.g. does it have the read/write 
> perms?). 
checking all existing bits is a bit tricky here (I tried it, then gave up):

- createTemporaryFile() creates a file with `owner_read | owner_write`
- writeToOutput() sets the written file to `all_read | all_write`

Both API don't provide a way to customize these bits, and they're internal 
details. We could test against them, but testing the implementation details 
seems subtle. And here we aim to verify the exe-bit not set by the 
`writeToOutput`, so I think just testing the exe-bit is not set should be 
enough. 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

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


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-27 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 534917.
hokein marked 2 inline comments as done.
hokein added a comment.

fix the test failures on windows


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

Files:
  llvm/lib/Support/raw_ostream.cpp
  llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
  llvm/unittests/Support/raw_ostream_test.cpp


Index: llvm/unittests/Support/raw_ostream_test.cpp
===
--- llvm/unittests/Support/raw_ostream_test.cpp
+++ llvm/unittests/Support/raw_ostream_test.cpp
@@ -495,6 +495,11 @@
   ASSERT_FALSE(sys::fs::createTemporaryFile("foo", "bar", FD, Path));
   FileRemover Cleanup(Path);
 
+#ifndef _WIN32
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  EXPECT_TRUE(Perms && !(*Perms & llvm::sys::fs::all_exe));
+#endif
+
   ASSERT_THAT_ERROR(writeToOutput(Path,
   [](raw_ostream ) -> Error {
 Out << "HelloWorld";
@@ -502,6 +507,12 @@
   }),
 Succeeded());
   checkFileData(Path, "HelloWorld");
+
+#ifndef _WIN32
+  // No exe bit set by the writeToOutput API.
+  Perms = llvm::sys::fs::getPermissions(Path);
+  EXPECT_TRUE(Perms && !(*Perms & llvm::sys::fs::all_exe));
+#endif
 }
 
 TEST(raw_ostreamTest, writeToNonexistingPath) {
Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
===
--- /dev/null
+++ llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
@@ -0,0 +1,51 @@
+## The Unix version of this test must use umask(1) because
+## llvm-dwarfutil respects the umask in setting output permissions.
+## Setting the umask to 0 ensures deterministic permissions across
+## test environments.
+# UNSUPPORTED: system-windows
+# REQUIRES: shell
+
+# RUN: touch %t
+# RUN: chmod 0777 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0777
+# RUN: chmod 0666 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0666
+# RUN: chmod 0640 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0640
+
+## Set umask to be permissive of all permissions,
+## only test mirroring of permissions.
+# RUN: umask 0
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: chmod 0777 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0777
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0777
+
+# RUN: chmod 0666 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0666
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0666
+
+# RUN: chmod 0640 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0640
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0640
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:ELFDATA2LSB
+  Type:ET_EXEC
+  Machine: EM_X86_64
Index: llvm/lib/Support/raw_ostream.cpp
===
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -1007,7 +1007,7 @@
 return Write(Out);
   }
 
-  unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
   Expected Temp =
   sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%", Mode);
   if (!Temp)


Index: llvm/unittests/Support/raw_ostream_test.cpp
===
--- llvm/unittests/Support/raw_ostream_test.cpp
+++ llvm/unittests/Support/raw_ostream_test.cpp
@@ -495,6 +495,11 @@
   ASSERT_FALSE(sys::fs::createTemporaryFile("foo", "bar", FD, Path));
   FileRemover Cleanup(Path);
 
+#ifndef _WIN32
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  EXPECT_TRUE(Perms && !(*Perms & llvm::sys::fs::all_exe));
+#endif
+
   ASSERT_THAT_ERROR(writeToOutput(Path,
   [](raw_ostream ) -> Error {
 Out << "HelloWorld";
@@ -502,6 +507,12 @@
   }),
 Succeeded());
   checkFileData(Path, "HelloWorld");
+
+#ifndef _WIN32
+  // No exe bit set by the writeToOutput API.
+  Perms = llvm::sys::fs::getPermissions(Path);
+  EXPECT_TRUE(Perms && !(*Perms & llvm::sys::fs::all_exe));
+#endif
 }
 
 TEST(raw_ostreamTest, writeToNonexistingPath) {
Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test

[PATCH] D153740: [llvm][Support] Deprecate llvm::writeFileAtomically API

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

In D153740#4448408 , @avl wrote:

> added @jkorous who originally added llvm::writeFileAtomically.
>
>> Let me know what you think about it -- I considered keeping the 
>> llvm::writeFileAtomically and migrating its underlying implementation to 
>> llvm::writeToOutput, but it doesn't seem to worth, there are only 4 in-tree 
>> usages of this API, I think it is probably better just remove it.
>
> I think it is OK to leave only one API (f.e. llvm::writeToOutput) and remove 
> another. It would probably be better to split this patch to  lldb, thinlto, 
> clang and removal parts.

Sounds good. I will split it once https://reviews.llvm.org/D153652 is landed.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153740

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


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks for the comment.

> unit test which checks llvm::writeOutput may be added to 
> raw_ostream_test.cpp. Let`s this test check the case when "all_exec" is not 
> set. i.e. that after default usage of llvm::writeOutput the resulting file 
> does not have "all_exec", which is exact purpose of this patch.

OK, added one.




Comment at: llvm/test/tools/llvm-dwarfutil/ELF/X86/file-permissions.test:1
+# RUN: yaml2obj %p/Inputs/common.yaml -o %t.o
+# RUN: chmod a+x %t.o

jhenderson wrote:
> hokein wrote:
> > jhenderson wrote:
> > > It might make sense to reuse the test code from llvm-objcopy's 
> > > mirror-permissions tests. See my other inline comment too.
> > by reusing the code, I think you mean calling the `llvm-dwardfutil` tool in 
> > the `llvm-objcopy` lit test, I'm not sure it is a good idea, calling a 
> > different tool in the 
> > `llvm/test/tools/llvm-objcopy/mirror-permissions-*.test` seems like 
> > violating the layer.
> I meant that you could copy and adapt the existing llvm-objcopy test to 
> create a new llvm-dwarfutil test (in the llvm-dwarfutil test folder).
I see, adjusted the test per comment.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

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


[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 534507.
hokein added a comment.

address comments:

- add unittest for llvm::writeToOutput API
- refine the llvm-dwarfutil tool lit test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

Files:
  llvm/lib/Support/raw_ostream.cpp
  llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
  llvm/unittests/Support/raw_ostream_test.cpp


Index: llvm/unittests/Support/raw_ostream_test.cpp
===
--- llvm/unittests/Support/raw_ostream_test.cpp
+++ llvm/unittests/Support/raw_ostream_test.cpp
@@ -495,6 +495,10 @@
   ASSERT_FALSE(sys::fs::createTemporaryFile("foo", "bar", FD, Path));
   FileRemover Cleanup(Path);
 
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(!!Perms);
+  EXPECT_EQ(0, *Perms & llvm::sys::fs::all_exe);
+
   ASSERT_THAT_ERROR(writeToOutput(Path,
   [](raw_ostream ) -> Error {
 Out << "HelloWorld";
@@ -502,6 +506,10 @@
   }),
 Succeeded());
   checkFileData(Path, "HelloWorld");
+  // No exe bit set by the writeToOutput API.
+  Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(!!Perms);
+  EXPECT_EQ(0, *Perms & llvm::sys::fs::all_exe);
 }
 
 TEST(raw_ostreamTest, writeToNonexistingPath) {
Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
===
--- /dev/null
+++ llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
@@ -0,0 +1,51 @@
+## The Unix version of this test must use umask(1) because
+## llvm-darfutil respects the umask in setting output permissions.
+## Setting the umask to 0 ensures deterministic permissions across
+## test environments.
+# UNSUPPORTED: system-windows
+# REQUIRES: shell
+
+# RUN: touch %t
+# RUN: chmod 0777 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0777
+# RUN: chmod 0666 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0666
+# RUN: chmod 0640 %t
+# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0640
+
+## Set umask to be permissive of all permissions,
+## only test mirroring of permissions.
+# RUN: umask 0
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: chmod 0777 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0777
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0777
+
+# RUN: chmod 0666 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0666
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0666
+
+# RUN: chmod 0640 %t
+# RUN: llvm-dwarfutil --no-garbage-collection %t %t1
+# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms
+# RUN: cmp %t1.perms %t.0640
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t %t2
+# RUN: ls -l %t2 | cut -f 1 -d ' ' > %t2.perms
+# RUN: cmp %t2.perms %t.0640
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:ELFDATA2LSB
+  Type:ET_EXEC
+  Machine: EM_X86_64
Index: llvm/lib/Support/raw_ostream.cpp
===
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -1007,7 +1007,7 @@
 return Write(Out);
   }
 
-  unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
   Expected Temp =
   sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%", Mode);
   if (!Temp)


Index: llvm/unittests/Support/raw_ostream_test.cpp
===
--- llvm/unittests/Support/raw_ostream_test.cpp
+++ llvm/unittests/Support/raw_ostream_test.cpp
@@ -495,6 +495,10 @@
   ASSERT_FALSE(sys::fs::createTemporaryFile("foo", "bar", FD, Path));
   FileRemover Cleanup(Path);
 
+  ErrorOr Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(!!Perms);
+  EXPECT_EQ(0, *Perms & llvm::sys::fs::all_exe);
+
   ASSERT_THAT_ERROR(writeToOutput(Path,
   [](raw_ostream ) -> Error {
 Out << "HelloWorld";
@@ -502,6 +506,10 @@
   }),
 Succeeded());
   checkFileData(Path, "HelloWorld");
+  // No exe bit set by the writeToOutput API.
+  Perms = llvm::sys::fs::getPermissions(Path);
+  ASSERT_TRUE(!!Perms);
+  EXPECT_EQ(0, *Perms & llvm::sys::fs::all_exe);
 }
 
 TEST(raw_ostreamTest, writeToNonexistingPath) {
Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/mirror-permissions-unix.test
===
--- 

[PATCH] D153652: [Support] Don't set "all_exe" mode by default for file written by llvm::writeToOutput

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.

Thanks for the comments.

In D153652#4447976 , @jhenderson 
wrote:

> Is there anything that can be done to use gtest unit tests for this? The two 
> lit tests are useful, but the problem with them is that if they switch to 
> using a different approach to emitting their data, the lit tests won't cover 
> the Support code you're actually changing.

The usages of `llvm::writeOutput` are in the ToolMain.cpp files, I don't see a 
way to unittest them.

> Some commit message nits:
>
>> [llvm][Support] Don'tt set "all_exe" mode by default for file written by 
>> llvm::writeToOutput.
>
> There's no need to include the `[llvm]` tag - the `[Support]` tag already 
> indicates the library clearly enough IMHO. Also, typo "Don'tt" -> "Don't" and 
> we don't usually end commit titles with a ".".

Thanks, updated.

> Does the clang include cleaner tool have testing that covers its usage of 
> this API?

No, the clang-include-cleaner binary tool just literally writes the text code 
to an output file, it unlikes the `llvm-dwardfutil` and `llvm-objcopy` tools 
which has a preserving-input-file-permissions requirement.




Comment at: llvm/test/tools/llvm-dwarfutil/ELF/X86/file-permissions.test:1
+# RUN: yaml2obj %p/Inputs/common.yaml -o %t.o
+# RUN: chmod a+x %t.o

jhenderson wrote:
> It might make sense to reuse the test code from llvm-objcopy's 
> mirror-permissions tests. See my other inline comment too.
by reusing the code, I think you mean calling the `llvm-dwardfutil` tool in the 
`llvm-objcopy` lit test, I'm not sure it is a good idea, calling a different 
tool in the `llvm/test/tools/llvm-objcopy/mirror-permissions-*.test` seems like 
violating the layer.



Comment at: llvm/test/tools/llvm-objcopy/ELF/file-permissions.test:1
+# RUN: cp %p/Inputs/dwarf.dwo %t-exe.dwo
+# RUN: chmod a+x %t-exe.dwo

jhenderson wrote:
> llvm-objcopy already has testing for permissions - see 
> mirror-permissions-*.test and respect-umask.test. It seems like a new test 
> file would be a mistake. Furthermore, a casual inspection to me makes it seem 
> like this behaviour is already covered (and working correctly), which makes 
> me think that no new testing is needed for this tool, but please review the 
> existing test and see what you think.
thanks! I didn't notice there is an existing one. Taking a look on these test, 
I think it already covers the cases we aim to test. So no need to add a new one.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

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


[PATCH] D153652: [llvm][Support] Don'tt set "all_exe" mode by default for file written by llvm::writeToOutput.

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein updated this revision to Diff 534473.
hokein added a comment.

address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153652

Files:
  llvm/lib/Support/raw_ostream.cpp
  llvm/test/tools/llvm-dwarfutil/ELF/X86/file-permissions.test


Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/file-permissions.test
===
--- /dev/null
+++ llvm/test/tools/llvm-dwarfutil/ELF/X86/file-permissions.test
@@ -0,0 +1,9 @@
+# RUN: yaml2obj %p/Inputs/common.yaml -o %t.o
+# RUN: chmod a+x %t.o
+
+# Verify that the output file preserves the executable bit from the input file.
+# RUN: llvm-dwarfutil --no-garbage-collection %t.o %t1
+# RUN: test -x %t1
+
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t.o %t2
+# RUN: test -x %t2.debug
Index: llvm/lib/Support/raw_ostream.cpp
===
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -1007,7 +1007,7 @@
 return Write(Out);
   }
 
-  unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
   Expected Temp =
   sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%", Mode);
   if (!Temp)


Index: llvm/test/tools/llvm-dwarfutil/ELF/X86/file-permissions.test
===
--- /dev/null
+++ llvm/test/tools/llvm-dwarfutil/ELF/X86/file-permissions.test
@@ -0,0 +1,9 @@
+# RUN: yaml2obj %p/Inputs/common.yaml -o %t.o
+# RUN: chmod a+x %t.o
+
+# Verify that the output file preserves the executable bit from the input file.
+# RUN: llvm-dwarfutil --no-garbage-collection %t.o %t1
+# RUN: test -x %t1
+
+# RUN: llvm-dwarfutil --garbage-collection --separate-debug-file %t.o %t2
+# RUN: test -x %t2.debug
Index: llvm/lib/Support/raw_ostream.cpp
===
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -1007,7 +1007,7 @@
 return Write(Out);
   }
 
-  unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
+  unsigned Mode = sys::fs::all_read | sys::fs::all_write;
   Expected Temp =
   sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%", Mode);
   if (!Temp)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D153741: [Tooling][Rewriter] Remove the redundant AtomicallyMovedFile Implementation.

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: avl.
Herald added a project: All.
hokein requested review of this revision.
Herald added a project: clang.

Replace it with llvm::writeToOutput.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153741

Files:
  clang/lib/Rewrite/Rewriter.cpp


Index: clang/lib/Rewrite/Rewriter.cpp
===
--- clang/lib/Rewrite/Rewriter.cpp
+++ clang/lib/Rewrite/Rewriter.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
@@ -410,68 +411,21 @@
   return false;
 }
 
-namespace {
-
-// A wrapper for a file stream that atomically overwrites the target.
-//
-// Creates a file output stream for a temporary file in the constructor,
-// which is later accessible via getStream() if ok() return true.
-// Flushes the stream and moves the temporary file to the target location
-// in the destructor.
-class AtomicallyMovedFile {
-public:
-  AtomicallyMovedFile(DiagnosticsEngine , StringRef Filename,
-  bool )
-  : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
-TempFilename = Filename;
-TempFilename += "-";
-int FD;
-if (llvm::sys::fs::createUniqueFile(TempFilename, FD, TempFilename)) {
-  AllWritten = false;
-  Diagnostics.Report(clang::diag::err_unable_to_make_temp)
-<< TempFilename;
-} else {
-  FileStream.reset(new llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
-}
-  }
-
-  ~AtomicallyMovedFile() {
-if (!ok()) return;
-
-// Close (will also flush) theFileStream.
-FileStream->close();
-if (std::error_code ec = llvm::sys::fs::rename(TempFilename, Filename)) {
-  AllWritten = false;
-  Diagnostics.Report(clang::diag::err_unable_to_rename_temp)
-<< TempFilename << Filename << ec.message();
-  // If the remove fails, there's not a lot we can do - this is already an
-  // error.
-  llvm::sys::fs::remove(TempFilename);
-}
-  }
-
-  bool ok() { return (bool)FileStream; }
-  raw_ostream () { return *FileStream; }
-
-private:
-  DiagnosticsEngine 
-  StringRef Filename;
-  SmallString<128> TempFilename;
-  std::unique_ptr FileStream;
-  bool 
-};
-
-} // namespace
-
 bool Rewriter::overwriteChangedFiles() {
   bool AllWritten = true;
+  auto& Diag = getSourceMgr().getDiagnostics();
+  unsigned OverwriteFailure = Diag.getCustomDiagID(
+  DiagnosticsEngine::Error, "unable to overwrite file %0: %1");
   for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
-const FileEntry *Entry =
-getSourceMgr().getFileEntryForID(I->first);
-AtomicallyMovedFile File(getSourceMgr().getDiagnostics(), Entry->getName(),
- AllWritten);
-if (File.ok()) {
-  I->second.write(File.getStream());
+const FileEntry *Entry = getSourceMgr().getFileEntryForID(I->first);
+if (auto Error =
+llvm::writeToOutput(Entry->getName(), [&](raw_ostream ) {
+  I->second.write(OS);
+  return llvm::Error::success();
+})) {
+  Diag.Report(OverwriteFailure)
+  << Entry->getName() << llvm::toString(std::move(Error));
+  AllWritten = false;
 }
   }
   return !AllWritten;


Index: clang/lib/Rewrite/Rewriter.cpp
===
--- clang/lib/Rewrite/Rewriter.cpp
+++ clang/lib/Rewrite/Rewriter.cpp
@@ -23,6 +23,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
@@ -410,68 +411,21 @@
   return false;
 }
 
-namespace {
-
-// A wrapper for a file stream that atomically overwrites the target.
-//
-// Creates a file output stream for a temporary file in the constructor,
-// which is later accessible via getStream() if ok() return true.
-// Flushes the stream and moves the temporary file to the target location
-// in the destructor.
-class AtomicallyMovedFile {
-public:
-  AtomicallyMovedFile(DiagnosticsEngine , StringRef Filename,
-  bool )
-  : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
-TempFilename = Filename;
-TempFilename += "-";
-int FD;
-if (llvm::sys::fs::createUniqueFile(TempFilename, FD, TempFilename)) {
-  AllWritten = false;
-  Diagnostics.Report(clang::diag::err_unable_to_make_temp)
-<< TempFilename;
-} else {
-  FileStream.reset(new llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
-}
-  }
-
-  ~AtomicallyMovedFile() {
-if (!ok()) return;
-
-// Close (will also flush) theFileStream.
-FileStream->close();
-if (std::error_code ec 

[PATCH] D153740: [llvm][Support] Deprecate llvm::writeFileAtomically API

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein added a comment.
Herald added a subscriber: JDevlieghere.

Let me know what you think about it -- I considered keeping the 
`llvm::writeFileAtomically` and migrating its underlying implementation to 
`llvm::writeToOutput`, but it doesn't seem to worth, there are only 4 in-tree 
usages of this API, I think it is probably better just remove it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153740

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


[PATCH] D153740: [llvm][Support] Deprecate llvm::writeFileAtomically API

2023-06-26 Thread Haojian Wu via Phabricator via cfe-commits
hokein created this revision.
hokein added a reviewer: avl.
Herald added subscribers: ormris, kadircet, arphaman, steven_wu, hiraditya.
Herald added a project: All.
hokein requested review of this revision.
Herald added projects: clang, LLDB, LLVM, clang-tools-extra.
Herald added subscribers: llvm-commits, lldb-commits.

The new llvm::writeToOutput API does the same thing, and we're in favor
of it.

This patch migrates 4 exiting usages and removes the llvm::writeFileAtomically 
API.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153740

Files:
  clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp
  clang/lib/Frontend/ASTUnit.cpp
  clang/lib/Serialization/GlobalModuleIndex.cpp
  lldb/tools/lldb-server/lldb-platform.cpp
  llvm/include/llvm/Support/FileUtilities.h
  llvm/lib/LTO/ThinLTOCodeGenerator.cpp
  llvm/lib/Support/FileUtilities.cpp
  llvm/unittests/Support/CMakeLists.txt
  llvm/unittests/Support/FileUtilitiesTest.cpp

Index: llvm/unittests/Support/FileUtilitiesTest.cpp
===
--- llvm/unittests/Support/FileUtilitiesTest.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- llvm/unittest/Support/FileUtilitiesTest.cpp - unit tests ---===//
-//
-// 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
-//
-//===--===//
-
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Testing/Support/SupportHelpers.h"
-#include "gtest/gtest.h"
-#include 
-
-using namespace llvm;
-using namespace llvm::sys;
-
-using llvm::unittest::TempDir;
-
-#define ASSERT_NO_ERROR(x) \
-  if (std::error_code ASSERT_NO_ERROR_ec = x) {\
-SmallString<128> MessageStorage;   \
-raw_svector_ostream Message(MessageStorage);   \
-Message << #x ": did not return errc::success.\n"  \
-<< "error number: " << ASSERT_NO_ERROR_ec.value() << "\n"  \
-<< "error message: " << ASSERT_NO_ERROR_ec.message() << "\n";  \
-GTEST_FATAL_FAILURE_(MessageStorage.c_str());  \
-  } else { \
-  }
-
-namespace {
-TEST(writeFileAtomicallyTest, Test) {
-  // Create unique temporary directory for these tests
-  TempDir RootTestDirectory("writeFileAtomicallyTest", /*Unique*/ true);
-
-  SmallString<128> FinalTestfilePath(RootTestDirectory.path());
-  sys::path::append(FinalTestfilePath, "foo.txt");
-  const std::string TempUniqTestFileModel =
-  std::string(FinalTestfilePath) + "-";
-  const std::string TestfileContent = "fooFOOfoo";
-
-  llvm::Error Err = llvm::writeFileAtomically(TempUniqTestFileModel, FinalTestfilePath, TestfileContent);
-  ASSERT_FALSE(static_cast(Err));
-
-  std::ifstream FinalFileStream(std::string(FinalTestfilePath.str()));
-  std::string FinalFileContent;
-  FinalFileStream >> FinalFileContent;
-  ASSERT_EQ(FinalFileContent, TestfileContent);
-}
-} // anonymous namespace
Index: llvm/unittests/Support/CMakeLists.txt
===
--- llvm/unittests/Support/CMakeLists.txt
+++ llvm/unittests/Support/CMakeLists.txt
@@ -41,7 +41,6 @@
   ExtensibleRTTITest.cpp
   FileCollectorTest.cpp
   FileOutputBufferTest.cpp
-  FileUtilitiesTest.cpp
   FormatVariadicTest.cpp
   FSUniqueIDTest.cpp
   GlobPatternTest.cpp
Index: llvm/lib/Support/FileUtilities.cpp
===
--- llvm/lib/Support/FileUtilities.cpp
+++ llvm/lib/Support/FileUtilities.cpp
@@ -267,64 +267,6 @@
   return CompareFailed;
 }
 
-void llvm::AtomicFileWriteError::log(raw_ostream ) const {
-  OS << "atomic_write_error: ";
-  switch (Error) {
-  case atomic_write_error::failed_to_create_uniq_file:
-OS << "failed_to_create_uniq_file";
-return;
-  case atomic_write_error::output_stream_error:
-OS << "output_stream_error";
-return;
-  case atomic_write_error::failed_to_rename_temp_file:
-OS << "failed_to_rename_temp_file";
-return;
-  }
-  llvm_unreachable("unknown atomic_write_error value in "
-   "failed_to_rename_temp_file::log()");
-}
-
-llvm::Error llvm::writeFileAtomically(StringRef TempPathModel,
-  StringRef FinalPath, StringRef Buffer) {
-  return writeFileAtomically(TempPathModel, FinalPath,
- [](llvm::raw_ostream ) {
-   

  1   2   3   4   5   6   7   8   9   10   >