Index: clang/include/clang/Lex/DirectoryLookup.h =================================================================== --- clang/include/clang/Lex/DirectoryLookup.h +++ clang/include/clang/Lex/DirectoryLookup.h @@ -184,7 +184,7 @@ ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, - bool &HasBeenMapped, + bool &IsInHeaderMap, SmallVectorImpl &MappedName) const; private: Index: clang/lib/Lex/HeaderSearch.cpp =================================================================== --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -335,10 +335,11 @@ ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound, - bool &HasBeenMapped, + bool &IsInHeaderMap, SmallVectorImpl &MappedName) const { InUserSpecifiedSystemFramework = false; - HasBeenMapped = false; + IsInHeaderMap = false; + MappedName.clear(); SmallString<1024> TmpDir; if (isNormalDir()) { @@ -372,16 +373,16 @@ if (Dest.empty()) return nullptr; + IsInHeaderMap = true; + const FileEntry *Result; // Check if the headermap maps the filename to a framework include // ("Foo.h" -> "Foo/Foo.h"), in which case continue header lookup using the // framework include. if (llvm::sys::path::is_relative(Dest)) { - MappedName.clear(); MappedName.append(Dest.begin(), Dest.end()); Filename = StringRef(MappedName.begin(), MappedName.size()); - HasBeenMapped = true; Result = HM->LookupFile(Filename, HS.getFileMgr()); } else { Result = HS.getFileMgr().getFile(Dest); @@ -852,26 +853,30 @@ } SmallString<64> MappedName; + bool HasBeenMapped = false; // Check each directory in sequence to see if it contains this file. for (; i != SearchDirs.size(); ++i) { bool InUserSpecifiedSystemFramework = false; - bool HasBeenMapped = false; + bool CurrentInHeaderMap = false; bool IsFrameworkFoundInDir = false; const FileEntry *FE = SearchDirs[i].LookupFile( Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir, - HasBeenMapped, MappedName); - if (HasBeenMapped) { + CurrentInHeaderMap, MappedName); + if (!MappedName.empty()) { + assert(CurrentInHeaderMap && "MappedName should come from a header map"); CacheLookup.MappedName = - copyString(Filename, LookupFileCache.getAllocator()); - if (IsMapped) - *IsMapped = true; + copyString(MappedName, LookupFileCache.getAllocator()); + HasBeenMapped = true; } if (IsFrameworkFound) *IsFrameworkFound |= IsFrameworkFoundInDir; if (!FE) continue; + if (IsMapped) + *IsMapped = CurrentInHeaderMap || HasBeenMapped; + CurDir = &SearchDirs[i]; // This file is a system header or C++ unfriendly if the dir is. Index: clang/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json =================================================================== --- clang/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json +++ clang/test/Preprocessor/Inputs/nonportable-hmaps/foo.hmap.json @@ -1,6 +1,8 @@ { "mappings" : { - "Foo/Foo.h" : "headers/foo/Foo.h" + "Foo/Foo.h" : "headers/foo/Foo.h", + "Bar.h" : "headers/foo/Bar.h", + "Foo/Bar.h" : "INPUTS_DIR/nonportable-hmaps/headers/foo/Bar.h" } } Index: clang/test/Preprocessor/nonportable-include-with-hmap.c =================================================================== --- clang/test/Preprocessor/nonportable-include-with-hmap.c +++ clang/test/Preprocessor/nonportable-include-with-hmap.c @@ -1,5 +1,9 @@ +// REQUIRES: shell + // RUN: rm -f %t.hmap -// RUN: %hmaptool write %S/Inputs/nonportable-hmaps/foo.hmap.json %t.hmap +// RUN: sed -e "s:INPUTS_DIR:%S/Inputs:g" \ +// RUN: %S/Inputs/nonportable-hmaps/foo.hmap.json > %t.hmap.json +// RUN: %hmaptool write %t.hmap.json %t.hmap // RUN: %clang_cc1 -Eonly \ // RUN: -I%t.hmap \ // RUN: -I%S/Inputs/nonportable-hmaps \ @@ -16,3 +20,11 @@ // // There is nothing nonportable; -Wnonportable-include-path should not fire. #include "Foo/Foo.h" // expected-no-diagnostics + +// Verify files with absolute paths in the header map are handled too. +// "Bar.h" is included twice to make sure that when we see potentially +// nonportable path, the file has been already discovered through a relative +// path which triggers the file to be opened and `FileEntry::RealPathName` +// to be set. +#include "Bar.h" +#include "Foo/Bar.h" // expected-no-diagnostics