summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization/ASTReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization/ASTReader.cpp')
-rw-r--r--clang/lib/Serialization/ASTReader.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 2569e225b55..af12bf39fab 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -1705,6 +1705,26 @@ ASTReader::ReadASTBlock(Module &F) {
return IgnorePCH;
}
break;
+
+ case SUBMODULE_BLOCK_ID:
+ switch (ReadSubmoduleBlock(F)) {
+ case Success:
+ break;
+
+ case Failure:
+ Error("malformed submodule block in AST file");
+ return Failure;
+
+ case IgnorePCH:
+ return IgnorePCH;
+ }
+ break;
+
+ default:
+ if (!Stream.SkipBlock())
+ break;
+ Error("malformed block record in AST file");
+ return Failure;
}
continue;
}
@@ -2800,6 +2820,110 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
return std::string();
}
+ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(Module &F) {
+ // Enter the submodule block.
+ if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
+ Error("malformed submodule block record in AST file");
+ return Failure;
+ }
+
+ ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
+ ModuleMap::Module *CurrentModule = 0;
+ RecordData Record;
+ while (true) {
+ unsigned Code = F.Stream.ReadCode();
+ if (Code == llvm::bitc::END_BLOCK) {
+ if (F.Stream.ReadBlockEnd()) {
+ Error("error at end of submodule block in AST file");
+ return Failure;
+ }
+ return Success;
+ }
+
+ if (Code == llvm::bitc::ENTER_SUBBLOCK) {
+ // No known subblocks, always skip them.
+ F.Stream.ReadSubBlockID();
+ if (F.Stream.SkipBlock()) {
+ Error("malformed block record in AST file");
+ return Failure;
+ }
+ continue;
+ }
+
+ if (Code == llvm::bitc::DEFINE_ABBREV) {
+ F.Stream.ReadAbbrevRecord();
+ continue;
+ }
+
+ // Read a record.
+ const char *BlobStart;
+ unsigned BlobLen;
+ Record.clear();
+ switch (F.Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
+ default: // Default behavior: ignore.
+ break;
+
+ case SUBMODULE_DEFINITION: {
+ StringRef Name(BlobStart, BlobLen);
+ unsigned Parent = Record[0];
+ bool IsFramework = Record[1];
+ bool IsExplicit = Record[2];
+
+ ModuleMap::Module *ParentModule = 0;
+ if (Parent) {
+ if (Parent > F.Submodules.size()) {
+ Error("malformed submodule parent entry");
+ return Failure;
+ }
+
+ ParentModule = F.Submodules[Parent - 1];
+ }
+
+ // Retrieve this (sub)module from the module map, creating it if
+ // necessary.
+ CurrentModule = ModMap.findOrCreateModule(Name, ParentModule,
+ IsFramework,
+ IsExplicit).first;
+ F.Submodules.push_back(CurrentModule);
+ break;
+ }
+
+ case SUBMODULE_UMBRELLA: {
+ if (!CurrentModule)
+ break;
+
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *Umbrella = PP.getFileManager().getFile(FileName)) {
+ if (!CurrentModule->UmbrellaHeader)
+ CurrentModule->UmbrellaHeader = Umbrella;
+ else if (CurrentModule->UmbrellaHeader != Umbrella) {
+ Error("mismatched umbrella headers in submodule");
+ return Failure;
+ }
+ }
+ break;
+ }
+
+ case SUBMODULE_HEADER: {
+ if (!CurrentModule)
+ break;
+
+ // FIXME: Be more lazy about this!
+ StringRef FileName(BlobStart, BlobLen);
+ if (const FileEntry *File = PP.getFileManager().getFile(FileName)) {
+ if (std::find(CurrentModule->Headers.begin(),
+ CurrentModule->Headers.end(),
+ File) == CurrentModule->Headers.end())
+ CurrentModule->Headers.push_back(File);
+ }
+ break;
+ }
+ }
+ }
+
+ return Success;
+}
+
/// \brief Parse the record that corresponds to a LangOptions data
/// structure.
///
OpenPOWER on IntegriCloud