r267802 - [modules] When diagnosing a missing module import, suggest adding a #include if

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 27 14:57:06 PDT 2016


Author: rsmith
Date: Wed Apr 27 16:57:05 2016
New Revision: 267802

URL: http://llvm.org/viewvc/llvm-project?rev=267802&view=rev
Log:
[modules] When diagnosing a missing module import, suggest adding a #include if
the current language doesn't have an import syntax and we can figure out a
suitable file to include.

Added:
    cfe/trunk/test/Modules/Inputs/suggest-include/
    cfe/trunk/test/Modules/Inputs/suggest-include/empty.h
    cfe/trunk/test/Modules/Inputs/suggest-include/module.modulemap
    cfe/trunk/test/Modules/Inputs/suggest-include/private1.h
    cfe/trunk/test/Modules/Inputs/suggest-include/private2.h
    cfe/trunk/test/Modules/Inputs/suggest-include/private3.h
    cfe/trunk/test/Modules/Inputs/suggest-include/textual1.h
    cfe/trunk/test/Modules/Inputs/suggest-include/textual2.h
    cfe/trunk/test/Modules/Inputs/suggest-include/textual3.h
    cfe/trunk/test/Modules/Inputs/suggest-include/textual4.h
    cfe/trunk/test/Modules/Inputs/suggest-include/textual5.h
    cfe/trunk/test/Modules/Inputs/suggest-include/useprivate1.h
    cfe/trunk/test/Modules/Inputs/suggest-include/useprivate3.h
    cfe/trunk/test/Modules/Inputs/suggest-include/usetextual1.h
    cfe/trunk/test/Modules/Inputs/suggest-include/usetextual2.h
    cfe/trunk/test/Modules/Inputs/suggest-include/usetextual3.h
    cfe/trunk/test/Modules/Inputs/suggest-include/usetextual4.h
    cfe/trunk/test/Modules/Inputs/suggest-include/usetextual5.h
    cfe/trunk/test/Modules/suggest-include.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Lex/HeaderSearch.h
    cfe/trunk/include/clang/Lex/ModuleMap.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Lex/HeaderSearch.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/lib/Lex/PPDirectives.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 27 16:57:05 2016
@@ -8262,6 +8262,10 @@ def err_module_private_local_class : Err
 def err_module_unimported_use : Error<
   "%select{declaration|definition|default argument}0 of %1 must be imported "
   "from module '%2' before it is required">;
+def err_module_unimported_use_header : Error<
+  "missing '#include %3'; "
+  "%select{declaration|definition|default argument}0 of %1 must be imported "
+  "from module '%2' before it is required">;
 def err_module_unimported_use_multiple : Error<
   "%select{declaration|definition|default argument}0 of %1 must be imported "
   "from one of the following modules before it is required:%2">;

Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
+++ cfe/trunk/include/clang/Lex/HeaderSearch.h Wed Apr 27 16:57:05 2016
@@ -634,13 +634,18 @@ public:
   /// \brief Retrieve a uniqued framework name.
   StringRef getUniqueFrameworkName(StringRef Framework);
   
+  /// \brief Suggest a path by which the specified file could be found, for
+  /// use in diagnostics to suggest a #include.
+  ///
+  /// \param IsSystem If non-null, filled in to indicate whether the suggested
+  ///        path is relative to a system header directory.
+  std::string suggestPathToFileForDiagnostics(const FileEntry *File,
+                                              bool *IsSystem = nullptr);
+
   void PrintStats();
   
   size_t getTotalMemory() const;
 
-  static std::string NormalizeDashIncludePath(StringRef File,
-                                              FileManager &FileMgr);
-
 private:
   /// \brief Describes what happened when we tried to load a module map file.
   enum LoadModuleMapResult {

Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Wed Apr 27 16:57:05 2016
@@ -130,6 +130,12 @@ public:
       return getModule()->isAvailable();
     }
 
+    /// \brief Whether this header is accessible from the specified module.
+    bool isAccessibleFrom(Module *M) const {
+      return !(getRole() & PrivateHeader) ||
+             (M && M->getTopLevelModule() == getModule()->getTopLevelModule());
+    }
+
     // \brief Whether this known header is valid (i.e., it has an
     // associated module).
     explicit operator bool() const {

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Wed Apr 27 16:57:05 2016
@@ -1891,6 +1891,19 @@ public:
   /// directly or indirectly.
   Module *getModuleContainingLocation(SourceLocation Loc);
 
+  /// \brief We want to produce a diagnostic at location IncLoc concerning a
+  /// missing module import.
+  ///
+  /// \param IncLoc The location at which the missing import was detected.
+  /// \param MLoc A location within the desired module at which some desired
+  ///        effect occurred (eg, where a desired entity was declared).
+  ///
+  /// \return A file that can be #included to import a module containing MLoc.
+  ///         Null if no such file could be determined or if a #include is not
+  ///         appropriate.
+  const FileEntry *getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
+                                                          SourceLocation MLoc);
+
 private:
   // Macro handling.
   void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);

Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
+++ cfe/trunk/lib/Lex/HeaderSearch.cpp Wed Apr 27 16:57:05 2016
@@ -1419,3 +1419,54 @@ void HeaderSearch::loadSubdirectoryModul
 
   SearchDir.setSearchedAllModuleMaps(true);
 }
+
+std::string HeaderSearch::suggestPathToFileForDiagnostics(const FileEntry *File,
+                                                          bool *IsSystem) {
+  // FIXME: We assume that the path name currently cached in the FileEntry is
+  // the most appropriate one for this analysis (and that it's spelled the same
+  // way as the corresponding header search path).
+  const char *Name = File->getName();
+
+  unsigned BestPrefixLength = 0;
+  unsigned BestSearchDir;
+
+  for (unsigned I = 0; I != SearchDirs.size(); ++I) {
+    // FIXME: Support this search within frameworks and header maps.
+    if (!SearchDirs[I].isNormalDir())
+      continue;
+
+    const char *Dir = SearchDirs[I].getDir()->getName();
+    for (auto NI = llvm::sys::path::begin(Name),
+              NE = llvm::sys::path::end(Name),
+              DI = llvm::sys::path::begin(Dir),
+              DE = llvm::sys::path::end(Dir);
+         /*termination condition in loop*/; ++NI, ++DI) {
+      // '.' components in Name are ignored.
+      while (NI != NE && *NI == ".")
+        ++NI;
+      if (NI == NE)
+        break;
+
+      // '.' components in Dir are ignored.
+      while (DI != DE && *DI == ".")
+        ++DI;
+      if (DI == DE) {
+        // Dir is a prefix of Name, up to '.' components and choice of path
+        // separators.
+        unsigned PrefixLength = NI - llvm::sys::path::begin(Name);
+        if (PrefixLength > BestPrefixLength) {
+          BestPrefixLength = PrefixLength;
+          BestSearchDir = I;
+        }
+        break;
+      }
+
+      if (*NI != *DI)
+        break;
+    }
+  }
+
+  if (IsSystem)
+    *IsSystem = BestPrefixLength ? BestSearchDir >= SystemDirIdx : false;
+  return Name + BestPrefixLength;
+}

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Wed Apr 27 16:57:05 2016
@@ -209,29 +209,25 @@ ModuleMap::findHeaderInUmbrellaDirs(cons
 
 static bool violatesPrivateInclude(Module *RequestingModule,
                                    const FileEntry *IncFileEnt,
-                                   ModuleMap::ModuleHeaderRole Role,
-                                   Module *RequestedModule) {
-  bool IsPrivateRole = Role & ModuleMap::PrivateHeader;
+                                   ModuleMap::KnownHeader Header) {
 #ifndef NDEBUG
-  if (IsPrivateRole) {
+  if (Header.getRole() & ModuleMap::PrivateHeader) {
     // Check for consistency between the module header role
     // as obtained from the lookup and as obtained from the module.
     // This check is not cheap, so enable it only for debugging.
     bool IsPrivate = false;
     SmallVectorImpl<Module::Header> *HeaderList[] = {
-        &RequestedModule->Headers[Module::HK_Private],
-        &RequestedModule->Headers[Module::HK_PrivateTextual]};
+        &Header.getModule()->Headers[Module::HK_Private],
+        &Header.getModule()->Headers[Module::HK_PrivateTextual]};
     for (auto *Hs : HeaderList)
       IsPrivate |=
           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
             return H.Entry == IncFileEnt;
           }) != Hs->end();
-    assert((!IsPrivateRole || IsPrivate) && "inconsistent headers and roles");
+    assert(IsPrivate && "inconsistent headers and roles");
   }
 #endif
-  return IsPrivateRole && (!RequestingModule ||
-                           RequestedModule->getTopLevelModule() !=
-                               RequestingModule->getTopLevelModule());
+  return !Header.isAccessibleFrom(RequestingModule);
 }
 
 static Module *getTopLevelOrNull(Module *M) {
@@ -259,8 +255,7 @@ void ModuleMap::diagnoseHeaderInclusion(
   if (Known != Headers.end()) {
     for (const KnownHeader &Header : Known->second) {
       // Remember private headers for later printing of a diagnostic.
-      if (violatesPrivateInclude(RequestingModule, File, Header.getRole(),
-                                 Header.getModule())) {
+      if (violatesPrivateInclude(RequestingModule, File, Header)) {
         Private = Header.getModule();
         continue;
       }

Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Wed Apr 27 16:57:05 2016
@@ -597,6 +597,62 @@ Module *Preprocessor::getModuleContainin
       FullSourceLoc(Loc, SourceMgr));
 }
 
+const FileEntry *
+Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
+                                                     SourceLocation Loc) {
+  // If we have a module import syntax, we shouldn't include a header to
+  // make a particular module visible.
+  if (getLangOpts().ObjC2)
+    return nullptr;
+
+  // Figure out which module we'd want to import.
+  Module *M = getModuleContainingLocation(Loc);
+  if (!M)
+    return nullptr;
+
+  Module *TopM = M->getTopLevelModule();
+  Module *IncM = getModuleForLocation(IncLoc);
+
+  // Walk up through the include stack, looking through textual headers of M
+  // until we hit a non-textual header that we can #include. (We assume textual
+  // headers of a module with non-textual headers aren't meant to be used to
+  // import entities from the module.)
+  auto &SM = getSourceManager();
+  while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) {
+    auto ID = SM.getFileID(SM.getExpansionLoc(Loc));
+    auto *FE = SM.getFileEntryForID(ID);
+
+    bool InTextualHeader = false;
+    for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) {
+      if (!Header.getModule()->isSubModuleOf(TopM))
+        continue;
+
+      if (!(Header.getRole() & ModuleMap::TextualHeader)) {
+        // If this is an accessible, non-textual header of M's top-level module
+        // that transitively includes the given location and makes the
+        // corresponding module visible, this is the thing to #include.
+        if (Header.isAccessibleFrom(IncM))
+          return FE;
+
+        // It's in a private header; we can't #include it.
+        // FIXME: If there's a public header in some module that re-exports it,
+        // then we could suggest including that, but it's not clear that's the
+        // expected way to make this entity visible.
+        continue;
+      }
+
+      InTextualHeader = true;
+    }
+
+    if (!InTextualHeader)
+      break;
+
+    Loc = SM.getIncludeLoc(ID);
+  }
+
+  return nullptr;
+}
+
 const FileEntry *Preprocessor::LookupFile(
     SourceLocation FilenameLoc,
     StringRef Filename,

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=267802&r1=267801&r2=267802&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Apr 27 16:57:05 2016
@@ -4929,6 +4929,16 @@ void Sema::diagnoseMissingImport(SourceL
                         Recover);
 }
 
+/// \brief Get a "quoted.h" or <angled.h> include path to use in a diagnostic
+/// suggesting the addition of a #include of the specified file.
+static std::string getIncludeStringForHeader(Preprocessor &PP,
+                                             const FileEntry *E) {
+  bool IsSystem;
+  auto Path =
+      PP.getHeaderSearchInfo().suggestPathToFileForDiagnostics(E, &IsSystem);
+  return (IsSystem ? '<' : '"') + Path + (IsSystem ? '>' : '"');
+}
+
 void Sema::diagnoseMissingImport(SourceLocation UseLoc, NamedDecl *Decl,
                                  SourceLocation DeclLoc,
                                  ArrayRef<Module *> Modules,
@@ -4949,6 +4959,16 @@ void Sema::diagnoseMissingImport(SourceL
 
     Diag(UseLoc, diag::err_module_unimported_use_multiple)
       << (int)MIK << Decl << ModuleList;
+  } else if (const FileEntry *E =
+                 PP.getModuleHeaderToIncludeForDiagnostics(UseLoc, DeclLoc)) {
+    // The right way to make the declaration visible is to include a header;
+    // suggest doing so.
+    //
+    // FIXME: Find a smart place to suggest inserting a #include, and add
+    // a FixItHint there.
+    Diag(UseLoc, diag::err_module_unimported_use_header)
+      << (int)MIK << Decl << Modules[0]->getFullModuleName()
+      << getIncludeStringForHeader(PP, E);
   } else {
     Diag(UseLoc, diag::err_module_unimported_use)
       << (int)MIK << Decl << Modules[0]->getFullModuleName();

Added: cfe/trunk/test/Modules/Inputs/suggest-include/empty.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/empty.h?rev=267802&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Modules/Inputs/suggest-include/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/module.modulemap?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/module.modulemap Wed Apr 27 16:57:05 2016
@@ -0,0 +1,22 @@
+module X {
+  module Empty { header "empty.h" }
+
+  exclude header "textual1.h"
+  textual header "textual2.h"
+  textual header "textual3.h"
+
+  module A { header "usetextual1.h" }
+  module B { header "usetextual2.h" }
+  module C { header "usetextual3.h" }
+  module D { header "usetextual4.h" }
+  module E { header "usetextual5.h" }
+
+  module P { private header "private1.h" }
+  module Q { private header "private2.h" }
+  module R { private header "private3.h" }
+  module S { header "useprivate1.h" export * }
+  module T { header "useprivate3.h" }
+}
+
+module Other { textual header "textual4.h" }
+

Added: cfe/trunk/test/Modules/Inputs/suggest-include/private1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/private1.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/private1.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/private1.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+extern int private1;

Added: cfe/trunk/test/Modules/Inputs/suggest-include/private2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/private2.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/private2.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/private2.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+extern int private2;

Added: cfe/trunk/test/Modules/Inputs/suggest-include/private3.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/private3.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/private3.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/private3.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+extern int private3;

Added: cfe/trunk/test/Modules/Inputs/suggest-include/textual1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/textual1.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/textual1.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/textual1.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+#define FOO(X) X

Added: cfe/trunk/test/Modules/Inputs/suggest-include/textual2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/textual2.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/textual2.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/textual2.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+EXPAND_MACRO

Added: cfe/trunk/test/Modules/Inputs/suggest-include/textual3.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/textual3.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/textual3.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/textual3.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+extern int textual3;

Added: cfe/trunk/test/Modules/Inputs/suggest-include/textual4.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/textual4.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/textual4.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/textual4.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+extern int textual4;

Added: cfe/trunk/test/Modules/Inputs/suggest-include/textual5.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/textual5.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/textual5.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/textual5.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+extern int textual5;

Added: cfe/trunk/test/Modules/Inputs/suggest-include/useprivate1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/useprivate1.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/useprivate1.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/useprivate1.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+#include "private1.h"

Added: cfe/trunk/test/Modules/Inputs/suggest-include/useprivate3.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/useprivate3.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/useprivate3.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/useprivate3.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+#include "private3.h"

Added: cfe/trunk/test/Modules/Inputs/suggest-include/usetextual1.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/usetextual1.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/usetextual1.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/usetextual1.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1,2 @@
+#include "textual1.h"
+FOO(extern int usetextual1;)

Added: cfe/trunk/test/Modules/Inputs/suggest-include/usetextual2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/usetextual2.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/usetextual2.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/usetextual2.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1,2 @@
+#define EXPAND_MACRO extern int usetextual2;
+#include "textual2.h"

Added: cfe/trunk/test/Modules/Inputs/suggest-include/usetextual3.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/usetextual3.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/usetextual3.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/usetextual3.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+#include "textual3.h"

Added: cfe/trunk/test/Modules/Inputs/suggest-include/usetextual4.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/usetextual4.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/usetextual4.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/usetextual4.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+#include "textual4.h"

Added: cfe/trunk/test/Modules/Inputs/suggest-include/usetextual5.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/suggest-include/usetextual5.h?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/suggest-include/usetextual5.h (added)
+++ cfe/trunk/test/Modules/Inputs/suggest-include/usetextual5.h Wed Apr 27 16:57:05 2016
@@ -0,0 +1 @@
+#include "textual5.h"

Added: cfe/trunk/test/Modules/suggest-include.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/suggest-include.cpp?rev=267802&view=auto
==============================================================================
--- cfe/trunk/test/Modules/suggest-include.cpp (added)
+++ cfe/trunk/test/Modules/suggest-include.cpp Wed Apr 27 16:57:05 2016
@@ -0,0 +1,33 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs/suggest-include %s -verify
+
+#include "empty.h" // import the module file
+
+// expected-note at usetextual1.h:2 {{previous}}
+// expected-note at textual2.h:1 {{previous}}
+// expected-note at textual3.h:1 {{previous}}
+// expected-note at textual4.h:1 {{previous}}
+// expected-note at textual5.h:1 {{previous}}
+// expected-note at private1.h:1 {{previous}}
+// expected-note at private2.h:1 {{previous}}
+// expected-note at private3.h:1 {{previous}}
+
+void f() {
+  (void)::usetextual1; // expected-error {{missing '#include "usetextual1.h"'}}
+  (void)::usetextual2; // expected-error {{missing '#include "usetextual2.h"'}}
+  (void)::textual3; // expected-error-re {{{{^}}missing '#include "usetextual3.h"'}}
+  // Don't suggest a #include that includes the entity via a path that leaves
+  // the module. In that case we can't be sure that we've picked the right header.
+  (void)::textual4; // expected-error-re {{{{^}}declaration of 'textual4'}}
+  (void)::textual5; // expected-error-re {{{{^}}declaration of 'textual5'}}
+
+  // Don't suggest #including a private header.
+  // FIXME: We could suggest including "useprivate1.h" here, as it's the only
+  // public way to get at this declaration.
+  (void)::private1; // expected-error-re {{{{^}}declaration of 'private1'}}
+  // FIXME: Should we be suggesting an import at all here? Should declarations
+  // in private headers be visible when the surrounding module is imported?
+  (void)::private2; // expected-error-re {{{{^}}declaration of 'private2'}}
+  // Even if we suggest an include for private1, we should not do so here.
+  (void)::private3; // expected-error-re {{{{^}}declaration of 'private3'}}
+}




More information about the cfe-commits mailing list