[PATCH] D96744: clang-format IncludeBlocks: Regroup determination of "main" for framework-style includes fix

2023-08-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc abandoned this revision.
poelmanc added a comment.
Herald added a project: All.

We eventually updated our coding standards and our fairly massive code base to 
change only the very top "main" include from `#include ` to 
`#include "Foo.h"`.

For all include statements after that, we still use framework-style includes 
(`#include `).

It worked great and now we're happily using clang-format to order and group all 
our include statements, with no need for any changes to clang-format. Thanks to 
all for maintaining such an amazing tool!


Herald added a comment.

NOTE: Clang-Format Team Automated Review Comment

It looks like your clang-format review does not contain any unit tests, please 
try to ensure all code changes have a unit test (unless this is an `NFC` or 
refactoring, adding documentation etc..)

Add your unit tests in `clang/unittests/Format` and you can build with `ninja 
FormatTests`.  We recommend using the `verifyFormat(xxx)` format of unit tests 
rather than `EXPECT_EQ` as this will ensure you change is tolerant to random 
whitespace changes (see FormatTest.cpp as an example)

For situations where your change is altering the TokenAnnotator.cpp which can 
happen if you are trying to improve the annotation phase to ensure we are 
correctly identifying the type of a token, please add a token annotator test in 
`TokenAnnotatorTest.cpp`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D96744

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


[PATCH] D97625: fix check-clang-tools tests that fail due to Windows CRLF line endings

2022-02-04 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Sorry I somehow missed the acceptance back on 10 Jan. I lack commit access, it 
would be great if you could push for me, thanks!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D97625

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


[PATCH] D97620: Fix DecisionForestBenchmark.cpp compile errors

2021-03-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as done.
poelmanc added a comment.

Fixed comment as requested (keys()->size().) I don't have commit access so if 
you can push it that would be great, thanks!


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

https://reviews.llvm.org/D97620

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


[PATCH] D97620: Fix DecisionForestBenchmark.cpp compile errors

2021-03-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 327174.
poelmanc added a comment.

Fix comment.


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

https://reviews.llvm.org/D97620

Files:
  
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp


Index: 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
===
--- 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
+++ 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
@@ -21,7 +21,7 @@
 namespace clangd {
 namespace {
 std::vector generateRandomDataset(int NumExamples) {
-  auto FlipCoin = [&](float Probability) {
+  auto FlipCoin = [&](double Probability) {
 return rand() % 1000 <= Probability * 1000;
   };
   auto RandInt = [&](int Max) { return rand() % Max; };
@@ -38,15 +38,15 @@
 E.setIsImplementationDetail(FlipCoin(0.3)); // Boolean.
 E.setNumReferences(RandInt(1)); // Can be large integer.
 E.setSymbolCategory(RandInt(10));   // 10 Symbol Category.
-
+E.setNumNameInContext(RandInt(20)); // 0 to ContextWords->size().
+E.setFractionNameInContext(RandFloat(1.0)); // Float in range [0,1].
 E.setIsNameInContext(FlipCoin(0.5)); // Boolean.
-E.setIsForbidden(FlipCoin(0.1)); // Boolean.
 E.setIsInBaseClass(FlipCoin(0.3));   // Boolean.
-E.setFileProximityDistance(
+E.setFileProximityDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes file distance is not available.
   : RandInt(20));
 E.setSemaFileProximityScore(RandFloat(1)); // Float in range [0,1].
-E.setSymbolScopeDistance(
+E.setSymbolScopeDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes scope distance is not available.
   : RandInt(20));
 E.setSemaSaysInScope(FlipCoin(0.5));  // Boolean.
@@ -56,7 +56,6 @@
 E.setHadContextType(FlipCoin(0.6));   // Boolean.
 E.setHadSymbolType(FlipCoin(0.6));// Boolean.
 E.setTypeMatchesPreferred(FlipCoin(0.5)); // Boolean.
-E.setFilterLength(RandInt(15));
 Examples.push_back(E);
   }
   return Examples;


Index: clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
===
--- clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
+++ clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
@@ -21,7 +21,7 @@
 namespace clangd {
 namespace {
 std::vector generateRandomDataset(int NumExamples) {
-  auto FlipCoin = [&](float Probability) {
+  auto FlipCoin = [&](double Probability) {
 return rand() % 1000 <= Probability * 1000;
   };
   auto RandInt = [&](int Max) { return rand() % Max; };
@@ -38,15 +38,15 @@
 E.setIsImplementationDetail(FlipCoin(0.3)); // Boolean.
 E.setNumReferences(RandInt(1)); // Can be large integer.
 E.setSymbolCategory(RandInt(10));   // 10 Symbol Category.
-
+E.setNumNameInContext(RandInt(20)); // 0 to ContextWords->size().
+E.setFractionNameInContext(RandFloat(1.0)); // Float in range [0,1].
 E.setIsNameInContext(FlipCoin(0.5)); // Boolean.
-E.setIsForbidden(FlipCoin(0.1)); // Boolean.
 E.setIsInBaseClass(FlipCoin(0.3));   // Boolean.
-E.setFileProximityDistance(
+E.setFileProximityDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes file distance is not available.
   : RandInt(20));
 E.setSemaFileProximityScore(RandFloat(1)); // Float in range [0,1].
-E.setSymbolScopeDistance(
+E.setSymbolScopeDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes scope distance is not available.
   : RandInt(20));
 E.setSemaSaysInScope(FlipCoin(0.5));  // Boolean.
@@ -56,7 +56,6 @@
 E.setHadContextType(FlipCoin(0.6));   // Boolean.
 E.setHadSymbolType(FlipCoin(0.6));// Boolean.
 E.setTypeMatchesPreferred(FlipCoin(0.5)); // Boolean.
-E.setFilterLength(RandInt(15));
 Examples.push_back(E);
   }
   return Examples;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-28 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 326957.
poelmanc added a comment.

Removed a function in modernize/LoopConvertCheck.cpp that's no longer needed 
due to this patch. Fixed clang-format and clang-tidy issues identified by 
HarborMaster in prior submission.

Hopefully it's ready to go, but as always I'm happy to receive any feedback.


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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CMakeLists.txt
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -11,6 +11,7 @@
 #include "../Tooling/ReplacementTest.h"
 #include "clang/Tooling/Core/Replacement.h"
 
+#include "llvm/Testing/Support/Annotations.h"
 #include "gtest/gtest.h"
 
 using clang::tooling::ReplacementTest;
@@ -320,6 +321,11 @@
 return tooling::Replacement(FileName, Offset, Length, Text);
   }
 
+  tooling::Replacement createReplacement(llvm::Annotations::Range Range,
+ StringRef Text) {
+return createReplacement(Range.Begin, Range.End - Range.Begin, Text);
+  }
+
   tooling::Replacement createInsertion(StringRef IncludeDirective) {
 return createReplacement(UINT_MAX, 0, IncludeDirective);
   }
@@ -373,10 +379,12 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
+ "\n"
  "int x= 0;"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
  "int x= 0;"
  "}";
   tooling::Replacements Replaces =
@@ -386,6 +394,104 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code("namespace A {$r1[[ // Useless comment]]\n"
+ "  $r2[[int]] $r3[[x]]\t $r4[[=]] $r5[[0;]]\t\n"
+ "  int y\t = 0;$r6[[\t]]\n"
+ "} // namespace A\n");
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), ""),
+  createReplacement(Code.range("r5"), ""),
+  createReplacement(Code.range("r6"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code(R"cpp(struct A {
+  A()
+  $r3[[:]] $r1[[f()]]$r2[[,]]
+$r4[[g()]]
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp");
+  std::string Expected = R"cpp(struct A {
+  A()
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  // Not using raw string literals so newlines and spaces are clear and explicit
+  llvm::Annotations Code("struct A {\n"
+ "  A() {}\n"
+ "$r3[[]]  $r1[[int]] $r2[[f;]]\n" // "  int f;\n"
+ "  \n"
+ "$r4[[  ]]\n"
+ "};");
+  std::string Expected = "struct A {\n"
+ "  A() 

[PATCH] D97625: fix check-clang-tools tests that fail due to Windows CRLF line endings

2021-02-28 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added a reviewer: clang-tools-extra.
poelmanc added a project: clang-tools-extra.
Herald added a subscriber: jdoerfert.
poelmanc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Running `check-clang-tools` on Windows produces 5 test failures:

  Failed Tests (5):
Clang Tools :: clang-apply-replacements/ClangRenameClassReplacements.cpp
Clang Tools :: clang-apply-replacements/basic.cpp
Clang Tools :: clang-apply-replacements/format.cpp
Clang Tools :: clang-move/move-used-helper-decls.cpp
Clang Tools :: clang-tidy/infrastructure/export-diagnostics.cpp

Four of these failures are simply due to fixed character position offsets 
differing on Windows versus Linux, since Windows line endings take up two 
characters instead of one:

- clang-apply-replacements/ClangRenameClassReplacements.cpp runs `clang-rename 
-offset=254`
- clang-apply-replacements/Inputs/basic/file[12].yaml specify e.g. `FileOffset: 
148` and `Offset: 298`
- clang-apply-replacements/Inputs/format/{no,yes}.yaml specify e.g. 
`FileOffset: 94` and `Offset: 94`
- clang-tidy/infrastructure/export-diagnostics.cpp specifies e.g. 
`CHECK-YAML-NEXT: FileOffset: 30`

(The move-used-helper-decls.cpp failure seems more complex; clang-move adds a 
blank line after `void HelperFun1() {}` when 
clang-move/Inputs/helper_decls_test.cpp has LF line endings, but does //not// 
add a blank line when the input files has CRLF line endings. That difference in 
behavior seems like it may be an actual bug, but I have yet to track it down.)

Do other folks developing on Windows see this? Performing a git checkout with 
Linux (LF) or "as-is" line endings would make the tests pass, but the 
underlying clang tools need to work on on input files with various line ending 
types, so it seems best to test the code against various line ending types. For 
example, last year I found a clang-tidy fix that //chomped// a CRLF line ending 
in half by implicitly assuming a line ending to be one byte, and the above 
clang-move issue could be similar. Ideally the Windows BuildKite job should 
test input files with CRLF line endings; since the above tests pass, I'd guess 
it's checking out test files only with LF line endings?

- I considered changing export-diagnostics.cpp to e.g. `CHECK-YAML-NEXT: 
FileOffset: 3[01]` to accept either, but that would relax the test on Linux - 
we really want exactly 30 for LF line endings, and exactly 31 for CRLF line 
endings.
- An ideal fix might somehow enable different offset numbers depending on the 
input file line endings, but that seems like a big change.
- Instead this patch adds a .gitattributes file to specify Linux LF line 
endings only for the above files that use `-offset`, `FileOffset` and `Offset` 
in their tests, CRLF line endings for the one crlf.cpp test, and auto for 
everything else.

I'm open to any other thoughts, ideas, or hints about testing clang tools on 
inputs with various line ending types.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D97625

Files:
  clang-tools-extra/test/.gitattributes


Index: clang-tools-extra/test/.gitattributes
===
--- /dev/null
+++ clang-tools-extra/test/.gitattributes
@@ -0,0 +1,19 @@
+# CRLF (Windows) line endings take two bytes instead of one, so any tests that
+# rely on or check fixed character -offset, Offset: or FileOffset: locations
+# will fail when run on input files checked out with different line endings.
+
+# Most test input files should use native line endings, to ensure that we run
+# tests against both line ending types.
+* text=auto
+
+# These test input files rely on one-byte Unix (LF) line-endings, as they use
+# fixed -offset, FileOffset:, or Offset: numbers in their tests.
+clang-apply-replacements/ClangRenameClassReplacements.cpp text eol=lf
+clang-apply-replacements/Inputs/basic/basic.h text eol=lf
+clang-apply-replacements/Inputs/format/no.cpp text eol=lf
+clang-apply-replacements/Inputs/format/yes.cpp text eol=lf
+clang-tidy/infrastructure/export-diagnostics.cpp text eol=lf
+
+# These test input files rely on two-byte Windows (CRLF) line endings.
+clang-apply-replacements/Inputs/crlf/crlf.cpp text eol=crlf
+clang-apply-replacements/Inputs/crlf/crlf.cpp.expected text eol=crlf


Index: clang-tools-extra/test/.gitattributes
===
--- /dev/null
+++ clang-tools-extra/test/.gitattributes
@@ -0,0 +1,19 @@
+# CRLF (Windows) line endings take two bytes instead of one, so any tests that
+# rely on or check fixed character -offset, Offset: or FileOffset: locations
+# will fail when run on input files checked out with different line endings.
+
+# Most test input files should use native line endings, to ensure that we run
+# tests against both line ending types.
+* text=auto
+
+# These test input files rely on one-byte Unix 

[PATCH] D97620: Fix DecisionForestBenchmark.cpp compile errors

2021-02-27 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 326937.
poelmanc added a comment.

Shorten comment and add period.


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

https://reviews.llvm.org/D97620

Files:
  
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp


Index: 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
===
--- 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
+++ 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
@@ -21,7 +21,7 @@
 namespace clangd {
 namespace {
 std::vector generateRandomDataset(int NumExamples) {
-  auto FlipCoin = [&](float Probability) {
+  auto FlipCoin = [&](double Probability) {
 return rand() % 1000 <= Probability * 1000;
   };
   auto RandInt = [&](int Max) { return rand() % Max; };
@@ -38,15 +38,15 @@
 E.setIsImplementationDetail(FlipCoin(0.3)); // Boolean.
 E.setNumReferences(RandInt(1)); // Can be large integer.
 E.setSymbolCategory(RandInt(10));   // 10 Symbol Category.
-
+E.setNumNameInContext(RandInt(20)); // 0 to ContextWords->keys().
+E.setFractionNameInContext(RandFloat(1.0)); // Float in range [0,1].
 E.setIsNameInContext(FlipCoin(0.5)); // Boolean.
-E.setIsForbidden(FlipCoin(0.1)); // Boolean.
 E.setIsInBaseClass(FlipCoin(0.3));   // Boolean.
-E.setFileProximityDistance(
+E.setFileProximityDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes file distance is not available.
   : RandInt(20));
 E.setSemaFileProximityScore(RandFloat(1)); // Float in range [0,1].
-E.setSymbolScopeDistance(
+E.setSymbolScopeDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes scope distance is not available.
   : RandInt(20));
 E.setSemaSaysInScope(FlipCoin(0.5));  // Boolean.
@@ -56,7 +56,6 @@
 E.setHadContextType(FlipCoin(0.6));   // Boolean.
 E.setHadSymbolType(FlipCoin(0.6));// Boolean.
 E.setTypeMatchesPreferred(FlipCoin(0.5)); // Boolean.
-E.setFilterLength(RandInt(15));
 Examples.push_back(E);
   }
   return Examples;


Index: clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
===
--- clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
+++ clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
@@ -21,7 +21,7 @@
 namespace clangd {
 namespace {
 std::vector generateRandomDataset(int NumExamples) {
-  auto FlipCoin = [&](float Probability) {
+  auto FlipCoin = [&](double Probability) {
 return rand() % 1000 <= Probability * 1000;
   };
   auto RandInt = [&](int Max) { return rand() % Max; };
@@ -38,15 +38,15 @@
 E.setIsImplementationDetail(FlipCoin(0.3)); // Boolean.
 E.setNumReferences(RandInt(1)); // Can be large integer.
 E.setSymbolCategory(RandInt(10));   // 10 Symbol Category.
-
+E.setNumNameInContext(RandInt(20)); // 0 to ContextWords->keys().
+E.setFractionNameInContext(RandFloat(1.0)); // Float in range [0,1].
 E.setIsNameInContext(FlipCoin(0.5)); // Boolean.
-E.setIsForbidden(FlipCoin(0.1)); // Boolean.
 E.setIsInBaseClass(FlipCoin(0.3));   // Boolean.
-E.setFileProximityDistance(
+E.setFileProximityDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes file distance is not available.
   : RandInt(20));
 E.setSemaFileProximityScore(RandFloat(1)); // Float in range [0,1].
-E.setSymbolScopeDistance(
+E.setSymbolScopeDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes scope distance is not available.
   : RandInt(20));
 E.setSemaSaysInScope(FlipCoin(0.5));  // Boolean.
@@ -56,7 +56,6 @@
 E.setHadContextType(FlipCoin(0.6));   // Boolean.
 E.setHadSymbolType(FlipCoin(0.6));// Boolean.
 E.setTypeMatchesPreferred(FlipCoin(0.5)); // Boolean.
-E.setFilterLength(RandInt(15));
 Examples.push_back(E);
   }
   return Examples;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D97620: Fix DecisionForestBenchmark.cpp compile errors

2021-02-27 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added a reviewer: usaxena95.
poelmanc added a project: clang-tools-extra.
Herald added subscribers: kadircet, arphaman.
poelmanc requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added a project: clang.

clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp 
fails to compile since `"CompletionModel.h"` is auto-generated from 
clang-tools-extra/clangd/quality/model/features.json, which was changed in 
https://reviews.llvm.org/D94697 to remove `setFilterLength` and 
`setIsForbidden`, rename `setFileProximityDistance` and 
`setSymbolScopeDistance`, and add `setNumNameInContext` and 
`setFractionNameInContext`.  This patch removes calls to the two removed 
functions, updates calls to the two renamed functions, and adds calls to the 
two new functions. (`20` is an arbitrary choice for the `setNumNameInContext` 
argument.) It also changes the `FlipCoin` argument from float to double to 
silence lossy conversion warnings.

Note: I don't use this tool but encountered the build errors and took a shot at 
fixing them. Please holler if there's another recommended solution. Thanks!


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D97620

Files:
  
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp


Index: 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
===
--- 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
+++ 
clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
@@ -21,7 +21,7 @@
 namespace clangd {
 namespace {
 std::vector generateRandomDataset(int NumExamples) {
-  auto FlipCoin = [&](float Probability) {
+  auto FlipCoin = [&](double Probability) {
 return rand() % 1000 <= Probability * 1000;
   };
   auto RandInt = [&](int Max) { return rand() % Max; };
@@ -38,15 +38,15 @@
 E.setIsImplementationDetail(FlipCoin(0.3)); // Boolean.
 E.setNumReferences(RandInt(1)); // Can be large integer.
 E.setSymbolCategory(RandInt(10));   // 10 Symbol Category.
-
+E.setNumNameInContext(RandInt(20)); // 0 to 
Relevance.ContextWords->keys()
+E.setFractionNameInContext(RandFloat(1.0)); // Float in range [0,1].
 E.setIsNameInContext(FlipCoin(0.5)); // Boolean.
-E.setIsForbidden(FlipCoin(0.1)); // Boolean.
 E.setIsInBaseClass(FlipCoin(0.3));   // Boolean.
-E.setFileProximityDistance(
+E.setFileProximityDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes file distance is not available.
   : RandInt(20));
 E.setSemaFileProximityScore(RandFloat(1)); // Float in range [0,1].
-E.setSymbolScopeDistance(
+E.setSymbolScopeDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes scope distance is not available.
   : RandInt(20));
 E.setSemaSaysInScope(FlipCoin(0.5));  // Boolean.
@@ -56,7 +56,6 @@
 E.setHadContextType(FlipCoin(0.6));   // Boolean.
 E.setHadSymbolType(FlipCoin(0.6));// Boolean.
 E.setTypeMatchesPreferred(FlipCoin(0.5)); // Boolean.
-E.setFilterLength(RandInt(15));
 Examples.push_back(E);
   }
   return Examples;


Index: clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
===
--- clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
+++ clang-tools-extra/clangd/benchmarks/CompletionModel/DecisionForestBenchmark.cpp
@@ -21,7 +21,7 @@
 namespace clangd {
 namespace {
 std::vector generateRandomDataset(int NumExamples) {
-  auto FlipCoin = [&](float Probability) {
+  auto FlipCoin = [&](double Probability) {
 return rand() % 1000 <= Probability * 1000;
   };
   auto RandInt = [&](int Max) { return rand() % Max; };
@@ -38,15 +38,15 @@
 E.setIsImplementationDetail(FlipCoin(0.3)); // Boolean.
 E.setNumReferences(RandInt(1)); // Can be large integer.
 E.setSymbolCategory(RandInt(10));   // 10 Symbol Category.
-
+E.setNumNameInContext(RandInt(20)); // 0 to Relevance.ContextWords->keys()
+E.setFractionNameInContext(RandFloat(1.0)); // Float in range [0,1].
 E.setIsNameInContext(FlipCoin(0.5)); // Boolean.
-E.setIsForbidden(FlipCoin(0.1)); // Boolean.
 E.setIsInBaseClass(FlipCoin(0.3));   // Boolean.
-E.setFileProximityDistance(
+E.setFileProximityDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes file distance is not available.
   : RandInt(20));
 E.setSemaFileProximityScore(RandFloat(1)); // Float in range [0,1].
-E.setSymbolScopeDistance(
+E.setSymbolScopeDistanceCost(
 FlipCoin(0.1) ? 99 // Sometimes scope distance is not available.
   : RandInt(20));
 

[PATCH] D96744: clang-format IncludeBlocks: Regroup determination of "main" for framework-style includes fix

2021-02-26 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D96744#2564828 , @MyDeveloperDay 
wrote:

> Does this need to be an option?

It's easy to add an option, but there are already two //main include//-related 
options, so before adding a third I wanted to give this some thought. As 
someone new to `IncludeCategories`, I was genuinely impressed at how easy it 
was to use and how it gave me such complete control over the grouping via 
regular expressions. Yet in comparison the determination of //main// headers 
was less clear and more hard-coded; I had to examine the source code to figure 
out that the comparison is case-insensitive, it doesn't consider `<>` includes, 
only file stems are considered (e.g. the `foo/bar` in `foo/bar/baz.h` is 
ignored), and the behaviors of `IncludeIsMainSourceRegex` and 
`IncludeIsMainRegex` were a bit murky.

That's all fixable with a patch and minor documentation tweaks, but I wanted to 
consider some alternatives. Users of the `IncludeCategories` feature are 
comfortable with regular expressions, so imagine eliminating special handling 
of //main headers// entirely, and instead enabling users to write their own 
`IncludeCategories` rules for putting main headers first? We'd need to give 
them some bits of the source file path to use in their `Regex`, say called 
`${SourceStem}` and `${SourcePath}`.

Users unconcerned with formatting `foo_test.cc` or `foo_proto.cc` files could 
get the current functionality by including a simple rule like:

  - Regex:   '"(.*\/)?${SourceStem}(\..*)?"'
Priority:0
CaseSensitive:   false

I want case sensitivity, matching at least one component of the path, and angle 
brackets, so I'd use something like:

  - Regex:   '[<"]${SourcePath:1}${SourceStem}\..*[>"]'
Priority:0
CaseSensitive:   true

Then adding a generally-useful `ApplyToSourcesRegex` feature to apply any 
category regex only to certain source files, and an ability to trim a regular 
expression from the end of `${SourceStem}`, gives users full control, including 
mimicking current `isMainHeader()` behavior with rules like:

  - Regex:   
'"(.*\/)?${SourceStem-}(\..*)?"'
Priority:0
CaseSensitive:   false
ApplyToSourcesRegex: 
`((.*\.(c|cc|cpp|c\+\+|cxx|m|mm))|)`

For backwards-compatibility we'd automatically add the above rule if no special 
`${Source` tokens appear in any rules, and we can deprecate 
`IncludeIsMainRegex` and `IncludeIsMainSourceRegex` at any point. The special 
tokens for use in `Regex` are defined as:

- `${SourcePath:}` is a regular expression matching `n` or more trailing 
components of the source directory file path, using forward slashes and 
including any trailing slash (`0 <= n < 10`)
- `${SourceStem}` is a string starting after the last `/` in the source file 
path and includes up to but excluding the first dot
- `${SourceStem-}` is `${SourceStem}` with any trailing characters matching 
regular expression `re` removed

I have this coded up and it passes the ToolingTests, but wanted to run the idea 
by others. Thoughts? Should I update this patch with these changes? Start a 
separate issue? Stick with a new option `IncludeIsMainAllowBraces`?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D96744

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


[PATCH] D96744: clang-format IncludeBlocks: Regroup determination of "main" for framework-style includes fix

2021-02-16 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Thanks for the speedy reply and the great tool. With appropriate Regex and 
Priority settings, `IncludeCategories` worked flawlessly for me aside from not 
identifying the main header. Treating `#include "foo/bar/baz.h"` as the main 
header in file `bar/random/baz.h` seems like a bug, but I certainly see the 
dangers of changing current `<>` behavior. I also considered treating `<>` 
includes as main headers only if they also contain a forward-slash, e.g.:

  if (!IncludeName.startswith("\"") && !IncludeName.contains("/"))
return false;

That would resolve the `` case, although `#include ` in 
a file `anything/sys/types.h` would be identified as the main header. So making 
an option seems like the cleanest solution. Say, `bool 
IncludeIsMainAllowBraces`?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D96744

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


[PATCH] D96744: clang-format IncludeBlocks: Regroup determination of "main" for framework-style includes fix

2021-02-15 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: MyDeveloperDay, hokein, sammccall.
poelmanc added projects: clang-tools-extra, clang-format.
poelmanc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Most modern libraries and applications include files with relative paths from a 
root (e.g. `#include ` versus `#include "baz.h"`.) When 
regrouping, a file's "main include" should be left at the top (given priority 
0.) The existing `IncludeCategoryManager::isMainHeader()` checks only the file 
//stem// (e.g. `baz.h`), and fails to identify main includes with angle 
brackets despite a comment saying `// remove the surrounding "" or <>`.

This patch fixes these issues by comparing all directory components present in 
both the `#include` string and the file name, and by allowing angle bracket 
includes to be considered "main". It adds a new `IsMainHeader` unit test to 
check behavior of framework-style includes, which would fail without this patch.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D96744

Files:
  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
@@ -91,6 +91,28 @@
   EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
 }
 
+TEST_F(HeaderIncludesTest, IsMainHeader) {
+  Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+  .IncludeStyle;
+  std::vector FileNames{"foo/bar/baz.cpp", "foo/bar/baz.cu.cpp",
+   "foo/bar/baz_test.cu.cpp"};
+  for (const StringRef  : FileNames) {
+IncludeCategoryManager Manager(Style, FileName);
+// These framework-style includes should all be considered "main".
+EXPECT_EQ(Manager.getIncludePriority("", true), 0)
+<< "for source file " << FileName;
+EXPECT_EQ(Manager.getIncludePriority("\"bar/baz.h\"", true), 0)
+<< "for source file " << FileName;
+EXPECT_EQ(Manager.getIncludePriority("", true), 0)
+<< "for source file " << FileName;
+// These should not be considered "main" as the paths to baz.h differ.
+EXPECT_NE(Manager.getIncludePriority("", true), 0)
+<< "for source file " << FileName;
+EXPECT_NE(Manager.getIncludePriority("\"foo/baz.h\"", true), 0)
+<< "for source file " << FileName;
+  }
+}
+
 TEST_F(HeaderIncludesTest, InsertAfterMainHeader) {
   std::string Code = "#include \"fix.h\"\n"
  "\n"
Index: clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
===
--- clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
+++ clang/lib/Tooling/Inclusions/HeaderIncludes.cpp
@@ -233,9 +233,6 @@
   return Ret;
 }
 bool IncludeCategoryManager::isMainHeader(StringRef IncludeName) const {
-  if (!IncludeName.startswith("\""))
-return false;
-
   IncludeName =
   IncludeName.drop_front(1).drop_back(1); // remove the surrounding "" or 
<>
   // Not matchingStem: implementation files may have compound extensions but
@@ -259,8 +256,22 @@
   if (!Matching.empty()) {
 llvm::Regex MainIncludeRegex(HeaderStem.str() + Style.IncludeIsMainRegex,
  llvm::Regex::IgnoreCase);
-if (MainIncludeRegex.match(Matching))
+if (MainIncludeRegex.match(Matching)) {
+  // Matching is non-empty so these should be non-empty as well, making
+  // ++rbegin(IncludeName) and ++rbegin(FileName) safe.
+  assert(!IncludeName.empty());
+  assert(!FileName.empty());
+  // Checked stems above. Check remaining common path components here.
+  auto IncludePathRIter = ++llvm::sys::path::rbegin(IncludeName);
+  auto FilePathRiter = ++llvm::sys::path::rbegin(FileName);
+  for (; IncludePathRIter != llvm::sys::path::rend(IncludeName) &&
+ FilePathRiter != llvm::sys::path::rend(FileName);
+   ++IncludePathRIter, ++FilePathRiter) {
+if (*IncludePathRIter != *FilePathRiter)
+  return false;
+  }
   return true;
+}
   }
   return false;
 }


Index: clang/unittests/Tooling/HeaderIncludesTest.cpp
===
--- clang/unittests/Tooling/HeaderIncludesTest.cpp
+++ clang/unittests/Tooling/HeaderIncludesTest.cpp
@@ -91,6 +91,28 @@
   EXPECT_EQ(Expected, insert(Code, "\"a.h\""));
 }
 
+TEST_F(HeaderIncludesTest, IsMainHeader) {
+  Style = format::getGoogleStyle(format::FormatStyle::LanguageKind::LK_Cpp)
+  .IncludeStyle;
+  std::vector FileNames{"foo/bar/baz.cpp", "foo/bar/baz.cu.cpp",
+   "foo/bar/baz_test.cu.cpp"};
+  for (const StringRef  : FileNames) {
+IncludeCategoryManager Manager(Style, FileName);
+// These framework-style includes 

[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-02-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 322302.
poelmanc added a comment.

Capitalize `IsOrHasDescendant`, add `} namespace std` per HarborMaster feedback.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D95714

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering strong_ordering::equal = {0};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+  int *ptr = 0;
+  // CHECK-FIXES: int *ptr = nullptr;
+  result = (a1 > (ptr == 0 ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > (ptr == nullptr ? a1 : a2));
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : 
a2));
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -41,12 +41,28 @@
   
unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType(,
   unless(hasSourceExpression(hasType(sugaredNullptrType();
 
+  auto IsOrHasDescendant = [](auto InnerMatcher) {
+return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
+  };
+
   return traverse(
   TK_AsIs,
-  castExpr(anyOf(ImplicitCastToNull,
- explicitCastExpr(hasDescendant(ImplicitCastToNull))),
-   unless(hasAncestor(explicitCastExpr(
-  .bind(CastSequence));
+  anyOf(castExpr(anyOf(ImplicitCastToNull,
+   
explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+ unless(hasAncestor(explicitCastExpr())),
+ unless(hasAncestor(cxxRewrittenBinaryOperator(
+.bind(CastSequence),
+cxxRewrittenBinaryOperator(
+// Match rewritten operators, but verify (in the check method)
+// that if an implicit cast is found, it is not from another
+// nested rewritten operator.
+expr().bind("matchBinopOperands"),
+hasEitherOperand(IsOrHasDescendant(
+implicitCastExpr(
+ImplicitCastToNull,
+hasAncestor(cxxRewrittenBinaryOperator().bind(
+"checkBinopOperands")))
+.bind(CastSequence));
 }
 
 bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -480,6 +496,11 @@
   const auto *NullCast = Result.Nodes.getNodeAs(CastSequence);
   assert(NullCast && "Bad Callback. No node provided");
 
+  if (Result.Nodes.getNodeAs(
+  "matchBinopOperands") !=
+  Result.Nodes.getNodeAs("checkBinopOperands"))
+return;
+
   // Given an implicit null-ptr cast or an explicit cast with an implicit
   // null-to-pointer cast within use CastSequenceVisitor to identify sequences
   // of explicit casts that can be converted into 'nullptr'.


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering strong_ordering::equal = {0};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+} // namespace std
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  

[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D68682#2547906 , @kadircet wrote:

> It looks like premerge tests skipped your last diff with id 321451 
> (https://reviews.llvm.org/harbormaster/?after=87950). You can re-trigger by 
> uploading a new diff, in the meantime i would also file a bug to 
> https://github.com/google/llvm-premerge-checks/issues. mentioning your diff 
> id.

Thanks @kadircet, actually just reviewing the current bug list explained the 
problem: https://github.com/google/llvm-premerge-checks/issues/263, //Build is 
not triggered if diff repository is not set//. I wasn't selecting //rG 
 LLVM Github Monorepo// per 
instructions at https://llvm.org/docs/Phabricator.html that said //Leave the 
Repository field blank//.

HarborMaster has now run and passes all tests on Windows and Linux.

1. clang-format for a new test case in 
`clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp`.
 That test case formatting matches real-world examples so I'm reluctant to 
change it - I believe it's clang-formatted but with different settings from 
llvm-project's.
2. clang-tidy finds 8 `int` vs `size_t` comparisons. While `int` feels safer 
when subtraction is involved (since one can `assert` variables stay positive), 
this particular code would work fine with `int` variables changed to `size_t`, 
or alternatively with `static_cast` to silence the warnings.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68682

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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 322265.
poelmanc added a comment.

Call `llvm::Annoation` constructor rather than `operator=` to fix linux build 
issue, fix some issues identified by clang-format and clang-tidy.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CMakeLists.txt
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -11,6 +11,7 @@
 #include "../Tooling/ReplacementTest.h"
 #include "clang/Tooling/Core/Replacement.h"
 
+#include "llvm/Testing/Support/Annotations.h"
 #include "gtest/gtest.h"
 
 using clang::tooling::ReplacementTest;
@@ -320,6 +321,11 @@
 return tooling::Replacement(FileName, Offset, Length, Text);
   }
 
+  tooling::Replacement createReplacement(llvm::Annotations::Range Range,
+ StringRef Text) {
+return createReplacement(Range.Begin, Range.End - Range.Begin, Text);
+  }
+
   tooling::Replacement createInsertion(StringRef IncludeDirective) {
 return createReplacement(UINT_MAX, 0, IncludeDirective);
   }
@@ -373,10 +379,12 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
+ "\n"
  "int x= 0;"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
  "int x= 0;"
  "}";
   tooling::Replacements Replaces =
@@ -386,6 +394,104 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code("namespace A {$r1[[ // Useless comment]]\n"
+ "  $r2[[int]] $r3[[x]]\t $r4[[=]] $r5[[0;]]\t\n"
+ "  int y\t = 0;$r6[[\t]]\n"
+ "} // namespace A\n");
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), ""),
+  createReplacement(Code.range("r5"), ""),
+  createReplacement(Code.range("r6"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code(R"cpp(struct A {
+  A()
+  $r3[[:]] $r1[[f()]]$r2[[,]]
+$r4[[g()]]
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp");
+  std::string Expected = R"cpp(struct A {
+  A()
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  // Not using raw string literals so newlines and spaces are clear and explicit
+  llvm::Annotations Code("struct A {\n"
+ "  A() {}\n"
+ "$r3[[]]  $r1[[int]] $r2[[f;]]\n" // "  int f;\n"
+ "  \n"
+ "$r4[[  ]]\n"
+ "};");
+  std::string Expected = "struct A {\n"
+ "  A() {}\n"
+ "\n"
+ "\n"
+ "  \n"
+ "\t\n"
+  

[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-02-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 322253.
poelmanc added a comment.

Thanks for your patience, this one should work, as I used my normal `git show 
HEAD -U99` workflow.

(The requested change was just to add a period to a comment, so as a short-cut 
I tried "Raw Diff" -> copy -> "Update Diff" -> paste into "Raw Diff" field, -> 
add the period -> Continue -> Save. "Raw Diff" didn't show full context, but it 
appeared to work based on the web interface. I guess not. 
`modernize-use-nullptr-cxx20.cpp` is a whole new file, in case that matters.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D95714

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering strong_ordering::equal = {0};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+}
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+  int *ptr = 0;
+  // CHECK-FIXES: int *ptr = nullptr;
+  result = (a1 > (ptr == 0 ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > (ptr == nullptr ? a1 : a2));
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : 
a2));
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -41,12 +41,28 @@
   
unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType(,
   unless(hasSourceExpression(hasType(sugaredNullptrType();
 
+  auto isOrHasDescendant = [](auto InnerMatcher) {
+return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
+  };
+
   return traverse(
   TK_AsIs,
-  castExpr(anyOf(ImplicitCastToNull,
- explicitCastExpr(hasDescendant(ImplicitCastToNull))),
-   unless(hasAncestor(explicitCastExpr(
-  .bind(CastSequence));
+  anyOf(castExpr(anyOf(ImplicitCastToNull,
+   
explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+ unless(hasAncestor(explicitCastExpr())),
+ unless(hasAncestor(cxxRewrittenBinaryOperator(
+.bind(CastSequence),
+cxxRewrittenBinaryOperator(
+// Match rewritten operators, but verify (in the check method)
+// that if an implicit cast is found, it is not from another
+// nested rewritten operator.
+expr().bind("matchBinopOperands"),
+hasEitherOperand(isOrHasDescendant(
+implicitCastExpr(
+ImplicitCastToNull,
+hasAncestor(cxxRewrittenBinaryOperator().bind(
+"checkBinopOperands")))
+.bind(CastSequence));
 }
 
 bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -480,6 +496,11 @@
   const auto *NullCast = Result.Nodes.getNodeAs(CastSequence);
   assert(NullCast && "Bad Callback. No node provided");
 
+  if (Result.Nodes.getNodeAs(
+  "matchBinopOperands") !=
+  Result.Nodes.getNodeAs("checkBinopOperands"))
+return;
+
   // Given an implicit null-ptr cast or an explicit cast with an implicit
   // null-to-pointer cast within use CastSequenceVisitor to identify sequences
   // of explicit casts that can be converted into 'nullptr'.


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering 

[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-02-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D95714#2548735 , @njames93 wrote:

> LGTM, Same as last time for the commit?

That would be great, thanks!


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

https://reviews.llvm.org/D95714

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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 322108.
poelmanc added a comment.

Comment change, "beginning" to "start" for consistency, being sure to set 
Repository on "diff" page (not just on edit page) to see if 
https://github.com/google/llvm-premerge-checks/issues/263 was the problem.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CMakeLists.txt
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/Tooling/Core/Replacement.h"
 
 #include "gtest/gtest.h"
+#include "llvm/Testing/Support/Annotations.h"
 
 using clang::tooling::ReplacementTest;
 using clang::tooling::toReplacements;
@@ -320,6 +321,11 @@
 return tooling::Replacement(FileName, Offset, Length, Text);
   }
 
+  tooling::Replacement createReplacement(llvm::Annotations::Range Range,
+ StringRef Text) {
+return createReplacement(Range.Begin, Range.End - Range.Begin, Text);
+  }
+
   tooling::Replacement createInsertion(StringRef IncludeDirective) {
 return createReplacement(UINT_MAX, 0, IncludeDirective);
   }
@@ -373,10 +379,12 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
+ "\n"
  "int x= 0;"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
  "int x= 0;"
  "}";
   tooling::Replacements Replaces =
@@ -386,6 +394,104 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = "namespace A {$r1[[ // Useless comment]]\n"
+   "  $r2[[int]] $r3[[x]]\t $r4[[=]] $r5[[0;]]\t\n"
+   "  int y\t = 0;$r6[[\t]]\n"
+   "} // namespace A\n";
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), ""),
+  createReplacement(Code.range("r5"), ""),
+  createReplacement(Code.range("r6"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = R"cpp(struct A {
+  A()
+  $r3[[:]] $r1[[f()]]$r2[[,]]
+$r4[[g()]]
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  std::string Expected = R"cpp(struct A {
+  A()
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  // Not using raw string literals so newlines and spaces are clear and explicit
+  llvm::Annotations Code = "struct A {\n"
+ "  A() {}\n"
+ "$r3[[]]  $r1[[int]] $r2[[f;]]\n" // "  int f;\n"
+ "  \n"
+ "$r4[[  ]]\n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A() {}\n"
+ "\n"
+ "\n"
+   

[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-07 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 322033.
poelmanc added a comment.

Update one one comment, hopefully trigger HarborMaster to rerun.


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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CMakeLists.txt
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/Tooling/Core/Replacement.h"
 
 #include "gtest/gtest.h"
+#include "llvm/Testing/Support/Annotations.h"
 
 using clang::tooling::ReplacementTest;
 using clang::tooling::toReplacements;
@@ -320,6 +321,11 @@
 return tooling::Replacement(FileName, Offset, Length, Text);
   }
 
+  tooling::Replacement createReplacement(llvm::Annotations::Range Range,
+ StringRef Text) {
+return createReplacement(Range.Begin, Range.End - Range.Begin, Text);
+  }
+
   tooling::Replacement createInsertion(StringRef IncludeDirective) {
 return createReplacement(UINT_MAX, 0, IncludeDirective);
   }
@@ -373,10 +379,12 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
+ "\n"
  "int x= 0;"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
  "int x= 0;"
  "}";
   tooling::Replacements Replaces =
@@ -386,6 +394,104 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = "namespace A {$r1[[ // Useless comment]]\n"
+   "  $r2[[int]] $r3[[x]]\t $r4[[=]] $r5[[0;]]\t\n"
+   "  int y\t = 0;$r6[[\t]]\n"
+   "} // namespace A\n";
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), ""),
+  createReplacement(Code.range("r5"), ""),
+  createReplacement(Code.range("r6"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = R"cpp(struct A {
+  A()
+  $r3[[:]] $r1[[f()]]$r2[[,]]
+$r4[[g()]]
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  std::string Expected = R"cpp(struct A {
+  A()
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  // Not using raw string literals so newlines and spaces are clear and explicit
+  llvm::Annotations Code = "struct A {\n"
+ "  A() {}\n"
+ "$r3[[]]  $r1[[int]] $r2[[f;]]\n" // "  int f;\n"
+ "  \n"
+ "$r4[[  ]]\n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A() {}\n"
+ "\n"
+ "\n"
+ "  \n"
+ "\t\n"
+ "};";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), "   "),

[PATCH] D95771: [clang-tidy] fix modernize-loop-convert to retain needed array-like operator[]

2021-02-07 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D95771#2547366 , @njames93 wrote:

> In D95771#2547160 , @poelmanc wrote:
>
>> In D95771#2547102 , @njames93 wrote:
>>
>>> Should this be committed using `poelmanc `?
>>
>> That or `Conrad Poelman ` would be great, thanks.
>
> I committed using the email provided but its not attributed you on github. 
> It's attributed you here though. is that email not linked to your github 
> account?

Thanks for the commit, and thanks for the heads-up! I've now added the address 
in my github account.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D95771

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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-06 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

On 2 Feb Harbormaster found a bug  from my 
switching some char* code to use StringRef. I uploaded a new patch on 4 Feb, 
but Harbormaster does not appear to have rerun. What triggers Harbormaster - do 
I need to take some action? I haven't been able to find such options myself.

Please holler if there's a better place to ask this, thanks!


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

https://reviews.llvm.org/D68682

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


[PATCH] D95771: [clang-tidy] fix modernize-loop-convert to retain needed array-like operator[]

2021-02-06 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D95771#2547102 , @njames93 wrote:

> Should this be committed using `poelmanc `?

That or `Conrad Poelman ` would be great, thanks.


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

https://reviews.llvm.org/D95771

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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-04 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 321451.
poelmanc added a comment.
Herald added a subscriber: nullptr.cpp.

Change loop end condition in `findLineEnd` and add several `assert` statements.


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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CMakeLists.txt
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/Tooling/Core/Replacement.h"
 
 #include "gtest/gtest.h"
+#include "llvm/Testing/Support/Annotations.h"
 
 using clang::tooling::ReplacementTest;
 using clang::tooling::toReplacements;
@@ -320,6 +321,11 @@
 return tooling::Replacement(FileName, Offset, Length, Text);
   }
 
+  tooling::Replacement createReplacement(llvm::Annotations::Range Range,
+ StringRef Text) {
+return createReplacement(Range.Begin, Range.End - Range.Begin, Text);
+  }
+
   tooling::Replacement createInsertion(StringRef IncludeDirective) {
 return createReplacement(UINT_MAX, 0, IncludeDirective);
   }
@@ -373,10 +379,12 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
+ "\n"
  "int x= 0;"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
  "int x= 0;"
  "}";
   tooling::Replacements Replaces =
@@ -386,6 +394,104 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = "namespace A {$r1[[ // Useless comment]]\n"
+   "  $r2[[int]] $r3[[x]]\t $r4[[=]] $r5[[0;]]\t\n"
+   "  int y\t = 0;$r6[[\t]]\n"
+   "} // namespace A\n";
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), ""),
+  createReplacement(Code.range("r5"), ""),
+  createReplacement(Code.range("r6"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = R"cpp(struct A {
+  A()
+  $r3[[:]] $r1[[f()]]$r2[[,]]
+$r4[[g()]]
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  std::string Expected = R"cpp(struct A {
+  A()
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  // Not using raw string literals so newlines and spaces are clear and explicit
+  llvm::Annotations Code = "struct A {\n"
+ "  A() {}\n"
+ "$r3[[]]  $r1[[int]] $r2[[f;]]\n" // "  int f;\n"
+ "  \n"
+ "$r4[[  ]]\n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A() {}\n"
+ "\n"
+ "\n"
+ "  \n"
+ "\t\n"
+ "};";
+  tooling::Replacements Replaces =
+  

[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-02-03 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D95714#2540685 , @njames93 wrote:

> Can I ask if you could tidy the description of this, basically remove all the 
> stuff about hasGrandparent etc, probably best just remove everything after 
> `result = (a1 nullptr a2);` in the desc. It shows in the commit message and 
> its not strictly relevant.

Thanks, done. I never thought about all that showing up in the commit message, 
I'll be more concise.


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

https://reviews.llvm.org/D95714

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


[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-02-03 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Thanks for all the great feedback I received here. To give credit where 
credit's due, this updated revision to UseNullptrCheck.cpp is now actually 100% 
@steveire's //suggested// code. Even one of the tests cases was his. Whenever 
it's ready to land I'd appreciate it if someone could push it as I lack 
llvm-project commit access.


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

https://reviews.llvm.org/D95714

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


[PATCH] D95771: [clang-tidy] fix modernize-loop-convert to retain needed array-like operator[]

2021-02-03 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

@njames93 Thanks for the review and for accepting this revision. I lack 
llvm-project commit access so if it's good to go I would greatly appreciate it 
if you or someone could push this whenever you have have a chance. Thanks!


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

https://reviews.llvm.org/D95771

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


[PATCH] D95771: [clang-tidy] fix modernize-loop-convert to retain needed array-like operator[]

2021-02-02 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320704.
poelmanc marked an inline comment as done.
poelmanc added a comment.

Fix formatting, add suggested test case (which works.)


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

https://reviews.llvm.org/D95771

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t
+
+template 
+struct Vector {
+  using iterator = T*;
+  unsigned size() const;
+  const T [](int) const;
+  T [](int);
+  T *begin();
+  T *end();
+  const T *begin() const;
+  const T *end() const;
+};
+
+template 
+void copyArg(T);
+
+class TestArrayOfVector {
+  Vector W[2];
+
+  void foo() const {
+for (int I = 0; I < W[0].size(); ++I) {
+  if (W[0][I])
+copyArg(W[0][I]);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+// CHECK-FIXES: for (int I : W[0]) {
+// CHECK-FIXES-NEXT: if (I)
+// CHECK-FIXES-NEXT: copyArg(I);
+  }
+};
+
+class TestVectorOfVector {
+  Vector> X;
+
+  void foo() const {
+for (int J = 0; J < X[0].size(); ++J) {
+  if (X[0][J])
+copyArg(X[0][J]);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+// CHECK-FIXES: for (int J : X[0]) {
+// CHECK-FIXES-NEXT: if (J)
+// CHECK-FIXES-NEXT: copyArg(J);
+  }
+};
+
+void testVectorOfVectorOfVector() {
+  Vector>> Y;
+  for (int J = 0; J < Y[3].size(); ++J) {
+if (Y[3][J][7])
+  copyArg(Y[3][J][8]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & J : Y[3]) {
+  // CHECK-FIXES-NEXT: if (J[7])
+  // CHECK-FIXES-NEXT: copyArg(J[8]);
+
+  for (int J = 0; J < Y[3][4].size(); ++J) {
+if (Y[3][4][J])
+  copyArg(Y[3][4][J]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int J : Y[3][4]) {
+  // CHECK-FIXES-NEXT: if (J)
+  // CHECK-FIXES-NEXT: copyArg(J);
+}
+
+void testVectorOfVectorIterator() {
+  Vector> Z;
+  for (Vector::iterator it = Z[4].begin(); it != Z[4].end();  ++it) {
+if (*it)
+  copyArg(*it);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & it : Z[4]) {
+  // CHECK-FIXES-NEXT: if (it)
+  // CHECK-FIXES-NEXT: copyArg(it);
+}
Index: clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -722,10 +722,11 @@
   if (isa(ContainerExpr)) {
 ContainerString = "this";
   } else {
-// For CXXOperatorCallExpr (e.g. vector_ptr->size()), its first argument is
-// the class object (vector_ptr) we are targeting.
+// For CXXOperatorCallExpr such as vector_ptr->size() we want the class
+// object vector_ptr, but for vector[2] we need the whole expression.
 if (const auto* E = dyn_cast(ContainerExpr))
-  ContainerExpr = E->getArg(0);
+  if (E->getOperator() != OO_Subscript)
+ContainerExpr = E->getArg(0);
 ContainerString =
 getStringFromRange(Context->getSourceManager(), Context->getLangOpts(),
ContainerExpr->getSourceRange());
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 14 inline comments as done.
poelmanc added inline comments.



Comment at: clang/lib/Format/Format.cpp:2381
+// if so adds a Replacement to NewReplacements that removes the entire line.
+llvm::Error MaybeRemoveBlankLine(tooling::Replacements ,
+ StringRef FilePath, StringRef Code,

kadircet wrote:
> kadircet wrote:
> > can we rather make this function return a `tooling::Replacement` ?
> name should be `maybeRemoveBlankLine`
`maybeRemoveBlankLine` needs to be called twice so I tried to put maximum logic 
in it so to avoid replicating logic at the two calling sites. It doesn't always 
create a replacement, so I believe we could return 
`optional`. Then the caller would have to check the 
`optional`, and if set  call `NewReplaces.add()`, then check that result... I 
can do that if you like but please take a fresh look at the updated 
implementation. Thanks!



Comment at: clang/lib/Format/Format.cpp:2394
+assert(LineEndPos >= CheckedThroughPos);
+StringRef TrailingText(FileText + CheckedThroughPos,
+   LineEndPos - CheckedThroughPos);

kadircet wrote:
> ```
> if(!isAllWhiteSpace(Code.substr(CheckedThroughPos, LineEndPos - 
> CheckedThroughPos))
>   return llvm::Error::success();
> ```
Coming back after a year I found my own code here a bit hard to read... Your 
feedback prompted me to use `StringRef` over `char*` and reduce the number of 
intermediate variables. I put your two suggested `isAllWhiteSpace` calls 
`isAllWhiteSpace` together with `&&`, feel free to suggest further improvement.




Comment at: clang/lib/Format/Format.cpp:2397
+assert(LineEndPos >= LineStartPos);
+StringRef OriginalLine(FileText + LineStartPos, LineEndPos - LineStartPos);
+if (isAllWhitespace(TrailingText) && !isAllWhitespace(OriginalLine)) {

kadircet wrote:
> ```
> if(isAllWhiteSpace(Code.substr(LineStartPos, CheckedThroughPos - 
> LineStartPos))
>   return llvm::Error::success();
> ```
> 
> Also move this to the top, as it doesn't actually require any of the 
> computations you performed.
> 
> I would actually keep a `HasDeleted` flag in the caller, updating it by 
> looking at length of replacements, and call this function iff we've deleted 
> something in that line, but up to you.
Used suggested `isAllWhitespace` together in the `if` clause with above 
`isAllWhitespace`.



Comment at: clang/lib/Format/Format.cpp:2403
+  (CheckedThroughPos > 0 &&
+   isVerticalWhitespace(FileText[CheckedThroughPos - 1]))
+  ? (FileText + LineEndPos)

kadircet wrote:
> i don't follow what this check is about.
> 
> the comment talks about a replacement removing a trailing newline, but check 
> is for a preceding whitespace, and it is not even at the `LineEndPos` ?
> how come we get a vertical whitespace, in the middle of a line?
I clarified the comment to include an example: when the code is `...  
foo\n\n...` and `foo\n` is removed by a replacement already, the second `\n` 
actually represents the //next// line which we don't want to remove.



Comment at: clang/unittests/Format/CleanupTest.cpp:368
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  std::string Code = "namespace A { // Useless comment\n"
+ "  int x\t = 0;\t\n"

kadircet wrote:
> poelmanc wrote:
> > kadircet wrote:
> > > could you replace these with raw string literals instead to get rid of 
> > > `\n`s.
> > I like that modernization suggestion but as a fairly new llvm contributor I 
> > follow the style I see in the surrounding code. Perhaps we should submit a 
> > seperate patch to modernize whole files at a time to use raw string 
> > literals and see how the change is received by the community.
> modernization of the existing code, and introducing old code are different 
> things. former is harder because we would like to keep the history clean, but 
> we tend to do the latter to make sure quality improves over time.
> 
> feel free to keep it if you want though, this one isn't so important.
I tried raw string literals, but these particular tests are all about tabs, 
spaces, and newlines which I found harder to see and reason about using raw 
string literals. I kept the raw string literals in 
`RemoveLinesWhenAllNonWhitespaceRemoved`.



Comment at: clang/unittests/Format/CleanupTest.cpp:376
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 1, 14), 19, ""),
+  createReplacement(getOffset(Code, 2, 3), 3, ""),

kadircet wrote:
> poelmanc wrote:
> > kadircet wrote:
> > > can you make use of `Annotations` library in 
> > > `llvm/include/llvm/Testing/Support/Annotations.h` for getting offsets 
> > > into the code?
> > > 
> > > same for the following test cases
> > 

[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2021-02-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320678.
poelmanc changed the repository for this revision from rCTE Clang Tools Extra 
to rG LLVM Github Monorepo.
poelmanc added a comment.
Herald added subscribers: dexonsmith, mgorny.

Glad to be back after a year away from clang-tidy, and sorry to have let this 
patch linger. Running clang-tidy over a large codebase shows this patch still 
to be needed. I believe I've addressed all identified issues but welcome 
feedback.

@gribozavr @gribozavr2 requested changes to a very early version of this patch 
and I later reworked it to follow the `cleanupAroundReplacements` approach he 
suggested on 2019-10-11.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CMakeLists.txt
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -12,6 +12,7 @@
 #include "clang/Tooling/Core/Replacement.h"
 
 #include "gtest/gtest.h"
+#include "llvm/Testing/Support/Annotations.h"
 
 using clang::tooling::ReplacementTest;
 using clang::tooling::toReplacements;
@@ -320,6 +321,11 @@
 return tooling::Replacement(FileName, Offset, Length, Text);
   }
 
+  tooling::Replacement createReplacement(llvm::Annotations::Range Range,
+ StringRef Text) {
+return createReplacement(Range.Begin, Range.End - Range.Begin, Text);
+  }
+
   tooling::Replacement createInsertion(StringRef IncludeDirective) {
 return createReplacement(UINT_MAX, 0, IncludeDirective);
   }
@@ -373,10 +379,12 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
+ "\n"
  "int x= 0;"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
  "int x= 0;"
  "}";
   tooling::Replacements Replaces =
@@ -386,6 +394,104 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = "namespace A {$r1[[ // Useless comment]]\n"
+   "  $r2[[int]] $r3[[x]]\t $r4[[=]] $r5[[0;]]\t\n"
+   "  int y\t = 0;$r6[[\t]]\n"
+   "} // namespace A\n";
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), ""),
+  createReplacement(Code.range("r5"), ""),
+  createReplacement(Code.range("r6"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  llvm::Annotations Code = R"cpp(struct A {
+  A()
+  $r3[[:]] $r1[[f()]]$r2[[,]]
+$r4[[g()]]
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  std::string Expected = R"cpp(struct A {
+  A()
+  {}
+  int f = 0;
+  int g = 0;
+};)cpp";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(Code.range("r1"), ""),
+  createReplacement(Code.range("r2"), ""),
+  createReplacement(Code.range("r3"), ""),
+  createReplacement(Code.range("r4"), "")});
+
+  EXPECT_EQ(Expected, apply(Code.code(), Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  // Not using raw string literals so newlines and spaces are clear and explicit
+  llvm::Annotations Code = "struct A 

[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-02-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320637.
poelmanc added a comment.

Add period to end of comment.


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

https://reviews.llvm.org/D95714

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering strong_ordering::equal = {0};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+}
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+  int *ptr = 0;
+  // CHECK-FIXES: int *ptr = nullptr;
+  result = (a1 > (ptr == 0 ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > (ptr == nullptr ? a1 : a2));
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : 
a2));
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -41,12 +41,28 @@
   
unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType(,
   unless(hasSourceExpression(hasType(sugaredNullptrType();
 
+  auto isOrHasDescendant = [](auto InnerMatcher) {
+return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
+  };
+
   return traverse(
   TK_AsIs,
-  castExpr(anyOf(ImplicitCastToNull,
- explicitCastExpr(hasDescendant(ImplicitCastToNull))),
-   unless(hasAncestor(explicitCastExpr(
-  .bind(CastSequence));
+  anyOf(castExpr(anyOf(ImplicitCastToNull,
+   
explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+ unless(hasAncestor(explicitCastExpr())),
+ unless(hasAncestor(cxxRewrittenBinaryOperator(
+.bind(CastSequence),
+cxxRewrittenBinaryOperator(
+// Match rewritten operators, but verify (in the check method)
+// that if an implicit cast is found, it is not from another
+// nested rewritten operator.
+expr().bind("matchBinopOperands"),
+hasEitherOperand(isOrHasDescendant(
+implicitCastExpr(
+ImplicitCastToNull,
+hasAncestor(cxxRewrittenBinaryOperator().bind(
+"checkBinopOperands")))
+.bind(CastSequence));
 }
 
 bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -480,6 +496,11 @@
   const auto *NullCast = Result.Nodes.getNodeAs(CastSequence);
   assert(NullCast && "Bad Callback. No node provided");
 
+  if (Result.Nodes.getNodeAs(
+  "matchBinopOperands") !=
+  Result.Nodes.getNodeAs("checkBinopOperands"))
+return;
+
   // Given an implicit null-ptr cast or an explicit cast with an implicit
   // null-to-pointer cast within use CastSequenceVisitor to identify sequences
   // of explicit casts that can be converted into 'nullptr'.


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering strong_ordering::equal = {0};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+}
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // 

[PATCH] D95725: clang-extra: fix incorrect use of std::lock_guard by adding variable name (identified by MSVC [[nodiscard]] error)

2021-02-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as done.
poelmanc added a comment.

s/Guard/Lock/! I don't have commit access so appreciate a push.


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

https://reviews.llvm.org/D95725

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


[PATCH] D95725: clang-extra: fix incorrect use of std::lock_guard by adding variable name (identified by MSVC [[nodiscard]] error)

2021-02-01 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320594.
poelmanc added a comment.

Change Guard to Lock.


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

https://reviews.llvm.org/D95725

Files:
  clang-tools-extra/clangd/support/Function.h


Index: clang-tools-extra/clangd/support/Function.h
===
--- clang-tools-extra/clangd/support/Function.h
+++ clang-tools-extra/clangd/support/Function.h
@@ -51,7 +51,7 @@
 Subscription =(Subscription &) {
   // If *this is active, unsubscribe.
   if (Parent) {
-std::lock_guard(Parent->ListenersMu);
+std::lock_guard Lock(Parent->ListenersMu);
 llvm::erase_if(Parent->Listeners,
[&](const std::pair ) {
  return P.second == ListenerID;


Index: clang-tools-extra/clangd/support/Function.h
===
--- clang-tools-extra/clangd/support/Function.h
+++ clang-tools-extra/clangd/support/Function.h
@@ -51,7 +51,7 @@
 Subscription =(Subscription &) {
   // If *this is active, unsubscribe.
   if (Parent) {
-std::lock_guard(Parent->ListenersMu);
+std::lock_guard Lock(Parent->ListenersMu);
 llvm::erase_if(Parent->Listeners,
[&](const std::pair ) {
  return P.second == ListenerID;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95771: [clang-tidy] fix modernize-loop-convert to retain needed array-like operator[]

2021-01-31 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: sammccall, hokein.
poelmanc added a project: clang-tools-extra.
Herald added a subscriber: xazax.hun.
poelmanc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

`modernize-loop-convert` handles //array-like// objects like vectors fairly 
well, but strips slightly too much information from the iteration expression by 
converting:

  Vector> X;
  for (int J = 0; J < X[5].size(); ++J)
copyArg(X[5][J]);

to

  Vector> X;
  for (int J : X) // should be for (int J : X[5]) 
copyArg(J);

The `[5]` is a call to `operator[]` and gets stripped by 
`LoopConvertCheck::getContainerString`. This patch fixes that and adds several 
test cases.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95771

Files:
  clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp
===
--- /dev/null
+++ 
clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t
+
+template 
+struct Vector {
+  using iterator = T*;
+  unsigned size() const;
+  const T [](int) const;
+  T [](int);
+  T *begin();
+  T *end();
+  const T *begin() const;
+  const T *end() const;
+};
+
+template 
+void copyArg(T);
+
+class TestArrayOfVector {
+  Vector W[2];
+
+  void foo() const {
+for (int I = 0; I < W[0].size(); ++I) {
+  if (W[0][I])
+copyArg(W[0][I]);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+// CHECK-FIXES: for (int I : W[0]) {
+// CHECK-FIXES-NEXT: if (I)
+// CHECK-FIXES-NEXT: copyArg(I);
+  }
+};
+
+class TestVectorOfVector {
+  Vector> X;
+
+  void foo() const {
+for (int J = 0; J < X[0].size(); ++J) {
+  if (X[0][J])
+copyArg(X[0][J]);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+// CHECK-FIXES: for (int J : X[0]) {
+// CHECK-FIXES-NEXT: if (J)
+// CHECK-FIXES-NEXT: copyArg(J);
+  }
+};
+
+void testVectorOfVectorOfVector() {
+  Vector>> Y;
+  for (int J = 0; J < Y[3].size(); ++J) {
+if (Y[3][J][7])
+  copyArg(Y[3][J][8]);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (auto & J : Y[3]) {
+  // CHECK-FIXES-NEXT: if (J[7])
+  // CHECK-FIXES-NEXT: copyArg(J[8]);
+};
+
+void testVectorOfVectorIterator() {
+  Vector> Z;
+  for (Vector::iterator it = Z[4].begin(); it != Z[4].end();  ++it) {
+if (*it)
+  copyArg(*it);
+  }
+  // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop
+  // CHECK-FIXES: for (int & it : Z[4]) {
+  // CHECK-FIXES-NEXT: if (it)
+  // CHECK-FIXES-NEXT: copyArg(it);
+};
Index: clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -722,10 +722,11 @@
   if (isa(ContainerExpr)) {
 ContainerString = "this";
   } else {
-// For CXXOperatorCallExpr (e.g. vector_ptr->size()), its first argument is
-// the class object (vector_ptr) we are targeting.
+// For CXXOperatorCallExpr such as vector_ptr->size() we want the class
+// object vector_ptr, but for vector[2] we need the whole expression.
 if (const auto* E = dyn_cast(ContainerExpr))
-  ContainerExpr = E->getArg(0);
+  if ( E->getOperator() != OO_Subscript )
+ContainerExpr = E->getArg(0);
 ContainerString =
 getStringFromRange(Context->getSourceManager(), Context->getLangOpts(),
ContainerExpr->getSourceRange());


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-loop-convert-multidimensional.cpp
@@ -0,0 +1,70 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t
+
+template 
+struct Vector {
+  using iterator = T*;
+  unsigned size() const;
+  const T [](int) const;
+  T [](int);
+  T *begin();
+  T *end();
+  const T *begin() const;
+  const T *end() const;
+};
+
+template 
+void copyArg(T);
+
+class TestArrayOfVector {
+  Vector W[2];
+
+  void foo() const {
+for (int I = 0; I < W[0].size(); ++I) {
+  if (W[0][I])
+copyArg(W[0][I]);
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop
+// CHECK-FIXES: for (int I : W[0]) {
+// CHECK-FIXES-NEXT: if (I)
+// CHECK-FIXES-NEXT: copyArg(I);
+  }
+};
+
+class TestVectorOfVector {
+  Vector> X;
+
+  void foo() const {
+for 

[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-01-31 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320393.
poelmanc added a comment.

Thanks @steveire, that suggestion worked perfectly! I added the additional test 
case and shortened the mimicked `strong_ordering` code to a version from 
`clang/unittests.ASTMatchers/ASTMatchersTraversalTest.cpp`, but also manually 
tested this using both MSVC's and libstdc++v3's `` header.


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

https://reviews.llvm.org/D95714

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering strong_ordering::equal = {0};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+}
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+  int *ptr = 0;
+  // CHECK-FIXES: int *ptr = nullptr;
+  result = (a1 > (ptr == 0 ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > (ptr == nullptr ? a1 : a2));
+  result = (a1 > ((a1 > (ptr == 0 ? a1 : a2)) ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : 
a2));
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -41,12 +41,28 @@
   
unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType(,
   unless(hasSourceExpression(hasType(sugaredNullptrType();
 
+  auto isOrHasDescendant = [](auto InnerMatcher) {
+return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
+  };
+
   return traverse(
   TK_AsIs,
-  castExpr(anyOf(ImplicitCastToNull,
- explicitCastExpr(hasDescendant(ImplicitCastToNull))),
-   unless(hasAncestor(explicitCastExpr(
-  .bind(CastSequence));
+  anyOf(castExpr(anyOf(ImplicitCastToNull,
+   
explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+ unless(hasAncestor(explicitCastExpr())),
+ unless(hasAncestor(cxxRewrittenBinaryOperator(
+.bind(CastSequence),
+cxxRewrittenBinaryOperator(
+// Match rewritten operators, but verify (in the check method)
+// that if an implicit cast is found, it is not from another
+// nested rewritten operator
+expr().bind("matchBinopOperands"),
+hasEitherOperand(isOrHasDescendant(
+implicitCastExpr(
+ImplicitCastToNull,
+hasAncestor(cxxRewrittenBinaryOperator().bind(
+"checkBinopOperands")))
+.bind(CastSequence));
 }
 
 bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
@@ -480,6 +496,11 @@
   const auto *NullCast = Result.Nodes.getNodeAs(CastSequence);
   assert(NullCast && "Bad Callback. No node provided");
 
+  if (Result.Nodes.getNodeAs(
+  "matchBinopOperands") !=
+  Result.Nodes.getNodeAs("checkBinopOperands"))
+return;
+
   // Given an implicit null-ptr cast or an explicit cast with an implicit
   // null-to-pointer cast within use CastSequenceVisitor to identify sequences
   // of explicit casts that can be converted into 'nullptr'.


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,34 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+struct strong_ordering {
+  int n;
+  constexpr operator int() const { return n; }
+  static const strong_ordering equal, greater, less;
+};
+constexpr strong_ordering strong_ordering::equal = {0};
+constexpr strong_ordering strong_ordering::greater = {1};
+constexpr strong_ordering strong_ordering::less = {-1};
+}
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void 

[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-01-31 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D95714#2532565 , @njames93 wrote:

> This does highlight an issue where the mimicked std library stubs used for 
> tests don't correspond exactly to what the stdlib actually looks like and can 
> result in subtly different ASTs that have added/removed implicit nodes.
>
> Going a little off point here but a few months back I pushed a fix for 
> another check that passed its tests. 
> However the bug report was re-opened as the bug was still observable in the 
> real word. 
> Turned out the implementation of std::string used for the test had a trivial 
> destructor resulting in the AST not needed to emit `CXXBindTemporaryExpr`s 
> all over the place, which threw off the matching logic.
>
> Unfortunately this kind of disparity is hard to detect in tests so it may be 
> wise to test this locally using the compare header from a real standard 
> library implementation (preferably all 3 main ones if you have the machines) 
> and see if this behaviour is correct.

Indeed the //mimicked std library// approach has real advantages like running 
fast and giving consistent results across platforms. But it also has drawbacks 
like the replication of //mimicked std// code across tests, and possible 
differences between test and real world behaviour. We could give tests a 
`CLANG_TIDY_TEST_NATIVE_STD` macro to switch between //mimicked std// code and 
real headers, and set up CI to test both ways, to catch these issues at the 
expense of added complexity. But that's a broader discussion.

Back to `modernize-use-nullptr`, these days I'm working in MSVC and the tests 
pass with MSVC's ``, with my mimicked compare, and a shorter mimicked 
`strong_ordering` that I found in `ASTTraverserTest.cpp`. But I fetched gcc's 
`` from 
https://raw.githubusercontent.com/gcc-mirror/gcc/master/libstdc%2B%2B-v3/libsupc%2B%2B/compare
 and now see the same ASTs as you, and the proposed fix fails.

Thoughts on which option seems like the best path forward?

1. In the ASTs I've seen so far the third child of the 
`CXXRewrittenBinaryOperator`'s `CXXOperatorCallExpr ` is the one to ignore. But 
comments in :268-283 imply that perhaps sometimes the `0` 
may appear first? There should be some way to determine which child was added 
by the `CXXRewrittenBinaryOperator` rewrite and skip that child, regardless of 
`std` implementation, but I have yet to figure that out.
2. Roll back to `hasAncestor`, fixing the immediate problem of creating invalid 
fixes (`a1 nullptr 2a`) and accepting that some rare but fixable code (`a1 < ( 
ptr == 0 ? a2 : a3`) will not be modernized to `nullptr`.
3. Change the bugfix approach here from AST-based to text-based. In 
`replaceWithNullptr` in `UseNullptrCheck.cpp:62`, add code to skip the planned 
replacement if the text we're about to replace with `nullptr` consists of `<`, 
`=`, and `>`. As a quick test, this version seems to make all tests pass and 
doesn't depend on std header implementation:

  static const std::string SuspiciousChars("<=>");
  char FirstCharToReplace = *SM.getCharacterData(StartLoc);
  char LastCharToReplace = *SM.getCharacterData(EndLoc);
  if (SuspiciousChars.find(FirstCharToReplace) != std::string::npos &&
  SuspiciousChars.find(LastCharToReplace) != std::string::npos)
return;


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

https://reviews.llvm.org/D95714

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


[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-01-30 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

@njames93 Thank you so much for the quick feedback, I made your suggested 
changes and added a test that it properly converts `result = (a1 > (ptr == 0 ? 
a1 : a2));` to `result = (a1 > (ptr == nullptr ? a1 : a2));` now.

In these examples so far, checking the grandparent works. Here's the AST:

  $ clang -std=c++20 -Xclang -ast-dump modernize-use-nullptr-cxx20.cpp
  ...
  |-BinaryOperator 0x22d30bec4e0  'bool' lvalue '=' // 
result = (a1 < a2); // result = (a1 > (ptr == 0 ? a1 : a2));
  | |-DeclRefExpr 0x22d30be8960  'bool' lvalue Var 0x22d30be88e0 
'result' 'bool'
  | `-ParenExpr 0x22d30bec4c0  'bool'
  |   `-CXXRewrittenBinaryOperator 0x22d30bec4a8  'bool'
  | `-CXXOperatorCallExpr 0x22d30bec470  'bool' '<' adl
  |   |-ImplicitCastExpr 0x22d30bec458  'bool (*)(const 
std::strong_ordering, std::strong_ordering::zero_type) noexcept' 

  |   | `-DeclRefExpr 0x22d30bec3d8  'bool (const 
std::strong_ordering, std::strong_ordering::zero_type) noexcept' lvalue 
Function 0x22d30ba9f28 'operator<' 'bool (const std::strong_ordering, 
std::strong_ordering::zero_type) noexcept'
  |   |-CXXOperatorCallExpr 0x22d30bec360  
'std::strong_ordering':'std::strong_ordering' '<=>'
  |   | |-ImplicitCastExpr 0x22d30bec348  'std::strong_ordering 
(*)(const A &) const noexcept' 
  |   | | `-DeclRefExpr 0x22d30be8a08  'std::strong_ordering 
(const A &) const noexcept' lvalue CXXMethod 0x22d30bedcd8 'operator<=>' 
'std::strong_ordering (const A &) const noexcept'
  |   | |-ImplicitCastExpr 0x22d30be89f0  'const A' lvalue 

  |   | | `-DeclRefExpr 0x22d30be8998  'A' lvalue Var 
0x22d30be8290 'a1' 'A'
  |   | `-ImplicitCastExpr 0x22d30be89d8  'const A' lvalue 

  |   |   `-DeclRefExpr 0x22d30be89b8  'A' lvalue Var 
0x22d30be87f0 'a2' 'A'
  |   `-ImplicitCastExpr 0x22d30bec3c0  
'std::strong_ordering::zero_type':'nullptr_t'  // Auto-generated 
cast we should ignore
  | `-IntegerLiteral 0x22d30bec398  'int' 0
  ...
  `-BinaryOperator 0x22d30becb20  'bool' lvalue '='
|-DeclRefExpr 0x22d30bec830  'bool' lvalue Var 0x22d30be88e0 
'result' 'bool'
`-ParenExpr 0x22d30becb00  'bool'
  `-CXXRewrittenBinaryOperator 0x22d30becae8  'bool'
`-CXXOperatorCallExpr 0x22d30becab0  'bool' '>' adl
  |-ImplicitCastExpr 0x22d30beca98  'bool (*)(const 
std::strong_ordering, std::strong_ordering::zero_type) noexcept' 

  | `-DeclRefExpr 0x22d30beca78  'bool (const 
std::strong_ordering, std::strong_ordering::zero_type) noexcept' lvalue 
Function 0x22d30baa1a0 'operator>' 'bool (const std::strong_ordering, 
std::strong_ordering::zero_type) noexcept'
  |-CXXOperatorCallExpr 0x22d30beca00  
'std::strong_ordering':'std::strong_ordering' '<=>'
  | |-ImplicitCastExpr 0x22d30bec9e8  'std::strong_ordering 
(*)(const A &) const noexcept' 
  | | `-DeclRefExpr 0x22d30bec9c8  'std::strong_ordering 
(const A &) const noexcept' lvalue CXXMethod 0x22d30bedcd8 'operator<=>' 
'std::strong_ordering (const A &) const noexcept'
  | |-ImplicitCastExpr 0x22d30bec9b0  'const A' lvalue 

  | | `-DeclRefExpr 0x22d30bec850  'A' lvalue Var 
0x22d30be8290 'a1' 'A'
  | `-ImplicitCastExpr 0x22d30bec998  'const A' 
lvalue 
  |   `-ParenExpr 0x22d30bec978  'A' lvalue
  | `-ConditionalOperator 0x22d30bec948  'A' 
lvalue
  |   |-BinaryOperator 0x22d30bec8e8  'bool' 
'=='
  |   | |-ImplicitCastExpr 0x22d30bec8b8  'int *' 

  |   | | `-DeclRefExpr 0x22d30bec870  'int *' lvalue 
Var 0x22d30bec758 'ptr' 'int *'
  |   | `-ImplicitCastExpr 0x22d30bec8d0  'int *' 
 // ptr == 0 cast that we want to convert to nullptr
  |   |   `-IntegerLiteral 0x22d30bec890  'int' 0
  |   |-DeclRefExpr 0x22d30bec908  'A' lvalue Var 
0x22d30be8290 'a1' 'A'
  |   `-DeclRefExpr 0x22d30bec928  'A' lvalue Var 
0x22d30be87f0 'a2' 'A'
  `-ImplicitCastExpr 0x22d30beca60  
'std::strong_ordering::zero_type':'nullptr_t'  // Auto-generated 
cast we should ignore
`-IntegerLiteral 0x22d30beca38  'int' 0

This looks a little bit different from your AST but I'm not sure what code your 
AST was generated from. If you have a test case I'd be happy to take a look. 
Thanks!


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

https://reviews.llvm.org/D95714

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


[PATCH] D95714: [clang-tidy] fix modernize-use-nullptr false positive with spaceship operator comparisons

2021-01-30 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320330.
poelmanc added a comment.

Thanks to the great feedback, changed 
`unless(hasAncestor(cxxRewrittenBinaryOperator()))` to 
`unless(hasParent(expr(hasParent(cxxRewrittenBinaryOperator()` and added a 
test to verify the improvement (and removed an extraneous comment.)


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

https://reviews.llvm.org/D95714

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,50 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+
+struct strong_ordering {
+  static const strong_ordering less;
+  static const strong_ordering equal;
+  static const strong_ordering greater;
+  using zero_type = decltype(nullptr);
+
+  friend constexpr bool operator<(const strong_ordering value, zero_type) 
noexcept {
+return value.comparison_value < 0;
+  }
+
+  friend constexpr bool operator>(const strong_ordering value, zero_type) 
noexcept {
+return value.comparison_value > 0;
+  }
+
+  friend constexpr bool operator>=(const strong_ordering value, zero_type) 
noexcept {
+return value.comparison_value >= 0;
+  }
+
+  signed char comparison_value;
+};
+
+inline constexpr strong_ordering strong_ordering::less{-1};
+inline constexpr strong_ordering strong_ordering::equal{0};
+inline constexpr strong_ordering strong_ordering::greater{1};
+
+} // namespace std
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+  int *ptr = 0;
+  // CHECK-FIXES: int *ptr = nullptr;
+  result = (a1 > (ptr == 0 ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > (ptr == nullptr ? a1 : a2));
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -45,6 +45,8 @@
   TK_AsIs,
   castExpr(anyOf(ImplicitCastToNull,
  explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+   // Skip implicit casts to 0 generated by operator<=> rewrites.
+   
unless(hasParent(expr(hasParent(cxxRewrittenBinaryOperator(),
unless(hasAncestor(explicitCastExpr(
   .bind(CastSequence));
 }


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,50 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+namespace std {
+
+struct strong_ordering {
+  static const strong_ordering less;
+  static const strong_ordering equal;
+  static const strong_ordering greater;
+  using zero_type = decltype(nullptr);
+
+  friend constexpr bool operator<(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value < 0;
+  }
+
+  friend constexpr bool operator>(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value > 0;
+  }
+
+  friend constexpr bool operator>=(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value >= 0;
+  }
+
+  signed char comparison_value;
+};
+
+inline constexpr strong_ordering strong_ordering::less{-1};
+inline constexpr strong_ordering strong_ordering::equal{0};
+inline constexpr strong_ordering strong_ordering::greater{1};
+
+} // namespace std
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+  int *ptr = 0;
+  // CHECK-FIXES: int *ptr = nullptr;
+  result = (a1 > (ptr == 0 ? a1 : a2));
+  // CHECK-FIXES: result = (a1 > (ptr == nullptr ? a1 : a2));
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -45,6 +45,8 @@
   TK_AsIs,
   

[PATCH] D95726: clang-tidy: modernize-use-nullptr mistakenly fixes rewritten spaceship operator comparisons - hasGrandparent version

2021-01-30 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Thanks for the quick feedback everyone. I agree too, withdrawing this in favor 
of https://reviews.llvm.org/D95714.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D95726

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


[PATCH] D95714: clang-tidy: modernize-use-nullptr mistakenly fixes rewritten spaceship operator comparisons

2021-01-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320286.
poelmanc added a comment.

Fix test failure in `modernize-use-nullptr-cxx20.cpp` by replacing `#include 
` with some minimal equivalent `std` code.


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

https://reviews.llvm.org/D95714

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,48 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+// Not all systems have #include  to define std::std_ordering
+// required by operator<=>, so recreate minimal version for tests below.
+namespace std {
+
+struct strong_ordering {
+  static const strong_ordering less;
+  static const strong_ordering equal;
+  static const strong_ordering greater;
+  using zero_type = decltype(nullptr);
+
+  friend constexpr bool operator<(const strong_ordering value, zero_type) 
noexcept {
+return value.comparison_value < 0;
+  }
+
+  friend constexpr bool operator>(const strong_ordering value, zero_type) 
noexcept {
+return value.comparison_value > 0;
+  }
+
+  friend constexpr bool operator>=(const strong_ordering value, zero_type) 
noexcept {
+return value.comparison_value >= 0;
+  }
+
+  signed char comparison_value;
+};
+
+inline constexpr strong_ordering strong_ordering::less{-1};
+inline constexpr strong_ordering strong_ordering::equal{0};
+inline constexpr strong_ordering strong_ordering::greater{1};
+
+} // namespace std
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -45,6 +45,8 @@
   TK_AsIs,
   castExpr(anyOf(ImplicitCastToNull,
  explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+   // Skip implicit casts to 0 generated by operator<=> rewrites.
+   unless(hasAncestor(cxxRewrittenBinaryOperator())),
unless(hasAncestor(explicitCastExpr(
   .bind(CastSequence));
 }


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,48 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+// Not all systems have #include  to define std::std_ordering
+// required by operator<=>, so recreate minimal version for tests below.
+namespace std {
+
+struct strong_ordering {
+  static const strong_ordering less;
+  static const strong_ordering equal;
+  static const strong_ordering greater;
+  using zero_type = decltype(nullptr);
+
+  friend constexpr bool operator<(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value < 0;
+  }
+
+  friend constexpr bool operator>(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value > 0;
+  }
+
+  friend constexpr bool operator>=(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value >= 0;
+  }
+
+  signed char comparison_value;
+};
+
+inline constexpr strong_ordering strong_ordering::less{-1};
+inline constexpr strong_ordering strong_ordering::equal{0};
+inline constexpr strong_ordering strong_ordering::greater{1};
+
+} // namespace std
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -45,6 +45,8 @@
   TK_AsIs,
   castExpr(anyOf(ImplicitCastToNull,
  explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+   // Skip implicit casts to 0 generated by operator<=> rewrites.
+   

[PATCH] D95726: clang-tidy: modernize-use-nullptr mistakenly fixes rewritten spaceship operator comparisons - hasGrandparent version

2021-01-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Fix test failure in `modernize-use-nullptr-cxx20.cpp` by replacing `#include 
` with some minimal equivalent `std` code.


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

https://reviews.llvm.org/D95726

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


[PATCH] D95726: clang-tidy: modernize-use-nullptr mistakenly fixes rewritten spaceship operator comparisons - hasGrandparent version

2021-01-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Fixed test failure in `modernize-use-nullptr-cxx20.cpp` by replacing `#include 
` with some minimal equivalent `std` code.


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

https://reviews.llvm.org/D95726

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


[PATCH] D95726: clang-tidy: modernize-use-nullptr mistakenly fixes rewritten spaceship operator comparisons - hasGrandparent version

2021-01-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 320284.
poelmanc added a comment.

Fix test failure in `modernize-use-nullptr-cxx20.cpp` by replacing `#include 
` with some minimal equivalent `std` code.


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

https://reviews.llvm.org/D95726

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp

Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -659,6 +659,8 @@
   ResultCache.clear();
 if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
   return matchesParentOf(Node, Matcher, Builder);
+else if (MatchMode == AncestorMatchMode::AMM_GrandparentOnly)
+  return matchesGrandparentOf(Node, Matcher, Builder);
 return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
   }
 
@@ -893,6 +895,18 @@
 return false;
   }
 
+  // Returns whether a direct grandparent of \p Node matches \p Matcher.
+  bool matchesGrandparentOf(const DynTypedNode ,
+  const DynTypedMatcher ,
+  BoundNodesTreeBuilder *Builder) {
+for (const auto  : ActiveASTContext->getParents(Node)) {
+  if (matchesParentOf(Parent, Matcher, Builder)) {
+return true;
+  }
+}
+return false;
+  }
+
   // Returns whether an ancestor of \p Node matches \p Matcher.
   //
   // The order of matching (which can lead to different nodes being bound in
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -654,7 +654,10 @@
 AMM_All,
 
 /// Direct parent only.
-AMM_ParentOnly
+AMM_ParentOnly,
+
+/// Direct grandparent only.
+AMM_GrandparentOnly
   };
 
   virtual ~ASTMatchFinder() = default;
@@ -1654,6 +1657,29 @@
   }
 };
 
+/// Matches nodes of type \c T that have a grandparent node of type
+/// \c GrandparentT for which the given inner matcher matches.
+///
+/// \c GrandparentT must be an AST base type.
+template 
+class HasGrandparentMatcher : public MatcherInterface {
+  static_assert(IsBaseType::value,
+"has parent only accepts base type matcher");
+
+  const DynTypedMatcher GrandparentMatcher;
+
+public:
+  explicit HasGrandparentMatcher(
+  const Matcher )
+  : GrandparentMatcher(GrandparentMatcher) {}
+
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+return Finder->matchesAncestorOf(Node, this->GrandparentMatcher, Builder,
+ ASTMatchFinder::AMM_GrandparentOnly);
+  }
+};
+
 /// Matches nodes of type \c T that have at least one ancestor node of
 /// type \c AncestorT for which the given inner matcher matches.
 ///
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3434,6 +3434,22 @@
 internal::TypeList>
 hasParent;
 
+/// Matches AST nodes that have a grandparent that matches the provided
+/// matcher.
+///
+/// Given
+/// \code
+/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } }
+/// \endcode
+/// \c compoundStmt(hasGrandparent(forStmt())) matches "{ int x = 43; }".
+///
+/// Usable as: Any Matcher
+extern const internal::ArgumentAdaptingMatcherFunc<
+internal::HasGrandparentMatcher,
+internal::TypeList,
+internal::TypeList>
+hasGrandparent;
+
 /// Matches AST nodes that have an ancestor that matches the provided
 /// matcher.
 ///
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,52 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+// Not all systems have #include  to define std::std_ordering
+// required by operator<=>, so recreate minimal version for tests below.
+namespace std {
+
+struct strong_ordering {
+  static const strong_ordering less;
+  static const strong_ordering equal;
+  static const strong_ordering greater;
+  using zero_type = decltype(nullptr);
+
+  friend constexpr bool operator<(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value < 0;
+  }
+
+  friend constexpr bool operator>(const strong_ordering value, zero_type) noexcept {
+return value.comparison_value > 0;
+ 

[PATCH] D95726: clang-tidy: modernize-use-nullptr mistakenly fixes rewritten spaceship operator comparisons - hasGrandparent version

2021-01-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: aaron.ballman, angelgarcia, hokein.
poelmanc added a project: clang-tools-extra.
Herald added a subscriber: yaxunl.
poelmanc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

As in https://reviews.llvm.org/D95714, `clang-tidy -std=c++20` with 
`modernize-use-nullptr` mistakenly inserts `nullptr` in place of the comparison 
operator if the comparison internally expands in the AST to a rewritten 
spaceship operator. This can be reproduced by running the new 
`modernize-use-nullptr-cxx20.cpp` test without applying the supplied patch to 
UseNullptrCheck.cpp; the current clang-tidy will mistakenly replace:

  result = (a1 < a2);

with

  result = (a1 nullptr a2);

Oops!

The supplied patch fixes this by adding just one comment and one line of code 
to UseNullptrCheck.cpp:

  // Skip implicit casts to 0 generated by operator<=> rewrites.
  unless(hasGrandparent(cxxRewrittenBinaryOperator())),

It also adds the new `hasGrandparent` matcher, which is necessary as opposed to 
`hasAncestor` to properly convert:

  result = (a1 > (ptr == 0 ? a1 : a2));

to

  result = (a1 > (ptr == nullptr ? a1 : a2));

In this case the AST has an "ancestor" that is a rewritten binary operator, but 
not a direct grandparent.

This is an alternative to https://reviews.llvm.org/D95714.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95726

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchFinder.cpp

Index: clang/lib/ASTMatchers/ASTMatchFinder.cpp
===
--- clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -659,6 +659,8 @@
   ResultCache.clear();
 if (MatchMode == AncestorMatchMode::AMM_ParentOnly)
   return matchesParentOf(Node, Matcher, Builder);
+else if (MatchMode == AncestorMatchMode::AMM_GrandparentOnly)
+  return matchesGrandparentOf(Node, Matcher, Builder);
 return matchesAnyAncestorOf(Node, Ctx, Matcher, Builder);
   }
 
@@ -893,6 +895,18 @@
 return false;
   }
 
+  // Returns whether a direct grandparent of \p Node matches \p Matcher.
+  bool matchesGrandparentOf(const DynTypedNode ,
+  const DynTypedMatcher ,
+  BoundNodesTreeBuilder *Builder) {
+for (const auto  : ActiveASTContext->getParents(Node)) {
+  if (matchesParentOf(Parent, Matcher, Builder)) {
+return true;
+  }
+}
+return false;
+  }
+
   // Returns whether an ancestor of \p Node matches \p Matcher.
   //
   // The order of matching (which can lead to different nodes being bound in
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -654,7 +654,10 @@
 AMM_All,
 
 /// Direct parent only.
-AMM_ParentOnly
+AMM_ParentOnly,
+
+/// Direct grandparent only.
+AMM_GrandparentOnly
   };
 
   virtual ~ASTMatchFinder() = default;
@@ -1654,6 +1657,29 @@
   }
 };
 
+/// Matches nodes of type \c T that have a grandparent node of type
+/// \c GrandparentT for which the given inner matcher matches.
+///
+/// \c GrandparentT must be an AST base type.
+template 
+class HasGrandparentMatcher : public MatcherInterface {
+  static_assert(IsBaseType::value,
+"has parent only accepts base type matcher");
+
+  const DynTypedMatcher GrandparentMatcher;
+
+public:
+  explicit HasGrandparentMatcher(
+  const Matcher )
+  : GrandparentMatcher(GrandparentMatcher) {}
+
+  bool matches(const T , ASTMatchFinder *Finder,
+   BoundNodesTreeBuilder *Builder) const override {
+return Finder->matchesAncestorOf(Node, this->GrandparentMatcher, Builder,
+ ASTMatchFinder::AMM_GrandparentOnly);
+  }
+};
+
 /// Matches nodes of type \c T that have at least one ancestor node of
 /// type \c AncestorT for which the given inner matcher matches.
 ///
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -3434,6 +3434,22 @@
 internal::TypeList>
 hasParent;
 
+/// Matches AST nodes that have a grandparent that matches the provided
+/// matcher.
+///
+/// Given
+/// \code
+/// void f() { for (;;) { int x = 42; if (true) { int x = 43; } } }
+/// \endcode
+/// \c compoundStmt(hasGrandparent(forStmt())) matches "{ int x = 43; }".
+///
+/// Usable as: Any Matcher
+extern const 

[PATCH] D95725: clang-extra: fix incorrect use of std::lock_guard by adding variable name (identified by MSVC [[nodiscard]] error)

2021-01-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: sammccall, ilya-biryukov.
poelmanc added a project: clang-tools-extra.
Herald added subscribers: usaxena95, kadircet, arphaman.
poelmanc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

`std::lock_guard` is an RAII class that needs a variable name whose scope 
determines the guard's lifetime. This particular usage lacked a variable name, 
meaning the guard could be destroyed before the line that it was indented to 
protect.

This line was identified by building clang with the latest MSVC preview 
release, which declares the std::lock_guard constructor to be `[[nodiscard]]` 
to draw attention to such issues.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95725

Files:
  clang-tools-extra/clangd/support/Function.h


Index: clang-tools-extra/clangd/support/Function.h
===
--- clang-tools-extra/clangd/support/Function.h
+++ clang-tools-extra/clangd/support/Function.h
@@ -51,7 +51,7 @@
 Subscription =(Subscription &) {
   // If *this is active, unsubscribe.
   if (Parent) {
-std::lock_guard(Parent->ListenersMu);
+std::lock_guard Guard(Parent->ListenersMu);
 llvm::erase_if(Parent->Listeners,
[&](const std::pair ) {
  return P.second == ListenerID;


Index: clang-tools-extra/clangd/support/Function.h
===
--- clang-tools-extra/clangd/support/Function.h
+++ clang-tools-extra/clangd/support/Function.h
@@ -51,7 +51,7 @@
 Subscription =(Subscription &) {
   // If *this is active, unsubscribe.
   if (Parent) {
-std::lock_guard(Parent->ListenersMu);
+std::lock_guard Guard(Parent->ListenersMu);
 llvm::erase_if(Parent->Listeners,
[&](const std::pair ) {
  return P.second == ListenerID;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D95714: clang-tidy: modernize-use-nullptr mistakenly fixes rewritten spaceship operator comparisons

2021-01-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: aaron.ballman, angelgarcia, hokein.
poelmanc added a project: clang-tools-extra.
Herald added a subscriber: yaxunl.
poelmanc requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

`clang-tidy -std=c++20` with `modernize-use-nullptr` mistakenly inserts 
`nullptr` in place of the comparison operator if the comparison internally 
expands in the AST to a rewritten spaceship operator. This can be reproduced by 
running the new `modernize-use-nullptr-cxx20.cpp` test without applying the 
supplied patch to `UseNullptrCheck.cpp`; the current clang-tidy will mistakenly 
replace:

  result = (a1 < a2);

with

  result = (a1 nullptr a2);

Oops!

The supplied patch fixes this by adding just one comment and one line of code 
to `UseNullptrCheck.cpp`:

  // Skip implicit casts to 0 generated by operator<=> rewrites.
  unless(hasAncestor(cxxRewrittenBinaryOperator())),

I looked for a `hasGrandparent` matcher which would be more precise, but none 
exists. This fix slightly overly-aggressively eliminates matches, so even with 
this patch `modernize-use-nullptr` will not convert

  result = (a1 > (ptr == 0 ? a1 : a2));

to

  result = (a1 > (ptr == nullptr ? a1 : a2));

because `ptr == 0` has an ancestor that is a rewritten spaceship operator. 
Changing the proposed one-line fix to:

  unless(hasGrandparent(cxxRewrittenBinaryOperator())),

resolves this, but requires another 57 lines of code across AstMatchers.h, 
AstMatchersInternal.h, and AstMatchFinder.cpp to create `hasGrandparent`. I'd 
be happy to supply that patch instead if folks think it worthwhile? Maybe 
others in the future can benefit from `hasGrandparent`?


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D95714

Files:
  clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+#include 
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -45,6 +45,8 @@
   TK_AsIs,
   castExpr(anyOf(ImplicitCastToNull,
  explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+   // Skip implicit casts to 0 generated by operator<=> rewrites.
+   unless(hasAncestor(cxxRewrittenBinaryOperator())),
unless(hasAncestor(explicitCastExpr(
   .bind(CastSequence));
 }


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-nullptr-cxx20.cpp
@@ -0,0 +1,19 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+
+#include 
+
+class A {
+public:
+  auto operator<=>(const A ) const = default;
+};
+
+void test_cxx_rewritten_binary_ops() {
+  A a1, a2;
+  bool result;
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 < a2);
+  // CHECK-FIXES: result = (a1 < a2);
+  // should not change next line to (a1 nullptr a2)
+  result = (a1 >= a2);
+  // CHECK-FIXES: result = (a1 >= a2);
+}
Index: clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -45,6 +45,8 @@
   TK_AsIs,
   castExpr(anyOf(ImplicitCastToNull,
  explicitCastExpr(hasDescendant(ImplicitCastToNull))),
+   // Skip implicit casts to 0 generated by operator<=> rewrites.
+   unless(hasAncestor(cxxRewrittenBinaryOperator())),
unless(hasAncestor(explicitCastExpr(
   .bind(CastSequence));
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-12-22 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 4 inline comments as done.
poelmanc added a comment.

In D68682#1754798 , @kadircet wrote:

> `ToolingTests/ApplyAtomicChangesTest.FormatsCorrectLineWhenHeaderIsRemoved` 
> also seems to be failing, you can run it with `ninja ToolingTests && 
> ./tools/clang/unittests/Tooling/ToolingTests 
> --gtest_filter="ApplyAtomicChangesTest.FormatsCorrectLineWhenHeaderIsRemoved"`


Thank you, this test revealed a real edge case for which the algorithm was 
failing, which I've now fixed and created a new test case to verify: If a set 
of Replacements removes all non-whitespace on a line **including** the trailing 
newline **and** the line is followed by a single newline character, it should 
not chomp the following newline as well.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682



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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-12-22 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as done.
poelmanc added inline comments.



Comment at: clang/include/clang/Basic/CharInfo.h:94
+LLVM_READONLY inline bool isWhitespace(llvm::StringRef S) {
+  for (StringRef::const_iterator I = S.begin(), E = S.end(); I != E; ++I) {
+if (!isWhitespace(*I))

alexfh wrote:
> I'd suggest to avoid overloading here. A name like `isWhitespaceOnly` would 
> be less ambiguous.
> 
> As for implementation, it can be less verbose:
> ```
> for (char C : S)
>   if (!isWhitespace(*I))
> return false;
> return true;
> ```
> or just
> ```
> return llvm::all_of(S, isWhitespace);
> ```
Thanks for the suggestion, I've removed the overloading and updated the 
implementation.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682



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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-12-22 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 13 inline comments as done.
poelmanc added inline comments.



Comment at: clang/lib/Format/Format.cpp:2385
+  const char *FileText = Code.data();
+  StringRef FilePath; // Must be the same for every Replacement
+  for (const auto  : Replaces) {

kadircet wrote:
> maybe assign `FilePath = Replaces.begin()->getFilePath()` here, and early 
> exit in the beginning if `Replaces` is empty?
> Then you can just `assert(FilePath == R.getFilePath())`
Thank you for the detailed review of the algorithm and the suggestions, sorry 
it took me so long to get back to this. Done.



Comment at: clang/lib/Format/Format.cpp:2391
+
+int CurrentRLineStartPos = RStartPos;
+while (CurrentRLineStartPos > 0 &&

kadircet wrote:
> it seems like this loop is trying to find line start, would be nice to 
> clarify with a comment.
> 
> If so seems like the logic is a little buggy, for example:
> 
> `int a^;` if the offset is at `^`(namely at `a`) then this will return 
> current position as line start, since `a` is preceded by a whitespace.
> Maybe change the logic to find the first `\n` before current offset, and skip 
> any whitespaces after that `\n` (if really necessary)
> 
> btw, please do explain why you are skipping the preceding whitespaces in the 
> comment.
> 
> could you also add a test case for this one?
Good point, I clarified by refactoring this code into a simple helper function 
`FindLineStart`.

I don't believe there's buggy logic but the term //vertical whitespace// may 
have caused confusion - it includes only newline characters (linefeed & 
carriage returns) whereas //whitespace// includes those plus spaces and tabs. 
Now that the function is called `FindLineStart` the logic is hopefully clear.



Comment at: clang/lib/Format/Format.cpp:2398
+assert(CurrentRLineStartPos >= LineStartPos);
+if (CurrentRLineStartPos != LineStartPos) {
+  // We've moved on to a new line. Wrap up the old one before moving on.

kadircet wrote:
> this logic might not work in cases like:
> 
> ```
> in^t a;
> int^ b;
> ```
> 
> let's assume you've got replacements at places marked with `^` again, then 
> they would have same start position so you would miss the line change event.
> maybe count number of `\n`s in the previous loop to detect current line 
> number.
> 
> Also please add a test for this case as well.
I'm not sure I understand this concern; if you could draft up a specific test 
case I'd be happy to ensure it works.



Comment at: clang/lib/Format/Format.cpp:2427
+  // (b) the original line was *not* blank.
+  for (const auto  : PotentialWholeLineCuts) {
+const int LineStartPos = LineCheckedThrough.first;

kadircet wrote:
> the second loop seems like an over-kill and complicates the code a lot.
> 
> IIUC, it is just checking whether any text after replacements is 
> "whitespace/newline" and if so deletes the whole line.
> Instead of doing all of this, in the previous loop, whenever we see a line 
> change could we scan until the EOL, and delete the EOL token if we didn't hit 
> anything but whitespaces?
> 
> this would mean you won't need to store `PotentialWholeLineCuts`.
I agree and thanks for the feedback! `PotentialWholeLineCuts` felt a bit hacky 
so I've eliminated it by creating a new `MaybeRemoveBlankLine` helper function 
that gets called in two places, eliminating the need for the second pass and 
the `PotentialWholeLineCuts` variable. Hopefully the code is easier to follow 
now.



Comment at: clang/unittests/Format/CleanupTest.cpp:368
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  std::string Code = "namespace A { // Useless comment\n"
+ "  int x\t = 0;\t\n"

kadircet wrote:
> could you replace these with raw string literals instead to get rid of `\n`s.
I like that modernization suggestion but as a fairly new llvm contributor I 
follow the style I see in the surrounding code. Perhaps we should submit a 
seperate patch to modernize whole files at a time to use raw string literals 
and see how the change is received by the community.



Comment at: clang/unittests/Format/CleanupTest.cpp:376
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 1, 14), 19, ""),
+  createReplacement(getOffset(Code, 2, 3), 3, ""),

kadircet wrote:
> can you make use of `Annotations` library in 
> `llvm/include/llvm/Testing/Support/Annotations.h` for getting offsets into 
> the code?
> 
> same for the following test cases
`Annotations` looks quite handy, but again I'd rather get this patch through 
consistent with the file's existing style and submit a separate patch to 
modernize a whole file at a time to use `Annotations`.


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  

[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-12-22 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 235090.
poelmanc marked 2 inline comments as done.
poelmanc added a comment.

Fix algorithm to fix failing 
`ToolingTests/ApplyAtomicChangesTest.FormatsCorrectLineWhenHeaderIsRemoved`. 
That test revealed a very specific but real failure case: if existing Removals 
removed all whitespace **including** the line's ending newline, **and** the 
subsequent line contained only a newline, it would delete the subsequent 
newline too, which was not desired. Added a new test 
`CleanUpReplacementsTest.RemoveLineAndNewlineLineButNotNext` to explicitly test 
this case.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -349,10 +349,12 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
+ "\n"
  "int x= 0;"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
  "int x= 0;"
  "}";
   tooling::Replacements Replaces =
@@ -362,6 +364,100 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  std::string Code = "namespace A { // Useless comment\n"
+ "  int x\t = 0;\t\n"
+ "  int y\t = 0;\t\n"
+ "} // namespace A\n";
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 1, 14), 19, ""),
+  createReplacement(getOffset(Code, 2, 3), 3, ""),
+  createReplacement(getOffset(Code, 2, 7), 1, ""),
+  createReplacement(getOffset(Code, 2, 10), 1, ""),
+  createReplacement(getOffset(Code, 2, 12), 2, ""),
+  createReplacement(getOffset(Code, 3, 14), 1, "")});
+
+  EXPECT_EQ(Expected, apply(Code, Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  std::string Code = "struct A {\n"
+ "  A()\n"
+ "  : f(),\n"
+ "g()\n"
+ "  {}\n"
+ "  int f = 0;\n"
+ "  int g = 0;\n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A()\n"
+ "  {}\n"
+ "  int f = 0;\n"
+ "  int g = 0;\n"
+ "};";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 3, 5), 3, ""),
+  createReplacement(getOffset(Code, 3, 8), 1, ""),
+  createReplacement(getOffset(Code, 3, 3), 1, ""),
+  createReplacement(getOffset(Code, 4, 5), 3, "")});
+
+  EXPECT_EQ(Expected, apply(Code, Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  std::string Code = "struct A {\n"
+ "  A() {}\n"
+ "  int f;\n"
+ "  \n"
+ "  \n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A() {}\n"
+ "\n"
+ "\n"
+ "  \n"
+ "\t\n"
+ "};";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 3, 3), 3, "   "),
+  

[PATCH] D70270: clang-tidy: modernize-use-using uses AST and now supports struct defintions and multiple types in a typedef

2019-12-21 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 235039.
poelmanc added a subscriber: sammccall.
poelmanc added a comment.

Update patch to rebase on latest: Changed `SourceLocation::contains` to 
`SourceLocation::fullyContains`, and removed new `SourceLocation` comparison 
operators since coincidentally @sammccall added them just days ago.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70270

Files:
  clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
  clang/include/clang/Basic/SourceLocation.h

Index: clang/include/clang/Basic/SourceLocation.h
===
--- clang/include/clang/Basic/SourceLocation.h
+++ clang/include/clang/Basic/SourceLocation.h
@@ -230,6 +230,11 @@
 return B != X.B || E != X.E;
   }
 
+  // Returns true iff other is wholly contained within this range.
+  bool fullyContains(const SourceRange ) const {
+return B <= other.B && E >= other.E;
+  }
+
   void print(raw_ostream , const SourceManager ) const;
   std::string printToString(const SourceManager ) const;
   void dump(const SourceManager ) const;
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
@@ -84,7 +84,11 @@
 
 typedef int bla1, bla2, bla3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef int bla1, bla2, bla3;
+// CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use 'using' instead of 'typedef'
+// CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using bla1 = int;
+// CHECK-FIXES-NEXT: using bla2 = int;
+// CHECK-FIXES-NEXT: using bla3 = int;
 
 #define CODE typedef int INT
 
@@ -136,16 +140,16 @@
 
 typedef struct Q1 { int a; } S1;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef struct Q1 { int a; } S1;
+// CHECK-FIXES: using S1 = struct Q1 { int a; };
 typedef struct { int b; } S2;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef struct { int b; } S2;
+// CHECK-FIXES: using S2 = struct { int b; };
 struct Q2 { int c; } typedef S3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: struct Q2 { int c; } typedef S3;
+// CHECK-FIXES: using S3 = struct Q2 { int c; };
 struct { int d; } typedef S4;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: struct { int d; } typedef S4;
+// CHECK-FIXES: using S4 = struct { int d; };
 
 namespace my_space {
   class my_cclass {};
@@ -196,11 +200,15 @@
 
 typedef S<(0 > 0), int> S_t, *S_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef S<(0 > 0), int> S_t, *S_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using S_t = S<(0 > 0), int>;
+// CHECK-FIXES-NEXT: using S_p = S_t*;
 
 typedef S<(0 < 0), int> S2_t, *S2_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef S<(0 < 0), int> S2_t, *S2_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:29: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using S2_t = S<(0 < 0), int>;
+// CHECK-FIXES-NEXT: using S2_p = S2_t*;
 
 typedef S<(0 > 0 && (3 > 1) && (1 < 1)), int> S3_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
@@ -213,7 +221,9 @@
 
 typedef Q Q_t, *Q_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef Q Q_t, *Q_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Q_t = Q;
+// CHECK-FIXES-NEXT: using Q_p = Q_t*;
 
 typedef Q Q2_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
@@ -227,7 +237,9 @@
 
 typedef Q Q3_t, *Q3_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef Q Q3_t, *Q3_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:27: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Q3_t = Q;
+// CHECK-FIXES-NEXT: using Q3_p = Q3_t*;
 
 typedef Q Q3_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
@@ -246,4 +258,12 @@
 
 typedef Variadic >, S<(0 < 0), Variadic > > > Variadic_t, *Variadic_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef Variadic >, S<(0 < 0), Variadic > > > Variadic_t, *Variadic_p;

[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-12-20 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 234976.
poelmanc added a comment.

Address most of the feedback, I'll comment individually.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -349,11 +349,13 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
- "int x= 0;"
+ "\n"
+ "int x= 0;\n"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
- "int x= 0;"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
+ "int x= 0;\n"
  "}";
   tooling::Replacements Replaces =
   toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""),
@@ -362,6 +364,87 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  std::string Code = "namespace A { // Useless comment\n"
+ "  int x\t = 0;\t\n"
+ "  int y\t = 0;\t\n"
+ "} // namespace A\n";
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 1, 14), 19, ""),
+  createReplacement(getOffset(Code, 2, 3), 3, ""),
+  createReplacement(getOffset(Code, 2, 7), 1, ""),
+  createReplacement(getOffset(Code, 2, 10), 1, ""),
+  createReplacement(getOffset(Code, 2, 12), 2, ""),
+  createReplacement(getOffset(Code, 3, 14), 1, "")});
+
+  EXPECT_EQ(Expected, apply(Code, Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  std::string Code = "struct A {\n"
+ "  A()\n"
+ "  : f(),\n"
+ "g()\n"
+ "  {}\n"
+ "  int f = 0;\n"
+ "  int g = 0;\n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A()\n"
+ "  {}\n"
+ "  int f = 0;\n"
+ "  int g = 0;\n"
+ "};";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 3, 5), 3, ""),
+  createReplacement(getOffset(Code, 3, 8), 1, ""),
+  createReplacement(getOffset(Code, 3, 3), 1, ""),
+  createReplacement(getOffset(Code, 4, 5), 3, "")});
+
+  EXPECT_EQ(Expected, apply(Code, Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, KeepLinesWithInsertsOrReplacesEvenIfBlank) {
+  std::string Code = "struct A {\n"
+ "  A() {}\n"
+ "  int f;\n"
+ "  \n"
+ "  \n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A() {}\n"
+ "\n"
+ "\n"
+ "  \n"
+ "\t\n"
+ "};";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 3, 3), 3, "   "),
+  createReplacement(getOffset(Code, 3, 7), 2, "  "),
+  createReplacement(getOffset(Code, 3, 1), 0, "\n"),
+  createReplacement(getOffset(Code, 5, 1), 2, "\t")});
+
+  EXPECT_EQ(Expected, apply(Code, Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, 

[PATCH] D70270: clang-tidy: modernize-use-using uses AST and now supports struct defintions and multiple types in a typedef

2019-12-20 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Any further feedback or thoughts on this?


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70270



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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-11-20 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as done.
poelmanc added a comment.

In D68682#1753357 , @kadircet wrote:

> also could you rename the revision so that it reflects the fact that, this is 
> a change to clang-format and has nothing to do with clang-tidy ?


Done but feel free to suggest a better title.

(This journey started out with me trying to fix what I thought was a small 
quirk in clang-tidy's readability-redundant-member-init. Great feedback from 
more experienced developers along the way steered me to 
`cleanupAroundReplacements`, which feels perfect, but now I realize that gives 
it a broader impact.)

Thank you so much for the review and feedback!


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682



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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-11-20 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 5 inline comments as done.
poelmanc added inline comments.



Comment at: clang/lib/AST/CommentParser.cpp:19
 
-static inline bool isWhitespace(llvm::StringRef S) {
+// Consider moving this useful function to a more general utility location.
+bool isWhitespace(llvm::StringRef S) {

kadircet wrote:
> poelmanc wrote:
> > gribozavr2 wrote:
> > > clang/include/clang/Basic/CharInfo.h ?
> > Done. I renamed it to `isWhitespaceStringRef` to avoid making it an 
> > overload of the existing `isWhitespace(unsigned char)`, which causes 
> > ambiguous overload errors at QueryParser.cpp:42 & CommentSema.cpp:237.
> > 
> > We could alternatively keep this as an `isWhitespace` overload and instead 
> > change those two lines to use a `static_cast > char)>(::isWhitespace)` or precede them with a line like:
> > ```
> > bool (*isWhitespaceOverload)(unsigned char) = ::isWhitespace;
> > ```
> ah that's unfortunate, I believe it makes sense to have this as an overload 
> though.
> 
> Could you instead make the predicate explicit by putting
> ```[](char c) { return clang::isWhitespace(c); }```
> instead of just `clang::isWhitespace` in those call sites?
Excellent! Better than the two ideas I thought of. Thanks!


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682



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


[PATCH] D68682: format::cleanupAroundReplacements removes whole line when Removals leave previously non-blank line blank

2019-11-20 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 230375.
poelmanc marked 3 inline comments as done.
poelmanc retitled this revision from "Clang-tidy fix removals removing all 
non-blank text from a line should remove the line" to 
"format::cleanupAroundReplacements removes whole line when Removals leave 
previously non-blank line blank".
poelmanc edited the summary of this revision.
poelmanc added a comment.

I addressed the latest code review comments, added tests to 
`clang/unittests/Format/CleanupTest.cpp`, and updated numerous tests to reflect 
improved removal of blank lines.

I now realize how widely used `cleanupAroundReplacements` is. That's great as 
this fix improves `clang-change-namespace` as a side-effect. However, I have 
little experience running tests beyond clang-tidy or on Linux (I'm testing with 
MSVC) and would appreciate help identifying any test failures or regressions. 
Also please check my change to `FixOnlyAffectedCodeAfterReplacements` in 
clang/unittests/Format/CleanupTest.cpp.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-query/QueryParser.cpp
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-redundant-void-arg.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang-tools-extra/test/clang-tidy/checkers/readability-simplify-bool-expr.cpp
  clang-tools-extra/unittests/clang-change-namespace/ChangeNamespaceTests.cpp
  clang-tools-extra/unittests/clang-move/ClangMoveTests.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/AST/CommentSema.cpp
  clang/lib/Format/Format.cpp
  clang/unittests/Format/CleanupTest.cpp

Index: clang/unittests/Format/CleanupTest.cpp
===
--- clang/unittests/Format/CleanupTest.cpp
+++ clang/unittests/Format/CleanupTest.cpp
@@ -349,11 +349,13 @@
  "namespace C {\n"
  "namespace D { int i; }\n"
  "inline namespace E { namespace { int y; } }\n"
- "int x= 0;"
+ "\n"
+ "int x= 0;\n"
  "}";
-  std::string Expected = "\n\nnamespace C {\n"
- "namespace D { int i; }\n\n"
- "int x= 0;"
+  std::string Expected = "\nnamespace C {\n"
+ "namespace D { int i; }\n"
+ "\n"
+ "int x= 0;\n"
  "}";
   tooling::Replacements Replaces =
   toReplacements({createReplacement(getOffset(Code, 3, 3), 6, ""),
@@ -362,6 +364,87 @@
   EXPECT_EQ(Expected, formatAndApply(Code, Replaces));
 }
 
+TEST_F(CleanUpReplacementsTest, RemoveLineWhenAllNonWhitespaceRemoved) {
+  std::string Code = "namespace A { // Useless comment\n"
+ "  int x\t = 0;\t\n"
+ "  int y\t = 0;\t\n"
+ "} // namespace A\n";
+  std::string Expected = "namespace A {\n"
+ "  int y\t = 0;\n"
+ "} // namespace A\n";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 1, 14), 19, ""),
+  createReplacement(getOffset(Code, 2, 3), 3, ""),
+  createReplacement(getOffset(Code, 2, 7), 1, ""),
+  createReplacement(getOffset(Code, 2, 10), 1, ""),
+  createReplacement(getOffset(Code, 2, 12), 2, ""),
+  createReplacement(getOffset(Code, 3, 14), 1, "")});
+
+  EXPECT_EQ(Expected, apply(Code, Replaces));
+}
+
+TEST_F(CleanUpReplacementsTest, RemoveLinesWhenAllNonWhitespaceRemoved) {
+  std::string Code = "struct A {\n"
+ "  A()\n"
+ "  : f(),\n"
+ "g()\n"
+ "  {}\n"
+ "  int f = 0;\n"
+ "  int g = 0;\n"
+ "};";
+  std::string Expected = "struct A {\n"
+ "  A()\n"
+ "  {}\n"
+ "  int f = 0;\n"
+ "  int g = 0;\n"
+ "};";
+  tooling::Replacements Replaces =
+  toReplacements({createReplacement(getOffset(Code, 3, 5), 3, ""),
+  createReplacement(getOffset(Code, 3, 8), 1, ""),
+  createReplacement(getOffset(Code, 3, 3), 1, ""),
+  createReplacement(getOffset(Code, 4, 5), 3, "")});
+
+  EXPECT_EQ(Expected, apply(Code, 

[PATCH] D70144: clang-tidy: modernize-use-equals-default avoid adding redundant semicolons

2019-11-19 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a subscriber: MyDeveloperDay.
poelmanc added a comment.

Just a quick update, I made some progress addressing the architectural 
limitation of `AnnotatedLines` and `evaluate()`. I changed the `AnnotatedLines` 
constructor to also take a `Line *PrevAnnotatedLine` argument and set 
`Line->First->Prev` to the `Last` of the previous line and `Line->Last->Next` 
to the `First` of the next line. So now the Tokens remain connected across 
lines, so individual `TokenAnalyzer` subclasses can easily peek ahead and 
behind the current changed Line if they wish. Places that previously iterated 
//e.g.// `while(Tok)` had to be changed to iterate `while(Tok && Tok != 
Line->Last->Next)` - I probably haven't found all of those places yet.

The good news is, with that architectural change my prior addition of:

  cleanupLeft(Line->First, tok::semi, tok::semi);

successfully removed redundant semicolons after `default`, even when the next 
semicolon was on the next line and/or separated by comments!

The bad news is this change also removed consecutive semicolons in //e.g.//:

  for( ;; )

which breaks some existing tests. I believe @MyDeveloperDay had thoughts on how 
to avoid replacing those meaningful consecutive semicolons? We have only tokens 
rather than an AST. We could search backwards for a `for` token, but I don't 
know how far backwards we would want to search to determine whether **this 
particular** `;;` is valid.

In D70144#1748881 , @JonasToth wrote:

> Hmm. I think this is fine, even though its not perfect.
>  @aaron.ballman wdyt?


The attached patch is nice and small: a 5-line generally useful utility 
function plus a few lines to call it.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70144



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


[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-11-18 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Thanks @lebedev.ri for taking the time to think this through and reply. All 
that makes sense, so I've changed the default to `0`.

In addition to adding it to the ReleaseNotes, once clang-tidy 10 is released 
I'll reply to a StackOverflow question about this error with a link to the new 
option. That should further increase the odds of anyone who searches on the 
`gcc` warning/error easily finding the clang-tidy option.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145



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


[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-11-18 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 229934.
poelmanc edited the summary of this revision.
poelmanc added a comment.

Switch default to `0`. Add Release Note with some detail to increase the 
chances of someone finding this with  an Internet search on the error message.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145

Files:
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s readability-redundant-member-init %t
+// RUN: %check_clang_tidy %s readability-redundant-member-init %t \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-member-init.IgnoreBaseInCopyConstructors, \
+// RUN:   value: 1}] \
+// RUN: }"
 
 struct S {
   S() = default;
@@ -116,6 +120,35 @@
   };
 };
 
+// struct whose inline copy constructor default-initializes its base class
+struct WithCopyConstructor1 : public T {
+  WithCopyConstructor1(const WithCopyConstructor1& other) : T(),
+f(),
+g()
+  {}
+  S f, g;
+};
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'f' is redundant
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'g' is redundant
+// CHECK-FIXES: WithCopyConstructor1(const WithCopyConstructor1& other) : T()
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT: {}
+
+// struct whose copy constructor default-initializes its base class
+struct WithCopyConstructor2 : public T {
+  WithCopyConstructor2(const WithCopyConstructor2& other);
+  S a;
+};
+WithCopyConstructor2::WithCopyConstructor2(const WithCopyConstructor2& other)
+  : T(), a()
+{}
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-3]]:10: warning: initializer for member 'a' is redundant
+// CHECK-FIXES: {{^}}  : T() {{$}}
+// CHECK-NEXT: {}
+
 // Initializer not written
 struct NF1 {
   NF1() {}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
@@ -6,7 +6,8 @@
 Finds member initializations that are unnecessary because the same default
 constructor would be called if they were not present.
 
-Example:
+Example
+---
 
 .. code-block:: c++
 
@@ -18,3 +19,27 @@
   private:
 std::string s;
   };
+
+Options
+---
+
+.. option:: IgnoreBaseInCopyConstructors
+
+Default is ``0``.
+
+When non-zero, the check will ignore unnecessary base class initializations
+within copy constructors, since some compilers issue warnings/errors when
+base classes are not explicitly intialized in copy constructors. For example,
+``gcc`` with ``-Wextra`` or ``-Werror=extra`` issues warning or error
+``base class ‘Bar’ should be explicitly initialized in the copy constructor``
+if ``Bar()`` were removed in the following example:
+
+.. code-block:: c++
+
+  // Explicitly initializing member s and base class Bar is unnecessary.
+  struct Foo : public Bar {
+// Remove s() below. If IgnoreBaseInCopyConstructors!=0, keep Bar().
+Foo(const Foo& foo) : Bar(), s() {}
+std::string s;
+  };
+
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -170,6 +170,13 @@
   The check now supports the ``AllowOverrideAndFinal`` option to eliminate
   conflicts with ``gcc -Wsuggest-override`` or ``gcc -Werror=suggest-override``.
 
+- Improved :doc:`readability-redundant-member-init
+  ` check.
+
+  The check  now supports the ``IgnoreBaseInCopyConstructors`` option to avoid
+  `"base class \‘Foo\’ should be explicitly initialized in the copy constructor"`
+  warnings or errors with ``gcc -Wextra`` or ``gcc -Werror=extra``.
+
 - The :doc:`readability-redundant-string-init
   ` check now supports a
   `StringNames` option enabling its application to custom string classes.
Index: clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h

[PATCH] D70270: clang-tidy: modernize-use-using uses AST and now supports struct defintions and multiple types in a typedef

2019-11-16 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

> If there's a way to match only `CXXRecordDecl`s that are immediately followed 
> by a `TypedefDecl`...

Alternatively, within `check()` when we get the `TypedefDecl`, is there any way 
to navigate up the AST to find its immediately preceding sibling node in the 
AST and check whether it's a `CXXRecordDecl`? If so we could eliminate 
`Finder->addMatcher(cxxRecordDecl(unless(isImplicit())).bind("struct"), this);` 
altogether. I didn't see a way to do that though.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70270



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


[PATCH] D70270: clang-tidy: modernize-use-using uses AST and now supports struct defintions and multiple types in a typedef

2019-11-16 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 6 inline comments as done.
poelmanc added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp:30
+  // They appear in the AST just *prior* to the typedefs.
+  Finder->addMatcher(cxxRecordDecl().bind("struct"), this);
 }

aaron.ballman wrote:
> It's unfortunate that we can't restrict this matcher more -- there tend to be 
> a lot of struct declarations, so I am a bit worried about the performance of 
> this matching on so many of them. At a minimum, I think you can restrict it 
> to non-implicit structs here and simplify the code in `check()` a bit.
Done, thanks!

If there's a way to match only `CXXRecordDecl`s that are //immediately 
followed// by a `TypedefDecl`, that would cut down the matches just to the ones 
we need. That said, at least the amount of work done on each `check()` call for 
the non-implicit `CXXRecordDecl`s is minimal: it just stores its `SourceRange` 
and returns.



Comment at: clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp:85
+ReplaceRange.setBegin(LastReplacementEnd);
+Using = "; using ";
+

aaron.ballman wrote:
> Should there be a newline here, to avoid putting all the using declarations 
> on the same line?
Done. Updated test cases and documentation to reflect this.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70270



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


[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-11-16 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a subscriber: mgehre.
poelmanc added a comment.

In D69145#1715611 , @mgehre wrote:

> Exactly due to the issue you are fixing here, we ended up disabling the 
> complete check because we didn't want to live with the warnings it produced 
> on -Wextra.
>  Therefore, I'm actually strongly in favor to enable the option by default.
>
> When others see that clang-tidy fixits introduce warnings (with -Wextra) or 
> even break their build (with -Werror), they might not look into check 
> options, but just disable the check directly.


Just pinging to see if anyone has any thoughts on moving forward with this. 
Thanks in advance for any feedback!


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145



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


[PATCH] D70270: clang-tidy: modernize-use-using uses AST and now supports struct defintions and multiple types in a typedef

2019-11-16 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 229678.
poelmanc edited the summary of this revision.

Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70270

Files:
  clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
  clang/include/clang/Basic/SourceLocation.h

Index: clang/include/clang/Basic/SourceLocation.h
===
--- clang/include/clang/Basic/SourceLocation.h
+++ clang/include/clang/Basic/SourceLocation.h
@@ -192,6 +192,18 @@
   return LHS.getRawEncoding() < RHS.getRawEncoding();
 }
 
+inline bool operator>(const SourceLocation , const SourceLocation ) {
+  return LHS.getRawEncoding() > RHS.getRawEncoding();
+}
+
+inline bool operator<=(const SourceLocation , const SourceLocation ) {
+  return !(LHS > RHS);
+}
+
+inline bool operator>=(const SourceLocation , const SourceLocation ) {
+  return !(LHS < RHS);
+}
+
 /// A trivial tuple used to represent a source range.
 class SourceRange {
   SourceLocation B;
@@ -219,6 +231,11 @@
 return B != X.B || E != X.E;
   }
 
+  // Returns true iff other is wholly contained within this range.
+  bool contains(const SourceRange ) const {
+return B <= other.B && E >= other.E;
+  }
+
   void print(raw_ostream , const SourceManager ) const;
   std::string printToString(const SourceManager ) const;
   void dump(const SourceManager ) const;
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
@@ -84,7 +84,11 @@
 
 typedef int bla1, bla2, bla3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef int bla1, bla2, bla3;
+// CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use 'using' instead of 'typedef'
+// CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using bla1 = int;
+// CHECK-FIXES-NEXT: using bla2 = int;
+// CHECK-FIXES-NEXT: using bla3 = int;
 
 #define CODE typedef int INT
 
@@ -136,16 +140,16 @@
 
 typedef struct Q1 { int a; } S1;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef struct Q1 { int a; } S1;
+// CHECK-FIXES: using S1 = struct Q1 { int a; };
 typedef struct { int b; } S2;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef struct { int b; } S2;
+// CHECK-FIXES: using S2 = struct { int b; };
 struct Q2 { int c; } typedef S3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: struct Q2 { int c; } typedef S3;
+// CHECK-FIXES: using S3 = struct Q2 { int c; };
 struct { int d; } typedef S4;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: struct { int d; } typedef S4;
+// CHECK-FIXES: using S4 = struct { int d; };
 
 namespace my_space {
   class my_cclass {};
@@ -196,11 +200,15 @@
 
 typedef S<(0 > 0), int> S_t, *S_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef S<(0 > 0), int> S_t, *S_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:28: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using S_t = S<(0 > 0), int>;
+// CHECK-FIXES-NEXT: using S_p = S_t*;
 
 typedef S<(0 < 0), int> S2_t, *S2_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef S<(0 < 0), int> S2_t, *S2_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:29: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using S2_t = S<(0 < 0), int>;
+// CHECK-FIXES-NEXT: using S2_p = S2_t*;
 
 typedef S<(0 > 0 && (3 > 1) && (1 < 1)), int> S3_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
@@ -213,7 +221,9 @@
 
 typedef Q Q_t, *Q_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef Q Q_t, *Q_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:24: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Q_t = Q;
+// CHECK-FIXES-NEXT: using Q_p = Q_t*;
 
 typedef Q Q2_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
@@ -227,7 +237,9 @@
 
 typedef Q Q3_t, *Q3_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef Q Q3_t, *Q3_p;
+// CHECK-MESSAGES: :[[@LINE-2]]:27: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Q3_t = Q;
+// CHECK-FIXES-NEXT: using Q3_p = Q3_t*;
 
 typedef Q Q3_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 

[PATCH] D70144: clang-tidy: modernize-use-equals-default avoid adding redundant semicolons

2019-11-14 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

> ! In D70144#1745583 , @JonasToth 
> wrote:
> 
>> ! In D70144#1745532 , 
>> @malcolm.parsons wrote:
> 
> Should `clang::format::cleanupAroundReplacements()` handle this instead?

My initial attempt did not go well. I thought perhaps adding:

  cleanupLeft(Line->First, tok::semi, tok::semi);

to clang/lib/Format/Format.cpp:1491 might do the trick. Stepping through that 
in the debugger shows that `cleanupPair` iterates over tokens on affected lines 
over the affected range. But after the newly added `default` token and 
subsequent `semi` token comes a nullptr - I could not see how to peek past the 
`default;` to see what else is on the line.

There's a comment admitting that this needs some architectural work:

  // FIXME: in the current implementation the granularity of affected range
  // is an annotated line. However, this is not sufficient. Furthermore,
  // redundant code introduced by replacements does not necessarily
  // intercept with ranges of replacements that result in the redundancy.
  // To determine if some redundant code is actually introduced by
  // replacements(e.g. deletions), we need to come up with a more
  // sophisticated way of computing affected ranges.

Agreed. Even if we could see all the tokens on a line, it seems the test case I 
added to this patch at clang-tidy/checkers/modernize-use-equals-default.cpp:50, 
where the redundant semicolon is on the next line, could never be addressed 
given the current architecture. Changing the TokenAnalyzer::analyze() interface 
would affect JavaScriptRequoter, ObjCHeaderStyleGuesser, 
JavaScriptImportSorter, Formatter, and others.

Thoughts on how to proceed?


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70144



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


[PATCH] D67460: clang-tidy: modernize-use-using work with multi-argument templates

2019-11-14 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as not done.
poelmanc added a comment.

In D67460#1737529 , @aaron.ballman 
wrote:

> I'm a bit worried that this manual parsing technique will need fixing again 
> in the future, but I think this is at least a reasonable incremental 
> improvement.


Thanks and I agree. Your comments encouraged me to take another stab at 
improving things. See D70270 , a whole new 
approach that removes manual parsing in favor of AST processing and 
successfully converts many more cases from `typedef` to `using`.

I didn't want to clobber this patch with that one in case any fatal flaws are 
discovered with the new approach. We can commit this one first - getting 
improved handling of commas and getting additional test cases - and treat 
D70270  as that next incremental improvement. 
Or we can keep this on hold until D70270  is 
worked out.

Thanks again for all your feedback and help!


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D67460



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


[PATCH] D70270: clang-tidy: modernize-use-using uses AST and now supports struct defintions and multiple types in a typedef

2019-11-14 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: alexfh, aaron.ballman.
poelmanc added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, mgehre.
Herald added a project: clang.

In D67460#1737529 , @aaron.ballman 
wrote:

> I'm a bit worried that this manual parsing technique will need fixing again 
> in the future


That concern plus prior comments and help from `clang -ast-dump` led me to 
develop this new approach based entirely on the AST that completely eliminates 
manual parsing. It now handles `typedef`s that include comma-separated multiple 
types, and handles embedded `struct` definitions, which previously could not be 
automatically converted.

For example, with this patch `modernize-use-using` now can convert:

  typedef struct { int a; } R_t, *R_p;

to:

  using R_t = struct { int a; }; using R_p = R_t*;

`-ast-dump` showed that the `CXXRecordDecl` definitions and multiple 
`TypedefDecl`s come consecutively in the tree, so `check()` stores information 
between calls to determine when it is receiving a second or additional 
`TypedefDecl` within a single `typedef`, or when the current `TypedefDecl` 
refers to an embedded `CXXRecordDecl` like a `struct`.

This patch is independent of D67460  except 
for borrowing its extended set of tests. All those tests pass, plus several 
that previously remained as `typedef` are now modernized to use `using`.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D70270

Files:
  clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize-use-using.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
  clang/include/clang/Basic/SourceLocation.h

Index: clang/include/clang/Basic/SourceLocation.h
===
--- clang/include/clang/Basic/SourceLocation.h
+++ clang/include/clang/Basic/SourceLocation.h
@@ -192,6 +192,18 @@
   return LHS.getRawEncoding() < RHS.getRawEncoding();
 }
 
+inline bool operator>(const SourceLocation , const SourceLocation ) {
+  return LHS.getRawEncoding() > RHS.getRawEncoding();
+}
+
+inline bool operator<=(const SourceLocation , const SourceLocation ) {
+  return !(LHS > RHS);
+}
+
+inline bool operator>=(const SourceLocation , const SourceLocation ) {
+  return !(LHS < RHS);
+}
+
 /// A trivial tuple used to represent a source range.
 class SourceRange {
   SourceLocation B;
@@ -219,6 +231,11 @@
 return B != X.B || E != X.E;
   }
 
+  // Returns true iff other is wholly contained within this range.
+  bool contains(const SourceRange ) const {
+return B <= other.B && E >= other.E;
+  }
+
   void print(raw_ostream , const SourceManager ) const;
   std::string printToString(const SourceManager ) const;
   void dump(const SourceManager ) const;
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
@@ -84,7 +84,9 @@
 
 typedef int bla1, bla2, bla3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef int bla1, bla2, bla3;
+// CHECK-MESSAGES: :[[@LINE-2]]:17: warning: use 'using' instead of 'typedef'
+// CHECK-MESSAGES: :[[@LINE-3]]:23: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using bla1 = int; using bla2 = int; using bla3 = int;
 
 #define CODE typedef int INT
 
@@ -136,16 +138,16 @@
 
 typedef struct Q1 { int a; } S1;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef struct Q1 { int a; } S1;
+// CHECK-FIXES: using S1 = struct Q1 { int a; };
 typedef struct { int b; } S2;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: typedef struct { int b; } S2;
+// CHECK-FIXES: using S2 = struct { int b; };
 struct Q2 { int c; } typedef S3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: struct Q2 { int c; } typedef S3;
+// CHECK-FIXES: using S3 = struct Q2 { int c; };
 struct { int d; } typedef S4;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: struct { int d; } typedef S4;
+// CHECK-FIXES: using S4 = struct { int d; };
 
 namespace my_space {
   class my_cclass {};
@@ -183,3 +185,77 @@
   void f() override { super::f(); }
 };
 }
+
+template 
+class TwoArgTemplate {
+  typedef TwoArgTemplate self;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using self = TwoArgTemplate;
+};
+
+template 
+struct S {};
+
+typedef S<(0 > 0), int> S_t, *S_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: 

[PATCH] D70165: clang-tidy: modernize-use-override new option AllowOverrideAndFinal

2019-11-14 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D70165#1745530 , @alexfh wrote:

> While I have no objections against this patch, I wonder whether someone had a 
> chance to ask GCC developers about this? Is it a conscious choice to suggest 
> `override` when `final` is present? What's the argument for doing so?


Thanks, someone should ask them as I believe this issue extends beyond 
clang-tidy: code with functions marked `final` //cannot// satisfy both `gcc 
-Wsuggest-override` and `clang -Winconsistent-missing-override`; `gcc` demands 
`override final` and `clang` demands just `final`.

Even if `clang` and `gcc` find a common ground, people will be stuck with 
current versions for quite a while, so this clang-tidy patch should prove 
helpful.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70165



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


[PATCH] D70144: clang-tidy: modernize-use-equals-default avoid adding redundant semicolons

2019-11-14 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D70144#1745583 , @JonasToth wrote:

> In D70144#1745532 , @malcolm.parsons 
> wrote:
>
> > Should `clang::format::cleanupAroundReplacements()` handle this instead?
>
>
> Of yes. Totally forgot that. That would probably the most elegant way :)


Interesting, so is the advantage of that approach that //any// fixit 
Replacement or Insertion that ends with a semicolon would have it removed if a 
semicolon already immediately follows it? That makes sense - once less thing 
for individual check developers to worry about.

I can take a look at doing that.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70144



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


[PATCH] D70165: clang-tidy: modernize-use-override new option AllowOverrideAndFinal

2019-11-13 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D70165#1744007 , @JonasToth wrote:

> LGTM!
>  Did you check on a real code-base that suffers from the issue, if that works 
> as expected?


Thanks! I have now run it on our real code base and it worked as expected.

I lack commit access and would appreciate anyone committing this on my behalf.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70165



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


[PATCH] D70144: clang-tidy: modernize-use-equals-default avoid adding redundant semicolons

2019-11-13 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 229202.
poelmanc added a comment.

Change to add just one helper function `findNextTokenSkippingComments` to 
`LexerUtils.h`, requiring no change to `Token::isOneOf`, and properly call it 
from `UseEqualsDefaultCheck.cpp`.

In D70144#1744737 , @JonasToth wrote:

> Are you using the lexer-util functions? Maybe i am just to tired, but they 
> seem to be unused.


Sorry, that was not you! I was experimenting with the `git show` command to 
generate these patches and failed to check the results closely. The correct 
calling code should be in the updated diff.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70144

Files:
  clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
@@ -7,7 +7,7 @@
   ~OL();
 };
 
-OL::OL() {}
+OL::OL() {};
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial default constructor [modernize-use-equals-default]
 // CHECK-FIXES: OL::OL() = default;
 OL::~OL() {}
@@ -17,9 +17,9 @@
 // Inline definitions.
 class IL {
 public:
-  IL() {}
+  IL() {} 	 ; // Note embedded tab on this line
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: IL() = default;
+  // CHECK-FIXES: IL() = default 	 ; // Note embedded tab on this line
   ~IL() {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: ~IL() = default;
@@ -46,18 +46,20 @@
 // Default member initializer
 class DMI {
 public:
-  DMI() {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: DMI() = default;
+  DMI() {} // Comment before semi-colon on next line
+  ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+  // CHECK-FIXES: DMI() = default // Comment before semi-colon on next line
+  // CHECK-FIXES-NEXT:   ;
   int Field = 5;
 };
 
 // Class member
 class CM {
 public:
-  CM() {}
+  CM() {} /* Comments */ /* before */ /* semicolon */;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: CM() = default;
+  // CHECK-FIXES: CM() = default /* Comments */ /* before */ /* semicolon */;
   OL o;
 };
 
@@ -66,7 +68,7 @@
   Priv() {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: Priv() = default;
-  ~Priv() {}
+  ~Priv() {};
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: ~Priv() = default;
 };
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
@@ -119,7 +119,7 @@
 struct BF {
   BF() = default;
   BF(const BF ) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3),
-Field4(Other.Field4) {}
+Field4(Other.Field4) {};
   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
   // CHECK-FIXES: BF(const BF ) {{$}}
   // CHECK-FIXES: = default;
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -141,6 +141,10 @@
 - The 'objc-avoid-spinlock' check was renamed to :doc:`darwin-avoid-spinlock
   `
 
+- The :doc:`modernize-use-equals-default
+  ` fix no longer adds
+  semicolons where they would be redundant.
+
 - New :doc:`readability-redundant-access-specifiers
   ` check.
 
Index: clang-tools-extra/clang-tidy/utils/LexerUtils.h
===
--- clang-tools-extra/clang-tidy/utils/LexerUtils.h
+++ clang-tools-extra/clang-tidy/utils/LexerUtils.h
@@ -80,6 +80,11 @@
   }
 }
 
+// Finds next token that's not a comment.
+Optional findNextTokenSkippingComments(SourceLocation Start,
+  const SourceManager ,
+  const LangOptions );
+
 /// Re-lex the provide \p Range and return \c false if either a macro spans
 /// multiple tokens, a pre-processor directive or failure to retrieve the
 /// next token is found, 

[PATCH] D70144: clang-tidy: modernize-use-equals-default avoid adding redundant semicolons

2019-11-13 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 229161.
poelmanc edited the summary of this revision.
poelmanc added a comment.

Update to add and use new `findNextTokenSkippingComments` and 
`findNextTokenSkippingKind` utility functions. Since the former calls the 
latter with just one token type, this required generalizing `Token::isOneOf()` 
to work with 1-to-N token kinds versus requiring 2-to-N.

Also added a release note.

To me the change to `Token::isOneOf()` is an improvement (less code and more 
flexibility when calling it from variadic templates), but if the team prefers 
not to modify `Token::isOneOf()`, we could eliminate the 
`findNextTokenSkippingKind` utility function and instead implement 
`findNextTokenSkippingComments` directly.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70144

Files:
  clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
  clang-tools-extra/clang-tidy/utils/LexerUtils.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
  clang/include/clang/Lex/Token.h

Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
@@ -7,7 +7,7 @@
   ~OL();
 };
 
-OL::OL() {}
+OL::OL() {};
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial default constructor [modernize-use-equals-default]
 // CHECK-FIXES: OL::OL() = default;
 OL::~OL() {}
@@ -17,9 +17,9 @@
 // Inline definitions.
 class IL {
 public:
-  IL() {}
+  IL() {} 	 ; // Note embedded tab on this line
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: IL() = default;
+  // CHECK-FIXES: IL() = default 	 ; // Note embedded tab on this line
   ~IL() {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: ~IL() = default;
@@ -46,18 +46,20 @@
 // Default member initializer
 class DMI {
 public:
-  DMI() {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: DMI() = default;
+  DMI() {} // Comment before semi-colon on next line
+  ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+  // CHECK-FIXES: DMI() = default // Comment before semi-colon on next line
+  // CHECK-FIXES-NEXT:   ;
   int Field = 5;
 };
 
 // Class member
 class CM {
 public:
-  CM() {}
+  CM() {} /* Comments */ /* before */ /* semicolon */;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: CM() = default;
+  // CHECK-FIXES: CM() = default /* Comments */ /* before */ /* semicolon */;
   OL o;
 };
 
@@ -66,7 +68,7 @@
   Priv() {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: Priv() = default;
-  ~Priv() {}
+  ~Priv() {};
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: ~Priv() = default;
 };
Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
@@ -119,7 +119,7 @@
 struct BF {
   BF() = default;
   BF(const BF ) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3),
-Field4(Other.Field4) {}
+Field4(Other.Field4) {};
   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
   // CHECK-FIXES: BF(const BF ) {{$}}
   // CHECK-FIXES: = default;
Index: clang/include/clang/Lex/Token.h
===
--- clang/include/clang/Lex/Token.h
+++ clang/include/clang/Lex/Token.h
@@ -96,12 +96,14 @@
   /// "if (Tok.is(tok::l_brace)) {...}".
   bool is(tok::TokenKind K) const { return Kind == K; }
   bool isNot(tok::TokenKind K) const { return Kind != K; }
-  bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
-return is(K1) || is(K2);
+
+  /// Single argument overload provides base case for recursive template below
+  bool isOneOf(tok::TokenKind K) const {
+return is(K);
   }
   template 
-  bool isOneOf(tok::TokenKind K1, tok::TokenKind K2, Ts... Ks) const {
-return is(K1) || isOneOf(K2, Ks...);
+  bool isOneOf(tok::TokenKind K1, Ts... Ks) const {
+return is(K1) || isOneOf(Ks...);
   }
 
   /// Return true if this is a raw identifier (when lexing
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- 

[PATCH] D70144: clang-tidy: modernize-use-equals-default avoid adding redundant semicolons

2019-11-13 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as done.
poelmanc added inline comments.



Comment at: clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp:306
+  if (ApplyFix) {
+// Peek ahead to see if there's a semicolon after Body->getSourceRange()
+Optional Token;

JonasToth wrote:
> There should be utility code in `clang-tidy/util/` that deals with custom 
> lexing, that should be able to do the job.
Thanks for the quick feedback! I looked there and couldn't find a utility 
function that searched (a) //forward// rather than backwards, and (b) for any 
token //not// of a given list of types. Here's a new helper function that could 
be placed in LexerUtils.h if you think it's generally useful:

```
// Analogous to findNextAnyTokenKind, finds next token not of
// the given set of TokenKinds. Useful for skipping comments.
template 
Optional findNextTokenSkippingKind(SourceLocation Start,
  const SourceManager ,
  const LangOptions ,
  TokenKind TK, TokenKinds... TKs) {
  Optional CurrentToken;
  do {
Optional CurrentToken = Lexer::findNextToken(Start, SM, LangOpts);
  } while (CurrentToken && CurrentToken.isOneOf(TK, TKs...));
  return CurrentToken;
}
```

Then the `do` loop below can be simplified to:
```
  Optional Token = findNextTokenSkippingKind(
  Body->getSourceRange().getEnd().getLocWithOffset(1),
  Result.Context->getSourceManager(), Result.Context->getLangOpts(),
  tok::comment);
```


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D70144



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


[PATCH] D70165: clang-tidy: modernize-use-override new option AllowOverrideAndFinal

2019-11-12 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: alexfh, djasper.
Herald added subscribers: cfe-commits, mgehre.
Herald added a project: clang.

In addition to adding `override` wherever possible, clang-tidy's 
`modernize-use-override` nicely removes `virtual` when `override` or `final` is 
specified, and further removes `override` when `final` is specified. While this 
is great default behavior, when code needs to be compiled with `gcc` at high 
warning levels that include `gcc -Wsuggest-override` or `gcc 
-Werror=suggest-override`, clang-tidy's removal of the redundant `override` 
keyword causes gcc to emit a warning or error. This discrepancy / conflict has 
been noted by others including a comment on Stack Overflow 

 and by Mozzilla's Firefox developers 
.

This patch adds an AllowOverrideAndFinal option defaulting to `0` - thus 
preserving current behavior - that when enabled allows both `override` and 
`final` to co-exist, while still fixing all other issues.

The patch includes a test file verifying all combinations of 
``virtual``/``override``/``final``, and mentions the new option in the release 
notes.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D70165

Files:
  clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseOverrideCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize-use-override-allow-override-and-final.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-override-allow-override-and-final.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-override-allow-override-and-final.cpp
@@ -0,0 +1,40 @@
+// RUN: %check_clang_tidy %s modernize-use-override %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-override.AllowOverrideAndFinal, value: 1}]}"
+
+struct Base {
+  virtual ~Base();
+  virtual void a();
+  virtual void b();
+  virtual void c();
+  virtual void d();
+  virtual void e();
+  virtual void f();
+  virtual void g();
+  virtual void h();
+  virtual void i();
+};
+
+struct Simple : public Base {
+  virtual ~Simple();
+  // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  ~Simple() override;
+  virtual void a() override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'override' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  void a() override;
+  virtual void b() final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'final' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  void b() final;
+  virtual void c() final override;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'final' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  void c() final override;
+  virtual void d() override final;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: 'virtual' is redundant since the function is already declared 'final' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  void d() override final;
+  void e() final override;
+  void f() override final;
+  void g() final;
+  void h() override;
+  void i();
+  // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: annotate this function with 'override' or (rarely) 'final' [modernize-use-override]
+  // CHECK-FIXES: {{^}}  void i() override;
+};
Index: clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst
+++ clang-tools-extra/docs/clang-tidy/checks/modernize-use-override.rst
@@ -27,6 +27,14 @@
 
If set to non-zero, this check will not diagnose destructors. Default is `0`.
 
+.. option:: AllowOverrideAndFinal
+
+   If set to non-zero, this check will not diagnose ``override`` as redundant
+   with ``final``. This is useful when code will be compiled by a compiler with
+   warning/error checking flags requiring ``override`` explicitly on overriden
+   members, such as ``gcc -Wsuggest-override``/``gcc -Werror=suggest-override``.
+   Default is `0`.
+
 .. option:: OverrideSpelling
 
Specifies a macro to use instead of ``override``. This is useful when
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -153,6 +153,12 @@
   Finds non-static member functions that can be made ``const``
   

[PATCH] D70144: clang-tidy: modernize-use-equals-default avoid adding redundant semicolons

2019-11-12 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added reviewers: malcolm.parsons, angelgarcia, aaron.ballman.
Herald added subscribers: cfe-commits, mgehre.
Herald added a project: clang.

`modernize-use-equals-default` replaces default constructors/destructors with 
`= default;`. When the optional semicolon after a member function 
 is present, this results in 
two consecutive semicolons.

This small patch checks to see if the next non-comment token after the code to 
be replaced is a semicolon, and if so offers a replacement of `= default` 
rather than `= default;`.

This patch adds trailing comments and semicolons to about 5 existing tests.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D70144

Files:
  clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
@@ -7,7 +7,7 @@
   ~OL();
 };
 
-OL::OL() {}
+OL::OL() {};
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a 
trivial default constructor [modernize-use-equals-default]
 // CHECK-FIXES: OL::OL() = default;
 OL::~OL() {}
@@ -17,9 +17,9 @@
 // Inline definitions.
 class IL {
 public:
-  IL() {}
+  IL() {}   ; // Note embedded tab on this line
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: IL() = default;
+  // CHECK-FIXES: IL() = default; // Note embedded tab on this line
   ~IL() {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: ~IL() = default;
@@ -46,18 +46,20 @@
 // Default member initializer
 class DMI {
 public:
-  DMI() {}
-  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: DMI() = default;
+  DMI() {} // Comment before semi-colon on next line
+  ;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
+  // CHECK-FIXES: DMI() = default // Comment before semi-colon on next line
+  // CHECK-FIXES-NEXT:   ;
   int Field = 5;
 };
 
 // Class member
 class CM {
 public:
-  CM() {}
+  CM() {} /* Comments */ /* before */ /* semicolon */;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
-  // CHECK-FIXES: CM() = default;
+  // CHECK-FIXES: CM() = default /* Comments */ /* before */ /* semicolon */;
   OL o;
 };
 
@@ -66,7 +68,7 @@
   Priv() {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: Priv() = default;
-  ~Priv() {}
+  ~Priv() {};
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: ~Priv() = default;
 };
Index: 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default-copy.cpp
@@ -119,7 +119,7 @@
 struct BF {
   BF() = default;
   BF(const BF ) : Field1(Other.Field1), Field2(Other.Field2), 
Field3(Other.Field3),
-Field4(Other.Field4) {}
+Field4(Other.Field4) {};
   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
   // CHECK-FIXES: BF(const BF ) {{$}}
   // CHECK-FIXES: = default;
Index: clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
@@ -302,9 +302,19 @@
   auto Diag = diag(Location, "use '= default' to define a trivial " +
  SpecialFunctionName);
 
-  if (ApplyFix)
-Diag << FixItHint::CreateReplacement(Body->getSourceRange(), "= default;")
+  if (ApplyFix) {
+// Peek ahead to see if there's a semicolon after Body->getSourceRange()
+Optional Token;
+do {
+  Token = Lexer::findNextToken(
+  Body->getSourceRange().getEnd().getLocWithOffset(1),
+  Result.Context->getSourceManager(), Result.Context->getLangOpts());
+} while (Token && Token->is(tok::comment));
+StringRef Replacement =
+Token && Token->is(tok::semi) ? "= default" : "= default;";
+Diag << FixItHint::CreateReplacement(Body->getSourceRange(), Replacement)
  << RemoveInitializers;
+  }
 }
 
 } // namespace modernize


Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-equals-default.cpp
===
--- 

[PATCH] D68682: Clang-tidy fix removals removing all non-blank text from a line should remove the line

2019-11-11 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 4 inline comments as done.
poelmanc added inline comments.



Comment at: clang/lib/AST/CommentLexer.cpp:20
+
+// Consider moving this useful function to a more general utility location.
+const char *skipNewline(const char *BufferPtr, const char *BufferEnd) {

gribozavr2 wrote:
> Please do so in this change. clang/include/clang/Basic/CharInfo.h?
Done. I renamed to skipNewlineChars to remind callers it might skip multiple (1 
or 2) characters, and to avoid a name clash with very similar function 
skipNewline helper function at DependencyDirectivesSourceMinimizer.cpp:228. 
That version modifies its first argument and returns the number of characters 
skipped (0, 1, or 2.)

We could alternatively remove DependencyDirectivesSourceMinimizer.cpp's local 
skipNewline() helper function and call this version, but one location (line 
370) would require a few lines of logic that I don't know how to test.



Comment at: clang/lib/AST/CommentParser.cpp:19
 
-static inline bool isWhitespace(llvm::StringRef S) {
+// Consider moving this useful function to a more general utility location.
+bool isWhitespace(llvm::StringRef S) {

gribozavr2 wrote:
> clang/include/clang/Basic/CharInfo.h ?
Done. I renamed it to `isWhitespaceStringRef` to avoid making it an overload of 
the existing `isWhitespace(unsigned char)`, which causes ambiguous overload 
errors at QueryParser.cpp:42 & CommentSema.cpp:237.

We could alternatively keep this as an `isWhitespace` overload and instead 
change those two lines to use a `static_cast(::isWhitespace)` or precede them with a line like:
```
bool (*isWhitespaceOverload)(unsigned char) = ::isWhitespace;
```


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682



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


[PATCH] D68682: Clang-tidy fix removals removing all non-blank text from a line should remove the line

2019-11-11 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 228795.
poelmanc edited the summary of this revision.
poelmanc added a comment.

Move isWhitespace and skipNewlines to clang/Basic/CharInfo.h (renaming to 
isWhitespaceStringRef and skipNewlinesChars to resolve name clashes) and add 
double-quotes around "/n" and "/r" in comments.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang/include/clang/Basic/CharInfo.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp

Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -25,6 +25,7 @@
 #include "UnwrappedLineParser.h"
 #include "UsingDeclarationsSorter.h"
 #include "WhitespaceManager.h"
+#include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/SourceManager.h"
@@ -2356,6 +2357,87 @@
 
 } // anonymous namespace
 
+llvm::Expected
+removeNewlyBlankLines(StringRef Code, const tooling::Replacements ) {
+  tooling::Replacements NewReplaces(Replaces);
+  // pair< LineStartPos, CheckedThroughPos > of lines that have been checked
+  // and confirmed that the replacement result so far will be entirely blank.
+  std::vector> PotentialWholeLineCuts;
+  int LineStartPos = -1;
+  int LineCheckedThroughPos = -1;
+  bool LineBlankSoFar = true;
+  const char *FileText = Code.data();
+  StringRef FilePath; // Must be the same for every Replacement
+  for (const auto  : Replaces) {
+assert(FilePath.empty() || FilePath == R.getFilePath());
+FilePath = R.getFilePath();
+const int RStartPos = R.getOffset();
+
+int CurrentRLineStartPos = RStartPos;
+while (CurrentRLineStartPos > 0 &&
+   !isVerticalWhitespace(FileText[CurrentRLineStartPos - 1])) {
+  --CurrentRLineStartPos;
+}
+
+assert(CurrentRLineStartPos >= LineStartPos);
+if (CurrentRLineStartPos != LineStartPos) {
+  // We've moved on to a new line. Wrap up the old one before moving on.
+  if (LineBlankSoFar) {
+PotentialWholeLineCuts.push_back(
+std::make_pair(LineStartPos, LineCheckedThroughPos));
+  }
+  LineCheckedThroughPos = CurrentRLineStartPos;
+  LineStartPos = CurrentRLineStartPos;
+  LineBlankSoFar = true;
+}
+
+// Check to see if line from LineCheckedThroughPos to here is blank.
+assert(RStartPos >= LineCheckedThroughPos);
+StringRef PriorTextToCheck(FileText + LineCheckedThroughPos,
+   RStartPos - LineCheckedThroughPos);
+StringRef ReplacementText = R.getReplacementText();
+LineBlankSoFar = LineBlankSoFar &&
+ isWhitespaceStringRef(PriorTextToCheck) &&
+ ReplacementText.empty();
+LineCheckedThroughPos = R.getOffset() + R.getLength();
+  }
+
+  if (LineBlankSoFar) {
+PotentialWholeLineCuts.push_back(
+std::make_pair(LineStartPos, LineCheckedThroughPos));
+  }
+
+  // Now remove whole line if and only if (a) rest of line is blank, and
+  // (b) the original line was *not* blank.
+  for (const auto  : PotentialWholeLineCuts) {
+const int LineStartPos = LineCheckedThrough.first;
+const int CheckedThroughPos = LineCheckedThrough.second;
+
+int LineEndPos = CheckedThroughPos;
+while (LineEndPos < Code.size() &&
+   !isVerticalWhitespace(FileText[LineEndPos])) {
+  ++LineEndPos;
+}
+
+assert(LineEndPos >= CheckedThroughPos);
+StringRef TrailingText(FileText + CheckedThroughPos,
+   LineEndPos - CheckedThroughPos);
+assert(LineEndPos >= LineStartPos);
+StringRef OriginalLine(FileText + LineStartPos, LineEndPos - LineStartPos);
+if (isWhitespaceStringRef(TrailingText) &&
+!isWhitespaceStringRef(OriginalLine)) {
+  const char *CutTo = skipNewlineChars(FileText + LineEndPos, Code.end());
+  int CutCount = CutTo - FileText - LineStartPos;
+  llvm::Error Err = NewReplaces.add(
+  tooling::Replacement(FilePath, LineStartPos, CutCount, ""));
+  if (Err) {
+return llvm::Expected(std::move(Err));
+  }
+}
+  }
+  return NewReplaces;
+}
+
 llvm::Expected
 cleanupAroundReplacements(StringRef Code, const tooling::Replacements ,
   const FormatStyle ) {
@@ -2369,7 +2451,12 @@
   // Make header insertion replacements insert new headers into correct blocks.
   tooling::Replacements NewReplaces =
   

[PATCH] D69548: Give clang-tidy readability-redundant-string-init a customizable list of string types to fix

2019-11-11 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 228769.
poelmanc added a comment.

Make requested fixes to documentation.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69548

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s readability-redundant-string-init %t
+// RUN: %check_clang_tidy -std=c++11,c++14 %s readability-redundant-string-init %t \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-init.StringNames, \
+// RUN:   value: "::std::basic_string;our::TestString"}] \
+// RUN: }"
 // FIXME: Fix the checker to work in C++17 mode.
 
 namespace std {
@@ -139,3 +143,82 @@
 void Param3(std::string param = "") {}
 void Param4(STRING param = "") {}
 
+namespace our {
+struct TestString {
+  TestString();
+  TestString(const TestString &);
+  TestString(const char *);
+  ~TestString();
+};
+}
+
+void ourTestStringTests() {
+  our::TestString a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString a;
+  our::TestString b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString b;
+  our::TestString c = R"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString c;
+  our::TestString d(R"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString d;
+
+  our::TestString u = "u";
+  our::TestString w("w");
+  our::TestString x = R"(x)";
+  our::TestString y(R"(y)");
+  our::TestString z;
+}
+
+namespace their {
+using TestString = our::TestString;
+}
+
+// their::TestString is the same type so should warn / fix
+void theirTestStringTests() {
+  their::TestString a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: redundant string initialization
+  // CHECK-FIXES: their::TestString a;
+  their::TestString b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: redundant string initialization
+  // CHECK-FIXES: their::TestString b;
+}
+
+namespace other {
+// Identical declarations to above but different type
+struct TestString {
+  TestString();
+  TestString(const TestString &);
+  TestString(const char *);
+  ~TestString();
+};
+
+// Identical declarations to above but different type
+template 
+class allocator {};
+template 
+class char_traits {};
+template , typename A = std::allocator>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  basic_string(const C *, const A  = A());
+  ~basic_string();
+};
+typedef basic_string string;
+typedef basic_string wstring;
+}
+
+// other::TestString, other::string, other::wstring are unrelated to the types
+// being checked. No warnings / fixes should be produced for these types.
+void otherTestStringTests() {
+  other::TestString a = "";
+  other::TestString b("");
+  other::string c = "";
+  other::string d("");
+  other::wstring e = L"";
+  other::wstring f(L"");
+}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
@@ -5,7 +5,8 @@
 
 Finds unnecessary string initializations.
 
-Examples:
+Examples
+
 
 .. code-block:: c++
 
@@ -17,3 +18,15 @@
 
   std::string a;
   std::string b;
+
+Options
+---
+
+.. option:: StringNames
+
+Default is `::std::basic_string`.
+
+Semicolon-delimited list of class names to apply this check to.
+By default `::std::basic_string` applies to ``std::string`` and
+``std::wstring``. Set to e.g. `::std::basic_string;llvm::StringRef;QString`
+to perform this check on custom classes.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -153,6 +153,10 @@
   Finds non-static member functions that can be made ``const``
   because the functions don't use ``this`` in a non-const way.
 
+- The 

[PATCH] D67460: clang-tidy: modernize-use-using work with multi-argument templates

2019-11-11 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 2 inline comments as done.
poelmanc added a comment.

Done, thanks.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D67460



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


[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-11-11 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D69238#1740914 , @gribozavr2 wrote:

> Thanks! Do you have commit access or do you need me to commit for you?


I don't have commit access, if you could commit it for me that would be great. 
Thanks!


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238



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


[PATCH] D67460: clang-tidy: modernize-use-using work with multi-argument templates

2019-11-11 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 228767.
poelmanc added a comment.

Changed post-increment/decrement to pre-increment/decrement.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D67460

Files:
  clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize-use-using.cpp
@@ -183,3 +183,67 @@
   void f() override { super::f(); }
 };
 }
+
+template 
+class TwoArgTemplate {
+  typedef TwoArgTemplate self;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef'
+  // CHECK-FIXES: using self = TwoArgTemplate;
+};
+
+template 
+struct S {};
+
+typedef S<(0 > 0), int> S_t, *S_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef S<(0 > 0), int> S_t, *S_p;
+
+typedef S<(0 < 0), int> S2_t, *S2_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef S<(0 < 0), int> S2_t, *S2_p;
+
+typedef S<(0 > 0 && (3 > 1) && (1 < 1)), int> S3_t;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using S3_t = S<(0 > 0 && (3 > 1) && (1 < 1)), int>;
+
+template 
+struct Q {};
+
+constexpr bool b[1] = {true};
+
+typedef Q Q_t, *Q_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef Q Q_t, *Q_p;
+
+typedef Q Q2_t;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Q2_t = Q;
+
+struct T {
+  constexpr T(bool) {}
+
+  static constexpr bool b = true;
+};
+
+typedef Q Q3_t, *Q3_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef Q Q3_t, *Q3_p;
+
+typedef Q Q3_t;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Q3_t = Q;
+
+typedef TwoArgTemplate >, S<(0 < 0), Q > > Nested_t;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Nested_t = TwoArgTemplate >, S<(0 < 0), Q > >;
+
+template 
+class Variadic {};
+
+typedef Variadic >, S<(0 < 0), Variadic > > > Variadic_t;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: using Variadic_t = Variadic >, S<(0 < 0), Variadic > > >
+
+typedef Variadic >, S<(0 < 0), Variadic > > > Variadic_t, *Variadic_p;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
+// CHECK-FIXES: typedef Variadic >, S<(0 < 0), Variadic > > > Variadic_t, *Variadic_p;
Index: clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
===
--- clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -39,25 +39,46 @@
   File.begin(), TokenBegin, File.end());
 
   Token Tok;
-  int ParenLevel = 0;
+  int NestingLevel = 0; // Parens, braces, and square brackets
+  int AngleBracketLevel = 0;
   bool FoundTypedef = false;
 
   while (!DeclLexer.LexFromRawLexer(Tok) && !Tok.is(tok::semi)) {
 switch (Tok.getKind()) {
 case tok::l_brace:
-case tok::r_brace:
-  // This might be the `typedef struct {...} T;` case.
-  return false;
+  if (NestingLevel == 0 && AngleBracketLevel == 0) {
+// At top level, this might be the `typedef struct {...} T;` case.
+// Inside parens, square brackets, or angle brackets it's not.
+return false;
+  }
+  ++NestingLevel;
+  break;
 case tok::l_paren:
-  ParenLevel++;
+case tok::l_square:
+  ++NestingLevel;
   break;
+case tok::r_brace:
 case tok::r_paren:
-  ParenLevel--;
+case tok::r_square:
+  --NestingLevel;
+  break;
+case tok::less:
+  // If not nested in paren/brace/square bracket, treat as opening angle bracket.
+  if (NestingLevel == 0)
+++AngleBracketLevel;
+  break;
+case tok::greater:
+  // Per C++ 17 Draft N4659, Section 17.2/3
+  //   https://timsong-cpp.github.io/cppwp/n4659/temp.names#3:
+  // "When parsing a template-argument-list, the first non-nested > is
+  // taken as the ending delimiter rather than a greater-than operator."
+  // If not nested in paren/brace/square bracket, treat as closing angle bracket.
+  if (NestingLevel == 0)
+--AngleBracketLevel;
   break;
 case tok::comma:
-  if (ParenLevel == 0) {
-// If there is comma and we are not between open parenthesis then it is
-// two or more declarations in this chain.
+  if (NestingLevel == 0 && 

[PATCH] D68682: Clang-tidy fix removals removing all non-blank text from a line should remove the line

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 228558.
poelmanc added a comment.

I just rebased this patch on the latest master. I believe I've addressed all 
the comments raised so far. Should I add mention of this change to the release 
notes?


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D68682

Files:
  clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-control-flow.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-declaration.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
  clang/include/clang/AST/CommentLexer.h
  clang/include/clang/AST/CommentParser.h
  clang/include/clang/Format/Format.h
  clang/lib/AST/CommentLexer.cpp
  clang/lib/AST/CommentParser.cpp
  clang/lib/Format/Format.cpp

Index: clang/lib/Format/Format.cpp
===
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -25,6 +25,9 @@
 #include "UnwrappedLineParser.h"
 #include "UsingDeclarationsSorter.h"
 #include "WhitespaceManager.h"
+#include "clang/AST/CommentLexer.h"
+#include "clang/AST/CommentParser.h"
+#include "clang/Basic/CharInfo.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/SourceManager.h"
@@ -2356,6 +2359,85 @@
 
 } // anonymous namespace
 
+llvm::Expected
+removeNewlyBlankLines(StringRef Code, const tooling::Replacements ) {
+  tooling::Replacements NewReplaces(Replaces);
+  // pair< LineStartPos, CheckedThroughPos > of lines that have been checked
+  // and confirmed that the replacement result so far will be entirely blank.
+  std::list> PotentialWholeLineCuts;
+  int LineStartPos = -1;
+  int LineCheckedThroughPos = -1;
+  bool LineBlankSoFar = true;
+  const char *FileText = Code.data();
+  StringRef FilePath; // Must be the same for every Replacement
+  for (const auto  : Replaces) {
+assert(FilePath.empty() || FilePath == R.getFilePath());
+FilePath = R.getFilePath();
+const int RStartPos = R.getOffset();
+
+int CurrentRLineStartPos = RStartPos;
+while (CurrentRLineStartPos > 0 &&
+   !isVerticalWhitespace(FileText[CurrentRLineStartPos - 1])) {
+  --CurrentRLineStartPos;
+}
+
+assert(CurrentRLineStartPos >= LineStartPos);
+if (CurrentRLineStartPos != LineStartPos) {
+  // We've moved on to a new line. Wrap up the old one before moving on.
+  if (LineBlankSoFar) {
+PotentialWholeLineCuts.push_back(
+std::make_pair(LineStartPos, LineCheckedThroughPos));
+  }
+  LineCheckedThroughPos = CurrentRLineStartPos;
+  LineStartPos = CurrentRLineStartPos;
+  LineBlankSoFar = true;
+}
+
+// Check to see if line from LineCheckedThroughPos to here is blank.
+assert(RStartPos >= LineCheckedThroughPos);
+StringRef PriorTextToCheck(FileText + LineCheckedThroughPos,
+   RStartPos - LineCheckedThroughPos);
+StringRef ReplacementText = R.getReplacementText();
+LineBlankSoFar = LineBlankSoFar && isWhitespace(PriorTextToCheck) &&
+ ReplacementText.empty();
+LineCheckedThroughPos = R.getOffset() + R.getLength();
+  }
+
+  if (LineBlankSoFar) {
+PotentialWholeLineCuts.push_back(
+std::make_pair(LineStartPos, LineCheckedThroughPos));
+  }
+
+  // Now remove whole line if and only if (a) rest of line is blank, and
+  // (b) the original line was *not* blank.
+  for (const auto  : PotentialWholeLineCuts) {
+const int LineStartPos = LineCheckedThrough.first;
+const int CheckedThroughPos = LineCheckedThrough.second;
+
+int LineEndPos = CheckedThroughPos;
+while (LineEndPos < Code.size() &&
+   !isVerticalWhitespace(FileText[LineEndPos])) {
+  ++LineEndPos;
+}
+
+assert(LineEndPos >= CheckedThroughPos);
+StringRef TrailingText(FileText + CheckedThroughPos,
+   LineEndPos - CheckedThroughPos);
+assert(LineEndPos >= LineStartPos);
+StringRef OriginalLine(FileText + LineStartPos, LineEndPos - LineStartPos);
+if (isWhitespace(TrailingText) && !isWhitespace(OriginalLine)) {
+  const char *CutTo = skipNewline(FileText + LineEndPos, Code.end());
+  int CutCount = CutTo - FileText - LineStartPos;
+  llvm::Error Err = NewReplaces.add(
+  tooling::Replacement(FilePath, LineStartPos, CutCount, ""));
+  if (Err) {
+return llvm::Expected(std::move(Err));
+  }
+}
+  }
+  return NewReplaces;
+}
+
 llvm::Expected
 cleanupAroundReplacements(StringRef Code, const tooling::Replacements ,
   const FormatStyle ) {
@@ -2369,7 +2451,12 @@
   // Make header insertion replacements insert new headers into correct blocks.
   tooling::Replacements NewReplaces =
   fixCppIncludeInsertions(Code, Replaces, 

[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D69238#1739627 , @NoQ wrote:

> Clang's `-ast-dump` 
> .


Wow. That makes this so much easier... Thank you so much!

Looking at the AST showed that the `CXXConstructExpr`s that 
`readability-redundant-string-init` previously relied upon for `SourceRange` 
were being elided in C++17/2a, but that `VarDecl`s consistently held all the 
right info across all C++ modes. So I completely rewrote this patch to get the 
`SourceRange` from the `VarDecl`. All tests pass.

In case anyone cares or for posterity, what follows are a bunch of probably 
unnecessary details.

I made a super minimal readability-redundant-string-init.cpp:

  namespace std {
  struct string {
string();
string(const char *);
  };
  }
  
  void f() {
std::string a = "", b = "foo", c, d(""), e("bar");
  }

Running `clang -Xclang -ast-dump -std=c++11 
readability-redundant-string-init.cpp` yields:

  `-FunctionDecl 0x27a33bfd610  line:8:6 f 'void ()'
`-CompoundStmt 0x27a33bf6c78 
  `-DeclStmt 0x27a33bf6c60 
|-VarDecl 0x27a33bfd788  col:15 a 
'std::string':'std::string' cinit
| `-ExprWithCleanups 0x27a33bfddd0  
'std::string':'std::string'
|   `-CXXConstructExpr 0x27a33bfdda0  
'std::string':'std::string' 'void (std::string &&) noexcept' elidable
| `-MaterializeTemporaryExpr 0x27a33bfdd48  
'std::string':'std::string' xvalue
|   `-ImplicitCastExpr 0x27a33bfdc20  
'std::string':'std::string' 
| `-CXXConstructExpr 0x27a33bfdbf0  
'std::string':'std::string' 'void (const char *)'
|   `-ImplicitCastExpr 0x27a33bfdbd8  'const char *' 

| `-StringLiteral 0x27a33bfd868  'const char [1]' 
lvalue ""
|-VarDecl 0x27a33bfde08  col:23 b 
'std::string':'std::string' cinit
| `-ExprWithCleanups 0x27a33bfdfb0  
'std::string':'std::string'
|   `-CXXConstructExpr 0x27a33bfdf80  
'std::string':'std::string' 'void (std::string &&) noexcept' elidable
| `-MaterializeTemporaryExpr 0x27a33bfdf68  
'std::string':'std::string' xvalue
|   `-ImplicitCastExpr 0x27a33bfdf50  
'std::string':'std::string' 
| `-CXXConstructExpr 0x27a33bfdf20  
'std::string':'std::string' 'void (const char *)'
|   `-ImplicitCastExpr 0x27a33bfdf08  'const char *' 

| `-StringLiteral 0x27a33bfdee8  'const char [4]' 
lvalue "foo"
|-VarDecl 0x27a33bfdfe8  col:34 c 
'std::string':'std::string' callinit
| `-CXXConstructExpr 0x27a33bfe050  'std::string':'std::string' 
'void ()'
|-VarDecl 0x27a33bfe098  col:37 d 
'std::string':'std::string' callinit
| `-CXXConstructExpr 0x27a33bf6af0  
'std::string':'std::string' 'void (const char *)'
|   `-ImplicitCastExpr 0x27a33bf6ad8  'const char *' 

| `-StringLiteral 0x27a33bf6aa0  'const char [1]' lvalue ""
`-VarDecl 0x27a33bf6b40  col:44 e 
'std::string':'std::string' callinit
  `-CXXConstructExpr 0x27a33bf6c00  
'std::string':'std::string' 'void (const char *)'
`-ImplicitCastExpr 0x27a33bf6be8  'const char *' 

  `-StringLiteral 0x27a33bf6ba8  'const char [4]' lvalue 
"bar"

With -std=c++11, all of the outer `CXXConstructExpr` have the correct range to 
replace with just the variable names, which explains why all is fine with C++11.

Then running `clang -Xclang -ast-dump -std=c++17 
readability-redundant-string-init.cpp` yields:

  `-FunctionDecl 0x2b8e6ac96b0  line:8:6 f 'void ()'
`-CompoundStmt 0x2b8e6acc608 
  `-DeclStmt 0x2b8e6acc5f0 
|-VarDecl 0x2b8e6ac9828  col:15 a 
'std::string':'std::string' cinit
| `-ImplicitCastExpr 0x2b8e6ac9cc0  'std::string':'std::string' 

|   `-CXXConstructExpr 0x2b8e6ac9c90  
'std::string':'std::string' 'void (const char *)'
| `-ImplicitCastExpr 0x2b8e6ac9c78  'const char *' 

|   `-StringLiteral 0x2b8e6ac9908  'const char [1]' lvalue 
""
|-VarDecl 0x2b8e6ac9e08  col:23 b 
'std::string':'std::string' cinit
| `-ImplicitCastExpr 0x2b8e6ac9f50  'std::string':'std::string' 

|   `-CXXConstructExpr 0x2b8e6ac9f20  
'std::string':'std::string' 'void (const char *)'
| `-ImplicitCastExpr 0x2b8e6ac9f08  'const char *' 

|   `-StringLiteral 0x2b8e6ac9ee8  'const char [4]' lvalue 
"foo"
|-VarDecl 0x2b8e6ac9f88  col:34 c 
'std::string':'std::string' callinit
| `-CXXConstructExpr 0x2b8e6ac9ff0  'std::string':'std::string' 
'void ()'
|-VarDecl 0x2b8e6aca038  col:37 d 
'std::string':'std::string' callinit
| `-CXXConstructExpr 0x2b8e6aca0f0  
'std::string':'std::string' 'void (const char *)'
|   `-ImplicitCastExpr 0x2b8e6aca0d8  'const char *' 

| `-StringLiteral 0x2b8e6aca0a0  'const char [1]' lvalue ""
`-VarDecl 0x2b8e6acc4d0  col:44 e 

[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 228556.
poelmanc edited the summary of this revision.

Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
@@ -1,5 +1,4 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s 
readability-redundant-string-init %t
-// FIXME: Fix the checker to work in C++17 mode.
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
 
 namespace std {
 template 
@@ -131,6 +130,11 @@
   // CHECK-FIXES: std::string a, b, c;
 
   std::string d = "u", e = "u", f = "u";
+
+  std::string g = "u", h = "", i = "uuu", j = "", k;
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: redundant string initialization
+  // CHECK-MESSAGES: [[@LINE-2]]:43: warning: redundant string initialization
+  // CHECK-FIXES: std::string g = "u", h, i = "uuu", j, k;
 }
 
 // These cases should not generate warnings.
Index: 
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
@@ -1,5 +1,4 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s 
readability-redundant-string-init %t
-// FIXME: Fix the checker to work in C++17 mode.
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
 
 namespace std {
 template 
Index: clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
===
--- clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
@@ -46,23 +46,23 @@
   // string bar("");
   Finder->addMatcher(
   namedDecl(
-  varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
-  
hasDeclaration(cxxRecordDecl(hasName("basic_string")),
-  hasInitializer(expr(ignoringImplicit(anyOf(
-  EmptyStringCtorExpr,
-  EmptyStringCtorExprWithTemporaries)))
- .bind("expr"))),
-  unless(parmVarDecl()))
-  .bind("decl"),
+  varDecl(
+  hasType(hasUnqualifiedDesugaredType(recordType(
+  hasDeclaration(cxxRecordDecl(hasName("basic_string")),
+  hasInitializer(expr(ignoringImplicit(anyOf(
+  EmptyStringCtorExpr, EmptyStringCtorExprWithTemporaries)
+  .bind("vardecl"),
+  unless(parmVarDecl())),
   this);
 }
 
 void RedundantStringInitCheck::check(const MatchFinder::MatchResult ) {
-  const auto *CtorExpr = Result.Nodes.getNodeAs("expr");
-  const auto *Decl = Result.Nodes.getNodeAs("decl");
-  diag(CtorExpr->getExprLoc(), "redundant string initialization")
-  << FixItHint::CreateReplacement(CtorExpr->getSourceRange(),
-  Decl->getName());
+  const auto *VDecl = Result.Nodes.getNodeAs("vardecl");
+  // VarDecl's getSourceRange() spans 'string foo = ""' or 'string bar("")'.
+  // So start at getLocation() to span just 'foo = ""' or 'bar("")'.
+  SourceRange ReplaceRange(VDecl->getLocation(), VDecl->getEndLoc());
+  diag(VDecl->getLocation(), "redundant string initialization")
+  << FixItHint::CreateReplacement(ReplaceRange, VDecl->getName());
 }
 
 } // namespace readability


Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
@@ -1,5 +1,4 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s readability-redundant-string-init %t
-// FIXME: Fix the checker to work in C++17 mode.
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
 
 namespace std {
 template 
@@ -131,6 +130,11 @@
   // CHECK-FIXES: std::string a, b, c;
 
   std::string d = "u", e = "u", f = "u";
+
+  std::string g = "u", h = "", i = "uuu", j = "", k;
+  // CHECK-MESSAGES: [[@LINE-1]]:24: warning: redundant string initialization
+  // CHECK-MESSAGES: 

[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D69145#1725026 , @malcolm.parsons 
wrote:

> I like that this check warns about copy constructors that don't copy.
>  The warning can be suppressed with a NOLINT comment if not copying is 
> intentional.


Thanks for the comment! It's not clear to me how you suggest proceeding though.

I think it would be great to have a warning about "copy constructors that don't 
copy", which I would expect to warn regardless of whether the default 
initialization is explicit, e.g.

  MyClass( const MyClass& other) : BaseClass() {...}`

or implicit, e.g.

  MyClass( const MyClass& other) {...}

An intelligent "copy constructors that don't copy" warning might even examine 
the `{...}` to see what's being handled there.

Unfortunately currently we have two tools each of which warns in one case but 
not the other:

- `gcc -Wextra` warns only in the latter case, and can be fixed by changing 
each occurrence to the former.
- clang-tidy's current `readability-redundant-member-init` check warns only in 
the former case, and fixes it by changing each occurrence to the latter.
  - (Also clang-tidy's warning about `: BaseClass()` being redundant isn't a 
very clear warning about copy constructor that don't copy.)

This patch just offers an option to make peace between the two tools.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145



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


[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D69238#1739429 , @gribozavr2 wrote:

> If it is indeed the extra AST node for the elidable constructor, see if you 
> can use the `ignoringElidableConstructorCall` AST matcher to ignore it, 
> therefore smoothing over AST differences between language modes.


Thanks for the tip. Adding `ignoringElidableConstructorCall` in front of 
`cxxConstructExpr` for the `EmptyStringCtorExpr` and 
`EmptyStringCtorExprWithTemporaries` in RedundantStringInitCheck.cpp resulted 
in the checker no longer matching any of `std::string a = ""` lines, i.e. 
basically disabling the check for those types of lines.

Is there a tool to print the AST? That would show whether the AST already has 
some expression with the right SourceRange.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238



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


[PATCH] D69548: Give clang-tidy readability-redundant-string-init a customizable list of string types to fix

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 228541.
poelmanc edited the summary of this revision.
poelmanc added a comment.

Now allows namespaces on types and defaults to `::std::basic_string` as 
requested. The code uses namespaced string type names to check types, and uses 
non-namespaced string type names to check for the required one-argument or 
two-argument-defaulted constructors.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69548

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s readability-redundant-string-init %t
+// RUN: %check_clang_tidy -std=c++11,c++14 %s readability-redundant-string-init %t \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-init.StringNames, \
+// RUN:   value: "::std::basic_string;our::TestString"}] \
+// RUN: }"
 // FIXME: Fix the checker to work in C++17 mode.
 
 namespace std {
@@ -139,3 +143,82 @@
 void Param3(std::string param = "") {}
 void Param4(STRING param = "") {}
 
+namespace our {
+struct TestString {
+  TestString();
+  TestString(const TestString &);
+  TestString(const char *);
+  ~TestString();
+};
+}
+
+void ourTestStringTests() {
+  our::TestString a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString a;
+  our::TestString b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString b;
+  our::TestString c = R"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString c;
+  our::TestString d(R"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: redundant string initialization
+  // CHECK-FIXES: our::TestString d;
+
+  our::TestString u = "u";
+  our::TestString w("w");
+  our::TestString x = R"(x)";
+  our::TestString y(R"(y)");
+  our::TestString z;
+}
+
+namespace their {
+using TestString = our::TestString;
+}
+
+// their::TestString is the same type so should warn / fix
+void theirTestStringTests() {
+  their::TestString a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: redundant string initialization
+  // CHECK-FIXES: their::TestString a;
+  their::TestString b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:21: warning: redundant string initialization
+  // CHECK-FIXES: their::TestString b;
+}
+
+namespace other {
+// Identical declarations to above but different type
+struct TestString {
+  TestString();
+  TestString(const TestString &);
+  TestString(const char *);
+  ~TestString();
+};
+
+// Identical declarations to above but different type
+template 
+class allocator {};
+template 
+class char_traits {};
+template , typename A = std::allocator>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  basic_string(const C *, const A  = A());
+  ~basic_string();
+};
+typedef basic_string string;
+typedef basic_string wstring;
+}
+
+// other::TestString, other::string, other::wstring are unrelated to the types
+// being checked. No warnings / fixes should be produced for these types.
+void otherTestStringTests() {
+  other::TestString a = "";
+  other::TestString b("");
+  other::string c = "";
+  other::string d("");
+  other::wstring e = L"";
+  other::wstring f(L"");
+}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
@@ -5,7 +5,8 @@
 
 Finds unnecessary string initializations.
 
-Examples:
+Examples
+
 
 .. code-block:: c++
 
@@ -17,3 +18,15 @@
 
   std::string a;
   std::string b;
+
+Options
+---
+
+.. option:: StringNames
+
+Default is `::std::basic_string`.
+
+Semicolon-delimited list of base class names to apply this check to.
+By default `::std::basic_string` applies to std::string and std::wstring.
+Set to e.g. `::std::basic_string;llvm::StringRef;QString` to perform this
+check on custom classes.
Index: clang-tools-extra/docs/ReleaseNotes.rst

[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

In D69238#1736365 , @NoQ wrote:

> I suspect that it's not just the source range, but the whole AST for the 
> initializer is different, due to C++17 mandatory copy elision in the 
> equals-initializer syntax. Like, before C++17 it was a temporary constructor, 
> a temporary materialization (ironic!), and a copy constructor, but in C++17 
> and after it's a single direct constructor which looks exactly like the old 
> temporary constructor (except not being a `CXXTemporaryObjectExpr`). You're 
> most likely talking about //different construct-expressions// in different 
> language modes.
>
> That said, it should probably be possible to change the source range anyway 
> somehow.


Thanks to all the encouragement here, I spent a few more hours stepping through 
code and have found a one-line change to clang\lib\Sema\SemaInit.cpp:8053 that 
fixes this bug! Change:

  SourceLocation Loc = CurInit.get()->getBeginLoc();

to

  SourceLocation Loc = Kind.getLocation();

For `SK_UserConversion`, `CurInit` is set at SemaInit.cpp:7899 to `Args[0]`, 
i.e. the first argument to the constructor, which is `""` in this case. By 
changing `Loc` to `Kind.getLocation()`, the `BuildCXXConstructExpr` at 
SemaInit.cpp:8064 gets created with a SourceRange spanning `a = ""`. With just 
that change, the SourceRange for an expression like `std::string a = ""` 
becomes consistent across C++11/14/17/2a and 
`readability-redundant-string-init` tests pass in all C++ modes (so we can 
throw away my 70 lines of manual parsing code.)

I have no experience with the clang parsing code so I don't know what other 
effects this change might have or who else we might want to check with before 
committing this. Should I change my "diff" here to just that?

> Also i don't see any tests for multiple declarations in a single `DeclStmt`, 
> i.e.
> 
>   string A = "a", B = "";
> 
> 
> ... - which source range do you expect to have if you warn on `B`?

For that example I'd expect the warning source range to cover `B = ""`. 
`readability-redundant-string-init.cpp` does include tests almost like that: 
`std::string a = "", b = "", c = "";` warns on 3 separate source ranges, while 
`std::string d = "u", e = "u", f = "u";` doesn't warn at all. I'm happy to add 
a line that has some of each. I just added `std::string g = "u", h = "", i = 
"uuu", j = "", k;` and confirmed that it warns and fixes correctly (in C++11/14 
mode it should pass already; in C++17/2a mode it works correctly with the 
current patch.)


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238



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


[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Just documenting here that I sent the following email to cfe-...@lists.llvm.org:

> When parsing a named declaration with an equals sign with clang -std 
> c++11/14, clang builds an initializer expression whose SourceRange covers 
> from the variable name through the end of the initial value:
> 
>   std::string foo = "bar";
>   ^~~
> 
> When parsing the same code with clang -std c++17/2x, the initializer 
> expression's SourceRange only includes the initial value itself, and not the 
> variable name or the equals sign:
> 
>   std::string foo = "bar";
> ^
> 
> If the string is initialized using parentheses rather than an equals sign, in 
> all of c++11/14/17/2x the initializer expression's SourceRange includes the 
> variable name and both parentheses:
> 
>   std::string foo("bar");
>   ^~
> 
> This difference has broken clang-tidy's readability-remove-redundant-string 
> for c++17 and c++2x, as described in at reviews.llvm.org/D69238 
> . Is this SourceRange difference 
> intentional, and if not does anyone have thoughts on how to make the 
> SourceRange consistent across C++ standards? Thanks!
> 
> P.S. I've tried stepping through clang-tidy parsing the `std::string a = "";` 
> line in 
> `clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp`
>  with -std=c++11 and again with -std=c++17. In both cases 
> `Sema::AddInitializerToDecl` seems to create a correct `InitializationKind` 
> with the `Locations[0]` properly pointing to the start of the variable name. 
> I'm not sure how or where that gets translated to the expression's 
> SourceRange later on in some way that presumably differs between c++11 and 
> c++17. If this SourceRange difference is unintentional and needs to be 
> tracked down and fixed, any tips on where to look would be appreciated.

I didn't receive any email responses, I believe it prompted @NoQ to look this 
over and comment - thanks!


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238



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


[PATCH] D67460: clang-tidy: modernize-use-using work with multi-argument templates

2019-11-08 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

Thanks @aaron.ballman, I don't have commit access so will someone else commit 
this?

To address the minor nit, should I upload a new patch with 
post-increment/post-decrement changed to pre-increment/pre-decrement? (Does 
uploading changes undo the "Ready to Land" status?)


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D67460



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


[PATCH] D69548: Give clang-tidy readability-redundant-string-init a customizable list of string types to fix

2019-10-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as done.
poelmanc added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp:21
 
+const char DefaultStringNames[] = "basic_string";
+

aaron.ballman wrote:
> I think the default should probably be `::std::basic_string` to avoid getting 
> other things named `basic_string`?
The prior code had `basic_string` hard-coded at lines 27, 31, and 50 so I 
initially set the default to `basic_string` just to keep the default behavior 
unchanged.

I just now tried setting it to each of `std::basic_string`, 
`::std::basic_string`, and even `std::string;std::wstring` and the 
`readability-redundant-string-init.cpp` tests failed with any of those 
settings, so I've left it set to `basic_string`.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69548



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


[PATCH] D69548: Give clang-tidy readability-redundant-string-init a customizable list of string types to fix

2019-10-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 3 inline comments as done.
poelmanc added a comment.

@aaron.ballman Thanks for the `hasAnyName` feedback! From the name 
`internal::VariadicFunction` I assumed arguments were needed at compile-time, 
but thanks to your suggestion I found the overload taking `ArrayRef`.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69548



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


[PATCH] D69548: Give clang-tidy readability-redundant-string-init a customizable list of string types to fix

2019-10-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 226987.
poelmanc added a comment.

Added release notes, fixed backticks in documentation, removed blank line, 
removed new hasListedName matcher and used existing hasAnyName matcher.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69548

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
@@ -1,4 +1,8 @@
 // RUN: %check_clang_tidy %s readability-redundant-string-init %t
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-init.StringNames, \
+// RUN:   value: "basic_string;OurTestString"}] \
+// RUN: }"
 
 namespace std {
 template 
@@ -139,3 +143,31 @@
 void Param3(std::string param = "") {}
 void Param4(STRING param = "") {}
 
+struct OurTestString {
+  OurTestString();
+  OurTestString(const OurTestString &);
+  // MSVC headers define two constructors instead of using optional arguments.
+  OurTestString(const char *);
+  ~OurTestString();
+};
+
+void OurTestStringTests() {
+  OurTestString a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString a;
+  OurTestString b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString b;
+  OurTestString c = R"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString c;
+  OurTestString d(R"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString d;
+
+  OurTestString u = "u";
+  OurTestString w("w");
+  OurTestString x = R"(x)";
+  OurTestString y(R"(y)");
+  OurTestString z;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
@@ -5,7 +5,8 @@
 
 Finds unnecessary string initializations.
 
-Examples:
+Examples
+
 
 .. code-block:: c++
 
@@ -17,3 +18,16 @@
 
   std::string a;
   std::string b;
+
+Options
+---
+
+.. option:: StringNames
+
+Default is `basic_string`.
+
+Semicolon-delimited list of base class names to apply this check to.
+By default `basic_string` applies to std::string and std::wstring.
+Set to e.g. `basic_string;StringRef;QString` to perform this check on
+custom classes as well.
+
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -130,6 +130,10 @@
 - The 'objc-avoid-spinlock' check was renamed to :doc:`darwin-avoid-spinlock
   `
 
+- The :doc:`readability-redundant-string-init
+  ` check now supports a
+  `StringNames` option enabling its application to custom string classes.
+
 Improvements to include-fixer
 -
 
Index: clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
===
--- clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
+++ clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
@@ -10,6 +10,8 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_STRING_INIT_H
 
 #include "../ClangTidyCheck.h"
+#include 
+#include 
 
 namespace clang {
 namespace tidy {
@@ -18,10 +20,13 @@
 /// Finds unnecessary string initializations.
 class RedundantStringInitCheck : public ClangTidyCheck {
 public:
-  RedundantStringInitCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  RedundantStringInitCheck(StringRef Name, ClangTidyContext *Context);
+  void storeOptions(ClangTidyOptions::OptionMap ) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult ) override;
+
+private:
+  std::vector StringNames;
 };
 
 } // namespace readability
Index: clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
===
--- 

[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-10-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 2 inline comments as done.
poelmanc added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp:67-70
+// With -std c++14 or earlier (!LangOps.CPlusPlus17), it was sufficient to
+// return CtorExpr->getSourceRange(). However, starting with c++17, parsing
+// the expression 'std::string Name = ""' results in a CtorExpr whose
+// SourceRange includes just '""' rather than the previous 'Name = ""'.

aaron.ballman wrote:
> Are you sure that this behavioral difference isn't just a bug in Clang? I 
> can't think of why the source range should differ based on language mode, so 
> I wonder if the correct thing to do is fix how we calculate the source range 
> in Clang?
Thanks and no, I'm not sure at all. At the end of my summary paragraph I wrote:

> Or, is it possible that this change in SourceRange is an unintentional 
> difference in the parsing code? If so fixing that might make more sense.

Before starting this patch, I built a Debug build of LLVM and stepped through 
LLVM parsing code while running clang-tidy on the 
readability-redundant-string-init.cpp file. I set breakpoints and inspected 
variable values under both -std c++14 and -std c++17. The call stacks were 
clearly different. I could sometimes inspect character positions in the file 
and see where an expression's SourceLoc was set. However, a SourceLoc is a 
single character position; I couldn't figure out where an expression's 
SourceRange was even set. So I gave up and went down the current approach.

Should we ping the LLVM mailing list and see if this change rings a bell with 
anyone there?


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238



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


[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-10-29 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 226847.
poelmanc added a comment.

Changed default to 1, updated help accordingly, and removed an extraneous set 
of braces around a one-line statement.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145

Files:
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
@@ -1,4 +1,8 @@
 // RUN: %check_clang_tidy %s readability-redundant-member-init %t
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-member-init.IgnoreBaseInCopyConstructors, \
+// RUN:   value: 1}] \
+// RUN: }"
 
 struct S {
   S() = default;
@@ -116,6 +120,35 @@
   };
 };
 
+// struct whose inline copy constructor default-initializes its base class
+struct WithCopyConstructor1 : public T {
+  WithCopyConstructor1(const WithCopyConstructor1& other) : T(),
+f(),
+g()
+  {}
+  S f, g;
+};
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'f' is redundant
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'g' is redundant
+// CHECK-FIXES: WithCopyConstructor1(const WithCopyConstructor1& other) : T()
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT: {}
+
+// struct whose copy constructor default-initializes its base class
+struct WithCopyConstructor2 : public T {
+  WithCopyConstructor2(const WithCopyConstructor2& other);
+  S a;
+};
+WithCopyConstructor2::WithCopyConstructor2(const WithCopyConstructor2& other)
+  : T(), a()
+{}
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-3]]:10: warning: initializer for member 'a' is redundant
+// CHECK-FIXES: {{^}}  : T() {{$}}
+// CHECK-NEXT: {}
+
 // Initializer not written
 struct NF1 {
   NF1() {}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
@@ -6,7 +6,8 @@
 Finds member initializations that are unnecessary because the same default
 constructor would be called if they were not present.
 
-Example:
+Example
+---
 
 .. code-block:: c++
 
@@ -18,3 +19,27 @@
   private:
 std::string s;
   };
+
+Options
+---
+
+.. option:: IgnoreBaseInCopyConstructors
+
+Default is ``1``.
+
+When non-zero, the check will ignore unnecessary base class initializations
+within copy constructors, since some compilers issue warnings/errors when
+base classes are not explicitly intialized in copy constructors. For example,
+``gcc`` with ``-Wextra`` or ``-Werror=extra`` issues warning or error
+``base class ‘Bar’ should be explicitly initialized in the copy constructor``
+if ``Bar()`` were removed in the following example:
+
+.. code-block:: c++
+
+  // Explicitly initializing member s and base class Bar is unnecessary.
+  struct Foo : public Bar {
+// Remove s() below. If IgnoreBaseInCopyConstructors!=0, keep Bar().
+Foo(const Foo& foo) : Bar(), s() {}
+std::string s;
+  };
+
Index: clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
===
--- clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
+++ clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
@@ -23,9 +23,15 @@
 class RedundantMemberInitCheck : public ClangTidyCheck {
 public:
   RedundantMemberInitCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  : ClangTidyCheck(Name, Context),
+IgnoreBaseInCopyConstructors(
+Options.get("IgnoreBaseInCopyConstructors", 1)) {}
+  void storeOptions(ClangTidyOptions::OptionMap ) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult ) override;
+
+private:
+  bool IgnoreBaseInCopyConstructors;
 };
 
 } // namespace readability
Index: clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
===
--- 

[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-10-28 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 3 inline comments as done.
poelmanc added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp:50
   varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
   
hasDeclaration(cxxRecordDecl(hasName("basic_string")),
   hasInitializer(expr(ignoringImplicit(anyOf(

MyDeveloperDay wrote:
> driveby aside comment (feel free to ignore): wouldn't it be good if 
> "basic_string" here was configurable, this would allow anyone who defines a 
> string class (say like StringRef) which could have this kind of redundant 
> string initialization be able to catch them.
> 
> Couldn't this be then used to find code like `StringRef EnabledPrefixOut = 
> "";`
> 
> ```
> static void ParseMRecip(const Driver , const ArgList ,
> ArgStringList ) {
>   StringRef DisabledPrefixIn = "!";
>   StringRef DisabledPrefixOut = "!";
>   StringRef EnabledPrefixOut = "";
>   StringRef Out = "-mrecip=";
> ```
> 
Great suggestion, done. See https://reviews.llvm.org/D69548. (I figured it 
should be a separate topic from this one, but holler if you prefer I add it to 
this patch.)


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238



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


[PATCH] D69548: Give clang-tidy readability-redundant-string-init a customizable list of string types to fix

2019-10-28 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc created this revision.
poelmanc added a reviewer: MyDeveloperDay.
poelmanc added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, mgehre.
Herald added a project: clang.

This patch adds a feature requested by @MyDeveloperDay at 
https://reviews.llvm.org/D69238, @MyDeveloperDay to enable 
`readability-redundant-string-init` to take a list of strings to apply the fix 
to rather than hard-coding `basic_string`. It adds a `StringNames` option of 
semicolon-delimited names of string classes to which to apply this fix. Tests 
ensure this works with test class OurTestString as well as std::string and 
std::wstring as before. It should be applicable to llvm::StringRef, QString, 
etc.

This diff is currently based on https://reviews.llvm.org/D69238. Both make 
changes to the top of readability-redundant-string-init.cpp. I'm happy to 
rebase it on any version desired.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D69548

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
  clang/include/clang/ASTMatchers/ASTMatchers.h

Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2551,6 +2551,19 @@
 internal::hasAnyNameFunc>
 hasAnyName;
 
+/// Matches NamedDecl nodes that have any of the specified names.
+///
+/// \code
+/// hasListedName({a, b, c,...})
+/// \endcode
+///  is equivalent to
+/// \code
+/// anyOf(hasName(a), hasName(b), hasName(c),...)
+/// \endcode
+inline internal::Matcher hasListedName(const std::vector ) {
+  return internal::Matcher(new internal::HasNameMatcher(Names));
+}
+
 /// Matches NamedDecl nodes whose fully qualified names contain
 /// a substring matched by the given RegExp.
 ///
Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
@@ -1,4 +1,8 @@
 // RUN: %check_clang_tidy %s readability-redundant-string-init %t
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-string-init.StringNames, \
+// RUN:   value: "basic_string;OurTestString"}] \
+// RUN: }"
 
 namespace std {
 template 
@@ -139,3 +143,31 @@
 void Param3(std::string param = "") {}
 void Param4(STRING param = "") {}
 
+struct OurTestString {
+  OurTestString();
+  OurTestString(const OurTestString &);
+  // MSVC headers define two constructors instead of using optional arguments.
+  OurTestString(const char *);
+  ~OurTestString();
+};
+
+void OurTestStringTests() {
+  OurTestString a = "";
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString a;
+  OurTestString b("");
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString b;
+  OurTestString c = R"()";
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString c;
+  OurTestString d(R"()");
+  // CHECK-MESSAGES: [[@LINE-1]]:17: warning: redundant string initialization
+  // CHECK-FIXES: OurTestString d;
+
+  OurTestString u = "u";
+  OurTestString w("w");
+  OurTestString x = R"(x)";
+  OurTestString y(R"(y)");
+  OurTestString z;
+}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-string-init.rst
@@ -5,7 +5,8 @@
 
 Finds unnecessary string initializations.
 
-Examples:
+Examples
+
 
 .. code-block:: c++
 
@@ -17,3 +18,16 @@
 
   std::string a;
   std::string b;
+
+Options
+---
+
+.. option:: StringNames
+
+Default is ``basic_string``.
+
+Semicolon-delimited list of base class names to apply this check to.
+By default ``basic_string`` applies to std::string and std::wstring.
+Set to e.g. ``basic_string;StringRef;QString`` to perform this check on
+custom classes as well.
+
Index: clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
===
--- clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
+++ clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.h
@@ -11,6 +11,9 @@
 
 #include 

[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-10-28 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 5 inline comments as done.
poelmanc added a comment.

Thanks for the feedback, the new patch removes the extra `const`, `clang::`, 
and braces on one-line `if` statements, and now explains the regex in 
readability-redundant-string-init.cpp.




Comment at: 
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp:106
   DECL_STRING(e, "");
-  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // CHECK-MESSAGES: [[@LINE-1]]:1{{[58]}}: warning: redundant string 
initialization
 

aaron.ballman wrote:
> Why does this need a regex?
Thanks, I added a comment explaining that the character position of the warning 
differs slightly between C++11/14 (reports at the 'e') and C++17/2x (reports at 
the '"'), since the underlying parsing code has changed.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238



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


[PATCH] D69238: Fix clang-tidy readability-redundant-string-init for c++17/c++2a

2019-10-28 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 226695.
poelmanc added a comment.

Remove extra `const`, braces for one-line `if` statements, and `clang::`. Added 
a comment explaining the need for a regex on a warning test line.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69238

Files:
  clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init.cpp
@@ -1,5 +1,4 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s readability-redundant-string-init %t
-// FIXME: Fix the checker to work in C++17 mode.
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
 
 namespace std {
 template 
@@ -104,7 +103,8 @@
   // CHECK-MESSAGES: [[@LINE-1]]:10: warning: redundant string initialization
   // CHECK-FIXES: STRING d;
   DECL_STRING(e, "");
-  // CHECK-MESSAGES: [[@LINE-1]]:15: warning: redundant string initialization
+  // Warning at position :15 with -std=c++11/14, position :18 for -std=c++17/2x
+  // CHECK-MESSAGES: [[@LINE-2]]:1{{[58]}}: warning: redundant string initialization
 
   MyString f = "u";
   STRING g = "u";
Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-string-init-msvc.cpp
@@ -1,5 +1,4 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s readability-redundant-string-init %t
-// FIXME: Fix the checker to work in C++17 mode.
+// RUN: %check_clang_tidy %s readability-redundant-string-init %t
 
 namespace std {
 template 
Index: clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
===
--- clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp
@@ -57,12 +57,73 @@
   this);
 }
 
+// Returns the SourceRange for the string constructor expression and a bool
+// indicating whether to fix it (by replacing it with just the variable name)
+// or just issue a diagnostic warning. CtorExpr's SourceRange includes:
+//   foo = ""
+//   bar("")
+//   ""(only in C++17 and later)
+//
+// With -std c++14 or earlier (!LangOps.CPlusPlus17), it was sufficient to
+// return CtorExpr->getSourceRange(). However, starting with c++17, parsing
+// the expression 'std::string Name = ""' results in a CtorExpr whose
+// SourceRange includes just '""' rather than the previous 'Name = ""'.
+//
+// So if the CtorExpr's SourceRange doesn't already start with 'Name', we
+// search leftward for 'Name\b*=\b*' (where \b* represents optional whitespace)
+// and if found, extend the SourceRange to start at 'Name'.
+std::pair
+CtorSourceRange(const MatchFinder::MatchResult , const NamedDecl *Decl,
+const Expr *CtorExpr) {
+  const SourceManager  = *Result.SourceManager;
+  StringRef Name = Decl->getName();
+  int NameLength = Name.size();
+  SourceLocation CtorStartLoc(CtorExpr->getSourceRange().getBegin());
+  std::pair CtorLocInfo = SM.getDecomposedLoc(
+  CtorStartLoc.isMacroID() ? SM.getImmediateMacroCallerLoc(CtorStartLoc)
+   : CtorStartLoc);
+  int CtorStartPos = CtorLocInfo.second;
+  StringRef File = SM.getBufferData(CtorLocInfo.first);
+  StringRef CtorCheckName = File.substr(CtorStartPos, NameLength);
+  if (CtorCheckName == Name)
+// For 'std::string foo("");', CtorExpr is 'foo("")'
+return std::make_pair(CtorExpr->getSourceRange(), true);
+  // Scan backwards from CtorStartPos.
+  // If find "Name\b*=\b*", extend CtorExpr SourceRange leftwards to include it.
+  bool FoundEquals = false;
+  for (int Pos = CtorStartPos - 1; Pos >= 0; Pos--) {
+char Char = File.data()[Pos];
+if (Char == '=') {
+  if (FoundEquals)
+break; // Only allow one equals sign
+  FoundEquals = true;
+} else if (!isWhitespace(Char)) {
+  // First non-whitespace/non-equals char. Check for Name ending with it.
+  int CheckNameStart = Pos - NameLength + 1;
+  StringRef CheckName(File.data() + CheckNameStart, NameLength);
+  if (FoundEquals && Name == CheckName) {
+return std::make_pair(SourceRange(CtorStartLoc.getLocWithOffset(
+  CheckNameStart - CtorStartPos),
+

[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-10-24 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc added a comment.

What do @malcolm.parsons, @alexfh, @hokein, @aaron.ballman, @lebedev.ri think 
of @mgehre's suggestion to enable `IgnoreBaseInCopyConstructors` as the default 
setting, so gcc users won't experience build errors and think "clang-tidy broke 
my code!"

I could go either way and appreciate any input.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145



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


[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-10-21 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc updated this revision to Diff 225897.
poelmanc added a comment.

Rebase to latest master (tests moved into new "checkers" directory.)


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145

Files:
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
@@ -1,4 +1,8 @@
 // RUN: %check_clang_tidy %s readability-redundant-member-init %t
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-member-init.IgnoreBaseInCopyConstructors, \
+// RUN:   value: 1}] \
+// RUN: }"
 
 struct S {
   S() = default;
@@ -116,6 +120,35 @@
   };
 };
 
+// struct whose inline copy constructor default-initializes its base class
+struct WithCopyConstructor1 : public T {
+  WithCopyConstructor1(const WithCopyConstructor1& other) : T(),
+f(),
+g()
+  {}
+  S f, g;
+};
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'f' is redundant
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'g' is redundant
+// CHECK-FIXES: WithCopyConstructor1(const WithCopyConstructor1& other) : T()
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT: {}
+
+// struct whose copy constructor default-initializes its base class
+struct WithCopyConstructor2 : public T {
+  WithCopyConstructor2(const WithCopyConstructor2& other);
+  S a;
+};
+WithCopyConstructor2::WithCopyConstructor2(const WithCopyConstructor2& other)
+  : T(), a()
+{}
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-3]]:10: warning: initializer for member 'a' is redundant
+// CHECK-FIXES: {{^}}  : T() {{$}}
+// CHECK-NEXT: {}
+
 // Initializer not written
 struct NF1 {
   NF1() {}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
@@ -6,7 +6,8 @@
 Finds member initializations that are unnecessary because the same default
 constructor would be called if they were not present.
 
-Example:
+Example
+---
 
 .. code-block:: c++
 
@@ -18,3 +19,27 @@
   private:
 std::string s;
   };
+
+Options
+---
+
+.. option:: IgnoreBaseInCopyConstructors
+
+Default is ``0``.
+
+When non-zero, the check will ignore unnecessary base class initializations
+within copy constructors, since some compilers issue warnings/errors when
+base classes are not explicitly intialized in copy constructors. For example,
+``gcc`` with ``-Wextra`` or ``-Werror=extra`` issues warning or error
+``base class ‘Bar’ should be explicitly initialized in the copy constructor``
+if ``Bar()`` were removed in the following example:
+
+.. code-block:: c++
+
+  // Explicitly initializing member s and base class Bar is unnecessary.
+  struct Foo : public Bar {
+// Remove s() below. If IgnoreBaseInCopyConstructors!=0, keep Bar().
+Foo(const Foo& foo) : Bar(), s() {}
+std::string s;
+  };
+
Index: clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
===
--- clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
+++ clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
@@ -23,9 +23,15 @@
 class RedundantMemberInitCheck : public ClangTidyCheck {
 public:
   RedundantMemberInitCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  : ClangTidyCheck(Name, Context),
+IgnoreBaseInCopyConstructors(
+Options.get("IgnoreBaseInCopyConstructors", 0)) {}
+  void storeOptions(ClangTidyOptions::OptionMap ) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult ) override;
+
+private:
+  bool IgnoreBaseInCopyConstructors;
 };
 
 } // namespace readability
Index: clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
===
--- clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
+++ 

[PATCH] D69145: Give readability-redundant-member-init an option IgnoreBaseInCopyConstructors to avoid breaking code with gcc -Werror=extra

2019-10-21 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked 2 inline comments as done.
poelmanc added a comment.

Addressed these the other day but failed to check the "Done" boxes. Done!


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D69145



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


[PATCH] D67460: clang-tidy: modernize-use-using work with multi-argument templates

2019-10-21 Thread Conrad Poelman via Phabricator via cfe-commits
poelmanc marked an inline comment as done.
poelmanc added a comment.

Checked "Done". (I addressed @jonathanmeier's comment feedback with a previous 
update but forgot to check the box!)

I welcome any more feedback. Thanks.


Repository:
  rCTE Clang Tools Extra

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

https://reviews.llvm.org/D67460



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


  1   2   >