r182629 - [modules] If we hit a failure while loading a PCH/module, abort parsing instead of trying to continue in an invalid state.

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu May 23 22:44:09 PDT 2013


Author: akirtzidis
Date: Fri May 24 00:44:08 2013
New Revision: 182629

URL: http://llvm.org/viewvc/llvm-project?rev=182629&view=rev
Log:
[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

Added:
    cfe/trunk/test/Modules/fatal-module-loader-error.m
Modified:
    cfe/trunk/include/clang/Frontend/ASTUnit.h
    cfe/trunk/include/clang/Frontend/CompilerInstance.h
    cfe/trunk/include/clang/Lex/ModuleLoader.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Frontend/CompilerInstance.cpp
    cfe/trunk/lib/Lex/Lexer.cpp
    cfe/trunk/lib/Lex/PPDirectives.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp

Modified: cfe/trunk/include/clang/Frontend/ASTUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTUnit.h?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTUnit.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTUnit.h Fri May 24 00:44:08 2013
@@ -75,6 +75,7 @@ private:
   IntrusiveRefCntPtr<TargetOptions>       TargetOpts;
   IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts;
   ASTReader *Reader;
+  bool HadModuleLoaderFatalFailure;
 
   struct ASTWriterData;
   OwningPtr<ASTWriterData> WriterData;

Modified: cfe/trunk/include/clang/Frontend/CompilerInstance.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/CompilerInstance.h?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/CompilerInstance.h (original)
+++ cfe/trunk/include/clang/Frontend/CompilerInstance.h Fri May 24 00:44:08 2013
@@ -664,6 +664,10 @@ public:
                                  SourceLocation ImportLoc,
                                  bool Complain);
 
+  bool hadModuleLoaderFatalFailure() const {
+    return ModuleLoader::HadFatalFailure;
+  }
+
 };
 
 } // end namespace clang

Modified: cfe/trunk/include/clang/Lex/ModuleLoader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleLoader.h?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleLoader.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleLoader.h Fri May 24 00:44:08 2013
@@ -54,6 +54,8 @@ public:
 /// then loading that module.
 class ModuleLoader {
 public:
+  ModuleLoader() : HadFatalFailure(false) {}
+
   virtual ~ModuleLoader();
   
   /// \brief Attempt to load the given module.
@@ -85,6 +87,8 @@ public:
                                  Module::NameVisibilityKind Visibility,
                                  SourceLocation ImportLoc,
                                  bool Complain) = 0;
+
+  bool HadFatalFailure;
 };
   
 }

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Fri May 24 00:44:08 2013
@@ -457,6 +457,10 @@ public:
   /// \brief Retrieve the module loader associated with this preprocessor.
   ModuleLoader &getModuleLoader() const { return TheModuleLoader; }
 
+  bool hadModuleLoaderFatalFailure() const {
+    return TheModuleLoader.HadFatalFailure;
+  }
+
   /// \brief True if we are currently preprocessing a #if or #elif directive
   bool isParsingIfOrElifDirective() const { 
     return ParsingIfOrElifDirective;

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri May 24 00:44:08 2013
@@ -398,7 +398,8 @@ private:
   /// \brief Abruptly cut off parsing; mainly used when we have reached the
   /// code-completion point.
   void cutOffParsing() {
-    PP.setCodeCompletionReached();
+    if (PP.isCodeCompletionEnabled())
+      PP.setCodeCompletionReached();
     // Cut off parsing by acting as if we reached the end-of-file.
     Tok.setKind(tok::eof);
   }

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri May 24 00:44:08 2013
@@ -309,6 +309,10 @@ private:
   /// \brief The module manager which manages modules and their dependencies
   ModuleManager ModuleMgr;
 
+  /// \brief The location where the module file will be considered as
+  /// imported from. For non-module AST types it should be invalid.
+  SourceLocation CurrentImportLoc;
+
   /// \brief The global module index, if loaded.
   llvm::OwningPtr<GlobalModuleIndex> GlobalIndex;
 

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Fri May 24 00:44:08 2013
@@ -216,7 +216,8 @@ const unsigned DefaultPreambleRebuildInt
 static llvm::sys::cas_flag ActiveASTUnitObjects;
 
 ASTUnit::ASTUnit(bool _MainFileIsAST)
-  : Reader(0), OnlyLocalDecls(false), CaptureDiagnostics(false),
+  : Reader(0), HadModuleLoaderFatalFailure(false),
+    OnlyLocalDecls(false), CaptureDiagnostics(false),
     MainFileIsAST(_MainFileIsAST), 
     TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
     OwnsRemappedFileBuffers(true),
@@ -1705,6 +1706,7 @@ void ASTUnit::transferASTDataFromCompile
   CI.setFileManager(0);
   Target = &CI.getTarget();
   Reader = CI.getModuleManager();
+  HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure();
 }
 
 StringRef ASTUnit::getMainFileName() const {
@@ -2504,6 +2506,9 @@ void ASTUnit::CodeComplete(StringRef Fil
 }
 
 bool ASTUnit::Save(StringRef File) {
+  if (HadModuleLoaderFatalFailure)
+    return true;
+
   // Write to a temporary file and later rename it to the actual file, to avoid
   // possible race conditions.
   SmallString<128> TempPath;

Modified: cfe/trunk/lib/Frontend/CompilerInstance.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInstance.cpp?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInstance.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInstance.cpp Fri May 24 00:44:08 2013
@@ -1247,12 +1247,14 @@ CompilerInstance::loadModule(SourceLocat
     case ASTReader::VersionMismatch:
     case ASTReader::ConfigurationMismatch:
     case ASTReader::HadErrors:
+      ModuleLoader::HadFatalFailure = true;
       // FIXME: The ASTReader will already have complained, but can we showhorn
       // that diagnostic information into a more useful form?
       KnownModules[Path[0].first] = 0;
       return ModuleLoadResult();
 
     case ASTReader::Failure:
+      ModuleLoader::HadFatalFailure = true;
       // Already complained, but note now that we failed.
       KnownModules[Path[0].first] = 0;
       ModuleBuildFailed = true;

Modified: cfe/trunk/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Lexer.cpp (original)
+++ cfe/trunk/lib/Lex/Lexer.cpp Fri May 24 00:44:08 2013
@@ -3426,6 +3426,12 @@ HandleDirective:
   FormTokenWithChars(Result, CurPtr, tok::hash);
   PP->HandleDirective(Result);
 
+  if (PP->hadModuleLoaderFatalFailure()) {
+    // With a fatal failure in the module loader, we abort parsing.
+    assert(Result.is(tok::eof) && "Preprocessor did not set tok:eof");
+    return;
+  }
+
   // As an optimization, if the preprocessor didn't switch lexers, tail
   // recurse.
   if (PP->isCurrentLexer(this)) {

Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Fri May 24 00:44:08 2013
@@ -1512,6 +1512,20 @@ void Preprocessor::HandleIncludeDirectiv
                                    /*IsIncludeDirective=*/true);
     assert((Imported == 0 || Imported == SuggestedModule) &&
            "the imported module is different than the suggested one");
+
+    if (!Imported && hadModuleLoaderFatalFailure()) {
+      // With a fatal failure in the module loader, we abort parsing.
+      Token &Result = IncludeTok;
+      if (CurLexer) {
+        Result.startToken();
+        CurLexer->FormTokenWithChars(Result, CurLexer->BufferEnd, tok::eof);
+        CurLexer->cutOffLexing();
+      } else {
+        assert(CurPTHLexer && "#include but no current lexer set!");
+        CurPTHLexer->getEOF(Result);
+      }
+      return;
+    }
     
     // If this header isn't part of the module we're building, we're done.
     if (!BuildingImportedModule && Imported) {

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri May 24 00:44:08 2013
@@ -1884,7 +1884,13 @@ Parser::DeclGroupPtrTy Parser::ParseModu
     
     break;
   } while (true);
-  
+
+  if (PP.hadModuleLoaderFatalFailure()) {
+    // With a fatal failure in the module loader, we abort parsing.
+    cutOffParsing();
+    return DeclGroupPtrTy();
+  }
+
   DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path);
   ExpectAndConsumeSemi(diag::err_module_expected_semi);
   if (Import.isInvalid())

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=182629&r1=182628&r2=182629&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri May 24 00:44:08 2013
@@ -2900,6 +2900,9 @@ ASTReader::ASTReadResult ASTReader::Read
                                             ModuleKind Type,
                                             SourceLocation ImportLoc,
                                             unsigned ClientLoadCapabilities) {
+  llvm::SaveAndRestore<SourceLocation>
+    SetCurImportLocRAII(CurrentImportLoc, ImportLoc);
+
   // Bump the generation number.
   unsigned PreviousGeneration = CurrentGeneration++;
 
@@ -7167,7 +7170,7 @@ CXXTemporary *ASTReader::ReadCXXTemporar
 }
 
 DiagnosticBuilder ASTReader::Diag(unsigned DiagID) {
-  return Diag(SourceLocation(), DiagID);
+  return Diag(CurrentImportLoc, DiagID);
 }
 
 DiagnosticBuilder ASTReader::Diag(SourceLocation Loc, unsigned DiagID) {

Added: cfe/trunk/test/Modules/fatal-module-loader-error.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/fatal-module-loader-error.m?rev=182629&view=auto
==============================================================================
--- cfe/trunk/test/Modules/fatal-module-loader-error.m (added)
+++ cfe/trunk/test/Modules/fatal-module-loader-error.m Fri May 24 00:44:08 2013
@@ -0,0 +1,26 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: touch %t/Module.pcm
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t %s -fdisable-module-hash -F %S/Inputs -verify
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t %s -fdisable-module-hash -F %S/Inputs -DIMPLICIT -verify
+
+// This tests that after a fatal module loader error, we do not continue parsing.
+
+#ifdef IMPLICIT
+
+// expected-error at +1{{does not appear to be}}
+#import <Module/Module.h>
+#pragma clang __debug crash;
+
+#else
+
+// expected-error at +1{{does not appear to be}}
+ at import Module;
+#pragma clang __debug crash;
+
+#endif
+
+// Also check that libclang does not create a PCH with such an error.
+// RUN: c-index-test -write-pch %t.pch -fmodules -fmodules-cache-path=%t %s \
+// RUN:    -Xclang -fdisable-module-hash -F %S/Inputs 2>&1 | Filecheck %s
+// CHECK: Unable to write PCH file





More information about the cfe-commits mailing list