Skip to content

Commit dc9fdaf

Browse files
committed
[modules] If we hit a failure while loading a PCH/module, abort parsing instead of trying to continue in an invalid state.
Also don't let libclang create a PCH with such an error. Fixes rdar://13953768 llvm-svn: 182629
1 parent aa79068 commit dc9fdaf

File tree

13 files changed

+84
-4
lines changed

13 files changed

+84
-4
lines changed

clang/include/clang/Frontend/ASTUnit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class ASTUnit : public ModuleLoader {
7575
IntrusiveRefCntPtr<TargetOptions> TargetOpts;
7676
IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts;
7777
ASTReader *Reader;
78+
bool HadModuleLoaderFatalFailure;
7879

7980
struct ASTWriterData;
8081
OwningPtr<ASTWriterData> WriterData;

clang/include/clang/Frontend/CompilerInstance.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,10 @@ class CompilerInstance : public ModuleLoader {
664664
SourceLocation ImportLoc,
665665
bool Complain);
666666

667+
bool hadModuleLoaderFatalFailure() const {
668+
return ModuleLoader::HadFatalFailure;
669+
}
670+
667671
};
668672

669673
} // end namespace clang

clang/include/clang/Lex/ModuleLoader.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class ModuleLoadResult {
5454
/// then loading that module.
5555
class ModuleLoader {
5656
public:
57+
ModuleLoader() : HadFatalFailure(false) {}
58+
5759
virtual ~ModuleLoader();
5860

5961
/// \brief Attempt to load the given module.
@@ -85,6 +87,8 @@ class ModuleLoader {
8587
Module::NameVisibilityKind Visibility,
8688
SourceLocation ImportLoc,
8789
bool Complain) = 0;
90+
91+
bool HadFatalFailure;
8892
};
8993

9094
}

clang/include/clang/Lex/Preprocessor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,10 @@ class Preprocessor : public RefCountedBase<Preprocessor> {
457457
/// \brief Retrieve the module loader associated with this preprocessor.
458458
ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
459459

460+
bool hadModuleLoaderFatalFailure() const {
461+
return TheModuleLoader.HadFatalFailure;
462+
}
463+
460464
/// \brief True if we are currently preprocessing a #if or #elif directive
461465
bool isParsingIfOrElifDirective() const {
462466
return ParsingIfOrElifDirective;

clang/include/clang/Parse/Parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,8 @@ class Parser : public CodeCompletionHandler {
398398
/// \brief Abruptly cut off parsing; mainly used when we have reached the
399399
/// code-completion point.
400400
void cutOffParsing() {
401-
PP.setCodeCompletionReached();
401+
if (PP.isCodeCompletionEnabled())
402+
PP.setCodeCompletionReached();
402403
// Cut off parsing by acting as if we reached the end-of-file.
403404
Tok.setKind(tok::eof);
404405
}

clang/include/clang/Serialization/ASTReader.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ class ASTReader
309309
/// \brief The module manager which manages modules and their dependencies
310310
ModuleManager ModuleMgr;
311311

312+
/// \brief The location where the module file will be considered as
313+
/// imported from. For non-module AST types it should be invalid.
314+
SourceLocation CurrentImportLoc;
315+
312316
/// \brief The global module index, if loaded.
313317
llvm::OwningPtr<GlobalModuleIndex> GlobalIndex;
314318

clang/lib/Frontend/ASTUnit.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ const unsigned DefaultPreambleRebuildInterval = 5;
216216
static llvm::sys::cas_flag ActiveASTUnitObjects;
217217

218218
ASTUnit::ASTUnit(bool _MainFileIsAST)
219-
: Reader(0), OnlyLocalDecls(false), CaptureDiagnostics(false),
219+
: Reader(0), HadModuleLoaderFatalFailure(false),
220+
OnlyLocalDecls(false), CaptureDiagnostics(false),
220221
MainFileIsAST(_MainFileIsAST),
221222
TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
222223
OwnsRemappedFileBuffers(true),
@@ -1705,6 +1706,7 @@ void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) {
17051706
CI.setFileManager(0);
17061707
Target = &CI.getTarget();
17071708
Reader = CI.getModuleManager();
1709+
HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
17081710
}
17091711

17101712
StringRef ASTUnit::getMainFileName() const {
@@ -2504,6 +2506,9 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
25042506
}
25052507

25062508
bool ASTUnit::Save(StringRef File) {
2509+
if (HadModuleLoaderFatalFailure)
2510+
return true;
2511+
25072512
// Write to a temporary file and later rename it to the actual file, to avoid
25082513
// possible race conditions.
25092514
SmallString<128> TempPath;

clang/lib/Frontend/CompilerInstance.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,12 +1247,14 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
12471247
case ASTReader::VersionMismatch:
12481248
case ASTReader::ConfigurationMismatch:
12491249
case ASTReader::HadErrors:
1250+
ModuleLoader::HadFatalFailure = true;
12501251
// FIXME: The ASTReader will already have complained, but can we showhorn
12511252
// that diagnostic information into a more useful form?
12521253
KnownModules[Path[0].first] = 0;
12531254
return ModuleLoadResult();
12541255

12551256
case ASTReader::Failure:
1257+
ModuleLoader::HadFatalFailure = true;
12561258
// Already complained, but note now that we failed.
12571259
KnownModules[Path[0].first] = 0;
12581260
ModuleBuildFailed = true;

clang/lib/Lex/Lexer.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3426,6 +3426,12 @@ void Lexer::LexTokenInternal(Token &Result) {
34263426
FormTokenWithChars(Result, CurPtr, tok::hash);
34273427
PP->HandleDirective(Result);
34283428

3429+
if (PP->hadModuleLoaderFatalFailure()) {
3430+
// With a fatal failure in the module loader, we abort parsing.
3431+
assert(Result.is(tok::eof) && "Preprocessor did not set tok:eof");
3432+
return;
3433+
}
3434+
34293435
// As an optimization, if the preprocessor didn't switch lexers, tail
34303436
// recurse.
34313437
if (PP->isCurrentLexer(this)) {

clang/lib/Lex/PPDirectives.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,20 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
15121512
/*IsIncludeDirective=*/true);
15131513
assert((Imported == 0 || Imported == SuggestedModule) &&
15141514
"the imported module is different than the suggested one");
1515+
1516+
if (!Imported && hadModuleLoaderFatalFailure()) {
1517+
// With a fatal failure in the module loader, we abort parsing.
1518+
Token &Result = IncludeTok;
1519+
if (CurLexer) {
1520+
Result.startToken();
1521+
CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
1522+
CurLexer->cutOffLexing();
1523+
} else {
1524+
assert(CurPTHLexer && "#include but no current lexer set!");
1525+
CurPTHLexer->getEOF(Result);
1526+
}
1527+
return;
1528+
}
15151529

15161530
// If this header isn't part of the module we're building, we're done.
15171531
if (!BuildingImportedModule && Imported) {

0 commit comments

Comments
 (0)