flx updated this revision to Diff 357993.
flx added a comment.

Make offset operations safer.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D105734

Files:
  clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
  
clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
===================================================================
--- 
clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -596,8 +596,15 @@
   // CHECK-FIXES: int i = 0; // Foo bar.
   auto TrailingCommentRemoved = ExpensiveTypeReference(); // Trailing comment.
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 
'TrailingCommentRemoved' is copy-constructed from a const reference but is 
never used;
-  // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference(); 
// Trailing comment.
+  // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference();
+  // CHECK-FIXES-NOT: // Trailing comment.
   // clang-format on
+
+  auto UnusedAndUnnecessary = ExpensiveTypeReference();
+  // Comments on a new line should not be deleted.
+  // CHECK-MESSAGES: [[@LINE-2]]:8: warning: the variable 
'UnusedAndUnnecessary' is copy-constructed
+  // CHECK-FIXES-NOT: auto UnusedAndUnnecessary = ExpensiveTypeReference();
+  // CHECK-FIXES: // Comments on a new line should not be deleted.
 }
 
 void negativeloopedOverObjectIsModified() {
Index: 
clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
===================================================================
--- clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -39,14 +39,35 @@
   }
 }
 
+llvm::Optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
+                                                    SourceManager &SM) {
+  bool Invalid;
+  const char *TextAfter = SM.getCharacterData(Loc, &Invalid);
+  if (Invalid) {
+    return llvm::None;
+  }
+  size_t Offset = std::strcspn(TextAfter, "\n");
+  return Loc.getLocWithOffset(TextAfter[Offset] != '\0' ? Offset + 1 : Offset);
+}
+
 void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
                    DiagnosticBuilder &Diagnostic) {
-  // Attempt to remove the whole line until the next non-comment token.
-  auto Tok = utils::lexer::findNextTokenSkippingComments(
-      Stmt.getEndLoc(), Context.getSourceManager(), Context.getLangOpts());
-  if (Tok) {
-    Diagnostic << FixItHint::CreateRemoval(SourceRange(
-        Stmt.getBeginLoc(), Tok->getLocation().getLocWithOffset(-1)));
+  auto &SM = Context.getSourceManager();
+  // Attempt to remove trailing comments as well.
+  auto Tok = utils::lexer::findNextTokenSkippingComments(Stmt.getEndLoc(), SM,
+                                                         
Context.getLangOpts());
+  llvm::Optional<SourceLocation> PastNewLine =
+      firstLocAfterNewLine(Stmt.getEndLoc(), SM);
+  if (Tok && PastNewLine) {
+    auto BeforeFirstTokenAfterComment = 
Tok->getLocation().getLocWithOffset(-1);
+    // Remove until the end of the line or the end of a trailing comment which
+    // ever comes first.
+    auto End =
+        SM.isBeforeInTranslationUnit(*PastNewLine, 
BeforeFirstTokenAfterComment)
+            ? *PastNewLine
+            : BeforeFirstTokenAfterComment;
+    Diagnostic << FixItHint::CreateRemoval(
+        SourceRange(Stmt.getBeginLoc(), End));
   } else {
     Diagnostic << FixItHint::CreateRemoval(Stmt.getSourceRange());
   }


Index: clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-copy-initialization.cpp
@@ -596,8 +596,15 @@
   // CHECK-FIXES: int i = 0; // Foo bar.
   auto TrailingCommentRemoved = ExpensiveTypeReference(); // Trailing comment.
   // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'TrailingCommentRemoved' is copy-constructed from a const reference but is never used;
-  // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference(); // Trailing comment.
+  // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference();
+  // CHECK-FIXES-NOT: // Trailing comment.
   // clang-format on
+
+  auto UnusedAndUnnecessary = ExpensiveTypeReference();
+  // Comments on a new line should not be deleted.
+  // CHECK-MESSAGES: [[@LINE-2]]:8: warning: the variable 'UnusedAndUnnecessary' is copy-constructed
+  // CHECK-FIXES-NOT: auto UnusedAndUnnecessary = ExpensiveTypeReference();
+  // CHECK-FIXES: // Comments on a new line should not be deleted.
 }
 
 void negativeloopedOverObjectIsModified() {
Index: clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
===================================================================
--- clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -39,14 +39,35 @@
   }
 }
 
+llvm::Optional<SourceLocation> firstLocAfterNewLine(SourceLocation Loc,
+                                                    SourceManager &SM) {
+  bool Invalid;
+  const char *TextAfter = SM.getCharacterData(Loc, &Invalid);
+  if (Invalid) {
+    return llvm::None;
+  }
+  size_t Offset = std::strcspn(TextAfter, "\n");
+  return Loc.getLocWithOffset(TextAfter[Offset] != '\0' ? Offset + 1 : Offset);
+}
+
 void recordRemoval(const DeclStmt &Stmt, ASTContext &Context,
                    DiagnosticBuilder &Diagnostic) {
-  // Attempt to remove the whole line until the next non-comment token.
-  auto Tok = utils::lexer::findNextTokenSkippingComments(
-      Stmt.getEndLoc(), Context.getSourceManager(), Context.getLangOpts());
-  if (Tok) {
-    Diagnostic << FixItHint::CreateRemoval(SourceRange(
-        Stmt.getBeginLoc(), Tok->getLocation().getLocWithOffset(-1)));
+  auto &SM = Context.getSourceManager();
+  // Attempt to remove trailing comments as well.
+  auto Tok = utils::lexer::findNextTokenSkippingComments(Stmt.getEndLoc(), SM,
+                                                         Context.getLangOpts());
+  llvm::Optional<SourceLocation> PastNewLine =
+      firstLocAfterNewLine(Stmt.getEndLoc(), SM);
+  if (Tok && PastNewLine) {
+    auto BeforeFirstTokenAfterComment = Tok->getLocation().getLocWithOffset(-1);
+    // Remove until the end of the line or the end of a trailing comment which
+    // ever comes first.
+    auto End =
+        SM.isBeforeInTranslationUnit(*PastNewLine, BeforeFirstTokenAfterComment)
+            ? *PastNewLine
+            : BeforeFirstTokenAfterComment;
+    Diagnostic << FixItHint::CreateRemoval(
+        SourceRange(Stmt.getBeginLoc(), End));
   } else {
     Diagnostic << FixItHint::CreateRemoval(Stmt.getSourceRange());
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to