diff options
author | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2016-10-21 01:41:56 +0000 |
---|---|---|
committer | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2016-10-21 01:41:56 +0000 |
commit | ed84df008f609f7245871a9b6d00b57cb19410aa (patch) | |
tree | f1023c080423e162cdcdc393264e04ad853ce7b0 /clang/lib/Lex/ModuleMap.cpp | |
parent | d15477b09d3142b4301f6e7bc8835ec04d639f59 (diff) | |
download | bcm5719-llvm-ed84df008f609f7245871a9b6d00b57cb19410aa.tar.gz bcm5719-llvm-ed84df008f609f7245871a9b6d00b57cb19410aa.zip |
[Modules] Add 'no_undeclared_includes' module map attribute
The 'no_undeclared_includes' attribute should be used in a module to
tell that only non-modular headers and headers from used modules are
accepted.
The main motivation behind this is to prevent dep cycles between system
libraries (such as darwin) and libc++.
Patch by Richard Smith!
llvm-svn: 284797
Diffstat (limited to 'clang/lib/Lex/ModuleMap.cpp')
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 4b49083bbb6..429b2cc0738 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -327,9 +327,10 @@ static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, return false; } -ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) { +ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, + bool AllowTextual) { auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { - if (R.getRole() & ModuleMap::TextualHeader) + if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) return ModuleMap::KnownHeader(); return R; }; @@ -674,6 +675,8 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, Attrs.IsSystem |= inferred->second.Attrs.IsSystem; Attrs.IsExternC |= inferred->second.Attrs.IsExternC; Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; + Attrs.NoUndeclaredIncludes |= + inferred->second.Attrs.NoUndeclaredIncludes; ModuleMapFile = inferred->second.ModuleMapFile; } } @@ -711,6 +714,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, Result->IsSystem |= Attrs.IsSystem; Result->IsExternC |= Attrs.IsExternC; Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; + Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; Result->Directory = FrameworkDir; // umbrella header "umbrella-header-name" @@ -1309,7 +1313,9 @@ namespace { /// \brief The 'extern_c' attribute. AT_extern_c, /// \brief The 'exhaustive' attribute. - AT_exhaustive + AT_exhaustive, + /// \brief The 'no_undeclared_includes' attribute. + AT_no_undeclared_includes }; } @@ -1479,6 +1485,9 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->IsSystem = true; if (Attrs.IsExternC) ActiveModule->IsExternC = true; + if (Attrs.NoUndeclaredIncludes || + (!ActiveModule->Parent && ModuleName == "Darwin")) + ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; bool Done = false; @@ -1845,13 +1854,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // If Clang supplies this header but the underlying system does not, // just silently swap in our builtin version. Otherwise, we'll end // up adding both (later). - // - // For local visibility, entirely replace the system file with our - // one and textually include the system one. We need to pass macros - // from our header to the system one if we #include_next it. - // - // FIXME: Can we do this in all cases? - if (BuiltinFile && (!File || Map.LangOpts.ModulesLocalVisibility)) { + if (BuiltinFile && !File) { File = BuiltinFile; RelativePathName = BuiltinPathName; BuiltinFile = nullptr; @@ -1877,15 +1880,16 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, Module::Header H = {RelativePathName.str(), File}; Map.excludeHeader(ActiveModule, H); } else { - // If there is a builtin counterpart to this file, add it now, before - // the "real" header, so we build the built-in one first when building - // the module. + // If there is a builtin counterpart to this file, add it now as a textual + // header, so it can be #include_next'd by the wrapper header, and can + // receive macros from the wrapper header. if (BuiltinFile) { // FIXME: Taking the name from the FileEntry is unstable and can give // different results depending on how we've previously named that file // in this build. Module::Header H = { BuiltinFile->getName(), BuiltinFile }; - Map.addHeader(ActiveModule, H, Role); + Map.addHeader(ActiveModule, H, ModuleMap::ModuleHeaderRole( + Role | ModuleMap::TextualHeader)); } // Record this header. @@ -2375,6 +2379,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { = llvm::StringSwitch<AttributeKind>(Tok.getString()) .Case("exhaustive", AT_exhaustive) .Case("extern_c", AT_extern_c) + .Case("no_undeclared_includes", AT_no_undeclared_includes) .Case("system", AT_system) .Default(AT_unknown); switch (Attribute) { @@ -2394,6 +2399,10 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { case AT_exhaustive: Attrs.IsExhaustive = true; break; + + case AT_no_undeclared_includes: + Attrs.NoUndeclaredIncludes = true; + break; } consumeToken(); |