Skip to content

Commit 01400e9

Browse files
vgvassilevhahnjo
authored andcommitted
Implement a module attribute 'optional' to allow missing headers.
This deals with the fact that our modulemaps include headers which can vary across library versions and that attribute is a way to express this.
1 parent 1dd3662 commit 01400e9

File tree

4 files changed

+23
-3
lines changed

4 files changed

+23
-3
lines changed

clang/include/clang/Basic/Module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,9 @@ class alignas(8) Module {
371371
LLVM_PREFERRED_TYPE(bool)
372372
unsigned NoUndeclaredIncludes : 1;
373373

374+
/// Whether the submodule is allowed to have missing headers.
375+
unsigned IsOptional: 1;
376+
374377
/// Whether this module came from a "private" module map, found next
375378
/// to a regular (public) module map.
376379
LLVM_PREFERRED_TYPE(bool)

clang/include/clang/Lex/ModuleMap.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,12 @@ class ModuleMap {
248248
LLVM_PREFERRED_TYPE(bool)
249249
unsigned NoUndeclaredIncludes : 1;
250250

251+
/// Whether we can have a submodule with missing header files.
252+
unsigned IsOptional : 1;
253+
251254
Attributes()
252255
: IsSystem(false), IsExternC(false), IsExhaustive(false),
253-
NoUndeclaredIncludes(false) {}
256+
NoUndeclaredIncludes(false), IsOptional(false) {}
254257
};
255258

256259
/// A directory for which framework modules can be inferred.

clang/lib/Basic/Module.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
4343
IsSystem(false), IsExternC(false), IsInferred(false),
4444
InferSubmodules(false), InferExplicitSubmodules(false),
4545
InferExportWildcard(false), ConfigMacrosExhaustive(false),
46-
NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
46+
NoUndeclaredIncludes(false), IsOptional(false), ModuleMapIsPrivate(false),
4747
NamedModuleHasInit(true), NameVisibility(Hidden) {
4848
if (Parent) {
4949
IsAvailable = Parent->isAvailable();
5050
IsUnimportable = Parent->isUnimportable();
5151
IsSystem = Parent->IsSystem;
5252
IsExternC = Parent->IsExternC;
5353
NoUndeclaredIncludes = Parent->NoUndeclaredIncludes;
54+
IsOptional = Parent->IsOptional;
5455
ModuleMapIsPrivate = Parent->ModuleMapIsPrivate;
5556

5657
Parent->SubModuleIndex[Name] = Parent->SubModules.size();

clang/lib/Lex/ModuleMap.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ void ModuleMap::resolveHeader(Module *Mod,
317317
// this was supposed to modularize the builtin header alone.
318318
} else if (Header.Kind == Module::HK_Excluded) {
319319
// Ignore missing excluded header files. They're optional anyway.
320+
} else if (Mod->IsOptional) {
321+
// Optional submodules can have missing headers.
320322
} else {
321323
// If we find a module that has a missing header, we mark this module as
322324
// unavailable and store the header directive for displaying diagnostics.
@@ -1099,6 +1101,7 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
10991101
Result->IsExternC |= Attrs.IsExternC;
11001102
Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
11011103
Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1104+
Result->IsOptional |= Attrs.IsOptional;
11021105
Result->Directory = FrameworkDir;
11031106

11041107
// Chop off the first framework bit, as that is implied.
@@ -1841,7 +1844,10 @@ namespace {
18411844
AT_exhaustive,
18421845

18431846
/// The 'no_undeclared_includes' attribute.
1844-
AT_no_undeclared_includes
1847+
AT_no_undeclared_includes,
1848+
1849+
/// The 'optional' attribute.
1850+
AT_optional
18451851
};
18461852

18471853
} // namespace
@@ -2118,6 +2124,8 @@ void ModuleMapParser::parseModuleDecl() {
21182124
ActiveModule->IsExternC = true;
21192125
if (Attrs.NoUndeclaredIncludes)
21202126
ActiveModule->NoUndeclaredIncludes = true;
2127+
if (Attrs.IsOptional)
2128+
ActiveModule->IsOptional = true;
21212129
ActiveModule->Directory = Directory;
21222130

21232131
StringRef MapFileName(ModuleMapFile.getName());
@@ -3020,6 +3028,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
30203028
.Case("exhaustive", AT_exhaustive)
30213029
.Case("extern_c", AT_extern_c)
30223030
.Case("no_undeclared_includes", AT_no_undeclared_includes)
3031+
.Case("optional", AT_optional)
30233032
.Case("system", AT_system)
30243033
.Default(AT_unknown);
30253034
switch (Attribute) {
@@ -3043,6 +3052,10 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
30433052
case AT_no_undeclared_includes:
30443053
Attrs.NoUndeclaredIncludes = true;
30453054
break;
3055+
3056+
case AT_optional:
3057+
Attrs.IsOptional = true;
3058+
break;
30463059
}
30473060
consumeToken();
30483061

0 commit comments

Comments
 (0)