loskutov created this revision.
loskutov added reviewers: sbenza, PiotrZSL.
loskutov added a project: clang-tools-extra.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
loskutov requested review of this revision.
Herald added a subscriber: cfe-commits.

Due to guaranteed copy elision, not only do some nodes get removed from the AST,
but also some existing nodes change the source locations they correspond to.
Hence, the check works slightly differently in pre-C++17 and C++17-and-later 
modes
in terms of what gets highlighted.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158371

Files:
  clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/dangling-handle.cpp
@@ -1,8 +1,12 @@
-// RUN: %check_clang_tidy -std=c++11,c++14 %s bugprone-dangling-handle %t -- \
+// RUN: %check_clang_tidy -std=c++11,c++14 -check-suffix=,CXX14 %s bugprone-dangling-handle %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:             {bugprone-dangling-handle.HandleClasses: \
+// RUN:               'std::basic_string_view; ::llvm::StringRef;'}}"
+
+// RUN: %check_clang_tidy -std=c++17-or-later -check-suffix=,CXX17 %s bugprone-dangling-handle %t -- \
 // RUN:   -config="{CheckOptions: \
 // RUN:             {bugprone-dangling-handle.HandleClasses: \
 // RUN:               'std::basic_string_view; ::llvm::StringRef;'}}"
-// FIXME: Fix the checker to work in C++17 or later mode.
 
 namespace std {
 
@@ -84,27 +88,32 @@
 
 void Positives() {
   std::string_view view1 = std::string();
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
 
   std::string_view view_2 = ReturnsAString();
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:29: warning: std::basic_string_view outlives its value [bugprone-dangling-handle]
 
   view1 = std::string();
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
 
   const std::string& str_ref = "";
   std::string_view view3 = true ? "A" : str_ref;
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:28: warning: std::basic_string_view outlives
   view3 = true ? "A" : str_ref;
   // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives
 
   std::string_view view4(ReturnsAString());
-  // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:20: warning: std::basic_string_view outlives
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:26: warning: std::basic_string_view outlives
 }
 
 void OtherTypes() {
   llvm::StringRef ref = std::string();
-  // CHECK-MESSAGES: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
+  // CHECK-MESSAGES-CXX14: [[@LINE-1]]:19: warning: llvm::StringRef outlives its value
+  // CHECK-MESSAGES-CXX17: [[@LINE-2]]:25: warning: llvm::StringRef outlives its value
 }
 
 const char static_array[] = "A";
Index: clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp
@@ -37,8 +37,8 @@
   // temporary value. If one of them is not a temporary then it must be copied
   // into one to satisfy the type of the operator.
   const auto TemporaryTernary =
-      conditionalOperator(hasTrueExpression(cxxBindTemporaryExpr()),
-                          hasFalseExpression(cxxBindTemporaryExpr()));
+      conditionalOperator(hasTrueExpression(ignoringParenImpCasts(cxxBindTemporaryExpr())),
+                          hasFalseExpression(ignoringParenImpCasts(cxxBindTemporaryExpr())));
 
   return handleFrom(IsAHandle, anyOf(cxxBindTemporaryExpr(), TemporaryTernary));
 }
@@ -103,26 +103,17 @@
 void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
   const auto ConvertedHandle = handleFromTemporaryValue(IsAHandle);
 
-  // Find 'Handle foo(ReturnsAValue());'
+  // Find 'Handle foo(ReturnsAValue());', 'Handle foo = ReturnsAValue();'
   Finder->addMatcher(
       varDecl(hasType(hasUnqualifiedDesugaredType(
                   recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
+              unless(parmVarDecl()),
               hasInitializer(
-                  exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle)))
+                  exprWithCleanups(ignoringElidableConstructorCall(has(
+                                       ignoringParenImpCasts(ConvertedHandle))))
                       .bind("bad_stmt"))),
       this);
 
-  // Find 'Handle foo = ReturnsAValue();'
-  Finder->addMatcher(
-      traverse(TK_AsIs,
-               varDecl(hasType(hasUnqualifiedDesugaredType(recordType(
-                           hasDeclaration(cxxRecordDecl(IsAHandle))))),
-                       unless(parmVarDecl()),
-                       hasInitializer(exprWithCleanups(
-                                          has(ignoringParenImpCasts(handleFrom(
-                                              IsAHandle, ConvertedHandle))))
-                                          .bind("bad_stmt")))),
-      this);
   // Find 'foo = ReturnsAValue();  // foo is Handle'
   Finder->addMatcher(
       traverse(TK_AsIs,
@@ -146,10 +137,9 @@
           returnStmt(
               // The AST contains two constructor calls:
               //   1. Value to Handle conversion.
-              //   2. Handle copy construction.
+              //   2. Handle copy construction (elided in C++17+).
               // We have to match both.
-              has(ignoringImplicit(handleFrom(
-                  IsAHandle,
+              has(ignoringImplicit(ignoringElidableConstructorCall(ignoringImplicit(
                   handleFrom(IsAHandle,
                              declRefExpr(to(varDecl(
                                  // Is function scope ...
@@ -158,7 +148,7 @@
                                  anyOf(hasType(arrayType()),
                                        hasType(hasUnqualifiedDesugaredType(
                                            recordType(hasDeclaration(recordDecl(
-                                               unless(IsAHandle)))))))))))))),
+                                               unless(IsAHandle))))))))))))))),
               // Temporary fix for false positives inside lambdas.
               unless(hasAncestor(lambdaExpr())))
               .bind("bad_stmt")),
@@ -168,8 +158,9 @@
   Finder->addMatcher(
       traverse(
           TK_AsIs,
-          returnStmt(has(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
-                         IsAHandle, handleFromTemporaryValue(IsAHandle)))))))
+          returnStmt(has(exprWithCleanups(ignoringElidableConstructorCall(
+                    has(ignoringParenImpCasts(
+			handleFromTemporaryValue(IsAHandle)))))))
               .bind("bad_stmt")),
       this);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to