summaryrefslogtreecommitdiffstats
path: root/clang/lib/Lex/PPDirectives.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-04-27 21:57:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-04-27 21:57:05 +0000
commit4eb8393c636b5525ac92ee0ac8efcf263e0a2541 (patch)
tree4e85116ed26bc9b32d45f3fc6002ec97899023b2 /clang/lib/Lex/PPDirectives.cpp
parent575ad8c2e13d6099f67d9d5e816fad8968c6e900 (diff)
downloadbcm5719-llvm-4eb8393c636b5525ac92ee0ac8efcf263e0a2541.tar.gz
bcm5719-llvm-4eb8393c636b5525ac92ee0ac8efcf263e0a2541.zip
[modules] When diagnosing a missing module import, suggest adding a #include if
the current language doesn't have an import syntax and we can figure out a suitable file to include. llvm-svn: 267802
Diffstat (limited to 'clang/lib/Lex/PPDirectives.cpp')
-rw-r--r--clang/lib/Lex/PPDirectives.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 59ea27c5868..c33f9aba267 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -597,6 +597,62 @@ Module *Preprocessor::getModuleContainingLocation(SourceLocation Loc) {
FullSourceLoc(Loc, SourceMgr));
}
+const FileEntry *
+Preprocessor::getModuleHeaderToIncludeForDiagnostics(SourceLocation IncLoc,
+ SourceLocation Loc) {
+ // If we have a module import syntax, we shouldn't include a header to
+ // make a particular module visible.
+ if (getLangOpts().ObjC2)
+ return nullptr;
+
+ // Figure out which module we'd want to import.
+ Module *M = getModuleContainingLocation(Loc);
+ if (!M)
+ return nullptr;
+
+ Module *TopM = M->getTopLevelModule();
+ Module *IncM = getModuleForLocation(IncLoc);
+
+ // Walk up through the include stack, looking through textual headers of M
+ // until we hit a non-textual header that we can #include. (We assume textual
+ // headers of a module with non-textual headers aren't meant to be used to
+ // import entities from the module.)
+ auto &SM = getSourceManager();
+ while (!Loc.isInvalid() && !SM.isInMainFile(Loc)) {
+ auto ID = SM.getFileID(SM.getExpansionLoc(Loc));
+ auto *FE = SM.getFileEntryForID(ID);
+
+ bool InTextualHeader = false;
+ for (auto Header : HeaderInfo.getModuleMap().findAllModulesForHeader(FE)) {
+ if (!Header.getModule()->isSubModuleOf(TopM))
+ continue;
+
+ if (!(Header.getRole() & ModuleMap::TextualHeader)) {
+ // If this is an accessible, non-textual header of M's top-level module
+ // that transitively includes the given location and makes the
+ // corresponding module visible, this is the thing to #include.
+ if (Header.isAccessibleFrom(IncM))
+ return FE;
+
+ // It's in a private header; we can't #include it.
+ // FIXME: If there's a public header in some module that re-exports it,
+ // then we could suggest including that, but it's not clear that's the
+ // expected way to make this entity visible.
+ continue;
+ }
+
+ InTextualHeader = true;
+ }
+
+ if (!InTextualHeader)
+ break;
+
+ Loc = SM.getIncludeLoc(ID);
+ }
+
+ return nullptr;
+}
+
const FileEntry *Preprocessor::LookupFile(
SourceLocation FilenameLoc,
StringRef Filename,
OpenPOWER on IntegriCloud