Introduce module attributes into the module map grammar, along with a
single attribute ("system") that allows us to mark a module as being a
"system" module. Each of the headers that makes up a system module is
considered to be a system header, so that we (for example) suppress
warnings there.
If a module is being inferred for a framework, and that framework
directory is within a system frameworks directory, infer it as a
system framework.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149143 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 7af7c93..ff63bdb 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -134,7 +134,9 @@
llvm::sys::path::append(FrameworkDirName, ModuleName + ".framework");
if (const DirectoryEntry *FrameworkDir
= FileMgr.getDirectory(FrameworkDirName)) {
- Module = getFrameworkModule(ModuleName, FrameworkDir);
+ bool IsSystem
+ = SearchDirs[Idx].getDirCharacteristic() != SrcMgr::C_User;
+ Module = getFrameworkModule(ModuleName, FrameworkDir, IsSystem);
if (Module)
break;
}
@@ -319,8 +321,10 @@
Module *Module = 0;
if (SuggestedModule) {
if (const DirectoryEntry *FrameworkDir
- = FileMgr.getDirectory(FrameworkName))
- Module = HS.getFrameworkModule(ModuleName, FrameworkDir);
+ = FileMgr.getDirectory(FrameworkName)) {
+ bool IsSystem = getDirCharacteristic() != SrcMgr::C_User;
+ Module = HS.getFrameworkModule(ModuleName, FrameworkDir, IsSystem);
+ }
}
// Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h"
@@ -858,7 +862,8 @@
}
Module *HeaderSearch::getFrameworkModule(StringRef Name,
- const DirectoryEntry *Dir) {
+ const DirectoryEntry *Dir,
+ bool IsSystem) {
if (Module *Module = ModMap.findModule(Name))
return Module;
@@ -907,7 +912,8 @@
// Try to infer a module map from the top-level framework directory.
Module *Result = ModMap.inferFrameworkModule(SubmodulePath.back(),
- TopFrameworkDir,
+ TopFrameworkDir,
+ IsSystem,
/*Parent=*/0);
// Follow the submodule path to find the requested (sub)framework module
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 08a1e23..708da94 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -284,6 +284,7 @@
Module *
ModuleMap::inferFrameworkModule(StringRef ModuleName,
const DirectoryEntry *FrameworkDir,
+ bool IsSystem,
Module *Parent) {
// Check whether we've already found this module.
if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
@@ -305,6 +306,9 @@
Module *Result = new Module(ModuleName, SourceLocation(), Parent,
/*IsFramework=*/true, /*IsExplicit=*/false);
+ if (IsSystem)
+ Result->IsSystem = IsSystem;
+
if (!Parent)
Modules[ModuleName] = Result;
@@ -338,7 +342,7 @@
= FileMgr.getDirectory(Dir->path())) {
// FIXME: Do we want to warn about subframeworks without umbrella headers?
inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir,
- Result);
+ IsSystem, Result);
}
}
@@ -454,7 +458,9 @@
Star,
StringLiteral,
LBrace,
- RBrace
+ RBrace,
+ LSquare,
+ RSquare
} Kind;
unsigned Location;
@@ -579,6 +585,10 @@
Tok.Kind = MMToken::LBrace;
break;
+ case tok::l_square:
+ Tok.Kind = MMToken::LSquare;
+ break;
+
case tok::period:
Tok.Kind = MMToken::Period;
break;
@@ -587,6 +597,10 @@
Tok.Kind = MMToken::RBrace;
break;
+ case tok::r_square:
+ Tok.Kind = MMToken::RSquare;
+ break;
+
case tok::star:
Tok.Kind = MMToken::Star;
break;
@@ -625,27 +639,42 @@
void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
unsigned braceDepth = 0;
+ unsigned squareDepth = 0;
do {
switch (Tok.Kind) {
case MMToken::EndOfFile:
return;
case MMToken::LBrace:
- if (Tok.is(K) && braceDepth == 0)
+ if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
return;
++braceDepth;
break;
-
+
+ case MMToken::LSquare:
+ if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
+ return;
+
+ ++squareDepth;
+ break;
+
case MMToken::RBrace:
if (braceDepth > 0)
--braceDepth;
else if (Tok.is(K))
return;
break;
-
+
+ case MMToken::RSquare:
+ if (squareDepth > 0)
+ --squareDepth;
+ else if (Tok.is(K))
+ return;
+ break;
+
default:
- if (braceDepth == 0 && Tok.is(K))
+ if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
return;
break;
}
@@ -681,10 +710,28 @@
return false;
}
+namespace {
+ /// \brief Enumerates the known attributes.
+ enum AttributeKind {
+ /// \brief An unknown attribute.
+ AT_unknown,
+ /// \brief The 'system' attribute.
+ AT_system
+ };
+}
+
/// \brief Parse a module declaration.
///
/// module-declaration:
-/// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* }
+/// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
+/// { module-member* }
+///
+/// attributes:
+/// attribute attributes
+/// attribute
+///
+/// attribute:
+/// [ identifier ]
///
/// module-member:
/// requires-declaration
@@ -777,6 +824,49 @@
StringRef ModuleName = Id.back().first;
SourceLocation ModuleNameLoc = Id.back().second;
+ // Parse the optional attribute list.
+ bool IsSystem = false;
+ while (Tok.is(MMToken::LSquare)) {
+ // Consume the '['.
+ SourceLocation LSquareLoc = consumeToken();
+
+ // Check whether we have an attribute name here.
+ if (!Tok.is(MMToken::Identifier)) {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
+ skipUntil(MMToken::RSquare);
+ if (Tok.is(MMToken::RSquare))
+ consumeToken();
+ continue;
+ }
+
+ // Decode the attribute name.
+ AttributeKind Attribute
+ = llvm::StringSwitch<AttributeKind>(Tok.getString())
+ .Case("system", AT_system)
+ .Default(AT_unknown);
+ switch (Attribute) {
+ case AT_unknown:
+ Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
+ << Tok.getString();
+ break;
+
+ case AT_system:
+ IsSystem = true;
+ break;
+ }
+ consumeToken();
+
+ // Consume the ']'.
+ if (!Tok.is(MMToken::RSquare)) {
+ Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
+ Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
+ skipUntil(MMToken::RSquare);
+ }
+
+ if (Tok.is(MMToken::RSquare))
+ consumeToken();
+ }
+
// Parse the opening brace.
if (!Tok.is(MMToken::LBrace)) {
Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
@@ -818,6 +908,8 @@
ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
Explicit).first;
ActiveModule->DefinitionLoc = ModuleNameLoc;
+ if (IsSystem)
+ ActiveModule->IsSystem = true;
bool Done = false;
do {
@@ -1251,8 +1343,10 @@
case MMToken::HeaderKeyword:
case MMToken::Identifier:
case MMToken::LBrace:
+ case MMToken::LSquare:
case MMToken::Period:
case MMToken::RBrace:
+ case MMToken::RSquare:
case MMToken::RequiresKeyword:
case MMToken::Star:
case MMToken::StringLiteral: