Hi doug.gregor, rsmith, djasper,

When searching for a header, Clang will first try to look in the current 
directory.  But if we find the header in this case, we don't set 
'SuggestedModule', so the header is included in non-modular way, even if 
module.map has an entry for it.  Fixing this issue fixes module tests for 
-fmodules-decluse, and test/Modules/submodules.cpp.

test/Modules/submodules.cpp already had a FIXME that this patch fixes.

-fmodules-decluse tests had dormant errors that this patch uncovers and fixes.  
Specifically, XC and XD #included "b.h", but did not specify the use dependency 
in module.map.

Please review.

http://llvm-reviews.chandlerc.com/D2374

Files:
  include/clang/Lex/HeaderSearch.h
  include/clang/Lex/Preprocessor.h
  lib/Frontend/VerifyDiagnosticConsumer.cpp
  lib/Lex/HeaderSearch.cpp
  lib/Lex/PPDirectives.cpp
  test/Modules/Inputs/declare-use/h.h
  test/Modules/Inputs/declare-use/module.map
  test/Modules/declare-use2.cpp
  test/Modules/submodules.cpp
Index: include/clang/Lex/HeaderSearch.h
===================================================================
--- include/clang/Lex/HeaderSearch.h
+++ include/clang/Lex/HeaderSearch.h
@@ -125,6 +125,10 @@
   void setHeaderRole(ModuleMap::ModuleHeaderRole Role) {
     HeaderRole = Role;
   }
+
+  SrcMgr::CharacteristicKind getDirInfo() const {
+    return static_cast<SrcMgr::CharacteristicKind>(DirInfo);
+  }
 };
 
 /// \brief An external source of header file information, which may supply
Index: include/clang/Lex/Preprocessor.h
===================================================================
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -1271,18 +1271,37 @@
   /// in ""'s.
   bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Filename);
 
+private:
+  const FileEntry *lookupFileImpl(SourceLocation FilenameLoc,
+                                  StringRef Filename,
+                                  bool IsAngled,
+                                  const DirectoryLookup *FromDir,
+                                  const DirectoryLookup *&CurDir,
+                                  SmallVectorImpl<char> *SearchPath,
+                                  SmallVectorImpl<char> *RelativePath,
+                                  ModuleMap::KnownHeader *SuggestedModule,
+                                  bool SkipCache);
+
+public:
   /// \brief Given a "foo" or \<foo> reference, look up the indicated file.
   ///
   /// Returns null on failure.  \p isAngled indicates whether the file
   /// reference is for system \#include's or not (i.e. using <> instead of "").
   const FileEntry *LookupFile(SourceLocation FilenameLoc, StringRef Filename,
-                              bool isAngled, const DirectoryLookup *FromDir,
+                              bool IsAngled, const DirectoryLookup *FromDir,
                               const DirectoryLookup *&CurDir,
                               SmallVectorImpl<char> *SearchPath,
                               SmallVectorImpl<char> *RelativePath,
                               ModuleMap::KnownHeader *SuggestedModule,
                               bool SkipCache = false);
 
+  /// \brief Lookup a file using normal rules, like \#include, but don't count
+  /// this as a module use.  This should be used for diagnostics purposes when
+  /// the file is not actually included in the translation unit.
+  const FileEntry *lookupFileForDiagnostics(SourceLocation FilenameLoc,
+                                            StringRef Filename,
+                                            bool IsAngled);
+
   /// \brief Get the DirectoryLookup structure used to find the current
   /// FileEntry, if CurLexer is non-null and if applicable. 
   ///
Index: lib/Frontend/VerifyDiagnosticConsumer.cpp
===================================================================
--- lib/Frontend/VerifyDiagnosticConsumer.cpp
+++ lib/Frontend/VerifyDiagnosticConsumer.cpp
@@ -370,9 +370,8 @@
         PH.Advance();
 
         // Lookup file via Preprocessor, like a #include.
-        const DirectoryLookup *CurDir;
-        const FileEntry *FE = PP->LookupFile(Pos, Filename, false, NULL, CurDir,
-                                             NULL, NULL, 0);
+        const FileEntry *FE =
+            PP->lookupFileForDiagnostics(Pos, Filename, /*IsAngled=*/false);
         if (!FE) {
           Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
                        diag::err_verify_missing_file) << Filename << KindStr;
Index: lib/Lex/HeaderSearch.cpp
===================================================================
--- lib/Lex/HeaderSearch.cpp
+++ lib/Lex/HeaderSearch.cpp
@@ -549,38 +549,35 @@
   // a subsequent include of "baz.h" should resolve to "whatever/foo/baz.h".
   // This search is not done for <> headers.
   if (CurFileEnt && !isAngled && !NoCurDirSearch) {
-    SmallString<1024> TmpDir;
-    // Concatenate the requested file onto the directory.
-    // FIXME: Portability.  Filename concatenation should be in sys::Path.
-    TmpDir += CurFileEnt->getDir()->getName();
-    TmpDir.push_back('/');
-    TmpDir.append(Filename.begin(), Filename.end());
-    if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(),/*openFile=*/true)) {
+    HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt);
+    bool InUserSpecifiedSystemFramework = false;
+    DirectoryLookup DL(CurFileEnt->getDir(), IncludingHFI.getDirInfo(),
+                       !IncludingHFI.Framework.empty());
+    if (const FileEntry *FE =
+            DL.LookupFile(Filename, *this, SearchPath, RelativePath,
+                          SuggestedModule, InUserSpecifiedSystemFramework)) {
       // Leave CurDir unset.
       // This file is a system header or C++ unfriendly if the old file is.
       //
       // Note that we only use one of FromHFI/ToHFI at once, due to potential
       // reallocation of the underlying vector potentially making the first
       // reference binding dangling.
       HeaderFileInfo &FromHFI = getFileInfo(CurFileEnt);
-      unsigned DirInfo = FromHFI.DirInfo;
+      SrcMgr::CharacteristicKind DirInfo = FromHFI.getDirInfo();
       bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader;
       StringRef Framework = FromHFI.Framework;
 
       HeaderFileInfo &ToHFI = getFileInfo(FE);
       ToHFI.DirInfo = DirInfo;
       ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
       ToHFI.Framework = Framework;
 
-      if (SearchPath != NULL) {
-        StringRef SearchPathRef(CurFileEnt->getDir()->getName());
-        SearchPath->clear();
-        SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
-      }
-      if (RelativePath != NULL) {
-        RelativePath->clear();
-        RelativePath->append(Filename.begin(), Filename.end());
-      }
+      // If the directory characteristic is User but this framework was
+      // user-specified to be treated as a system framework, promote the
+      // characteristic.
+      if (ToHFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework)
+        ToHFI.DirInfo = SrcMgr::C_System;
+
       return FE;
     }
   }
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -613,10 +613,10 @@
         << RequestingModule->getFullModuleName() << Filename;
 }
 
-const FileEntry *Preprocessor::LookupFile(
+const FileEntry *Preprocessor::lookupFileImpl(
     SourceLocation FilenameLoc,
     StringRef Filename,
-    bool isAngled,
+    bool IsAngled,
     const DirectoryLookup *FromDir,
     const DirectoryLookup *&CurDir,
     SmallVectorImpl<char> *SearchPath,
@@ -645,13 +645,10 @@
   // Do a standard file entry lookup.
   CurDir = CurDirLookup;
   const FileEntry *FE = HeaderInfo.LookupFile(
-      Filename, isAngled, FromDir, CurDir, CurFileEnt,
+      Filename, IsAngled, FromDir, CurDir, CurFileEnt,
       SearchPath, RelativePath, SuggestedModule, SkipCache);
-  if (FE) {
-    if (SuggestedModule)
-      verifyModuleInclude(FilenameLoc, Filename, FE);
+  if (FE)
     return FE;
-  }
 
   // Otherwise, see if this is a subframework header.  If so, this is relative
   // to one of the headers on the #include stack.  Walk the list of the current
@@ -680,6 +677,31 @@
   return 0;
 }
 
+const FileEntry *Preprocessor::LookupFile(
+    SourceLocation FilenameLoc,
+    StringRef Filename,
+    bool IsAngled,
+    const DirectoryLookup *FromDir,
+    const DirectoryLookup *&CurDir,
+    SmallVectorImpl<char> *SearchPath,
+    SmallVectorImpl<char> *RelativePath,
+    ModuleMap::KnownHeader *SuggestedModule,
+    bool SkipCache) {
+  const FileEntry *FE =
+      lookupFileImpl(FilenameLoc, Filename, IsAngled, FromDir, CurDir,
+                     SearchPath, RelativePath, SuggestedModule, SkipCache);
+  if (FE && SuggestedModule)
+    verifyModuleInclude(FilenameLoc, Filename, FE);
+  return FE;
+}
+
+const FileEntry *Preprocessor::lookupFileForDiagnostics(
+      SourceLocation FilenameLoc, StringRef Filename, bool IsAngled) {
+  const DirectoryLookup *CurDir;
+  return lookupFileImpl(FilenameLoc, Filename, IsAngled, NULL, CurDir,
+                        NULL, NULL, NULL, false);
+}
+
 
 //===----------------------------------------------------------------------===//
 // Preprocessor Directive Handling.
Index: test/Modules/Inputs/declare-use/h.h
===================================================================
--- test/Modules/Inputs/declare-use/h.h
+++ test/Modules/Inputs/declare-use/h.h
@@ -1,7 +1,7 @@
 #ifndef H_H
 #define H_H
 #include "c.h"
-#include "d.h" // expected-error {{does not depend on a module exporting}}
+#include "d.h" // expected-error {{module XH does not depend on a module exporting 'd.h'}}
 #include "h1.h"
 const int h1 = aux_h*c*7*d;
 #endif
Index: test/Modules/Inputs/declare-use/module.map
===================================================================
--- test/Modules/Inputs/declare-use/module.map
+++ test/Modules/Inputs/declare-use/module.map
@@ -9,11 +9,13 @@
 module XC {
   header "c.h"
   use XA
+  use XB
 }
 
 module XD {
   header "d.h"
   use XA
+  use XB
 }
 
 module XE {
Index: test/Modules/declare-use2.cpp
===================================================================
--- test/Modules/declare-use2.cpp
+++ test/Modules/declare-use2.cpp
@@ -3,5 +3,5 @@
 
 #include "h.h"
 #include "e.h"
-#include "f.h" // expected-error {{does not depend on a module exporting}}
+#include "f.h" // expected-error {{module XH does not depend on a module exporting 'f.h'}}
 const int h2 = h1+e+f;
Index: test/Modules/submodules.cpp
===================================================================
--- test/Modules/submodules.cpp
+++ test/Modules/submodules.cpp
@@ -31,6 +31,6 @@
 extern MyTypeA import_self_test_a; // expected-error {{must be imported from module 'import_self.a'}}
 // [email protected]:1 {{here}}
 extern MyTypeC import_self_test_c;
-// FIXME: This should be valid; import_self.b re-exports import_self.d.
-extern MyTypeD import_self_test_d; // expected-error {{must be imported from module 'import_self.d'}}
-// [email protected]:1 {{here}}
+
+// import_self.b re-exports import_self.d.
+extern MyTypeD import_self_test_d;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to