forked from OSchip/llvm-project
[libclang] Record ranges skipped by the preprocessor and expose them with libclang.
Patch by Erik Verbruggen! llvm-svn: 196487
This commit is contained in:
parent
011e6a5f44
commit
9ef5775a94
|
@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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]
|
|
@ -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]);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue