summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-11-07 18:30:23 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-11-07 18:30:23 +0000
commitf17ed937a60b76b8b8c9c5c4056a163fcea745fa (patch)
treee0f2790950e228663472f34e0f06048de77b325c
parentd299d7e192c57367037485286327ab8da9c6928a (diff)
[refactor] rename field references in __builtin_offsetof
rdar://33875453 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317599 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h12
-rw-r--r--test/Refactor/LocalRename/BuiltinOffsetof.cpp32
2 files changed, 44 insertions, 0 deletions
diff --git a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
index 8b01a61256..d96ad78ad8 100644
--- a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
+++ b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h
@@ -70,6 +70,18 @@ public:
return visit(Expr->getFoundDecl().getDecl(), Expr->getMemberLoc());
}
+ bool VisitOffsetOfExpr(const OffsetOfExpr *S) {
+ for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
+ const OffsetOfNode &Component = S->getComponent(I);
+ if (Component.getKind() == OffsetOfNode::Field) {
+ if (!visit(Component.getField(), Component.getLocEnd()))
+ return false;
+ }
+ // FIXME: Try to resolve dependent field references.
+ }
+ return true;
+ }
+
// Other visitors:
bool VisitTypeLoc(const TypeLoc Loc) {
diff --git a/test/Refactor/LocalRename/BuiltinOffsetof.cpp b/test/Refactor/LocalRename/BuiltinOffsetof.cpp
new file mode 100644
index 0000000000..3119eeb7e5
--- /dev/null
+++ b/test/Refactor/LocalRename/BuiltinOffsetof.cpp
@@ -0,0 +1,32 @@
+// RUN: clang-refactor local-rename -selection=test:%s -new-name=bar %s -- | grep -v CHECK | FileCheck %s
+
+struct Struct {
+ int /*range f=*/field;
+};
+
+struct Struct2 {
+ Struct /*range array=*/array[4][2];
+};
+
+void foo() {
+ (void)__builtin_offsetof(Struct, /*range f=*/field);
+ (void)__builtin_offsetof(Struct2, /*range array=*/array[1][0]./*range f=*/field);
+}
+
+#define OFFSET_OF_(X, Y) __builtin_offsetof(X, Y)
+
+class SubclassOffsetof : public Struct {
+ void foo() {
+ (void)OFFSET_OF_(SubclassOffsetof, field);
+ }
+};
+
+// CHECK: 2 'array' results:
+// CHECK: Struct /*range array=*/bar[4][2];
+// CHECK: __builtin_offsetof(Struct2, /*range array=*/bar[1][0]./*range f=*/field);
+
+// CHECK: 3 'f' results:
+// CHECK: int /*range f=*/bar;
+// CHECK: __builtin_offsetof(Struct, /*range f=*/bar);
+// CHECK-NEXT: __builtin_offsetof(Struct2, /*range array=*/array[1][0]./*range f=*/bar);
+// CHECK: OFFSET_OF_(SubclassOffsetof, bar);