[Preprocessor] Add a note with framework location for "file not found" error.

When a framework with the same name is available at multiple framework
search paths, we use the first matching location. If a framework at this
location doesn't have all the headers, it can be confusing for
developers because they see only an error `'Foo/Foo.h' file not found`,
can find the complete framework with required header, and don't know the
incomplete framework was used instead.

Add a note explaining a framework without required header was found.
Also mention framework directory path to make it easier to find the
incomplete framework.

rdar://problem/39246514

Reviewers: arphaman, erik.pilkington, jkorous

Reviewed By: jkorous

Subscribers: jkorous, dexonsmith, cfe-commits

Differential Revision: https://reviews.llvm.org/D56561

llvm-svn: 353231
This commit is contained in:
Volodymyr Sapsai 2019-02-05 22:34:55 +00:00
parent ce10d5ead4
commit 421380a108
13 changed files with 100 additions and 40 deletions

View File

@ -418,6 +418,8 @@ def err_pp_file_not_found_angled_include_not_fatal : Error<
"'%0' file not found with <angled> include; use \"quotes\" instead">; "'%0' file not found with <angled> include; use \"quotes\" instead">;
def err_pp_file_not_found_typo_not_fatal def err_pp_file_not_found_typo_not_fatal
: Error<"'%0' file not found, did you mean '%1'?">; : Error<"'%0' file not found, did you mean '%1'?">;
def note_pp_framework_without_header : Note<
"did not find header '%0' in framework '%1' (loaded from '%2')">;
def err_pp_error_opening_file : Error< def err_pp_error_opening_file : Error<
"error opening file '%0': %1">, DefaultFatal; "error opening file '%0': %1">, DefaultFatal;
def err_pp_empty_filename : Error<"empty filename">; def err_pp_empty_filename : Error<"empty filename">;

View File

@ -170,6 +170,9 @@ public:
/// set to true if the file is located in a framework that has been /// set to true if the file is located in a framework that has been
/// user-specified to be treated as a system framework. /// user-specified to be treated as a system framework.
/// ///
/// \param [out] IsFrameworkFound For a framework directory set to true if
/// specified '.framework' directory is found.
///
/// \param [out] MappedName if this is a headermap which maps the filename to /// \param [out] MappedName if this is a headermap which maps the filename to
/// a framework include ("Foo.h" -> "Foo/Foo.h"), set the new name to this /// a framework include ("Foo.h" -> "Foo/Foo.h"), set the new name to this
/// vector and point Filename to it. /// vector and point Filename to it.
@ -180,6 +183,7 @@ public:
Module *RequestingModule, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework, bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
bool &HasBeenMapped, bool &HasBeenMapped,
SmallVectorImpl<char> &MappedName) const; SmallVectorImpl<char> &MappedName) const;
@ -190,7 +194,8 @@ private:
SmallVectorImpl<char> *RelativePath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework) const; bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound) const;
}; };

View File

@ -142,22 +142,22 @@ public:
virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0; virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
}; };
/// This structure is used to record entries in our framework cache.
struct FrameworkCacheEntry {
/// The directory entry which should be used for the cached framework.
const DirectoryEntry *Directory;
/// Whether this framework has been "user-specified" to be treated as if it
/// were a system framework (even if it was found outside a system framework
/// directory).
bool IsUserSpecifiedSystemFramework;
};
/// Encapsulates the information needed to find the file referenced /// Encapsulates the information needed to find the file referenced
/// by a \#include or \#include_next, (sub-)framework lookup, etc. /// by a \#include or \#include_next, (sub-)framework lookup, etc.
class HeaderSearch { class HeaderSearch {
friend class DirectoryLookup; friend class DirectoryLookup;
/// This structure is used to record entries in our framework cache.
struct FrameworkCacheEntry {
/// The directory entry which should be used for the cached framework.
const DirectoryEntry *Directory;
/// Whether this framework has been "user-specified" to be treated as if it
/// were a system framework (even if it was found outside a system framework
/// directory).
bool IsUserSpecifiedSystemFramework;
};
/// Header-search options used to initialize this header search. /// Header-search options used to initialize this header search.
std::shared_ptr<HeaderSearchOptions> HSOpts; std::shared_ptr<HeaderSearchOptions> HSOpts;
@ -390,13 +390,18 @@ public:
/// ///
/// \param IsMapped If non-null, and the search involved header maps, set to /// \param IsMapped If non-null, and the search involved header maps, set to
/// true. /// true.
///
/// \param IsFrameworkFound If non-null, will be set to true if a framework is
/// found in any of searched SearchDirs. Doesn't guarantee the requested file
/// is found.
const FileEntry *LookupFile( const FileEntry *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<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
bool *IsMapped, bool SkipCache = false, bool BuildSystemModule = false); bool *IsMapped, bool *IsFrameworkFound, bool SkipCache = false,
bool BuildSystemModule = false);
/// Look up a subframework for the specified \#include file. /// Look up a subframework for the specified \#include file.
/// ///

View File

@ -1854,7 +1854,8 @@ public:
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath, SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule, ModuleMap::KnownHeader *SuggestedModule,
bool *IsMapped, bool SkipCache = false); bool *IsMapped, bool *IsFrameworkFound,
bool SkipCache = false);
/// Get the DirectoryLookup structure used to find the current /// Get the DirectoryLookup structure used to find the current
/// FileEntry, if CurLexer is non-null and if applicable. /// FileEntry, if CurLexer is non-null and if applicable.

View File

@ -286,7 +286,7 @@ bool GenerateHeaderModuleAction::BeginSourceFileAction(
const DirectoryLookup *CurDir = nullptr; const DirectoryLookup *CurDir = nullptr;
const FileEntry *FE = HS.LookupFile( const FileEntry *FE = HS.LookupFile(
Name, SourceLocation(), /*Angled*/ false, nullptr, CurDir, Name, SourceLocation(), /*Angled*/ false, nullptr, CurDir,
None, nullptr, nullptr, nullptr, nullptr, nullptr); None, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
if (!FE) { if (!FE) {
CI.getDiagnostics().Report(diag::err_module_header_file_not_found) CI.getDiagnostics().Report(diag::err_module_header_file_not_found)
<< Name; << Name;

View File

@ -414,7 +414,7 @@ bool InclusionRewriter::HandleHasInclude(
// FIXME: Why don't we call PP.LookupFile here? // FIXME: Why don't we call PP.LookupFile here?
const FileEntry *File = PP.getHeaderSearchInfo().LookupFile( const FileEntry *File = PP.getHeaderSearchInfo().LookupFile(
Filename, SourceLocation(), isAngled, Lookup, CurDir, Includers, nullptr, Filename, SourceLocation(), isAngled, Lookup, CurDir, Includers, nullptr,
nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr, nullptr);
FileExists = File != nullptr; FileExists = File != nullptr;
return true; return true;

View File

@ -480,7 +480,7 @@ static bool ParseDirective(StringRef S, ExpectedData *ED, SourceManager &SM,
const DirectoryLookup *CurDir; const DirectoryLookup *CurDir;
const FileEntry *FE = const FileEntry *FE =
PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir, PP->LookupFile(Pos, Filename, false, nullptr, nullptr, CurDir,
nullptr, nullptr, nullptr, nullptr); nullptr, nullptr, nullptr, nullptr, nullptr);
if (!FE) { if (!FE) {
Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin), Diags.Report(Pos.getLocWithOffset(PH.C-PH.Begin),
diag::err_verify_missing_file) << Filename << KindStr; diag::err_verify_missing_file) << Filename << KindStr;

View File

@ -334,6 +334,7 @@ const FileEntry *DirectoryLookup::LookupFile(
Module *RequestingModule, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework, bool &InUserSpecifiedSystemFramework,
bool &IsFrameworkFound,
bool &HasBeenMapped, bool &HasBeenMapped,
SmallVectorImpl<char> &MappedName) const { SmallVectorImpl<char> &MappedName) const {
InUserSpecifiedSystemFramework = false; InUserSpecifiedSystemFramework = false;
@ -362,7 +363,7 @@ const FileEntry *DirectoryLookup::LookupFile(
if (isFramework()) if (isFramework())
return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath, return DoFrameworkLookup(Filename, HS, SearchPath, RelativePath,
RequestingModule, SuggestedModule, RequestingModule, SuggestedModule,
InUserSpecifiedSystemFramework); InUserSpecifiedSystemFramework, IsFrameworkFound);
assert(isHeaderMap() && "Unknown directory lookup"); assert(isHeaderMap() && "Unknown directory lookup");
const HeaderMap *HM = getHeaderMap(); const HeaderMap *HM = getHeaderMap();
@ -462,7 +463,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath, Module *RequestingModule, SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
ModuleMap::KnownHeader *SuggestedModule, ModuleMap::KnownHeader *SuggestedModule,
bool &InUserSpecifiedSystemFramework) const { bool &InUserSpecifiedSystemFramework, bool &IsFrameworkFound) const {
FileManager &FileMgr = HS.getFileMgr(); FileManager &FileMgr = HS.getFileMgr();
// Framework names must have a '/' in the filename. // Framework names must have a '/' in the filename.
@ -471,7 +472,7 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
// Find out if this is the home for the specified framework, by checking // Find out if this is the home for the specified framework, by checking
// HeaderSearch. Possible answers are yes/no and unknown. // HeaderSearch. Possible answers are yes/no and unknown.
HeaderSearch::FrameworkCacheEntry &CacheEntry = FrameworkCacheEntry &CacheEntry =
HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); HS.LookupFrameworkCache(Filename.substr(0, SlashPos));
// If it is known and in some other directory, fail. // If it is known and in some other directory, fail.
@ -516,8 +517,9 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(
} }
} }
// Set the 'user-specified system framework' flag. // Set out flags.
InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework;
IsFrameworkFound = CacheEntry.Directory;
if (RelativePath) { if (RelativePath) {
RelativePath->clear(); RelativePath->clear();
@ -696,10 +698,14 @@ const FileEntry *HeaderSearch::LookupFile(
ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers,
SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
bool *IsMapped, bool SkipCache, bool BuildSystemModule) { bool *IsMapped, bool *IsFrameworkFound, bool SkipCache,
bool BuildSystemModule) {
if (IsMapped) if (IsMapped)
*IsMapped = false; *IsMapped = false;
if (IsFrameworkFound)
*IsFrameworkFound = false;
if (SuggestedModule) if (SuggestedModule)
*SuggestedModule = ModuleMap::KnownHeader(); *SuggestedModule = ModuleMap::KnownHeader();
@ -851,16 +857,19 @@ const FileEntry *HeaderSearch::LookupFile(
for (; i != SearchDirs.size(); ++i) { for (; i != SearchDirs.size(); ++i) {
bool InUserSpecifiedSystemFramework = false; bool InUserSpecifiedSystemFramework = false;
bool HasBeenMapped = false; bool HasBeenMapped = false;
bool IsFrameworkFoundInDir = false;
const FileEntry *FE = SearchDirs[i].LookupFile( const FileEntry *FE = SearchDirs[i].LookupFile(
Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule, Filename, *this, IncludeLoc, SearchPath, RelativePath, RequestingModule,
SuggestedModule, InUserSpecifiedSystemFramework, HasBeenMapped, SuggestedModule, InUserSpecifiedSystemFramework, IsFrameworkFoundInDir,
MappedName); HasBeenMapped, MappedName);
if (HasBeenMapped) { if (HasBeenMapped) {
CacheLookup.MappedName = CacheLookup.MappedName =
copyString(Filename, LookupFileCache.getAllocator()); copyString(Filename, LookupFileCache.getAllocator());
if (IsMapped) if (IsMapped)
*IsMapped = true; *IsMapped = true;
} }
if (IsFrameworkFound)
*IsFrameworkFound |= IsFrameworkFoundInDir;
if (!FE) continue; if (!FE) continue;
CurDir = &SearchDirs[i]; CurDir = &SearchDirs[i];
@ -926,10 +935,10 @@ const FileEntry *HeaderSearch::LookupFile(
ScratchFilename += '/'; ScratchFilename += '/';
ScratchFilename += Filename; ScratchFilename += Filename;
const FileEntry *FE = const FileEntry *FE = LookupFile(
LookupFile(ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir,
CurDir, Includers.front(), SearchPath, RelativePath, Includers.front(), SearchPath, RelativePath, RequestingModule,
RequestingModule, SuggestedModule, IsMapped); SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr);
if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) {
if (SuggestedModule) if (SuggestedModule)

View File

@ -665,7 +665,8 @@ const FileEntry *Preprocessor::LookupFile(
const DirectoryLookup *FromDir, const FileEntry *FromFile, const DirectoryLookup *FromDir, const FileEntry *FromFile,
const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath,
SmallVectorImpl<char> *RelativePath, SmallVectorImpl<char> *RelativePath,
ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool SkipCache) { ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped,
bool *IsFrameworkFound, bool SkipCache) {
Module *RequestingModule = getModuleForLocation(FilenameLoc); Module *RequestingModule = getModuleForLocation(FilenameLoc);
bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc); bool RequestingModuleIsModuleInterface = !SourceMgr.isInMainFile(FilenameLoc);
@ -723,7 +724,8 @@ const FileEntry *Preprocessor::LookupFile(
while (const FileEntry *FE = HeaderInfo.LookupFile( while (const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir, Filename, FilenameLoc, isAngled, TmpFromDir, TmpCurDir,
Includers, SearchPath, RelativePath, RequestingModule, Includers, SearchPath, RelativePath, RequestingModule,
SuggestedModule, /*IsMapped=*/nullptr, SkipCache)) { SuggestedModule, /*IsMapped=*/nullptr,
/*IsFrameworkFound=*/nullptr, SkipCache)) {
// Keep looking as if this file did a #include_next. // Keep looking as if this file did a #include_next.
TmpFromDir = TmpCurDir; TmpFromDir = TmpCurDir;
++TmpFromDir; ++TmpFromDir;
@ -739,8 +741,8 @@ const FileEntry *Preprocessor::LookupFile(
// Do a standard file entry lookup. // Do a standard file entry lookup.
const FileEntry *FE = HeaderInfo.LookupFile( const FileEntry *FE = HeaderInfo.LookupFile(
Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath, Filename, FilenameLoc, isAngled, FromDir, CurDir, Includers, SearchPath,
RelativePath, RequestingModule, SuggestedModule, IsMapped, SkipCache, RelativePath, RequestingModule, SuggestedModule, IsMapped,
BuildSystemModule); IsFrameworkFound, SkipCache, BuildSystemModule);
if (FE) { if (FE) {
if (SuggestedModule && !LangOpts.AsmPreprocessor) if (SuggestedModule && !LangOpts.AsmPreprocessor)
HeaderInfo.getModuleMap().diagnoseHeaderInclusion( HeaderInfo.getModuleMap().diagnoseHeaderInclusion(
@ -1756,6 +1758,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
// Search include directories. // Search include directories.
bool IsMapped = false; bool IsMapped = false;
bool IsFrameworkFound = false;
const DirectoryLookup *CurDir; const DirectoryLookup *CurDir;
SmallString<1024> SearchPath; SmallString<1024> SearchPath;
SmallString<1024> RelativePath; SmallString<1024> RelativePath;
@ -1774,7 +1777,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, FilenameLoc, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename,
isAngled, LookupFrom, LookupFromFile, CurDir, isAngled, LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr, Callbacks ? &SearchPath : nullptr, Callbacks ? &RelativePath : nullptr,
&SuggestedModule, &IsMapped); &SuggestedModule, &IsMapped, &IsFrameworkFound);
if (!File) { if (!File) {
if (Callbacks) { if (Callbacks) {
@ -1791,7 +1794,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
FilenameLoc, FilenameLoc,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, isAngled,
LookupFrom, LookupFromFile, CurDir, nullptr, nullptr, LookupFrom, LookupFromFile, CurDir, nullptr, nullptr,
&SuggestedModule, &IsMapped, /*SkipCache*/ true); &SuggestedModule, &IsMapped, /*IsFrameworkFound=*/nullptr,
/*SkipCache*/ true);
} }
} }
} }
@ -1806,7 +1810,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false, LangOpts.MSVCCompat ? NormalizedPath.c_str() : Filename, false,
LookupFrom, LookupFromFile, CurDir, LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr, Callbacks ? &SearchPath : nullptr,
Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped); Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
/*IsFrameworkFound=*/nullptr);
if (File) { if (File) {
SourceRange Range(FilenameTok.getLocation(), CharEnd); SourceRange Range(FilenameTok.getLocation(), CharEnd);
Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal) << Diag(FilenameTok, diag::err_pp_file_not_found_angled_include_not_fatal) <<
@ -1842,7 +1847,8 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
: TypoCorrectionName, : TypoCorrectionName,
isAngled, LookupFrom, LookupFromFile, CurDir, isAngled, LookupFrom, LookupFromFile, CurDir,
Callbacks ? &SearchPath : nullptr, Callbacks ? &SearchPath : nullptr,
Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped); Callbacks ? &RelativePath : nullptr, &SuggestedModule, &IsMapped,
/*IsFrameworkFound=*/nullptr);
if (File) { if (File) {
SourceRange Range(FilenameTok.getLocation(), CharEnd); SourceRange Range(FilenameTok.getLocation(), CharEnd);
auto Hint = isAngled auto Hint = isAngled
@ -1859,9 +1865,22 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc,
} }
// If the file is still not found, just go with the vanilla diagnostic // If the file is still not found, just go with the vanilla diagnostic
if (!File) if (!File) {
Diag(FilenameTok, diag::err_pp_file_not_found) << OriginalFilename Diag(FilenameTok, diag::err_pp_file_not_found) << OriginalFilename
<< FilenameRange; << FilenameRange;
if (IsFrameworkFound) {
size_t SlashPos = OriginalFilename.find('/');
assert(SlashPos != StringRef::npos &&
"Include with framework name should have '/' in the filename");
StringRef FrameworkName = OriginalFilename.substr(0, SlashPos);
FrameworkCacheEntry &CacheEntry =
HeaderInfo.LookupFrameworkCache(FrameworkName);
assert(CacheEntry.Directory && "Found framework should be in cache");
Diag(FilenameTok, diag::note_pp_framework_without_header)
<< OriginalFilename.substr(SlashPos + 1) << FrameworkName
<< CacheEntry.Directory->getName();
}
}
} }
} }

View File

@ -1235,7 +1235,7 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
const DirectoryLookup *CurDir; const DirectoryLookup *CurDir;
const FileEntry *File = const FileEntry *File =
PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile, PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile,
CurDir, nullptr, nullptr, nullptr, nullptr); CurDir, nullptr, nullptr, nullptr, nullptr, nullptr);
if (PPCallbacks *Callbacks = PP.getPPCallbacks()) { if (PPCallbacks *Callbacks = PP.getPPCallbacks()) {
SrcMgr::CharacteristicKind FileType = SrcMgr::C_User; SrcMgr::CharacteristicKind FileType = SrcMgr::C_User;

View File

@ -506,7 +506,7 @@ void Preprocessor::HandlePragmaDependency(Token &DependencyTok) {
const DirectoryLookup *CurDir; const DirectoryLookup *CurDir;
const FileEntry *File = const FileEntry *File =
LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr, LookupFile(FilenameTok.getLocation(), Filename, isAngled, nullptr,
nullptr, CurDir, nullptr, nullptr, nullptr, nullptr); nullptr, CurDir, nullptr, nullptr, nullptr, nullptr, nullptr);
if (!File) { if (!File) {
if (!SuppressIncludeNotFoundError) if (!SuppressIncludeNotFoundError)
Diag(FilenameTok, diag::err_pp_file_not_found) << Filename; Diag(FilenameTok, diag::err_pp_file_not_found) << Filename;

View File

@ -566,7 +566,8 @@ void Preprocessor::EnterMainSourceFile() {
SourceLocation(), PPOpts->PCHThroughHeader, SourceLocation(), PPOpts->PCHThroughHeader,
/*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir, /*isAngled=*/false, /*FromDir=*/nullptr, /*FromFile=*/nullptr, CurDir,
/*SearchPath=*/nullptr, /*RelativePath=*/nullptr, /*SearchPath=*/nullptr, /*RelativePath=*/nullptr,
/*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr); /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr,
/*IsFrameworkFound=*/nullptr);
if (!File) { if (!File) {
Diag(SourceLocation(), diag::err_pp_through_header_not_found) Diag(SourceLocation(), diag::err_pp_through_header_not_found)
<< PPOpts->PCHThroughHeader; << PPOpts->PCHThroughHeader;

View File

@ -0,0 +1,18 @@
// RUN: %clang_cc1 -fsyntax-only -F %S/Inputs -verify %s
// RUN: %clang_cc1 -fsyntax-only -F %S/Inputs -DTYPO_CORRECTION -verify %s
// After finding a requested framework, we don't look for the same framework in
// a different location even if requested header is not found in the framework.
// It can be confusing when there is a framework with required header later in
// header search paths. Mention in diagnostics where the header lookup stopped.
#ifndef TYPO_CORRECTION
#include <TestFramework/NotExistingHeader.h>
// expected-error@-1 {{'TestFramework/NotExistingHeader.h' file not found}}
// expected-note@-2 {{did not find header 'NotExistingHeader.h' in framework 'TestFramework' (loaded from}}
#else
// Don't emit extra note for unsuccessfully typo-corrected include.
#include <#TestFramework/NotExistingHeader.h>
// expected-error@-1 {{'#TestFramework/NotExistingHeader.h' file not found}}
#endif // TYPO_CORRECTION