}
}
-bool ASTReader::ReadASTBlock(ModuleFile &F) {
+ASTReader::ASTReadResult
+ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
BitstreamCursor &Stream = F.Stream;
if (Stream.EnterSubBlock(AST_BLOCK_ID)) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
// Read all of the records and blocks for the AST file.
switch (Entry.Kind) {
case llvm::BitstreamEntry::Error:
Error("error at end of module block in AST file");
- return true;
+ return Failure;
case llvm::BitstreamEntry::EndBlock: {
// Outside of C++, we do not store a lookup map for the translation unit.
// Instead, mark it as needing a lookup map to be built if this module
!getContext().getLangOpts().CPlusPlus)
DC->setMustBuildLookupTable();
- return false;
+ return Success;
}
case llvm::BitstreamEntry::SubBlock:
switch (Entry.ID) {
// Read the abbrevs.
ReadBlockAbbrevs(F.DeclsCursor, DECLTYPES_BLOCK_ID)) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
break;
if (Stream.SkipBlock() ||
ReadBlockAbbrevs(F.MacroCursor, PREPROCESSOR_BLOCK_ID)) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
F.MacroStartOffset = F.MacroCursor.GetCurrentBitNo();
break;
ReadBlockAbbrevs(F.PreprocessorDetailCursor,
PREPROCESSOR_DETAIL_BLOCK_ID)) {
Error("malformed preprocessor detail record in AST file");
- return true;
+ return Failure;
}
F.PreprocessorDetailStartOffset
= F.PreprocessorDetailCursor.GetCurrentBitNo();
case SOURCE_MANAGER_BLOCK_ID:
if (ReadSourceManagerBlock(F))
- return true;
+ return Failure;
break;
case SUBMODULE_BLOCK_ID:
- if (ReadSubmoduleBlock(F))
- return true;
+ if (ASTReadResult Result = ReadSubmoduleBlock(F, ClientLoadCapabilities))
+ return Result;
break;
case COMMENTS_BLOCK_ID: {
if (Stream.SkipBlock() ||
ReadBlockAbbrevs(C, COMMENTS_BLOCK_ID)) {
Error("malformed comments block in AST file");
- return true;
+ return Failure;
}
CommentsCursors.push_back(std::make_pair(C, &F));
break;
default:
if (Stream.SkipBlock()) {
Error("malformed block record in AST file");
- return true;
+ return Failure;
}
break;
}
case TYPE_OFFSET: {
if (F.LocalNumTypes != 0) {
Error("duplicate TYPE_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.TypeOffsets = (const uint32_t *)Blob.data();
F.LocalNumTypes = Record[0];
case DECL_OFFSET: {
if (F.LocalNumDecls != 0) {
Error("duplicate DECL_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.DeclOffsets = (const DeclOffset *)Blob.data();
F.LocalNumDecls = Record[0];
case IDENTIFIER_OFFSET: {
if (F.LocalNumIdentifiers != 0) {
Error("duplicate IDENTIFIER_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.IdentifierOffsets = (const uint32_t *)Blob.data();
F.LocalNumIdentifiers = Record[0];
if (SpecialTypes.size() != Record.size()) {
Error("invalid special-types record");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; ++I) {
case WEAK_UNDECLARED_IDENTIFIERS:
if (Record.size() % 4 != 0) {
Error("invalid weak identifiers record");
- return true;
+ return Failure;
}
// FIXME: Ignore weak undeclared identifiers from non-original PCH
ModuleFile *OM = ModuleMgr.lookup(Name);
if (!OM) {
Error("SourceLocation remap refers to unknown module");
- return true;
+ return Failure;
}
uint32_t SLocOffset =
case SOURCE_MANAGER_LINE_TABLE:
if (ParseLineTable(F, Record))
- return true;
+ return Failure;
break;
case SOURCE_LOCATION_PRELOADS: {
// which is based off F.SLocEntryBaseID.
if (!F.PreloadSLocEntries.empty()) {
Error("Multiple SOURCE_LOCATION_PRELOADS records in AST file");
- return true;
+ return Failure;
}
F.PreloadSLocEntries.swap(Record);
case VTABLE_USES:
if (Record.size() % 3 != 0) {
Error("Invalid VTABLE_USES record");
- return true;
+ return Failure;
}
// Later tables overwrite earlier ones.
case PENDING_IMPLICIT_INSTANTIATIONS:
if (PendingInstantiations.size() % 2 != 0) {
Error("Invalid existing PendingInstantiations");
- return true;
+ return Failure;
}
if (Record.size() % 2 != 0) {
Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
case SEMA_DECL_REFS:
if (Record.size() != 2) {
Error("Invalid SEMA_DECL_REFS block");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; ++I)
SemaDeclRefs.push_back(getGlobalDeclID(F, Record[I]));
case DECL_UPDATE_OFFSETS: {
if (Record.size() % 2 != 0) {
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
- return true;
+ return Failure;
}
// FIXME: If we've already loaded the decl, perform the updates now.
for (unsigned I = 0, N = Record.size(); I != N; I += 2)
case DECL_REPLACEMENTS: {
if (Record.size() % 3 != 0) {
Error("invalid DECL_REPLACEMENTS block in AST file");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; I += 3)
ReplacedDecls[getGlobalDeclID(F, Record[I])]
case OBJC_CATEGORIES_MAP: {
if (F.LocalNumObjCCategoriesInMap != 0) {
Error("duplicate OBJC_CATEGORIES_MAP record in AST file");
- return true;
+ return Failure;
}
F.LocalNumObjCCategoriesInMap = Record[0];
case CXX_BASE_SPECIFIER_OFFSETS: {
if (F.LocalNumCXXBaseSpecifiers != 0) {
Error("duplicate CXX_BASE_SPECIFIER_OFFSETS record in AST file");
- return true;
+ return Failure;
}
F.LocalNumCXXBaseSpecifiers = Record[0];
case UNDEFINED_BUT_USED:
if (UndefinedButUsed.size() % 2 != 0) {
Error("Invalid existing UndefinedButUsed");
- return true;
+ return Failure;
}
if (Record.size() % 2 != 0) {
Error("invalid undefined-but-used record");
- return true;
+ return Failure;
}
for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
UndefinedButUsed.push_back(getGlobalDeclID(F, Record[I++]));
case LOCAL_REDECLARATIONS_MAP: {
if (F.LocalNumRedeclarationsInMap != 0) {
Error("duplicate LOCAL_REDECLARATIONS_MAP record in AST file");
- return true;
+ return Failure;
}
F.LocalNumRedeclarationsInMap = Record[0];
case MACRO_OFFSET: {
if (F.LocalNumMacros != 0) {
Error("duplicate MACRO_OFFSET record in AST file");
- return true;
+ return Failure;
}
F.MacroOffsets = (const uint32_t *)Blob.data();
F.LocalNumMacros = Record[0];
ModuleFile &F = *M->Mod;
// Read the AST block.
- if (ReadASTBlock(F))
- return Failure;
+ if (ASTReadResult Result = ReadASTBlock(F, ClientLoadCapabilities))
+ return Result;
// Once read, set the ModuleFile bit base offset and update the size in
// bits of all files we've seen.
return !readASTFileControlBlock(Filename, FileMgr, validator);
}
-bool ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
+ASTReader::ASTReadResult
+ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
// Enter the submodule block.
if (F.Stream.EnterSubBlock(SUBMODULE_BLOCK_ID)) {
Error("malformed submodule block record in AST file");
- return true;
+ return Failure;
}
ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap();
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
Error("malformed block record in AST file");
- return true;
+ return Failure;
case llvm::BitstreamEntry::EndBlock:
- return false;
+ return Success;
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
case SUBMODULE_DEFINITION: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (Record.size() < 8) {
Error("malformed module definition");
- return true;
+ return Failure;
}
StringRef Name = Blob;
if (GlobalIndex >= SubmodulesLoaded.size() ||
SubmodulesLoaded[GlobalIndex]) {
Error("too many submodules");
- return true;
+ return Failure;
}
if (!ParentModule) {
<< CurFile->getName()
<< F.File->getName();
}
- return true;
+ return Failure;
}
}
case SUBMODULE_UMBRELLA_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
if (!CurrentModule->getUmbrellaHeader())
ModMap.setUmbrellaHeader(CurrentModule, Umbrella);
else if (CurrentModule->getUmbrellaHeader() != Umbrella) {
- Error("mismatched umbrella headers in submodule");
- return true;
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Error("mismatched umbrella headers in submodule");
+ return OutOfDate;
}
}
break;
case SUBMODULE_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_EXCLUDED_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_PRIVATE_HEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_TOPHEADER: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_UMBRELLA_DIR: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
if (!CurrentModule->getUmbrellaDir())
ModMap.setUmbrellaDir(CurrentModule, Umbrella);
else if (CurrentModule->getUmbrellaDir() != Umbrella) {
- Error("mismatched umbrella directories in submodule");
- return true;
+ if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
+ Error("mismatched umbrella directories in submodule");
+ return OutOfDate;
}
}
break;
case SUBMODULE_METADATA: {
if (!First) {
Error("submodule metadata record not at beginning of block");
- return true;
+ return Failure;
}
First = false;
case SUBMODULE_IMPORTS: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_EXPORTS: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_REQUIRES: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_LINK_LIBRARY:
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_CONFIG_MACRO:
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)
case SUBMODULE_CONFLICT: {
if (First) {
Error("missing submodule metadata record at beginning of block");
- return true;
+ return Failure;
}
if (!CurrentModule)