[libclang] Record ranges skipped by the preprocessor and expose them with libclang.

Patch by Erik Verbruggen!

llvm-svn: 196487
This commit is contained in:
Argyrios Kyrtzidis 2013-12-05 08:19:32 +00:00
parent 011e6a5f44
commit 9ef5775a94
7 changed files with 124 additions and 1 deletions

View File

@ -30,7 +30,7 @@
* compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
*/
#define CINDEX_VERSION_MAJOR 0
#define CINDEX_VERSION_MINOR 20
#define CINDEX_VERSION_MINOR 21
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@ -598,6 +598,33 @@ CINDEX_LINKAGE CXSourceLocation clang_getRangeStart(CXSourceRange range);
*/
CINDEX_LINKAGE CXSourceLocation clang_getRangeEnd(CXSourceRange range);
/**
* \brief Identifies an array of ranges that were skipped by the preprocessor.
*
* The preprocessor will skip lines when they are surrounded by an
* if/ifdef/ifndef directive whose condition does not evaluate to true.
*/
typedef struct {
/** \brief The number of ranges in the \c ranges array. */
unsigned count;
/**
* \brief An array of \c CXSourceRange, where each range starts at the
* preprocessor directive after the # token, and ends at the end of the
* corresponding endif.
*/
CXSourceRange *ranges;
} CXSkippedRanges;
/**
* \brief Retrieve all ranges that were skipped by the preprocessor.
*/
CINDEX_LINKAGE CXSkippedRanges *clang_getSkippedRanges(CXTranslationUnit tu, CXFile file);
/**
* \brief Destroy the given \c CXSkippedRanges.
*/
CINDEX_LINKAGE void clang_disposeSkippedRanges(CXSkippedRanges *skipped);
/**
* @}
*/

View File

@ -304,6 +304,9 @@ namespace clang {
/// and are referenced by the iterator using negative indices.
std::vector<PreprocessedEntity *> LoadedPreprocessedEntities;
/// \brief The set of ranges that were skipped by the preprocessor,
std::vector<SourceRange> SkippedRanges;
/// \brief Global (loaded or local) ID for a preprocessed entity.
/// Negative values are used to indicate preprocessed entities
/// loaded from the external source while non-negative values are used to
@ -557,6 +560,11 @@ namespace clang {
/// \c MacroInfo.
MacroDefinition *findMacroDefinition(const MacroInfo *MI);
/// \brief Retrieve all ranges that got skipped while preprocessing.
const std::vector<SourceRange> &getSkippedRanges() const {
return SkippedRanges;
}
private:
virtual void MacroExpands(const Token &Id, const MacroDirective *MD,
SourceRange Range, const MacroArgs *Args);
@ -579,6 +587,8 @@ namespace clang {
virtual void Defined(const Token &MacroNameTok, const MacroDirective *MD,
SourceRange Range);
virtual void SourceRangeSkipped(SourceRange Range);
void addMacroExpansion(const Token &Id, const MacroInfo *MI,
SourceRange Range);

View File

@ -406,6 +406,10 @@ void PreprocessingRecord::Defined(const Token &MacroNameTok,
MacroNameTok.getLocation());
}
void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) {
SkippedRanges.push_back(Range);
}
void PreprocessingRecord::MacroExpands(const Token &Id,const MacroDirective *MD,
SourceRange Range,
const MacroArgs *Args) {

View File

@ -0,0 +1,25 @@
#define cool
#if defined(cool)
#if defined(really_cool)
#endif // really_cool
#elif defined(hot)
// hot
#endif // trailing comment
#ifndef cool
#ifndef uncool
int probably_hot = 1;
#endif // uncool
#endif // cool
// RUN: env CINDEXTEST_SHOW_SKIPPED_RANGES=1 c-index-test -test-annotate-tokens=%s:1:1:16:1 %s | FileCheck %s
// CHECK: Skipping: [5:2 - 6:7]
// CHECK: Skipping: [8:2 - 12:7]
// CHECK: Skipping: [14:2 - 20:7]

View File

@ -3183,6 +3183,7 @@ int perform_token_annotation(int argc, const char **argv) {
CXSourceLocation startLoc, endLoc;
CXFile file = 0;
CXCursor *cursors = 0;
CXSkippedRanges *skipped_ranges = 0;
unsigned i;
input += strlen("-test-annotate-tokens=");
@ -3271,6 +3272,19 @@ int perform_token_annotation(int argc, const char **argv) {
goto teardown;
}
skipped_ranges = clang_getSkippedRanges(TU, file);
for (i = 0; i != skipped_ranges->count; ++i) {
unsigned start_line, start_column, end_line, end_column;
clang_getSpellingLocation(clang_getRangeStart(skipped_ranges->ranges[i]),
0, &start_line, &start_column, 0);
clang_getSpellingLocation(clang_getRangeEnd(skipped_ranges->ranges[i]),
0, &end_line, &end_column, 0);
printf("Skipping: ");
PrintExtent(stdout, start_line, start_column, end_line, end_column);
printf("\n");
}
clang_disposeSkippedRanges(skipped_ranges);
for (i = 0; i != num_tokens; ++i) {
const char *kind = "<unknown>";
CXString spelling = clang_getTokenSpelling(TU, tokens[i]);

View File

@ -6494,6 +6494,47 @@ void clang_disposeCXTUResourceUsage(CXTUResourceUsage usage) {
delete (MemUsageEntries*) usage.data;
}
CXSkippedRanges *clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
CXSkippedRanges *skipped = new CXSkippedRanges;
skipped->count = 0;
skipped->ranges = 0;
if (!file)
return skipped;
ASTUnit *astUnit = cxtu::getASTUnit(TU);
PreprocessingRecord *ppRec = astUnit->getPreprocessor().getPreprocessingRecord();
if (!ppRec)
return skipped;
ASTContext &Ctx = astUnit->getASTContext();
SourceManager &sm = Ctx.getSourceManager();
FileEntry *fileEntry = static_cast<FileEntry *>(file);
FileID wantedFileID = sm.translateFile(fileEntry);
const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
std::vector<SourceRange> wantedRanges;
for (std::vector<SourceRange>::const_iterator i = SkippedRanges.begin(), ei = SkippedRanges.end();
i != ei; ++i) {
if (sm.getFileID(i->getBegin()) == wantedFileID || sm.getFileID(i->getEnd()) == wantedFileID)
wantedRanges.push_back(*i);
}
skipped->count = wantedRanges.size();
skipped->ranges = new CXSourceRange[skipped->count];
for (unsigned i = 0, ei = skipped->count; i != ei; ++i)
skipped->ranges[i] = cxloc::translateSourceRange(Ctx, wantedRanges[i]);
return skipped;
}
void clang_disposeSkippedRanges(CXSkippedRanges *skipped) {
if (skipped) {
delete[] skipped->ranges;
delete skipped;
}
}
} // end extern "C"
void clang::PrintLibclangResourceUsage(CXTranslationUnit TU) {

View File

@ -101,6 +101,7 @@ clang_disposeDiagnosticSet
clang_disposeIndex
clang_disposeOverriddenCursors
clang_disposeCXPlatformAvailability
clang_disposeSkippedRanges
clang_disposeString
clang_disposeTokens
clang_disposeTranslationUnit
@ -207,6 +208,7 @@ clang_getRangeStart
clang_getRemappings
clang_getRemappingsFromFileList
clang_getResultType
clang_getSkippedRanges
clang_getSpecializedCursorTemplate
clang_getSpellingLocation
clang_getTUResourceUsageName