]> granicus.if.org Git - clang/commitdiff
Factor out and unify emission of "module is unavailable" diagnostics.
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 5 Jun 2017 18:57:56 +0000 (18:57 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 5 Jun 2017 18:57:56 +0000 (18:57 +0000)
Inspired by post-commit review of r304190.

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

include/clang/Basic/DiagnosticFrontendKinds.td
include/clang/Lex/Preprocessor.h
lib/Frontend/CompilerInstance.cpp
lib/Frontend/FrontendAction.cpp
lib/Lex/PPDirectives.cpp
lib/Lex/Pragma.cpp
test/Modules/requires-coroutines.mm
test/Modules/requires-gnuinlineasm.m
test/Modules/requires.m
test/Modules/requires.mm

index 1267f8d09f58ad7c9b0bc14156c2a40074241470..8b4cb47e545d939e019bb9f23b532c7439735bf5 100644 (file)
@@ -196,6 +196,7 @@ def err_no_submodule_suggest : Error<
   "no submodule named %0 in module '%1'; did you mean '%2'?">;
 def warn_missing_submodule : Warning<"missing submodule '%0'">,
   InGroup<IncompleteUmbrella>;
+def note_module_import_here : Note<"module imported here">;
 def err_module_cannot_create_includes : Error<
   "cannot create includes file for module %0: %1">;
 def warn_module_config_macro_undef : Warning<
index aeca83a90716f1a719cbbf019baf55465deb77aa..7958cd0e1a48995fe3472f59391a57f62a6530dd 100644 (file)
@@ -1954,6 +1954,13 @@ private:
   void HandleMicrosoftImportDirective(Token &Tok);
 
 public:
+  /// Check that the given module is available, producing a diagnostic if not.
+  /// \return \c true if the check failed (because the module is not available).
+  ///         \c false if the module appears to be usable.
+  static bool checkModuleIsAvailable(const LangOptions &LangOpts,
+                                     const TargetInfo &TargetInfo,
+                                     DiagnosticsEngine &Diags, Module *M);
+
   // Module inclusion testing.
   /// \brief Find the module that owns the source or header file that
   /// \p Loc points to. If the location is in a file that was included
index e92672a785daf121fa92f28ba98e5fa989d0735c..3e390c96e11d95125bc6ea946188b009697a9100 100644 (file)
@@ -1824,20 +1824,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
     }
 
     // Check whether this module is available.
-    clang::Module::Requirement Requirement;
-    clang::Module::UnresolvedHeaderDirective MissingHeader;
-    if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement,
-                             MissingHeader)) {
-      if (MissingHeader.FileNameLoc.isValid()) {
-        getDiagnostics().Report(MissingHeader.FileNameLoc,
-                                diag::err_module_header_missing)
-          << MissingHeader.IsUmbrella << MissingHeader.FileName;
-      } else {
-        getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
-          << Module->getFullModuleName()
-          << Requirement.second << Requirement.first
-          << SourceRange(Path.front().second, Path.back().second);
-      }
+    if (Preprocessor::checkModuleIsAvailable(getLangOpts(), getTarget(),
+                                             getDiagnostics(), Module)) {
+      getDiagnostics().Report(ImportLoc, diag::note_module_import_here)
+        << SourceRange(Path.front().second, Path.back().second);
       LastModuleImportLoc = ImportLoc;
       LastModuleImportResult = ModuleLoadResult();
       return ModuleLoadResult();
index ef98172b55ba5d7e107f69a4ec488609aa0dc7a8..2de8f06e7122f0219835a914b6b5bdae85cde316 100644 (file)
@@ -443,21 +443,9 @@ static Module *prepareToBuildModule(CompilerInstance &CI,
   }
 
   // Check whether we can build this module at all.
-  clang::Module::Requirement Requirement;
-  clang::Module::UnresolvedHeaderDirective MissingHeader;
-  if (!M->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
-                      MissingHeader)) {
-    if (MissingHeader.FileNameLoc.isValid()) {
-      CI.getDiagnostics().Report(MissingHeader.FileNameLoc,
-                                 diag::err_module_header_missing)
-        << MissingHeader.IsUmbrella << MissingHeader.FileName;
-    } else {
-      CI.getDiagnostics().Report(diag::err_module_unavailable)
-        << M->getFullModuleName() << Requirement.second << Requirement.first;
-    }
-
+  if (Preprocessor::checkModuleIsAvailable(CI.getLangOpts(), CI.getTarget(),
+                                           CI.getDiagnostics(), M))
     return nullptr;
-  }
 
   // Inform the preprocessor that includes from within the input buffer should
   // be resolved relative to the build directory of the module map file.
index 2d3ad690987eb86fe19bc5c249e643363c75615a..b2c3c2e707653ec5c42c1d4776b948e487f2fd4a 100644 (file)
@@ -1654,6 +1654,26 @@ static bool trySimplifyPath(SmallVectorImpl<StringRef> &Components,
   return SuggestReplacement;
 }
 
+bool Preprocessor::checkModuleIsAvailable(const LangOptions &LangOpts,
+                                          const TargetInfo &TargetInfo,
+                                          DiagnosticsEngine &Diags, Module *M) {
+  Module::Requirement Requirement;
+  Module::UnresolvedHeaderDirective MissingHeader;
+  if (M->isAvailable(LangOpts, TargetInfo, Requirement, MissingHeader))
+    return false;
+
+  if (MissingHeader.FileNameLoc.isValid()) {
+    Diags.Report(MissingHeader.FileNameLoc, diag::err_module_header_missing)
+        << MissingHeader.IsUmbrella << MissingHeader.FileName;
+  } else {
+    // FIXME: Track the location at which the requirement was specified, and
+    // use it here.
+    Diags.Report(M->DefinitionLoc, diag::err_module_unavailable)
+        << M->getFullModuleName() << Requirement.second << Requirement.first;
+  }
+  return true;
+}
+
 /// HandleIncludeDirective - The "\#include" tokens have just been read, read
 /// the file to be included from the lexer, then include it!  This is a common
 /// routine with functionality shared between \#include, \#include_next and
@@ -1835,23 +1855,11 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
     // unavailable, diagnose the situation and bail out.
     // FIXME: Remove this; loadModule does the same check (but produces
     // slightly worse diagnostics).
-    if (!SuggestedModule.getModule()->isAvailable()) {
-      Module::Requirement Requirement;
-      Module::UnresolvedHeaderDirective MissingHeader;
-      Module *M = SuggestedModule.getModule();
-      // Identify the cause.
-      (void)M->isAvailable(getLangOpts(), getTargetInfo(), Requirement,
-                           MissingHeader);
-      if (MissingHeader.FileNameLoc.isValid()) {
-        Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing)
-            << MissingHeader.IsUmbrella << MissingHeader.FileName;
-      } else {
-        Diag(M->DefinitionLoc, diag::err_module_unavailable)
-            << M->getFullModuleName() << Requirement.second << Requirement.first;
-      }
+    if (checkModuleIsAvailable(getLangOpts(), getTargetInfo(), getDiagnostics(),
+                               SuggestedModule.getModule())) {
       Diag(FilenameTok.getLocation(),
            diag::note_implicit_top_level_module_import_here)
-          << M->getTopLevelModuleName();
+          << SuggestedModule.getModule()->getTopLevelModuleName();
       return;
     }
 
index e1d981527bec570cf105404a15503b87b1ae171d..dd52abd74f5181c9b65d092854cf27970534e970 100644 (file)
@@ -1408,18 +1408,8 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
     }
 
     // If the module isn't available, it doesn't make sense to enter it.
-    if (!M->isAvailable()) {
-      Module::Requirement Requirement;
-      Module::UnresolvedHeaderDirective MissingHeader;
-      (void)M->isAvailable(PP.getLangOpts(), PP.getTargetInfo(),
-                           Requirement, MissingHeader);
-      if (MissingHeader.FileNameLoc.isValid()) {
-        PP.Diag(MissingHeader.FileNameLoc, diag::err_module_header_missing)
-          << MissingHeader.IsUmbrella << MissingHeader.FileName;
-      } else {
-        PP.Diag(M->DefinitionLoc, diag::err_module_unavailable)
-          << M->getFullModuleName() << Requirement.second << Requirement.first;
-      }
+    if (Preprocessor::checkModuleIsAvailable(
+            PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics(), M)) {
       PP.Diag(BeginLoc, diag::note_pp_module_begin_here)
         << M->getTopLevelModuleName();
       return;
index d3519cd2bba75789cfe68bdc3551960b41715d13..8e25a3c575211ab6637082cb1532103219a525f3 100644 (file)
@@ -1,12 +1,13 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -fcoroutines-ts -DCOROUTINES
-
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify
+// RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify -fcoroutines-ts -DCOROUTINES
 
 #ifdef COROUTINES
 @import DependsOnModule.Coroutines;
-@import DependsOnModule.NotCoroutines; // expected-error {{module 'DependsOnModule.NotCoroutines' is incompatible with feature 'coroutines'}}
+// expected-error@module.map:29 {{module 'DependsOnModule.NotCoroutines' is incompatible with feature 'coroutines'}}
+@import DependsOnModule.NotCoroutines; // expected-note {{module imported here}}
 #else
 @import DependsOnModule.NotCoroutines;
-@import DependsOnModule.Coroutines; // expected-error {{module 'DependsOnModule.Coroutines' requires feature 'coroutines'}}
+// expected-error@module.map:25 {{module 'DependsOnModule.Coroutines' requires feature 'coroutines'}}
+@import DependsOnModule.Coroutines; // expected-note {{module imported here}}
 #endif
index 80b1b18d0742fb500f8c23d633bc68900e8b3ef1..e710b6bf8d4b500a010abf2f7c5af52f617d75ad 100644 (file)
@@ -1,6 +1,7 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules \
 // RUN:     -fimplicit-module-maps -F %S/Inputs/GNUAsm %s \
+// RUN:     -I %S/Inputs/GNUAsm \
 // RUN:     -fno-gnu-inline-asm -DNO_ASM_INLINE -verify
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules-cache-path=%t -fmodules \
@@ -8,7 +9,8 @@
 // RUN:     -DASM_INLINE -verify
 
 #ifdef NO_ASM_INLINE
-@import NeedsGNUInlineAsm.Asm; // expected-error{{module 'NeedsGNUInlineAsm.Asm' requires feature 'gnuinlineasm'}}
+// expected-error@NeedsGNUInlineAsm.framework/module.map:4 {{module 'NeedsGNUInlineAsm.Asm' requires feature 'gnuinlineasm'}}
+@import NeedsGNUInlineAsm.Asm; // expected-note {{module imported here}}
 #endif
 
 #ifdef ASM_INLINE
index 1a013727108b74050baa34864aacfa433f453227..d61de6bd48d0ecc346ac59cb6e6a70a9ecf6a46f 100644 (file)
@@ -1,12 +1,17 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify -fmodule-feature custom_req1
+// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs %s -verify -fmodule-feature custom_req1
 
-@import DependsOnModule.CXX; // expected-error{{module 'DependsOnModule.CXX' requires feature 'cplusplus'}}
+// expected-error@DependsOnModule.framework/module.map:7 {{module 'DependsOnModule.CXX' requires feature 'cplusplus'}}
+@import DependsOnModule.CXX; // expected-note {{module imported here}}
 @import DependsOnModule.NotCXX;
-@import DependsOnModule.NotObjC; // expected-error{{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}}
+// expected-error@DependsOnModule.framework/module.map:15 {{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}}
+@import DependsOnModule.NotObjC; // expected-note {{module imported here}}
 @import DependsOnModule.CustomReq1; // OK
-@import DependsOnModule.CustomReq2; // expected-error{{module 'DependsOnModule.CustomReq2' requires feature 'custom_req2'}}
+// expected-error@DependsOnModule.framework/module.map:22 {{module 'DependsOnModule.CustomReq2' requires feature 'custom_req2'}}
+@import DependsOnModule.CustomReq2; // expected-note {{module imported here}}
 
 @import RequiresWithMissingHeader; // OK
-@import RequiresWithMissingHeader.HeaderBefore; // expected-error{{module 'RequiresWithMissingHeader.HeaderBefore' requires feature 'missing'}}
-@import RequiresWithMissingHeader.HeaderAfter; // expected-error{{module 'RequiresWithMissingHeader.HeaderAfter' requires feature 'missing'}}
+// expected-error@module.map:* {{module 'RequiresWithMissingHeader.HeaderBefore' requires feature 'missing'}}
+@import RequiresWithMissingHeader.HeaderBefore; // expected-note {{module imported here}}
+// expected-error@module.map:* {{module 'RequiresWithMissingHeader.HeaderAfter' requires feature 'missing'}}
+@import RequiresWithMissingHeader.HeaderAfter; // expected-note {{module imported here}}
index cc64a500bd5789dc753574b98dbd17cb7a1606b2..f90622ece842afaf56a448373fc434e01a43f939 100644 (file)
@@ -1,6 +1,8 @@
 // RUN: rm -rf %t
-// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs %s -verify
+// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -F %S/Inputs -I %S/Inputs/DependsOnModule.framework %s -verify
 
 @import DependsOnModule.CXX;
-@import DependsOnModule.NotCXX; // expected-error{{module 'DependsOnModule.NotCXX' is incompatible with feature 'cplusplus'}}
-@import DependsOnModule.NotObjC; // expected-error{{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}}
+// expected-error@module.map:11 {{module 'DependsOnModule.NotCXX' is incompatible with feature 'cplusplus'}}
+@import DependsOnModule.NotCXX; // expected-note {{module imported here}}
+// expected-error@module.map:15 {{module 'DependsOnModule.NotObjC' is incompatible with feature 'objc'}}
+@import DependsOnModule.NotObjC; // expected-note {{module imported here}}