aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-08-14 01:14:06 +0000
committerTed Kremenek <kremenek@apple.com>2010-08-14 01:14:06 +0000
commit3f4046004be223b03f1f895bb934e44921ccf805 (patch)
treeb8677a28f84477e091cf785c379e81e0b1cd1240
parent87c08a5d6b9e1e44ae6f554df40139d3a6f60b33 (diff)
As a heuristic, annotate tokens (via clang_annotateTokens) that are the arguments of a macro instantiation using the closest cursor with the same spelling location. Because macro arguments can get token pasted in any arbitrary order, we use the annotation map to paper over the token -> cursor annotations during our post-processing stage. This fixes most of <rdar://problem/8044584>, but still doesn't work for assert().
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111062 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--test/Index/annotate-tokens-pp.c77
-rw-r--r--tools/libclang/CIndex.cpp17
2 files changed, 93 insertions, 1 deletions
diff --git a/test/Index/annotate-tokens-pp.c b/test/Index/annotate-tokens-pp.c
index 485786e1c4..bd0d89124b 100644
--- a/test/Index/annotate-tokens-pp.c
+++ b/test/Index/annotate-tokens-pp.c
@@ -7,7 +7,18 @@ int BAR STILL_NOTHING;
#include "foo.h"
#undef BAR
-// RUN: c-index-test -test-annotate-tokens=%s:2:1:9:1 -I%S/Inputs %s | FileCheck %s
+#define REVERSE_MACRO(x,y) y + x
+#define TWICE_MACRO(y) y + y
+
+void test_macro_args() {
+ int z = 1;
+ int t = 2;
+ int k = REVERSE_MACRO(t,z);
+ int j = TWICE_MACRO(k + k);
+ int w = j + j;
+}
+
+// RUN: c-index-test -test-annotate-tokens=%s:2:1:19:1 -I%S/Inputs %s | FileCheck %s
// CHECK: Punctuation: "#" [2:1 - 2:2] preprocessing directive=
// CHECK: Identifier: "define" [2:2 - 2:8] preprocessing directive=
// CHECK: Identifier: "STILL_NOTHING" [2:9 - 2:22] macro definition=STILL_NOTHING
@@ -56,3 +67,67 @@ int BAR STILL_NOTHING;
// CHECK: Punctuation: "#" [8:1 - 8:2] preprocessing directive=
// CHECK: Identifier: "undef" [8:2 - 8:7] preprocessing directive=
// CHECK: Identifier: "BAR" [8:8 - 8:11] preprocessing directive=
+// CHECK: Punctuation: "#" [10:1 - 10:2] preprocessing directive=
+// CHECK: Identifier: "define" [10:2 - 10:8] preprocessing directive=
+// CHECK: Identifier: "REVERSE_MACRO" [10:9 - 10:22] macro definition=REVERSE_MACRO
+// CHECK: Punctuation: "(" [10:22 - 10:23] preprocessing directive=
+// CHECK: Identifier: "x" [10:23 - 10:24] preprocessing directive=
+// CHECK: Punctuation: "," [10:24 - 10:25] preprocessing directive=
+// CHECK: Identifier: "y" [10:25 - 10:26] preprocessing directive=
+// CHECK: Punctuation: ")" [10:26 - 10:27] preprocessing directive=
+// CHECK: Identifier: "y" [10:28 - 10:29] preprocessing directive=
+// CHECK: Punctuation: "+" [10:30 - 10:31] preprocessing directive=
+// CHECK: Identifier: "x" [10:32 - 10:33] preprocessing directive=
+// CHECK: Punctuation: "#" [11:1 - 11:2] preprocessing directive=
+// CHECK: Identifier: "define" [11:2 - 11:8] preprocessing directive=
+// CHECK: Identifier: "TWICE_MACRO" [11:9 - 11:20] macro definition=TWICE_MACRO
+// CHECK: Punctuation: "(" [11:20 - 11:21] preprocessing directive=
+// CHECK: Identifier: "y" [11:21 - 11:22] preprocessing directive=
+// CHECK: Punctuation: ")" [11:22 - 11:23] preprocessing directive=
+// CHECK: Identifier: "y" [11:24 - 11:25] preprocessing directive=
+// CHECK: Punctuation: "+" [11:26 - 11:27] preprocessing directive=
+// CHECK: Identifier: "y" [11:28 - 11:29] preprocessing directive=
+// CHECK: Keyword: "void" [13:1 - 13:5] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Identifier: "test_macro_args" [13:6 - 13:21] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Punctuation: "(" [13:21 - 13:22] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Punctuation: ")" [13:22 - 13:23] FunctionDecl=test_macro_args:13:6 (Definition)
+// CHECK: Punctuation: "{" [13:24 - 13:25] UnexposedStmt=
+// CHECK: Keyword: "int" [14:3 - 14:6] VarDecl=z:14:7 (Definition)
+// CHECK: Identifier: "z" [14:7 - 14:8] VarDecl=z:14:7 (Definition)
+// CHECK: Punctuation: "=" [14:9 - 14:10] VarDecl=z:14:7 (Definition)
+// CHECK: Literal: "1" [14:11 - 14:12] UnexposedExpr=
+// CHECK: Punctuation: ";" [14:12 - 14:13] UnexposedStmt=
+// CHECK: Keyword: "int" [15:3 - 15:6] VarDecl=t:15:7 (Definition)
+// CHECK: Identifier: "t" [15:7 - 15:8] VarDecl=t:15:7 (Definition)
+// CHECK: Punctuation: "=" [15:9 - 15:10] VarDecl=t:15:7 (Definition)
+// CHECK: Literal: "2" [15:11 - 15:12] UnexposedExpr=
+// CHECK: Punctuation: ";" [15:12 - 15:13] UnexposedStmt=
+// CHECK: Keyword: "int" [16:3 - 16:6] VarDecl=k:16:7 (Definition)
+// CHECK: Identifier: "k" [16:7 - 16:8] VarDecl=k:16:7 (Definition)
+// CHECK: Punctuation: "=" [16:9 - 16:10] VarDecl=k:16:7 (Definition)
+// CHECK: Identifier: "REVERSE_MACRO" [16:11 - 16:24] macro instantiation=REVERSE_MACRO:10:9
+// CHECK: Punctuation: "(" [16:24 - 16:25] UnexposedStmt=
+// CHECK: Identifier: "t" [16:25 - 16:26] DeclRefExpr=t:15:7
+// CHECK: Punctuation: "," [16:26 - 16:27] UnexposedStmt=
+// CHECK: Identifier: "z" [16:27 - 16:28] DeclRefExpr=z:14:7
+// CHECK: Punctuation: ")" [16:28 - 16:29] UnexposedStmt=
+// CHECK: Punctuation: ";" [16:29 - 16:30] UnexposedStmt=
+// CHECK: Keyword: "int" [17:3 - 17:6] VarDecl=j:17:7 (Definition)
+// CHECK: Identifier: "j" [17:7 - 17:8] VarDecl=j:17:7 (Definition)
+// CHECK: Punctuation: "=" [17:9 - 17:10] VarDecl=j:17:7 (Definition)
+// CHECK: Identifier: "TWICE_MACRO" [17:11 - 17:22] macro instantiation=TWICE_MACRO:11:9
+// CHECK: Punctuation: "(" [17:22 - 17:23] UnexposedStmt=
+// CHECK: Identifier: "k" [17:23 - 17:24] DeclRefExpr=k:16:7
+// CHECK: Punctuation: "+" [17:25 - 17:26] UnexposedStmt=
+// CHECK: Identifier: "k" [17:27 - 17:28] DeclRefExpr=k:16:7
+// CHECK: Punctuation: ")" [17:28 - 17:29] UnexposedStmt=
+// CHECK: Punctuation: ";" [17:29 - 17:30] UnexposedStmt=
+// CHECK: Keyword: "int" [18:3 - 18:6] VarDecl=w:18:7 (Definition)
+// CHECK: Identifier: "w" [18:7 - 18:8] VarDecl=w:18:7 (Definition)
+// CHECK: Punctuation: "=" [18:9 - 18:10] VarDecl=w:18:7 (Definition)
+// CHECK: Identifier: "j" [18:11 - 18:12] DeclRefExpr=j:17:7
+// CHECK: Punctuation: "+" [18:13 - 18:14] UnexposedExpr=
+// CHECK: Identifier: "j" [18:15 - 18:16] DeclRefExpr=j:17:7
+// CHECK: Punctuation: ";" [18:16 - 18:17] UnexposedStmt=
+// CHECK: Punctuation: "}" [19:1 - 19:2] UnexposedStmt=
+
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index f7dce99c72..4de675370e 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -2655,6 +2655,23 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
}
}
+ // If the location of the cursor occurs within a macro instantiation, record
+ // the spelling location of the cursor in our annotation map. We can then
+ // paper over the token labelings during a post-processing step to try and
+ // get cursor mappings for tokens that are the *arguments* of a macro
+ // instantiation.
+ if (L.isMacroID()) {
+ unsigned rawEncoding = SrcMgr.getSpellingLoc(L).getRawEncoding();
+ // Only invalidate the old annotation if it isn't part of a preprocessing
+ // directive. Here we assume that the default construction of CXCursor
+ // results in CXCursor.kind being an initialized value (i.e., 0). If
+ // this isn't the case, we can fix by doing lookup + insertion.
+
+ CXCursor &oldC = Annotated[rawEncoding];
+ if (!clang_isPreprocessing(oldC.kind))
+ oldC = cursor;
+ }
+
const enum CXCursorKind K = clang_getCursorKind(parent);
const CXCursor updateC =
(clang_isInvalid(K) || K == CXCursor_TranslationUnit ||