]> granicus.if.org Git - clang/commitdiff
[modules] If we're given a module file, via -fmodule-file=, for a module, but
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 5 Nov 2015 00:54:55 +0000 (00:54 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 5 Nov 2015 00:54:55 +0000 (00:54 +0000)
we can't load that file due to a configuration mismatch, and implicit module
building is disabled, and the user turns off the error-by-default warning for
that situation, then fall back to textual inclusion for the module rather than
giving an error if any of its headers are included.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@252114 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Module.h
lib/Basic/Module.cpp
lib/Frontend/CompilerInstance.cpp
lib/Serialization/ASTReader.cpp
test/Modules/merge-target-features.cpp

index cb3341026fa4975e6d588091e1ed9cc4cd41eb22..fa032e9eb6695197cacfe936a569918aa45cc3f8 100644 (file)
@@ -152,6 +152,9 @@ public:
   /// \brief Whether this module is missing a feature from \c Requirements.
   unsigned IsMissingRequirement : 1;
 
+  /// \brief Whether we tried and failed to load a module file for this module.
+  unsigned HasIncompatibleModuleFile : 1;
+
   /// \brief Whether this module is available in the current translation unit.
   ///
   /// If the module is missing headers or does not meet all requirements then
index 4188cefc8498f613fa1f7d0c09a5584f275c3b99..0b7832636943988c3239ef1737ca4b6d8d00331f 100644 (file)
@@ -28,11 +28,12 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
                bool IsFramework, bool IsExplicit, unsigned VisibilityID)
     : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(),
       Umbrella(), Signature(0), ASTFile(nullptr), VisibilityID(VisibilityID),
-      IsMissingRequirement(false), IsAvailable(true), IsFromModuleFile(false),
-      IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false),
-      IsExternC(false), IsInferred(false), InferSubmodules(false),
-      InferExplicitSubmodules(false), InferExportWildcard(false),
-      ConfigMacrosExhaustive(false), NameVisibility(Hidden) {
+      IsMissingRequirement(false), HasIncompatibleModuleFile(false),
+      IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework),
+      IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
+      IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
+      InferExportWildcard(false), ConfigMacrosExhaustive(false),
+      NameVisibility(Hidden) {
   if (Parent) {
     if (!Parent->isAvailable())
       IsAvailable = false;
index c3f19a3a00d375021044a55dbc7c42a7537fc89d..c0cf64cecbe802176650a92adf158392341ee09c 100644 (file)
@@ -1327,6 +1327,17 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
       }
       LoadedModules.clear();
     }
+
+    void markAllUnavailable() {
+      for (auto *II : LoadedModules) {
+        if (Module *M = CI.getPreprocessor()
+                            .getHeaderSearchInfo()
+                            .getModuleMap()
+                            .findModule(II->getName()))
+          M->HasIncompatibleModuleFile = true;
+      }
+      LoadedModules.clear();
+    }
   };
 
   // If we don't already have an ASTReader, create one now.
@@ -1343,15 +1354,18 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) {
                                  SourceLocation(),
                                  ASTReader::ARR_ConfigurationMismatch)) {
   case ASTReader::Success:
-  // We successfully loaded the module file; remember the set of provided
-  // modules so that we don't try to load implicit modules for them.
-  ListenerRef.registerAll();
-  return true;
+    // We successfully loaded the module file; remember the set of provided
+    // modules so that we don't try to load implicit modules for them.
+    ListenerRef.registerAll();
+    return true;
 
   case ASTReader::ConfigurationMismatch:
     // Ignore unusable module files.
     getDiagnostics().Report(SourceLocation(), diag::warn_module_config_mismatch)
         << FileName;
+    // All modules provided by any files we tried and failed to load are now
+    // unavailable; includes of those modules should now be handled textually.
+    ListenerRef.markAllUnavailable();
     return true;
 
   default:
@@ -1407,6 +1421,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
     std::string ModuleFileName =
         PP->getHeaderSearchInfo().getModuleFileName(Module);
     if (ModuleFileName.empty()) {
+      if (Module->HasIncompatibleModuleFile) {
+        // We tried and failed to load a module file for this module. Fall
+        // back to textual inclusion for its headers.
+        return ModuleLoadResult(nullptr, /*missingExpected*/true);
+      }
+
       getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
           << ModuleName;
       ModuleBuildFailed = true;
index b7b56f68b81405629241b47c15b77d1ce40f9a5d..32656037921054b768c65ba620309ca720d7ff7c 100644 (file)
@@ -2151,6 +2151,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
                             const ModuleFile *ImportedBy,
                             unsigned ClientLoadCapabilities) {
   BitstreamCursor &Stream = F.Stream;
+  ASTReadResult Result = Success;
 
   if (Stream.EnterSubBlock(CONTROL_BLOCK_ID)) {
     Error("malformed block record in AST file");
@@ -2211,7 +2212,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
         }
       }
 
-      return Success;
+      return Result;
     }
 
     case llvm::BitstreamEntry::SubBlock:
@@ -2239,16 +2240,21 @@ ASTReader::ReadControlBlock(ModuleFile &F,
           bool AllowCompatibleConfigurationMismatch =
               F.Kind == MK_ExplicitModule;
 
-          auto Result = ReadOptionsBlock(Stream, ClientLoadCapabilities,
-                                         AllowCompatibleConfigurationMismatch,
-                                         *Listener, SuggestedPredefines);
+          Result = ReadOptionsBlock(Stream, ClientLoadCapabilities,
+                                    AllowCompatibleConfigurationMismatch,
+                                    *Listener, SuggestedPredefines);
           if (Result == Failure) {
             Error("malformed block record in AST file");
             return Result;
           }
 
-          if (!DisableValidation && Result != Success &&
-              (Result != ConfigurationMismatch || !AllowConfigurationMismatch))
+          if (DisableValidation ||
+              (AllowConfigurationMismatch && Result == ConfigurationMismatch))
+            Result = Success;
+
+          // If we've diagnosed a problem, we're done.
+          if (Result != Success &&
+              isDiagnosedResult(Result, ClientLoadCapabilities))
             return Result;
         } else if (Stream.SkipBlock()) {
           Error("malformed block record in AST file");
index 0ca5679ad160c663e0bc03201dbd612f5b499ff5..9ca0539e6a22ed15414da9d9a9d8abcc33917fd6 100644 (file)
@@ -20,7 +20,9 @@
 // RUN:   -target-cpu i386 \
 // RUN:   -fsyntax-only merge-target-features.cpp 2>&1 \
 // RUN:   | FileCheck --check-prefix=SUBSET %s
+// SUBSET-NOT: error:
 // SUBSET: error: {{.*}} configuration mismatch
+// SUBSET-NOT: error:
 //
 // RUN: %clang_cc1 -fmodules -x c++ -fmodules-cache-path=%t \
 // RUN:   -iquote Inputs/merge-target-features \
@@ -56,7 +58,9 @@
 // RUN:   -target-cpu i386 -target-feature +cx16 \
 // RUN:   -fsyntax-only merge-target-features.cpp 2>&1 \
 // RUN:   | FileCheck --check-prefix=MISMATCH %s
+// MISMATCH-NOT: error:
 // MISMATCH: error: {{.*}} configuration mismatch
+// MISMATCH-NOT: error:
 
 #include "foo.h"