r198082 - Implement MSVC header search algorithm in MicrosoftMode.
Reid Kleckner
rnk at google.com
Tue Jan 14 18:48:56 PST 2014
This warning fires a handful of times in a clang self-host, and ultimately
the problem is a false positive as described in
http://llvm.org/bugs/show_bug.cgi?id=18481
On Fri, Dec 27, 2013 at 11:46 AM, Will Wilson <will at indefiant.com> wrote:
> Author: lantictac
> Date: Fri Dec 27 13:46:16 2013
> New Revision: 198082
>
> URL: http://llvm.org/viewvc/llvm-project?rev=198082&view=rev
> Log:
> Implement MSVC header search algorithm in MicrosoftMode.
> Follows algorithm described here:
> http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
>
> Added:
> cfe/trunk/test/Preprocessor/microsoft-header-search/
> cfe/trunk/test/Preprocessor/microsoft-header-search.c
> cfe/trunk/test/Preprocessor/microsoft-header-search/a/
> cfe/trunk/test/Preprocessor/microsoft-header-search/a/b/
> cfe/trunk/test/Preprocessor/microsoft-header-search/a/b/include3.h
> cfe/trunk/test/Preprocessor/microsoft-header-search/a/findme.h
> cfe/trunk/test/Preprocessor/microsoft-header-search/a/include2.h
> cfe/trunk/test/Preprocessor/microsoft-header-search/findme.h
> cfe/trunk/test/Preprocessor/microsoft-header-search/include1.h
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
> cfe/trunk/include/clang/Lex/HeaderSearch.h
> cfe/trunk/lib/Lex/HeaderSearch.cpp
> cfe/trunk/lib/Lex/PPDirectives.cpp
> cfe/trunk/lib/Rewrite/Frontend/InclusionRewriter.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=198082&r1=198081&r2=198082&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Fri Dec 27
> 13:46:16 2013
> @@ -300,6 +300,9 @@ def ext_pp_import_directive : Extension<
> InGroup<DiagGroup<"import-preprocessor-directive-pedantic">>;
> def err_pp_import_directive_ms : Error<
> "#import of type library is an unsupported Microsoft feature">;
> +def ext_pp_include_search_ms : ExtWarn<
> + "#include resolved using non-portable MSVC search rules as: %0">,
> + InGroup<DiagGroup<"msvc-include">>;
>
> def ext_pp_ident_directive : Extension<"#ident is a language extension">;
> def ext_pp_include_next_directive : Extension<
>
> Modified: cfe/trunk/include/clang/Lex/HeaderSearch.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/HeaderSearch.h?rev=198082&r1=198081&r2=198082&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Lex/HeaderSearch.h (original)
> +++ cfe/trunk/include/clang/Lex/HeaderSearch.h Fri Dec 27 13:46:16 2013
> @@ -158,6 +158,8 @@ class HeaderSearch {
> /// \brief Header-search options used to initialize this header search.
> IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts;
>
> + DiagnosticsEngine &Diags;
> + SourceManager &SourceMgr;
> FileManager &FileMgr;
> /// \#include search path information. Requests for \#include "x"
> search the
> /// directory of the \#including file first, then each directory in
> SearchDirs
> @@ -349,13 +351,15 @@ public:
> /// \returns If successful, this returns 'UsedDir', the DirectoryLookup
> member
> /// the file was found in, or null if not applicable.
> ///
> + /// \param IncludeLoc Used for diagnostics if valid.
> + ///
> /// \param isAngled indicates whether the file reference is a <>
> reference.
> ///
> /// \param CurDir If non-null, the file was found in the specified
> directory
> /// search location. This is used to implement \#include_next.
> ///
> - /// \param CurFileEnt If non-null, indicates where the \#including file
> is, in
> - /// case a relative search is needed.
> + /// \param Includers Indicates where the \#including file(s) are, in
> case
> + /// relative searches are needed. In reverse order of inclusion.
> ///
> /// \param SearchPath If non-null, will be set to the search path
> relative
> /// to which the file was found. If the include path is absolute,
> SearchPath
> @@ -368,10 +372,10 @@ public:
> /// \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
> /// be imported instead of preprocessing/parsing the file found.
> - const FileEntry *LookupFile(StringRef Filename, bool isAngled,
> - const DirectoryLookup *FromDir,
> + const FileEntry *LookupFile(StringRef Filename, SourceLocation
> IncludeLoc,
> + bool isAngled, const DirectoryLookup
> *FromDir,
> const DirectoryLookup *&CurDir,
> - const FileEntry *CurFileEnt,
> + ArrayRef<const FileEntry *> Includers,
> SmallVectorImpl<char> *SearchPath,
> SmallVectorImpl<char> *RelativePath,
> ModuleMap::KnownHeader *SuggestedModule,
>
> Modified: cfe/trunk/lib/Lex/HeaderSearch.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/HeaderSearch.cpp?rev=198082&r1=198081&r2=198082&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Lex/HeaderSearch.cpp (original)
> +++ cfe/trunk/lib/Lex/HeaderSearch.cpp Fri Dec 27 13:46:16 2013
> @@ -12,12 +12,12 @@
>
> //===----------------------------------------------------------------------===//
>
> #include "clang/Lex/HeaderSearch.h"
> -#include "clang/Basic/Diagnostic.h"
> #include "clang/Basic/FileManager.h"
> #include "clang/Basic/IdentifierTable.h"
> #include "clang/Lex/HeaderMap.h"
> #include "clang/Lex/HeaderSearchOptions.h"
> #include "clang/Lex/Lexer.h"
> +#include "clang/Lex/LexDiagnostic.h"
> #include "llvm/ADT/SmallString.h"
> #include "llvm/Support/Capacity.h"
> #include "llvm/Support/FileSystem.h"
> @@ -45,11 +45,11 @@ ExternalHeaderFileInfoSource::~ExternalH
>
> HeaderSearch::HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts,
> SourceManager &SourceMgr, DiagnosticsEngine
> &Diags,
> - const LangOptions &LangOpts,
> + const LangOptions &LangOpts,
> const TargetInfo *Target)
> - : HSOpts(HSOpts), FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
> - ModMap(SourceMgr, Diags, LangOpts, Target, *this)
> -{
> + : HSOpts(HSOpts), Diags(Diags), SourceMgr(SourceMgr),
> + FileMgr(SourceMgr.getFileManager()), FrameworkMap(64),
> + ModMap(SourceMgr, Diags, LangOpts, Target, *this) {
> AngledDirIdx = 0;
> SystemDirIdx = 0;
> NoCurDirSearch = false;
> @@ -493,20 +493,15 @@ void HeaderSearch::setTarget(const Targe
>
> /// LookupFile - Given a "foo" or \<foo> reference, look up the indicated
> file,
> /// return null on failure. isAngled indicates whether the file
> reference is
> -/// for system \#include's or not (i.e. using <> instead of "").
> CurFileEnt, if
> -/// non-null, indicates where the \#including file is, in case a relative
> search
> -/// is needed.
> +/// for system \#include's or not (i.e. using <> instead of "").
> Includers, if
> +/// non-empty, indicates where the \#including file(s) are, in case a
> relative
> +/// search is needed. Microsoft mode will pass all \#including files.
> const FileEntry *HeaderSearch::LookupFile(
> - StringRef Filename,
> - bool isAngled,
> - const DirectoryLookup *FromDir,
> - const DirectoryLookup *&CurDir,
> - const FileEntry *CurFileEnt,
> - SmallVectorImpl<char> *SearchPath,
> + 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)
> -{
> + ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) {
> if (!HSOpts->ModuleMapFiles.empty()) {
> // Preload all explicitly specified module map files. This enables
> modules
> // map files lying in a directory structure separate from the header
> files
> @@ -546,44 +541,53 @@ const FileEntry *HeaderSearch::LookupFil
> }
>
> // Unless disabled, check to see if the file is in the #includer's
> - // directory. This has to be based on CurFileEnt, not CurDir, because
> - // CurFileEnt could be a #include of a subdirectory (#include
> "foo/bar.h") and
> - // a subsequent include of "baz.h" should resolve to
> "whatever/foo/baz.h".
> + // directory. This cannot be based on CurDir, because each includer
> could be
> + // a #include of a subdirectory (#include "foo/bar.h") and a subsequent
> + // include of "baz.h" should resolve to "whatever/foo/baz.h".
> // This search is not done for <> headers.
> - if (CurFileEnt && !isAngled && !NoCurDirSearch) {
> + if (!Includers.empty() && !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)) {
> - // 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;
> - 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());
> + for (ArrayRef<const FileEntry *>::iterator I(Includers.begin()),
> + E(Includers.end());
> + I != E; ++I) {
> + const FileEntry *Includer = *I;
> + // Concatenate the requested file onto the directory.
> + // FIXME: Portability. Filename concatenation should be in
> sys::Path.
> + TmpDir = Includer->getDir()->getName();
> + TmpDir.push_back('/');
> + TmpDir.append(Filename.begin(), Filename.end());
> + if (const FileEntry *FE =
> + FileMgr.getFile(TmpDir.str(), /*openFile=*/true)) {
> + // 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(Includer);
> + unsigned DirInfo = FromHFI.DirInfo;
> + 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(Includer->getDir()->getName());
> + SearchPath->clear();
> + SearchPath->append(SearchPathRef.begin(), SearchPathRef.end());
> + }
> + if (RelativePath != NULL) {
> + RelativePath->clear();
> + RelativePath->append(Filename.begin(), Filename.end());
> + }
> + if (I != Includers.begin())
> + Diags.Report(IncludeLoc, diag::ext_pp_include_search_ms)
> + << FE->getName();
> + return FE;
> }
> - return FE;
> }
> }
>
> @@ -667,18 +671,18 @@ const FileEntry *HeaderSearch::LookupFil
> // a header in a framework that is currently being built, and we
> couldn't
> // resolve "foo.h" any other way, change the include to <Foo/foo.h>,
> where
> // "Foo" is the name of the framework in which the including header was
> found.
> - if (CurFileEnt && !isAngled && Filename.find('/') == StringRef::npos) {
> - HeaderFileInfo &IncludingHFI = getFileInfo(CurFileEnt);
> + if (!Includers.empty() && !isAngled &&
> + Filename.find('/') == StringRef::npos) {
> + HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front());
> if (IncludingHFI.IndexHeaderMapHeader) {
> SmallString<128> ScratchFilename;
> ScratchFilename += IncludingHFI.Framework;
> ScratchFilename += '/';
> ScratchFilename += Filename;
> -
> - const FileEntry *Result = LookupFile(ScratchFilename,
> /*isAngled=*/true,
> - FromDir, CurDir, CurFileEnt,
> - SearchPath, RelativePath,
> - SuggestedModule);
> +
> + const FileEntry *Result = LookupFile(
> + ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
> + Includers.front(), SearchPath, RelativePath, SuggestedModule);
> std::pair<unsigned, unsigned> &CacheLookup
> = LookupFileCache.GetOrCreateValue(Filename).getValue();
> CacheLookup.second
>
> Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=198082&r1=198081&r2=198082&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
> +++ cfe/trunk/lib/Lex/PPDirectives.cpp Fri Dec 27 13:46:16 2013
> @@ -560,12 +560,12 @@ const FileEntry *Preprocessor::LookupFil
> SmallVectorImpl<char> *RelativePath,
> ModuleMap::KnownHeader *SuggestedModule,
> bool SkipCache) {
> - // If the header lookup mechanism may be relative to the current file,
> pass in
> - // info about where the current file is.
> - const FileEntry *CurFileEnt = 0;
> + // If the header lookup mechanism may be relative to the current
> inclusion
> + // stack, record the parent #includes.
> + SmallVector<const FileEntry *, 16> Includers;
> if (!FromDir) {
> FileID FID = getCurrentFileLexer()->getFileID();
> - CurFileEnt = SourceMgr.getFileEntryForID(FID);
> + const FileEntry *FileEnt = SourceMgr.getFileEntryForID(FID);
>
> // If there is no file entry associated with this file, it must be the
> // predefines buffer. Any other file is not lexed with a normal
> lexer, so
> @@ -573,17 +573,31 @@ const FileEntry *Preprocessor::LookupFil
> // 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 (CurFileEnt == 0) {
> - FID = SourceMgr.getMainFileID();
> - CurFileEnt = SourceMgr.getFileEntryForID(FID);
> + if (!FileEnt)
> + FileEnt = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
> +
> + if (FileEnt)
> + Includers.push_back(FileEnt);
> +
> + // MSVC searches the current include stack from top to bottom for
> + // headers included by quoted include directives.
> + // See: http://msdn.microsoft.com/en-us/library/36k2cdd4.aspx
> + if (LangOpts.MicrosoftMode && !isAngled) {
> + for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
> + IncludeStackInfo &ISEntry = IncludeMacroStack[e - i - 1];
> + if (IsFileLexer(ISEntry))
> + if ((FileEnt = SourceMgr.getFileEntryForID(
> + ISEntry.ThePPLexer->getFileID())))
> + Includers.push_back(FileEnt);
> + }
> }
> }
>
> // Do a standard file entry lookup.
> CurDir = CurDirLookup;
> const FileEntry *FE = HeaderInfo.LookupFile(
> - Filename, isAngled, FromDir, CurDir, CurFileEnt,
> - SearchPath, RelativePath, SuggestedModule, SkipCache);
> + Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers,
> SearchPath,
> + RelativePath, SuggestedModule, SkipCache);
> if (FE) {
> if (SuggestedModule)
> HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
> @@ -591,6 +605,7 @@ const FileEntry *Preprocessor::LookupFil
> return FE;
> }
>
> + const FileEntry *CurFileEnt;
> // 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
> // headers on the #include stack and pass them to HeaderInfo.
>
> Modified: cfe/trunk/lib/Rewrite/Frontend/InclusionRewriter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/Frontend/InclusionRewriter.cpp?rev=198082&r1=198081&r2=198082&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Rewrite/Frontend/InclusionRewriter.cpp (original)
> +++ cfe/trunk/lib/Rewrite/Frontend/InclusionRewriter.cpp Fri Dec 27
> 13:46:16 2013
> @@ -335,7 +335,7 @@ bool InclusionRewriter::HandleHasInclude
> bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(),
> Filename);
> const DirectoryLookup *CurDir;
> const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
> - Filename, isAngled, 0, CurDir,
> + Filename, SourceLocation(), isAngled, 0, CurDir,
> PP.getSourceManager().getFileEntryForID(FileId), 0, 0, 0, false);
>
> FileExists = File != 0;
>
> Added: cfe/trunk/test/Preprocessor/microsoft-header-search.c
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-header-search.c?rev=198082&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Preprocessor/microsoft-header-search.c (added)
> +++ cfe/trunk/test/Preprocessor/microsoft-header-search.c Fri Dec 27
> 13:46:16 2013
> @@ -0,0 +1,6 @@
> +// RUN: %clang_cc1 -I%S/microsoft-header-search %s -fms-compatibility
> -verify
> +
> +// expected-warning at microsoft-header-search/a/findme.h:3 {{findme.h
> successfully included using MS search rules}}
> +// expected-warning at microsoft-header-search/a/b/include3.h:3 {{#include
> resolved using non-portable MSVC search rules as}}
> +
> +#include "microsoft-header-search/include1.h"
> \ No newline at end of file
>
> Added: cfe/trunk/test/Preprocessor/microsoft-header-search/a/b/include3.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-header-search/a/b/include3.h?rev=198082&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Preprocessor/microsoft-header-search/a/b/include3.h
> (added)
> +++ cfe/trunk/test/Preprocessor/microsoft-header-search/a/b/include3.h Fri
> Dec 27 13:46:16 2013
> @@ -0,0 +1,3 @@
> +#pragma once
> +
> +#include "findme.h"
> \ No newline at end of file
>
> Added: cfe/trunk/test/Preprocessor/microsoft-header-search/a/findme.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-header-search/a/findme.h?rev=198082&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Preprocessor/microsoft-header-search/a/findme.h (added)
> +++ cfe/trunk/test/Preprocessor/microsoft-header-search/a/findme.h Fri Dec
> 27 13:46:16 2013
> @@ -0,0 +1,3 @@
> +#pragma once
> +
> +#warning findme.h successfully included using MS search rules
> \ No newline at end of file
>
> Added: cfe/trunk/test/Preprocessor/microsoft-header-search/a/include2.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-header-search/a/include2.h?rev=198082&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Preprocessor/microsoft-header-search/a/include2.h
> (added)
> +++ cfe/trunk/test/Preprocessor/microsoft-header-search/a/include2.h Fri
> Dec 27 13:46:16 2013
> @@ -0,0 +1,6 @@
> +#pragma once
> +
> +#include "b/include3.h"
> +#pragma once
> +
> +#include "b/include3.h"
> \ No newline at end of file
>
> Added: cfe/trunk/test/Preprocessor/microsoft-header-search/findme.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-header-search/findme.h?rev=198082&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Preprocessor/microsoft-header-search/findme.h (added)
> +++ cfe/trunk/test/Preprocessor/microsoft-header-search/findme.h Fri Dec
> 27 13:46:16 2013
> @@ -0,0 +1,3 @@
> +#pragma once
> +
> +#error Wrong findme.h included, MSVC header search incorrect
> \ No newline at end of file
>
> Added: cfe/trunk/test/Preprocessor/microsoft-header-search/include1.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-header-search/include1.h?rev=198082&view=auto
>
> ==============================================================================
> --- cfe/trunk/test/Preprocessor/microsoft-header-search/include1.h (added)
> +++ cfe/trunk/test/Preprocessor/microsoft-header-search/include1.h Fri Dec
> 27 13:46:16 2013
> @@ -0,0 +1,6 @@
> +#pragma once
> +
> +#include "a/include2.h"
> +#pragma once
> +
> +#include "a/include2.h"
> \ No newline at end of file
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140114/d73cbb7e/attachment.html>
More information about the cfe-commits
mailing list