Browse Source

Correctly implement -include search logic.

According to the gcc docs, -include uses the current working directory
for the lookup instead of the main source file.

This patch gets rid of NormalizeIncludePath (which relied on an
implementation detail of FileManager / FileEntry for the include path
logic to work), and instead hands the correct lookup information down to
LookupFile.

This will allow us to change the FileEntry's behavior regarding its Name
caching.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215433 91177308-0d34-0410-b5e6-96231b3b80d8
Manuel Klimek 11 years ago
parent
commit
0e5c52d478

+ 6 - 8
include/clang/Lex/HeaderSearch.h

@@ -384,14 +384,12 @@ public:
   /// \param SuggestedModule If non-null, and the file found is semantically
   /// \param SuggestedModule If non-null, and the file found is semantically
   /// part of a known module, this will be set to the module that should
   /// part of a known module, this will be set to the module that should
   /// be imported instead of preprocessing/parsing the file found.
   /// be imported instead of preprocessing/parsing the file found.
-  const FileEntry *LookupFile(StringRef Filename, SourceLocation IncludeLoc,
-                              bool isAngled, const DirectoryLookup *FromDir,
-                              const DirectoryLookup *&CurDir,
-                              ArrayRef<const FileEntry *> Includers,
-                              SmallVectorImpl<char> *SearchPath,
-                              SmallVectorImpl<char> *RelativePath,
-                              ModuleMap::KnownHeader *SuggestedModule,
-                              bool SkipCache = false);
+  const FileEntry *LookupFile(
+      StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
+      const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
+      ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
+      SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
+      ModuleMap::KnownHeader *SuggestedModule, bool SkipCache = false);
 
 
   /// \brief Look up a subframework for the specified \#include file.
   /// \brief Look up a subframework for the specified \#include file.
   ///
   ///

+ 10 - 14
lib/Frontend/InitPreprocessor.cpp

@@ -65,17 +65,14 @@ static void DefineBuiltinMacro(MacroBuilder &Builder, StringRef Macro,
 
 
 /// AddImplicitInclude - Add an implicit \#include of the specified file to the
 /// AddImplicitInclude - Add an implicit \#include of the specified file to the
 /// predefines buffer.
 /// predefines buffer.
-static void AddImplicitInclude(MacroBuilder &Builder, StringRef File,
-                               FileManager &FileMgr) {
-  Builder.append(Twine("#include \"") +
-                 HeaderSearch::NormalizeDashIncludePath(File, FileMgr) + "\"");
+/// As these includes are generated by -include arguments the header search
+/// logic is going to search relatively to the current working directory.
+static void AddImplicitInclude(MacroBuilder &Builder, StringRef File) {
+  Builder.append(Twine("#include \"") + File + "\"");
 }
 }
 
 
-static void AddImplicitIncludeMacros(MacroBuilder &Builder,
-                                     StringRef File,
-                                     FileManager &FileMgr) {
-  Builder.append(Twine("#__include_macros \"") +
-                 HeaderSearch::NormalizeDashIncludePath(File, FileMgr) + "\"");
+static void AddImplicitIncludeMacros(MacroBuilder &Builder, StringRef File) {
+  Builder.append(Twine("#__include_macros \"") + File + "\"");
   // Marker token to stop the __include_macros fetch loop.
   // Marker token to stop the __include_macros fetch loop.
   Builder.append("##"); // ##?
   Builder.append("##"); // ##?
 }
 }
@@ -94,7 +91,7 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP,
     return;
     return;
   }
   }
 
 
-  AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
+  AddImplicitInclude(Builder, OriginalFile);
 }
 }
 
 
 /// \brief Add an implicit \#include using the original file used to generate
 /// \brief Add an implicit \#include using the original file used to generate
@@ -107,7 +104,7 @@ static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP,
   if (OriginalFile.empty())
   if (OriginalFile.empty())
     return;
     return;
 
 
-  AddImplicitInclude(Builder, OriginalFile, PP.getFileManager());
+  AddImplicitInclude(Builder, OriginalFile);
 }
 }
 
 
 /// PickFP - This is used to pick a value based on the FP semantics of the
 /// PickFP - This is used to pick a value based on the FP semantics of the
@@ -927,8 +924,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
   // If -imacros are specified, include them now.  These are processed before
   // If -imacros are specified, include them now.  These are processed before
   // any -include directives.
   // any -include directives.
   for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
   for (unsigned i = 0, e = InitOpts.MacroIncludes.size(); i != e; ++i)
-    AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i],
-                             PP.getFileManager());
+    AddImplicitIncludeMacros(Builder, InitOpts.MacroIncludes[i]);
 
 
   // Process -include-pch/-include-pth directives.
   // Process -include-pch/-include-pth directives.
   if (!InitOpts.ImplicitPCHInclude.empty())
   if (!InitOpts.ImplicitPCHInclude.empty())
@@ -939,7 +935,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
   // Process -include directives.
   // Process -include directives.
   for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
   for (unsigned i = 0, e = InitOpts.Includes.size(); i != e; ++i) {
     const std::string &Path = InitOpts.Includes[i];
     const std::string &Path = InitOpts.Includes[i];
-    AddImplicitInclude(Builder, Path, PP.getFileManager());
+    AddImplicitInclude(Builder, Path);
   }
   }
 
 
   // Exit the command line and go back to <built-in> (2 is LC_LEAVE).
   // Exit the command line and go back to <built-in> (2 is LC_LEAVE).

+ 6 - 3
lib/Frontend/Rewrite/InclusionRewriter.cpp

@@ -333,10 +333,13 @@ bool InclusionRewriter::HandleHasInclude(
   // FIXME: Subframeworks aren't handled here. Do we care?
   // FIXME: Subframeworks aren't handled here. Do we care?
   bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
   bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
   const DirectoryLookup *CurDir;
   const DirectoryLookup *CurDir;
+  const FileEntry *FileEnt = PP.getSourceManager().getFileEntryForID(FileId);
+  SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 1>
+      Includers;
+  Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
   const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
   const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
-      Filename, SourceLocation(), isAngled, nullptr, CurDir,
-      PP.getSourceManager().getFileEntryForID(FileId), nullptr, nullptr,
-      nullptr, false);
+      Filename, SourceLocation(), isAngled, nullptr, CurDir, Includers, nullptr,
+      nullptr, nullptr, false);
 
 
   FileExists = File != nullptr;
   FileExists = File != nullptr;
   return true;
   return true;

+ 14 - 36
lib/Lex/HeaderSearch.cpp

@@ -566,8 +566,8 @@ static const char *copyString(StringRef Str, llvm::BumpPtrAllocator &Alloc) {
 const FileEntry *HeaderSearch::LookupFile(
 const FileEntry *HeaderSearch::LookupFile(
     StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
     StringRef Filename, SourceLocation IncludeLoc, bool isAngled,
     const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
     const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir,
-    ArrayRef<const FileEntry *> Includers, SmallVectorImpl<char> *SearchPath,
-    SmallVectorImpl<char> *RelativePath,
+    ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
+    SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
     ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
     ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
   if (!HSOpts->ModuleMapFiles.empty()) {
   if (!HSOpts->ModuleMapFiles.empty()) {
     // Preload all explicitly specified module map files. This enables modules
     // Preload all explicitly specified module map files. This enables modules
@@ -618,13 +618,13 @@ const FileEntry *HeaderSearch::LookupFile(
   // This search is not done for <> headers.
   // This search is not done for <> headers.
   if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
   if (!Includers.empty() && !isAngled && !NoCurDirSearch) {
     SmallString<1024> TmpDir;
     SmallString<1024> TmpDir;
-    for (ArrayRef<const FileEntry *>::iterator I = Includers.begin(),
-                                               E = Includers.end();
-         I != E; ++I) {
-      const FileEntry *Includer = *I;
+    bool First = true;
+    for (const auto &IncluderAndDir : Includers) {
+      const FileEntry *Includer = IncluderAndDir.first;
+
       // Concatenate the requested file onto the directory.
       // Concatenate the requested file onto the directory.
       // FIXME: Portability.  Filename concatenation should be in sys::Path.
       // FIXME: Portability.  Filename concatenation should be in sys::Path.
-      TmpDir = Includer->getDir()->getName();
+      TmpDir = IncluderAndDir.second->getName();
       TmpDir.push_back('/');
       TmpDir.push_back('/');
       TmpDir.append(Filename.begin(), Filename.end());
       TmpDir.append(Filename.begin(), Filename.end());
 
 
@@ -633,10 +633,9 @@ const FileEntry *HeaderSearch::LookupFile(
       // a container that could be reallocated across this call.
       // a container that could be reallocated across this call.
       bool IncluderIsSystemHeader =
       bool IncluderIsSystemHeader =
           getFileInfo(Includer).DirInfo != SrcMgr::C_User;
           getFileInfo(Includer).DirInfo != SrcMgr::C_User;
-      if (const FileEntry *FE =
-              getFileAndSuggestModule(*this, TmpDir.str(), Includer->getDir(),
-                                      IncluderIsSystemHeader,
-                                      SuggestedModule)) {
+      if (const FileEntry *FE = getFileAndSuggestModule(
+              *this, TmpDir.str(), IncluderAndDir.second,
+              IncluderIsSystemHeader, SuggestedModule)) {
         // Leave CurDir unset.
         // Leave CurDir unset.
         // This file is a system header or C++ unfriendly if the old file is.
         // This file is a system header or C++ unfriendly if the old file is.
         //
         //
@@ -654,7 +653,7 @@ const FileEntry *HeaderSearch::LookupFile(
         ToHFI.Framework = Framework;
         ToHFI.Framework = Framework;
 
 
         if (SearchPath) {
         if (SearchPath) {
-          StringRef SearchPathRef(Includer->getDir()->getName());
+          StringRef SearchPathRef(IncluderAndDir.second->getName());
           SearchPath->clear();
           SearchPath->clear();
           SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
           SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
         }
         }
@@ -662,7 +661,7 @@ const FileEntry *HeaderSearch::LookupFile(
           RelativePath->clear();
           RelativePath->clear();
           RelativePath->append(Filename.begin(), Filename.end());
           RelativePath->append(Filename.begin(), Filename.end());
         }
         }
-        if (I == Includers.begin())
+        if (First)
           return FE;
           return FE;
 
 
         // Otherwise, we found the path via MSVC header search rules.  If
         // Otherwise, we found the path via MSVC header search rules.  If
@@ -679,6 +678,7 @@ const FileEntry *HeaderSearch::LookupFile(
           break;
           break;
         }
         }
       }
       }
+      First = false;
     }
     }
   }
   }
 
 
@@ -780,7 +780,7 @@ const FileEntry *HeaderSearch::LookupFile(
   // "Foo" is the name of the framework in which the including header was found.
   // "Foo" is the name of the framework in which the including header was found.
   if (!Includers.empty() && !isAngled &&
   if (!Includers.empty() && !isAngled &&
       Filename.find('/') == StringRef::npos) {
       Filename.find('/') == StringRef::npos) {
-    HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front());
+    HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first);
     if (IncludingHFI.IndexHeaderMapHeader) {
     if (IncludingHFI.IndexHeaderMapHeader) {
       SmallString<128> ScratchFilename;
       SmallString<128> ScratchFilename;
       ScratchFilename += IncludingHFI.Framework;
       ScratchFilename += IncludingHFI.Framework;
@@ -939,28 +939,6 @@ LookupSubframeworkHeader(StringRef Filename,
   return FE;
   return FE;
 }
 }
 
 
-/// \brief Helper static function to normalize a path for injection into
-/// a synthetic header.
-/*static*/ std::string
-HeaderSearch::NormalizeDashIncludePath(StringRef File, FileManager &FileMgr) {
-  // Implicit include paths should be resolved relative to the current
-  // working directory first, and then use the regular header search
-  // mechanism. The proper way to handle this is to have the
-  // predefines buffer located at the current working directory, but
-  // it has no file entry. For now, workaround this by using an
-  // absolute path if we find the file here, and otherwise letting
-  // header search handle it.
-  SmallString<128> Path(File);
-  llvm::sys::fs::make_absolute(Path);
-  bool exists;
-  if (llvm::sys::fs::exists(Path.str(), exists) || !exists)
-    Path = File;
-  else if (exists)
-    FileMgr.getFile(File);
-
-  return Lexer::Stringify(Path.str());
-}
-
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 // File Info Management.
 // File Info Management.
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//

+ 11 - 8
lib/Lex/PPDirectives.cpp

@@ -541,7 +541,8 @@ const FileEntry *Preprocessor::LookupFile(
     bool SkipCache) {
     bool SkipCache) {
   // If the header lookup mechanism may be relative to the current inclusion
   // If the header lookup mechanism may be relative to the current inclusion
   // stack, record the parent #includes.
   // stack, record the parent #includes.
-  SmallVector<const FileEntry *, 16> Includers;
+  SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
+      Includers;
   if (!FromDir) {
   if (!FromDir) {
     FileID FID = getCurrentFileLexer()->getFileID();
     FileID FID = getCurrentFileLexer()->getFileID();
     const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID);
     const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID);
@@ -550,13 +551,15 @@ const FileEntry *Preprocessor::LookupFile(
     // predefines buffer.  Any other file is not lexed with a normal lexer, so
     // predefines buffer.  Any other file is not lexed with a normal lexer, so
     // it won't be scanned for preprocessor directives.   If we have the
     // it won't be scanned for preprocessor directives.   If we have the
     // predefines buffer, resolve #include references (which come from the
     // predefines buffer, resolve #include references (which come from the
-    // -include command line argument) as if they came from the main file, this
-    // affects file lookup etc.
-    if (!FileEnt)
+    // -include command line argument) from the current working directory
+    // instead of relative to the main file.
+    if (!FileEnt) {
       FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
       FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
-
-    if (FileEnt)
-      Includers.push_back(FileEnt);
+      if (FileEnt)
+        Includers.push_back(std::make_pair(FileEnt, FileMgr.getDirectory(".")));
+    } else {
+      Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
+    }
 
 
     // MSVC searches the current include stack from top to bottom for
     // MSVC searches the current include stack from top to bottom for
     // headers included by quoted include directives.
     // headers included by quoted include directives.
@@ -567,7 +570,7 @@ const FileEntry *Preprocessor::LookupFile(
         if (IsFileLexer(ISEntry))
         if (IsFileLexer(ISEntry))
           if ((FileEnt = SourceMgr.getFileEntryForID(
           if ((FileEnt = SourceMgr.getFileEntryForID(
                    ISEntry.ThePPLexer->getFileID())))
                    ISEntry.ThePPLexer->getFileID())))
-            Includers.push_back(FileEnt);
+            Includers.push_back(std::make_pair(FileEnt, FileEnt->getDir()));
       }
       }
     }
     }
   }
   }

+ 2 - 4
lib/Serialization/ASTReader.cpp

@@ -543,8 +543,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
       continue;
       continue;
 
 
     SuggestedPredefines += "#include \"";
     SuggestedPredefines += "#include \"";
-    SuggestedPredefines +=
-      HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+    SuggestedPredefines += File;
     SuggestedPredefines += "\"\n";
     SuggestedPredefines += "\"\n";
   }
   }
 
 
@@ -556,8 +555,7 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
       continue;
       continue;
 
 
     SuggestedPredefines += "#__include_macros \"";
     SuggestedPredefines += "#__include_macros \"";
-    SuggestedPredefines +=
-      HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+    SuggestedPredefines += File;
     SuggestedPredefines += "\"\n##\n";
     SuggestedPredefines += "\"\n##\n";
   }
   }
 
 

+ 1 - 0
test/Frontend/print-header-includes.c

@@ -1,3 +1,4 @@
+// RUN: cd %S
 // RUN: %clang_cc1 -include Inputs/test3.h -E -H -o %t.out %s 2> %t.stderr
 // RUN: %clang_cc1 -include Inputs/test3.h -E -H -o %t.out %s 2> %t.stderr
 // RUN: FileCheck < %t.stderr %s
 // RUN: FileCheck < %t.stderr %s