forked from OSchip/llvm-project
[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:
parent
ce10d5ead4
commit
421380a108
|
@ -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">;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
///
|
///
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue