From: Douglas Gregor Date: Thu, 9 Sep 2010 23:10:46 +0000 (+0000) Subject: Add libclang visitation for __builtin_offsetof's components (fields X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8ccef2d0322ebf2701cc10f1ab14c9ee49e17bd7;p=clang Add libclang visitation for __builtin_offsetof's components (fields and array references). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113556 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Index/load-exprs.c b/test/Index/load-exprs.c index 248bc6ebf5..1c27490d63 100644 --- a/test/Index/load-exprs.c +++ b/test/Index/load-exprs.c @@ -20,6 +20,17 @@ int test_blocks(int x) { return y; } +struct Y { + struct X array[3]; +}; + +enum { StartIndex = 1 }; + +void test_members(int aval, int bval) { + struct Y y0 = { .array[StartIndex].b = bval, .array[StartIndex].a = aval }; + __builtin_offsetof(struct Y, array[StartIndex].b); +} + // RUN: c-index-test -test-load-source all %s -fblocks | FileCheck %s // CHECK: load-exprs.c:1:13: TypedefDecl=T:1:13 (Definition) Extent=[1:13 - 1:14] @@ -52,4 +63,9 @@ int test_blocks(int x) { // CHECK: load-exprs.c:16:10: DeclRefExpr=z:13:17 Extent=[16:10 - 16:11] // CHECK: load-exprs.c:17:10: DeclRefExpr= Extent=[17:10 - 17:11] // CHECK: load-exprs.c:20:10: DeclRefExpr=y:11:15 Extent=[20:10 - 20:11] +// CHECK: load-exprs.c:29:6: FunctionDecl=test_members:29:6 (Definition) +// CHECK: load-exprs.c:31:29: TypeRef=struct Y:23:8 Extent=[31:29 - 31:30] +// CHECK: load-exprs.c:31:32: MemberRef=array:24:12 Extent=[31:32 - 31:37] +// CHECK: load-exprs.c:31:38: DeclRefExpr=StartIndex:27:8 Extent=[31:38 - 31:48] +// CHECK: load-exprs.c:31:50: MemberRef=b:2:19 Extent=[31:50 - 31:51] diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index cb2f7b53dc..35e28ad429 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1555,11 +1555,34 @@ bool CursorVisitor::VisitBlockExpr(BlockExpr *B) { } bool CursorVisitor::VisitOffsetOfExpr(OffsetOfExpr *E) { - // FIXME: Visit fields as well? + // Visit the type into which we're computing an offset. if (Visit(E->getTypeSourceInfo()->getTypeLoc())) return true; + + // Visit the components of the offsetof expression. + for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { + typedef OffsetOfExpr::OffsetOfNode OffsetOfNode; + const OffsetOfNode &Node = E->getComponent(I); + switch (Node.getKind()) { + case OffsetOfNode::Array: + if (Visit(MakeCXCursor(E->getIndexExpr(Node.getArrayExprIndex()), + StmtParent, TU))) + return true; + break; + + case OffsetOfNode::Field: + if (Visit(MakeCursorMemberRef(Node.getField(), Node.getRange().getEnd(), + TU))) + return true; + break; + + case OffsetOfNode::Identifier: + case OffsetOfNode::Base: + continue; + } + } - return VisitExpr(E); + return false; } bool CursorVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {