diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-11-09 06:24:54 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-11-09 06:24:54 +0000 |
commit | a9b06d4c246d6c301e3dd1844f5dba669ed9c631 (patch) | |
tree | 250b364482b355d61c7306c371105fd26e031519 | |
parent | 27a31fe6fac7eb98ece172bf83af93a3a103f5b4 (diff) |
ntroduce clang_getSpellingLocation() into libclang, to provide the
location where we're spelling a token even within a
macro. clang_getInstantiationLocation() tells where we instantiated
the macro.
I'm still not thrilled with the CXSourceLocation/CXSourceRange APIs,
since they gloss over macro-instantiation information.
Take 2: this time, adjusted tests appropriately and used a "simple"
approach to the spelling location.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118495 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang-c/Index.h | 35 | ||||
-rw-r--r-- | test/Index/annotate-tokens-pp.c | 2 | ||||
-rw-r--r-- | test/Index/blocks.c | 1 | ||||
-rw-r--r-- | test/Index/code-complete-errors.c | 9 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 44 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 48 | ||||
-rw-r--r-- | tools/libclang/CIndexDiagnostic.cpp | 14 | ||||
-rw-r--r-- | tools/libclang/libclang.darwin.exports | 1 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 1 |
9 files changed, 120 insertions, 35 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index b193600d9d..f3ba9974eb 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -257,8 +257,8 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu, * \brief Identifies a specific source location within a translation * unit. * - * Use clang_getInstantiationLocation() to map a source location to a - * particular file, line, and column. + * Use clang_getInstantiationLocation() or clang_getSpellingLocation() + * to map a source location to a particular file, line, and column. */ typedef struct { void *ptr_data[2]; @@ -325,6 +325,9 @@ CINDEX_LINKAGE CXSourceRange clang_getRange(CXSourceLocation begin, * \brief Retrieve the file, line, column, and offset represented by * the given source location. * + * If the location refers into a macro instantiation, retrieves the + * location of the macro instantiation. + * * \param location the location within a source file that will be decomposed * into its parts. * @@ -347,6 +350,34 @@ CINDEX_LINKAGE void clang_getInstantiationLocation(CXSourceLocation location, unsigned *offset); /** + * \brief Retrieve the file, line, column, and offset represented by + * the given source location. + * + * If the location refers into a macro instantiation, return where the + * location was originally spelled in the source file. + * + * \param location the location within a source file that will be decomposed + * into its parts. + * + * \param file [out] if non-NULL, will be set to the file to which the given + * source location points. + * + * \param line [out] if non-NULL, will be set to the line to which the given + * source location points. + * + * \param column [out] if non-NULL, will be set to the column to which the given + * source location points. + * + * \param offset [out] if non-NULL, will be set to the offset into the + * buffer to which the given source location points. + */ +CINDEX_LINKAGE void clang_getSpellingLocation(CXSourceLocation location, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset); + +/** * \brief Retrieve a source location representing the first character within a * source range. */ diff --git a/test/Index/annotate-tokens-pp.c b/test/Index/annotate-tokens-pp.c index a6e7fb99d6..3dd9ffeddc 100644 --- a/test/Index/annotate-tokens-pp.c +++ b/test/Index/annotate-tokens-pp.c @@ -173,7 +173,7 @@ void test() { // CHECK: Punctuation: "," [25:26 - 25:27] UnexposedStmt= // CHECK: Punctuation: "{" [25:28 - 25:29] UnexposedStmt= // CHECK: Keyword: "int" [25:30 - 25:33] UnexposedStmt= -// CHECK: Identifier: "z" [25:34 - 25:35] VarDecl=z:25:3 (Definition) +// CHECK: Identifier: "z" [25:34 - 25:35] VarDecl=z:25:34 (Definition) // CHECK: Punctuation: "=" [25:36 - 25:37] UnexposedStmt= // CHECK: Identifier: "x" [25:38 - 25:39] DeclRefExpr=x:24:7 // CHECK: Punctuation: ";" [25:39 - 25:40] UnexposedStmt= diff --git a/test/Index/blocks.c b/test/Index/blocks.c index 5a31a21255..a8965d2aa6 100644 --- a/test/Index/blocks.c +++ b/test/Index/blocks.c @@ -14,7 +14,6 @@ void test() { // CHECK: blocks.c:7:3: UnexposedStmt= Extent=[7:3 - 7:26] // CHECK: blocks.c:7:21: VarDecl=_foo:7:21 (Definition) Extent=[7:17 - 7:25] // CHECK: blocks.c:7:17: TypeRef=struct foo:4:8 Extent=[7:17 - 7:20] -// CHECK: blocks.c:8:3: UnexposedStmt= Extent=[8:3 - 8:17] // CHECK: blocks.c:8:11: VarDecl=i:8:11 (Definition) Extent=[8:11 - 8:16] // CHECK: blocks.c:8:15: UnexposedExpr= Extent=[8:15 - 8:16] // CHECK: blocks.c:9:3: CallExpr= Extent=[9:3 - 9:65] diff --git a/test/Index/code-complete-errors.c b/test/Index/code-complete-errors.c index 01c298c01d..4fe213eca6 100644 --- a/test/Index/code-complete-errors.c +++ b/test/Index/code-complete-errors.c @@ -10,7 +10,14 @@ int f(int *ptr1, float *ptr2) { return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15:{10:10-10:14}{10:18-10:22}: warning: comparison of distinct pointer types ('int *' and 'float *') } +#define expand_to_binary_function(ret, name, parm1, parm2, code) ret name(parm1, parm2) code + +expand_to_binary_function(int, g, int *ip, float *fp, { +// CHECK: code-complete-errors.c:17:15:{17:12-17:14}{17:18-17:20}: warning: comparison of distinct pointer types ('int *' and 'float *') + return ip == fp; + }) + void g() { } -// RUN: c-index-test -code-completion-at=%s:13:12 -pedantic %s 2> %t +// RUN: c-index-test -code-completion-at=%s:19:12 -pedantic %s 2> %t // RUN: FileCheck -check-prefix=CHECK %s < %t diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 83782fd0b8..ae36a8e996 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -192,13 +192,13 @@ static void PrintCursor(CXCursor Cursor) { printf(", "); Loc = clang_getCursorLocation(Ovl); - clang_getInstantiationLocation(Loc, 0, &line, &column, 0); + clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf("%d:%d", line, column); } printf("]"); } else { CXSourceLocation Loc = clang_getCursorLocation(Referenced); - clang_getInstantiationLocation(Loc, 0, &line, &column, 0); + clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf(":%d:%d", line, column); } } @@ -251,7 +251,7 @@ static void PrintCursor(CXCursor Cursor) { if (!clang_equalCursors(SpecializationOf, clang_getNullCursor())) { CXSourceLocation Loc = clang_getCursorLocation(SpecializationOf); CXString Name = clang_getCursorSpelling(SpecializationOf); - clang_getInstantiationLocation(Loc, 0, &line, &column, 0); + clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf(" [Specialization of %s:%d:%d]", clang_getCString(Name), line, column); clang_disposeString(Name); @@ -263,7 +263,7 @@ static void PrintCursor(CXCursor Cursor) { printf(" [Overrides "); for (I = 0; I != num_overridden; ++I) { CXSourceLocation Loc = clang_getCursorLocation(overridden[I]); - clang_getInstantiationLocation(Loc, 0, &line, &column, 0); + clang_getSpellingLocation(Loc, 0, &line, &column, 0); if (I) printf(", "); printf("@%d:%d", line, column); @@ -285,7 +285,7 @@ static const char* GetCursorSource(CXCursor Cursor) { CXSourceLocation Loc = clang_getCursorLocation(Cursor); CXString source; CXFile file; - clang_getInstantiationLocation(Loc, &file, 0, 0, 0); + clang_getSpellingLocation(Loc, &file, 0, 0, 0); source = clang_getFileName(file); if (!clang_getCString(source)) { clang_disposeString(source); @@ -319,8 +319,8 @@ void PrintDiagnostic(CXDiagnostic Diagnostic) { fprintf(stderr, "%s\n", clang_getCString(Msg)); clang_disposeString(Msg); - clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic), - &file, 0, 0, 0); + clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic), + &file, 0, 0, 0); if (!file) return; @@ -332,9 +332,9 @@ void PrintDiagnostic(CXDiagnostic Diagnostic) { CXSourceLocation end = clang_getRangeEnd(range); unsigned start_line, start_column, end_line, end_column; CXFile start_file, end_file; - clang_getInstantiationLocation(start, &start_file, &start_line, - &start_column, 0); - clang_getInstantiationLocation(end, &end_file, &end_line, &end_column, 0); + clang_getSpellingLocation(start, &start_file, &start_line, + &start_column, 0); + clang_getSpellingLocation(end, &end_file, &end_line, &end_column, 0); if (clang_equalLocations(start, end)) { /* Insertion. */ if (start_file == file) @@ -380,10 +380,10 @@ static void PrintCursorExtent(CXCursor C) { CXFile begin_file, end_file; unsigned begin_line, begin_column, end_line, end_column; - clang_getInstantiationLocation(clang_getRangeStart(extent), - &begin_file, &begin_line, &begin_column, 0); - clang_getInstantiationLocation(clang_getRangeEnd(extent), - &end_file, &end_line, &end_column, 0); + clang_getSpellingLocation(clang_getRangeStart(extent), + &begin_file, &begin_line, &begin_column, 0); + clang_getSpellingLocation(clang_getRangeEnd(extent), + &end_file, &end_line, &end_column, 0); if (!begin_file || !end_file) return; @@ -405,7 +405,7 @@ enum CXChildVisitResult FilteredPrintingVisitor(CXCursor Cursor, if (!Data->Filter || (Cursor.kind == *(enum CXCursorKind *)Data->Filter)) { CXSourceLocation Loc = clang_getCursorLocation(Cursor); unsigned line, column; - clang_getInstantiationLocation(Loc, 0, &line, &column, 0); + clang_getSpellingLocation(Loc, 0, &line, &column, 0); printf("// %s: %s:%d:%d: ", FileCheckPrefix, GetCursorSource(Cursor), line, column); PrintCursor(Cursor); @@ -449,7 +449,7 @@ static enum CXChildVisitResult FunctionScanVisitor(CXCursor Cursor, curColumn++; Loc = clang_getCursorLocation(Cursor); - clang_getInstantiationLocation(Loc, &file, 0, 0, 0); + clang_getSpellingLocation(Loc, &file, 0, 0, 0); source = clang_getFileName(file); if (clang_getCString(source)) { @@ -515,8 +515,8 @@ void InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack, for (i = 0; i < includeStackLen; ++i) { CXFile includingFile; unsigned line, column; - clang_getInstantiationLocation(includeStack[i], &includingFile, &line, - &column, 0); + clang_getSpellingLocation(includeStack[i], &includingFile, &line, + &column, 0); fname = clang_getFileName(includingFile); printf(" %s:%d:%d\n", clang_getCString(fname), line, column); clang_disposeString(fname); @@ -1228,10 +1228,10 @@ int perform_token_annotation(int argc, const char **argv) { case CXToken_Literal: kind = "Literal"; break; case CXToken_Comment: kind = "Comment"; break; } - clang_getInstantiationLocation(clang_getRangeStart(extent), - 0, &start_line, &start_column, 0); - clang_getInstantiationLocation(clang_getRangeEnd(extent), - 0, &end_line, &end_column, 0); + clang_getSpellingLocation(clang_getRangeStart(extent), + 0, &start_line, &start_column, 0); + clang_getSpellingLocation(clang_getRangeEnd(extent), + 0, &end_line, &end_column, 0); printf("%s: \"%s\" ", kind, clang_getCString(spelling)); PrintExtent(stdout, start_line, start_column, end_line, end_column); if (!clang_isInvalid(cursors[i].kind)) { diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 496833c723..454255516f 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -104,8 +104,9 @@ CXSourceRange cxloc::translateSourceRange(const SourceManager &SM, const CharSourceRange &R) { // We want the last character in this location, so we will adjust the // location accordingly. - // FIXME: How do do this with a macro instantiation location? SourceLocation EndLoc = R.getEnd(); + if (EndLoc.isValid() && EndLoc.isMacroID()) + EndLoc = SM.getSpellingLoc(EndLoc); if (R.isTokenRange() && !EndLoc.isInvalid() && EndLoc.isFileID()) { unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts); EndLoc = EndLoc.getFileLocWithOffset(Length); @@ -2455,6 +2456,51 @@ void clang_getInstantiationLocation(CXSourceLocation location, *offset = SM.getDecomposedLoc(InstLoc).second; } +void clang_getSpellingLocation(CXSourceLocation location, + CXFile *file, + unsigned *line, + unsigned *column, + unsigned *offset) { + SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); + + if (!location.ptr_data[0] || Loc.isInvalid()) { + if (file) + *file = 0; + if (line) + *line = 0; + if (column) + *column = 0; + if (offset) + *offset = 0; + return; + } + + const SourceManager &SM = + *static_cast<const SourceManager*>(location.ptr_data[0]); + SourceLocation SpellLoc = Loc; + if (SpellLoc.isMacroID()) { + SourceLocation SimpleSpellingLoc = SM.getImmediateSpellingLoc(SpellLoc); + if (SimpleSpellingLoc.isFileID() && + SM.getFileEntryForID(SM.getDecomposedLoc(SimpleSpellingLoc).first)) + SpellLoc = SimpleSpellingLoc; + else + SpellLoc = SM.getInstantiationLoc(SpellLoc); + } + + std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SpellLoc); + FileID FID = LocInfo.first; + unsigned FileOffset = LocInfo.second; + + if (file) + *file = (void *)SM.getFileEntryForID(FID); + if (line) + *line = SM.getLineNumber(FID, FileOffset); + if (column) + *column = SM.getColumnNumber(FID, FileOffset); + if (offset) + *offset = FileOffset; +} + CXSourceLocation clang_getRangeStart(CXSourceRange range) { CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] }, range.begin_int_data }; diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp index 0766548418..036a28b538 100644 --- a/tools/libclang/CIndexDiagnostic.cpp +++ b/tools/libclang/CIndexDiagnostic.cpp @@ -64,8 +64,8 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { // and source ranges. CXFile File; unsigned Line, Column; - clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic), - &File, &Line, &Column, 0); + clang_getSpellingLocation(clang_getDiagnosticLocation(Diagnostic), + &File, &Line, &Column, 0); if (File) { CXString FName = clang_getFileName(File); Out << clang_getCString(FName) << ":" << Line << ":"; @@ -81,11 +81,11 @@ CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) { CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I); unsigned StartLine, StartColumn, EndLine, EndColumn; - clang_getInstantiationLocation(clang_getRangeStart(Range), - &StartFile, &StartLine, &StartColumn, - 0); - clang_getInstantiationLocation(clang_getRangeEnd(Range), - &EndFile, &EndLine, &EndColumn, 0); + clang_getSpellingLocation(clang_getRangeStart(Range), + &StartFile, &StartLine, &StartColumn, + 0); + clang_getSpellingLocation(clang_getRangeEnd(Range), + &EndFile, &EndLine, &EndColumn, 0); if (StartFile != EndFile || StartFile != File) continue; diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports index 7d5ae8b732..09f3cf7d21 100644 --- a/tools/libclang/libclang.darwin.exports +++ b/tools/libclang/libclang.darwin.exports @@ -88,6 +88,7 @@ _clang_getRangeEnd _clang_getRangeStart _clang_getResultType _clang_getSpecializedCursorTemplate +_clang_getSpellingLocation _clang_getTemplateCursorKind _clang_getTokenExtent _clang_getTokenKind diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index da7f9c851f..6cbd2c63b7 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -88,6 +88,7 @@ clang_getRangeEnd clang_getRangeStart clang_getResultType clang_getSpecializedCursorTemplate +clang_getSpellingLocation clang_getTemplateCursorKind clang_getTokenExtent clang_getTokenKind |