cameron314 created this revision.
cameron314 added a reviewer: rsmith.
cameron314 added a subscriber: cfe-commits.
cameron314 set the repository for this revision to rL LLVM.
This fixes, for example, libclang's `clang_getAllSkippedRanges` returning zero
ranges after reparsing a translation unit.
Repository:
rL LLVM
http://reviews.llvm.org/D20124
Files:
include/clang/Lex/PreprocessingRecord.h
include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/Module.h
lib/Lex/PreprocessingRecord.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
lib/Serialization/Module.cpp
Index: lib/Serialization/Module.cpp
===================================================================
--- lib/Serialization/Module.cpp
+++ lib/Serialization/Module.cpp
@@ -31,6 +31,8 @@
LocalNumMacros(0), MacroOffsets(nullptr),
BasePreprocessedEntityID(0),
PreprocessedEntityOffsets(nullptr), NumPreprocessedEntities(0),
+ BasePreprocessedSkippedRangeID(0),
+ PreprocessedSkippedRangeOffsets(nullptr), NumPreprocessedSkippedRanges(0),
LocalNumHeaderFileInfos(0),
HeaderFileInfoTableData(nullptr), HeaderFileInfoTable(nullptr),
LocalNumSubmodules(0), BaseSubmoduleID(0),
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -953,6 +953,7 @@
RECORD(UNUSED_FILESCOPED_DECLS);
RECORD(PPD_ENTITIES_OFFSETS);
RECORD(VTABLE_USES);
+ RECORD(PPD_SKIPPED_RANGES);
RECORD(REFERENCED_SELECTOR_POOL);
RECORD(TU_UPDATE_LEXICAL);
RECORD(SEMA_DECL_REFS);
@@ -2408,6 +2409,26 @@
Stream.EmitRecordWithBlob(PPEOffsetAbbrev, Record,
bytes(PreprocessedEntityOffsets));
}
+
+ // Write the skipped region table for the preprocessing record.
+ const std::vector<SourceRange> &SkippedRanges = PPRec.getSkippedRanges();
+ if (SkippedRanges.size() > 0) {
+ std::vector<PPSkippedRange> SerializedSkippedRanges;
+ SerializedSkippedRanges.reserve(SkippedRanges.size());
+ for (auto const& Range : SkippedRanges)
+ SerializedSkippedRanges.emplace_back(Range);
+
+ using namespace llvm;
+ BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+ Abbrev->Add(BitCodeAbbrevOp(PPD_SKIPPED_RANGES));
+ Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));
+ unsigned PPESkippedRangeAbbrev = Stream.EmitAbbrev(Abbrev);
+
+ Record.clear();
+ Record.push_back(PPD_SKIPPED_RANGES);
+ Stream.EmitRecordWithBlob(PPESkippedRangeAbbrev, Record,
+ bytes(SerializedSkippedRanges));
+ }
}
unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -3020,6 +3020,24 @@
break;
}
+
+ case PPD_SKIPPED_RANGES: {
+ F.PreprocessedSkippedRangeOffsets = (const PPSkippedRange*)Blob.data();
+ assert(Blob.size() % sizeof(PPSkippedRange) == 0);
+ F.NumPreprocessedSkippedRanges = Blob.size() / sizeof(PPSkippedRange);
+
+ if (!PP.getPreprocessingRecord())
+ PP.createPreprocessingRecord();
+ if (!PP.getPreprocessingRecord()->getExternalSource())
+ PP.getPreprocessingRecord()->SetExternalSource(*this);
+ F.BasePreprocessedSkippedRangeID = PP.getPreprocessingRecord()
+ ->allocateSkippedRanges(F.NumPreprocessedSkippedRanges);
+
+ if (F.NumPreprocessedSkippedRanges > 0)
+ GlobalSkippedRangeMap.insert(
+ std::make_pair(F.BasePreprocessedSkippedRangeID, &F));
+ break;
+ }
case DECL_UPDATE_OFFSETS: {
if (Record.size() % 2 != 0) {
@@ -4874,6 +4892,20 @@
Mod.FileSortedDecls + Mod.NumFileSortedDecls));
}
+SourceRange ASTReader::ReadSkippedRange(unsigned GlobalIndex) {
+ auto I = GlobalSkippedRangeMap.find(GlobalIndex);
+ assert(I != GlobalSkippedRangeMap.end() &&
+ "Corrupted global skipped range map");
+ ModuleFile *M = I->second;
+ unsigned LocalIndex = GlobalIndex - M->BasePreprocessedSkippedRangeID;
+ assert(LocalIndex < M->NumPreprocessedSkippedRanges);
+ PPSkippedRange RawRange = M->PreprocessedSkippedRangeOffsets[LocalIndex];
+ SourceRange Range(TranslateSourceLocation(*M, RawRange.getBegin()),
+ TranslateSourceLocation(*M, RawRange.getEnd()));
+ assert(Range.isValid());
+ return Range;
+}
+
PreprocessedEntity *ASTReader::ReadPreprocessedEntity(unsigned Index) {
PreprocessedEntityID PPID = Index+1;
std::pair<ModuleFile *, unsigned> PPInfo = getModulePreprocessedEntity(Index);
Index: lib/Lex/PreprocessingRecord.cpp
===================================================================
--- lib/Lex/PreprocessingRecord.cpp
+++ lib/Lex/PreprocessingRecord.cpp
@@ -40,7 +40,8 @@
PreprocessingRecord::PreprocessingRecord(SourceManager &SM)
: SourceMgr(SM),
- ExternalSource(nullptr) {
+ ExternalSource(nullptr),
+ SkippedRangesAllLoaded(true) {
}
/// \brief Returns a pair of [Begin, End) iterators of preprocessed entities
@@ -318,6 +319,24 @@
return Result;
}
+unsigned PreprocessingRecord::allocateSkippedRanges(unsigned NumRanges) {
+ unsigned Result = SkippedRanges.size();
+ SkippedRanges.resize(SkippedRanges.size() + NumRanges);
+ SkippedRangesAllLoaded = false;
+ return Result;
+}
+
+void PreprocessingRecord::ensureSkippedRangesLoaded() {
+ if (SkippedRangesAllLoaded || !ExternalSource)
+ return;
+ for (unsigned Index = 0; Index != SkippedRanges.size(); ++Index) {
+ if (SkippedRanges[Index].isInvalid())
+ SkippedRanges[Index] = ExternalSource->ReadSkippedRange(Index);
+ }
+ SkippedRangesAllLoaded = true;
+}
+
+
void PreprocessingRecord::RegisterMacroDefinition(MacroInfo *Macro,
MacroDefinitionRecord *Def) {
MacroDefinitions[Macro] = Def;
@@ -406,6 +425,7 @@
}
void PreprocessingRecord::SourceRangeSkipped(SourceRange Range) {
+ assert(Range.isValid());
SkippedRanges.push_back(Range);
}
@@ -484,5 +504,6 @@
return BumpAlloc.getTotalMemory()
+ llvm::capacity_in_bytes(MacroDefinitions)
+ llvm::capacity_in_bytes(PreprocessedEntities)
- + llvm::capacity_in_bytes(LoadedPreprocessedEntities);
+ + llvm::capacity_in_bytes(LoadedPreprocessedEntities)
+ + llvm::capacity_in_bytes(SkippedRanges);
}
Index: include/clang/Serialization/Module.h
===================================================================
--- include/clang/Serialization/Module.h
+++ include/clang/Serialization/Module.h
@@ -315,6 +315,10 @@
const PPEntityOffset *PreprocessedEntityOffsets;
unsigned NumPreprocessedEntities;
+ unsigned BasePreprocessedSkippedRangeID;
+ const PPSkippedRange *PreprocessedSkippedRangeOffsets;
+ unsigned NumPreprocessedSkippedRanges;
+
// === Header search information ===
/// \brief The number of local HeaderFileInfo structures.
Index: include/clang/Serialization/ASTReader.h
===================================================================
--- include/clang/Serialization/ASTReader.h
+++ include/clang/Serialization/ASTReader.h
@@ -686,6 +686,13 @@
/// added to the global preprocessing entitiy ID to produce a local ID.
GlobalPreprocessedEntityMapType GlobalPreprocessedEntityMap;
+ typedef ContinuousRangeMap<unsigned, ModuleFile *, 4>
+ GlobalSkippedRangeMapType;
+
+ /// \brief Mapping from global skipped range base IDs to the module in which
+ /// the skipped ranges reside.
+ GlobalSkippedRangeMapType GlobalSkippedRangeMap;
+
/// \name CodeGen-relevant special data
/// \brief Fields containing data that is relevant to CodeGen.
//@{
@@ -1529,6 +1536,9 @@
Optional<bool> isPreprocessedEntityInFileID(unsigned Index,
FileID FID) override;
+ /// \brief Read a preallocated skipped range from the external source.
+ SourceRange ReadSkippedRange(unsigned Index) override;
+
/// \brief Read the header file information for the given file entry.
HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override;
Index: include/clang/Serialization/ASTBitCodes.h
===================================================================
--- include/clang/Serialization/ASTBitCodes.h
+++ include/clang/Serialization/ASTBitCodes.h
@@ -183,6 +183,25 @@
}
};
+ /// \brief Source range of a skipped preprocessor region
+ struct PPSkippedRange {
+ /// \brief Raw source location of beginning of range.
+ unsigned Begin;
+ /// \brief Raw source location of end of range.
+ unsigned End;
+
+ PPSkippedRange(SourceRange R)
+ : Begin(R.getBegin().getRawEncoding()),
+ End(R.getEnd().getRawEncoding()) { }
+
+ SourceLocation getBegin() const {
+ return SourceLocation::getFromRawEncoding(Begin);
+ }
+ SourceLocation getEnd() const {
+ return SourceLocation::getFromRawEncoding(End);
+ }
+ };
+
/// \brief Source range/offset of a preprocessed entity.
struct DeclOffset {
/// \brief Raw source location.
@@ -580,7 +599,10 @@
MSSTRUCT_PRAGMA_OPTIONS = 55,
/// \brief Record code for \#pragma ms_struct options.
- POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56
+ POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56,
+
+ /// \brief A table of skipped ranges within the preprocessing record.
+ PPD_SKIPPED_RANGES = 57
};
/// \brief Record types used within a source manager block.
Index: include/clang/Lex/PreprocessingRecord.h
===================================================================
--- include/clang/Lex/PreprocessingRecord.h
+++ include/clang/Lex/PreprocessingRecord.h
@@ -282,6 +282,9 @@
FileID FID) {
return None;
}
+
+ /// \brief Read a preallocated skipped range from the external source.
+ virtual SourceRange ReadSkippedRange(unsigned Index) = 0;
};
/// \brief A record of the steps taken while preprocessing a source file,
@@ -307,6 +310,8 @@
/// \brief The set of ranges that were skipped by the preprocessor,
std::vector<SourceRange> SkippedRanges;
+ bool SkippedRangesAllLoaded;
+
/// \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
@@ -359,6 +364,15 @@
/// corresponds to the first newly-allocated entity.
unsigned allocateLoadedEntities(unsigned NumEntities);
+ /// \brief Allocate space for a new set of loaded preprocessed skipped ranges.
+ ///
+ /// \returns The index into the set of loaded preprocessed ranges, which
+ /// corresponds to the first newly-allocated range.
+ unsigned allocateSkippedRanges(unsigned NumRanges);
+
+ /// \brief Ensures that all external skipped ranges have been loaded.
+ void ensureSkippedRangesLoaded();
+
/// \brief Register a new macro definition.
void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def);
@@ -481,7 +495,8 @@
MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI);
/// \brief Retrieve all ranges that got skipped while preprocessing.
- const std::vector<SourceRange> &getSkippedRanges() const {
+ const std::vector<SourceRange> &getSkippedRanges() {
+ ensureSkippedRangesLoaded();
return SkippedRanges;
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits