[PATCH] D50801: [rename] Use isPointWithin when looking for a declaration at location

Alex Lorenz via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 15 13:08:10 PDT 2018


arphaman created this revision.
arphaman added reviewers: jkorous, hokein, ioeric.
Herald added a subscriber: dexonsmith.

This patch is a followup to https://reviews.llvm.org/D50740 .

This patch fixes the issue where clang-refactor local-rename was unable to find a declaration in a header file if that header file was included more than once, and the location of the point of interest was in a different included instance of a file than then declaration itself. The use of `isPointWithin` ensures that we're checking if the point is in the source range regardless of the included file.


Repository:
  rC Clang

https://reviews.llvm.org/D50801

Files:
  lib/Tooling/Refactoring/Rename/USRFinder.cpp
  test/Refactor/LocalRename/Inputs/MultiHeader.h
  test/Refactor/LocalRename/IsPointWithinDifferentInclude.c


Index: test/Refactor/LocalRename/IsPointWithinDifferentInclude.c
===================================================================
--- /dev/null
+++ test/Refactor/LocalRename/IsPointWithinDifferentInclude.c
@@ -0,0 +1,16 @@
+// RUN: clang-refactor local-rename -selection=%S/Inputs/MultiHeader.h:5:9 -new-name=renamedField %s -- -I %S/Inputs 2>&1 | FileCheck %s
+
+// The MultiHeader file included twice.
+// The first inclusion contains no declarations. However, the selection
+// "MultiHeader:5:9" is mapped to a location in this inclusion of the file.
+#include "MultiHeader.h"
+
+// The second inclusion contains the declarations. The range of the
+// declaration we would like is located in this inclusion.
+#define HAVE_DECLS
+#include "MultiHeader.h"
+
+// Ensure that we still find the declaration even though the location and the
+// declaration's range are located in two different inclusions.
+// CHECK:      struct Foo {
+// CHECK-NEXT:   int renamedField;
Index: test/Refactor/LocalRename/Inputs/MultiHeader.h
===================================================================
--- /dev/null
+++ test/Refactor/LocalRename/Inputs/MultiHeader.h
@@ -0,0 +1,9 @@
+#ifdef HAVE_DECLS
+
+struct MyStruct {
+  struct Foo {
+    int field;
+  } bar;
+};
+
+#endif
Index: lib/Tooling/Refactoring/Rename/USRFinder.cpp
===================================================================
--- lib/Tooling/Refactoring/Rename/USRFinder.cpp
+++ lib/Tooling/Refactoring/Rename/USRFinder.cpp
@@ -48,7 +48,8 @@
       SourceLocation Start = Range.getBegin();
       SourceLocation End = Range.getEnd();
       if (!Start.isValid() || !Start.isFileID() || !End.isValid() ||
-          !End.isFileID() || !isPointWithin(Start, End))
+          !End.isFileID() ||
+          !Context.getSourceManager().isPointWithin(Point, Start, End))
         return true;
     }
     Result = ND;
@@ -58,14 +59,6 @@
   const NamedDecl *getNamedDecl() const { return Result; }
 
 private:
-  // Determines if the Point is within Start and End.
-  bool isPointWithin(const SourceLocation Start, const SourceLocation End) {
-    // FIXME: Add tests for Point == End.
-    return Point == Start || Point == End ||
-           (Context.getSourceManager().isBeforeInTranslationUnit(Start,
-                                                                 Point) &&
-            Context.getSourceManager().isBeforeInTranslationUnit(Point, End));
-  }
 
   const NamedDecl *Result = nullptr;
   const SourceLocation Point; // The location to find the NamedDecl.
@@ -80,14 +73,15 @@
   NamedDeclOccurrenceFindingVisitor Visitor(Point, Context);
 
   // Try to be clever about pruning down the number of top-level declarations we
-  // see. If both start and end is either before or after the point we're
-  // looking for the point cannot be inside of this decl. Don't even look at it.
+  // see. If the range of the declaration doesn't contain the source location,
+  // then don't even look at it.
   for (auto *CurrDecl : Context.getTranslationUnitDecl()->decls()) {
-    SourceLocation StartLoc = CurrDecl->getBeginLoc();
-    SourceLocation EndLoc = CurrDecl->getEndLoc();
-    if (StartLoc.isValid() && EndLoc.isValid() &&
-        SM.isBeforeInTranslationUnit(StartLoc, Point) !=
-            SM.isBeforeInTranslationUnit(EndLoc, Point))
+    CharSourceRange DeclRange = Lexer::makeFileCharRange(
+        CharSourceRange::getTokenRange(CurrDecl->getSourceRange()),
+        Context.getSourceManager(), Context.getLangOpts());
+    // FIXME: Use early break if the decl is found.
+    if (DeclRange.isValid() &&
+        SM.isPointWithin(Point, DeclRange.getBegin(), DeclRange.getEnd()))
       Visitor.TraverseDecl(CurrDecl);
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D50801.160899.patch
Type: text/x-patch
Size: 3711 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180815/968ed47e/attachment.bin>


More information about the cfe-commits mailing list