summaryrefslogtreecommitdiffstats
path: root/clang/lib/Lex/PPDirectives.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Lex/PPDirectives.cpp')
-rw-r--r--clang/lib/Lex/PPDirectives.cpp107
1 files changed, 84 insertions, 23 deletions
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 86d6ad9eb86..75919925961 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -532,6 +532,88 @@ void Preprocessor::PTHSkipExcludedConditionalBlock() {
}
}
+Module *Preprocessor::getModuleForLocation(SourceLocation FilenameLoc) {
+ ModuleMap &ModMap = HeaderInfo.getModuleMap();
+ if (SourceMgr.isInMainFile(FilenameLoc)) {
+ if (Module *CurMod = getCurrentModule())
+ return CurMod; // Compiling a module.
+ return HeaderInfo.getModuleMap().SourceModule; // Compiling a source.
+ }
+ // Try to determine the module of the include directive.
+ FileID IDOfIncl = SourceMgr.getFileID(FilenameLoc);
+ if (const FileEntry *EntryOfIncl = SourceMgr.getFileEntryForID(IDOfIncl)) {
+ // The include comes from a file.
+ return ModMap.findModuleForHeader(EntryOfIncl).getModule();
+ } else {
+ // The include does not come from a file,
+ // so it is probably a module compilation.
+ return getCurrentModule();
+ }
+}
+
+bool Preprocessor::violatesPrivateInclude(
+ Module *RequestingModule,
+ const FileEntry *IncFileEnt,
+ ModuleMap::ModuleHeaderRole Role,
+ Module *RequestedModule) {
+ #ifndef NDEBUG
+ // Check for consistency between the module header role
+ // as obtained from the lookup and as obtained from the module.
+ // This check is not cheap, so enable it only for debugging.
+ SmallVectorImpl<const FileEntry *> &PvtHdrs
+ = RequestedModule->PrivateHeaders;
+ SmallVectorImpl<const FileEntry *>::iterator Look
+ = std::find(PvtHdrs.begin(), PvtHdrs.end(), IncFileEnt);
+ bool IsPrivate = Look != PvtHdrs.end();
+ assert((IsPrivate && Role == ModuleMap::PrivateHeader)
+ || (!IsPrivate && Role != ModuleMap::PrivateHeader));
+ #endif
+ return Role == ModuleMap::PrivateHeader &&
+ RequestedModule->getTopLevelModule() != RequestingModule;
+}
+
+bool Preprocessor::violatesUseDeclarations(
+ Module *RequestingModule,
+ Module *RequestedModule) {
+ ModuleMap &ModMap = HeaderInfo.getModuleMap();
+ ModMap.resolveUses(RequestingModule, /*Complain=*/false);
+ const SmallVectorImpl<Module *> &AllowedUses = RequestingModule->DirectUses;
+ SmallVectorImpl<Module *>::const_iterator Declared =
+ std::find(AllowedUses.begin(), AllowedUses.end(), RequestedModule);
+ return Declared == AllowedUses.end();
+}
+
+void Preprocessor::verifyModuleInclude(
+ SourceLocation FilenameLoc,
+ StringRef Filename,
+ const FileEntry *IncFileEnt,
+ ModuleMap::KnownHeader *SuggestedModule) {
+ Module *RequestingModule = getModuleForLocation(FilenameLoc);
+ Module *RequestedModule = SuggestedModule->getModule();
+ if (!RequestedModule)
+ RequestedModule = HeaderInfo.findModuleForHeader(IncFileEnt).getModule();
+
+ if (RequestingModule == RequestedModule)
+ return; // No faults wihin a module, or between files both not in modules.
+
+ if (RequestingModule != HeaderInfo.getModuleMap().SourceModule)
+ return; // No errors for indirect modules.
+ // This may be a bit of a problem for modules with no source files.
+
+ if (RequestedModule &&
+ violatesPrivateInclude(RequestingModule, IncFileEnt,
+ SuggestedModule->getRole(), RequestedModule))
+ Diag(FilenameLoc, diag::error_use_of_private_header_outside_module)
+ << Filename;
+
+ // FIXME: Add support for FixIts in module map files and offer adding the
+ // required use declaration.
+ if (RequestingModule && getLangOpts().ModulesDeclUse &&
+ violatesUseDeclarations(RequestingModule, RequestedModule))
+ Diag(FilenameLoc, diag::error_undeclared_use_of_module)
+ << Filename;
+}
+
const FileEntry *Preprocessor::LookupFile(
SourceLocation FilenameLoc,
StringRef Filename,
@@ -567,29 +649,8 @@ const FileEntry *Preprocessor::LookupFile(
Filename, isAngled, FromDir, CurDir, CurFileEnt,
SearchPath, RelativePath, SuggestedModule, SkipCache);
if (FE) {
- if (SuggestedModule) {
- Module *RequestedModule = SuggestedModule->getModule();
- if (RequestedModule) {
- ModuleMap::ModuleHeaderRole Role = SuggestedModule->getRole();
- #ifndef NDEBUG
- // Check for consistency between the module header role
- // as obtained from the lookup and as obtained from the module.
- // This check is not cheap, so enable it only for debugging.
- SmallVectorImpl<const FileEntry *> &PvtHdrs
- = RequestedModule->PrivateHeaders;
- SmallVectorImpl<const FileEntry *>::iterator Look
- = std::find(PvtHdrs.begin(), PvtHdrs.end(), FE);
- bool IsPrivate = Look != PvtHdrs.end();
- assert((IsPrivate && Role == ModuleMap::PrivateHeader)
- || (!IsPrivate && Role != ModuleMap::PrivateHeader));
- #endif
- if (Role == ModuleMap::PrivateHeader) {
- if (RequestedModule->getTopLevelModule() != getCurrentModule())
- Diag(FilenameLoc, diag::error_use_of_private_header_outside_module)
- << Filename;
- }
- }
- }
+ if (SuggestedModule)
+ verifyModuleInclude(FilenameLoc, Filename, FE, SuggestedModule);
return FE;
}
OpenPOWER on IntegriCloud