@@ -1307,6 +1307,23 @@ OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
1307
1307
// File Info Management.
1308
1308
// ===----------------------------------------------------------------------===//
1309
1309
1310
+ static void mergeHeaderFileInfoModuleBits (HeaderFileInfo &HFI,
1311
+ bool isModuleHeader,
1312
+ bool isTextualModuleHeader) {
1313
+ assert ((!isModuleHeader || !isTextualModuleHeader) &&
1314
+ " A header can't build with a module and be textual at the same time" );
1315
+ HFI.isModuleHeader |= isModuleHeader;
1316
+ if (HFI.isModuleHeader )
1317
+ HFI.isTextualModuleHeader = false ;
1318
+ else
1319
+ HFI.isTextualModuleHeader |= isTextualModuleHeader;
1320
+ }
1321
+
1322
+ void HeaderFileInfo::mergeModuleMembership (ModuleMap::ModuleHeaderRole Role) {
1323
+ mergeHeaderFileInfoModuleBits (*this , ModuleMap::isModular (Role),
1324
+ (Role & ModuleMap::TextualHeader));
1325
+ }
1326
+
1310
1327
// / Merge the header file info provided by \p OtherHFI into the current
1311
1328
// / header file info (\p HFI)
1312
1329
static void mergeHeaderFileInfo (HeaderFileInfo &HFI,
@@ -1315,7 +1332,8 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
1315
1332
1316
1333
HFI.isImport |= OtherHFI.isImport ;
1317
1334
HFI.isPragmaOnce |= OtherHFI.isPragmaOnce ;
1318
- HFI.isModuleHeader |= OtherHFI.isModuleHeader ;
1335
+ mergeHeaderFileInfoModuleBits (HFI, OtherHFI.isModuleHeader ,
1336
+ OtherHFI.isTextualModuleHeader );
1319
1337
1320
1338
if (!HFI.ControllingMacro && !HFI.ControllingMacroID ) {
1321
1339
HFI.ControllingMacro = OtherHFI.ControllingMacro ;
@@ -1403,94 +1421,119 @@ bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {
1403
1421
void HeaderSearch::MarkFileModuleHeader (FileEntryRef FE,
1404
1422
ModuleMap::ModuleHeaderRole Role,
1405
1423
bool isCompilingModuleHeader) {
1406
- bool isModularHeader = ModuleMap::isModular (Role);
1407
-
1408
1424
// Don't mark the file info as non-external if there's nothing to change.
1409
1425
if (!isCompilingModuleHeader) {
1410
- if (!isModularHeader )
1426
+ if ((Role & ModuleMap::ExcludedHeader) )
1411
1427
return ;
1412
1428
auto *HFI = getExistingFileInfo (FE);
1413
1429
if (HFI && HFI->isModuleHeader )
1414
1430
return ;
1415
1431
}
1416
1432
1417
1433
auto &HFI = getFileInfo (FE);
1418
- HFI.isModuleHeader |= isModularHeader ;
1434
+ HFI.mergeModuleMembership (Role) ;
1419
1435
HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
1420
1436
}
1421
1437
1422
1438
bool HeaderSearch::ShouldEnterIncludeFile (Preprocessor &PP,
1423
1439
FileEntryRef File, bool isImport,
1424
1440
bool ModulesEnabled, Module *M,
1425
1441
bool &IsFirstIncludeOfFile) {
1426
- ++NumIncluded; // Count # of attempted #includes.
1427
-
1442
+ // An include file should be entered if either:
1443
+ // 1. This is the first include of the file.
1444
+ // 2. This file can be included multiple times, that is it's not an
1445
+ // "include-once" file.
1446
+ //
1447
+ // Include-once is controlled by these preprocessor directives.
1448
+ //
1449
+ // #pragma once
1450
+ // This directive is in the include file, and marks it as an include-once
1451
+ // file.
1452
+ //
1453
+ // #import <file>
1454
+ // This directive is in the includer, and indicates that the include file
1455
+ // should only be entered if this is the first include.
1456
+ ++NumIncluded;
1428
1457
IsFirstIncludeOfFile = false ;
1429
-
1430
- // Get information about this file.
1431
1458
HeaderFileInfo &FileInfo = getFileInfo (File);
1432
1459
1433
- // FIXME: this is a workaround for the lack of proper modules-aware support
1434
- // for #import / #pragma once
1435
- auto TryEnterImported = [&]() -> bool {
1460
+ auto MaybeReenterImportedFile = [&]() -> bool {
1436
1461
if (!ModulesEnabled)
1437
1462
return false ;
1463
+ // Modules add a wrinkle though: what's included isn't necessarily visible.
1464
+ // Consider this module.
1465
+ // module Example {
1466
+ // module A { header "a.h" export * }
1467
+ // module B { header "b.h" export * }
1468
+ // }
1469
+ // b.h includes c.h. The main file includes a.h, which will trigger a module
1470
+ // build of Example, and c.h will be included. However, c.h isn't visible to
1471
+ // the main file. Normally this is fine, the main file can just include c.h
1472
+ // if it needs it. If c.h is in a module, the include will translate into a
1473
+ // module import, this function will be skipped, and everything will work as
1474
+ // expected. However, if c.h is not in a module (or is `textual`), then this
1475
+ // function will run. If c.h is include-once, it will not be entered from
1476
+ // the main file and it will still not be visible.
1477
+
1438
1478
// Ensure FileInfo bits are up to date.
1439
1479
ModMap.resolveHeaderDirectives (File);
1440
- // Modules with builtins are special; multiple modules use builtins as
1441
- // modular headers, example:
1442
- //
1443
- // module stddef { header "stddef.h" export * }
1444
- //
1445
- // After module map parsing, this expands to:
1446
- //
1447
- // module stddef {
1448
- // header "/path_to_builtin_dirs/stddef.h"
1449
- // textual "stddef.h"
1450
- // }
1480
+
1481
+ // This brings up a subtlety of #import - it's not a very good indicator of
1482
+ // include-once. Developers are often unaware of the difference between
1483
+ // #include and #import, and tend to use one or the other indiscrimiately.
1484
+ // In order to support #include on include-once headers that lack macro
1485
+ // guards and `#pragma once` (which is the vast majority of Objective-C
1486
+ // headers), if a file is ever included with #import, it's marked as
1487
+ // isImport in the HeaderFileInfo and treated as include-once. This allows
1488
+ // #include to work in Objective-C.
1489
+ // #include <Foundation/Foundation.h>
1490
+ // #include <Foundation/NSString.h>
1491
+ // Foundation.h has an #import of NSString.h, and so the second #include is
1492
+ // skipped even though NSString.h has no `#pragma once` and no macro guard.
1451
1493
//
1452
- // It's common that libc++ and system modules will both define such
1453
- // submodules. Make sure cached results for a builtin header won't
1454
- // prevent other builtin modules from potentially entering the builtin
1455
- // header. Note that builtins are header guarded and the decision to
1456
- // actually enter them is postponed to the controlling macros logic below.
1457
- bool TryEnterHdr = false ;
1458
- if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader )
1459
- TryEnterHdr = ModMap.isBuiltinHeader (File);
1460
-
1461
- // Textual headers can be #imported from different modules. Since ObjC
1462
- // headers find in the wild might rely only on #import and do not contain
1463
- // controlling macros, be conservative and only try to enter textual headers
1464
- // if such macro is present.
1465
- if (!FileInfo.isModuleHeader &&
1466
- FileInfo.getControllingMacro (ExternalLookup))
1467
- TryEnterHdr = true ;
1468
- return TryEnterHdr;
1494
+ // However, this helpfulness causes problems with modules. If c.h is not an
1495
+ // include-once file, but something included it with #import anyway (as is
1496
+ // typical in Objective-C code), this include will be skipped and c.h will
1497
+ // not be visible. If the file is not `#pragma once`, consider it not
1498
+ // include-once if it is a `textual` header in a module.
1499
+ return !FileInfo.isPragmaOnce && FileInfo.isTextualModuleHeader ;
1500
+ // If the include file has a macro guard, then it might still not be
1501
+ // re-entered if the controlling macro is visibly defined. e.g. another
1502
+ // header in the module being built included this file and local submodule
1503
+ // visibility is not enabled.
1504
+
1505
+ // It might be tempting to re-enter the include-once file if it's not
1506
+ // visible in an attempt to make it visible. However this will still cause
1507
+ // redeclaration errors against the known-but-not-visible declarations. The
1508
+ // include file not being visible will most likely cause "undefined x"
1509
+ // errors, but at least there's a slim chance of compilation succeeding.
1469
1510
};
1470
1511
1471
- // If this is a #import directive, check that we have not already imported
1472
- // this header.
1473
1512
if (isImport) {
1474
- // If this has already been imported, don't import it again.
1513
+ // As discussed above, record that this file was ever `#import`ed, and treat
1514
+ // it as an include-once file from here out.
1475
1515
FileInfo.isImport = true ;
1476
-
1477
- // Has this already been #import'ed or #include'd?
1478
- if (PP.alreadyIncluded (File) && !TryEnterImported ())
1516
+ if (PP.alreadyIncluded (File) && !MaybeReenterImportedFile ())
1479
1517
return false ;
1480
1518
} else {
1481
- // Otherwise, if this is a #include of a file that was previously #import'd
1482
- // or if this is the second #include of a #pragma once file, ignore it.
1483
- if ((FileInfo.isPragmaOnce || FileInfo.isImport ) && !TryEnterImported ())
1519
+ // isPragmaOnce and isImport are only set after the file has been included
1520
+ // at least once. If either are set then this is a repeat #include of an
1521
+ // include-once file.
1522
+ if (FileInfo.isPragmaOnce ||
1523
+ (FileInfo.isImport && !MaybeReenterImportedFile ()))
1484
1524
return false ;
1485
1525
}
1486
1526
1487
- // Next, check to see if the file is wrapped with #ifndef guards. If so, and
1488
- // if the macro that guards it is defined, we know the #include has no effect.
1489
- if (const IdentifierInfo *ControllingMacro
1490
- = FileInfo.getControllingMacro (ExternalLookup)) {
1527
+ // As a final optimization, check for a macro guard and skip entering the file
1528
+ // if the controlling macro is defined. The macro guard will effectively erase
1529
+ // the file's contents, and the include would have no effect other than to
1530
+ // waste time opening and reading a file.
1531
+ if (const IdentifierInfo *ControllingMacro =
1532
+ FileInfo.getControllingMacro (ExternalLookup)) {
1491
1533
// If the header corresponds to a module, check whether the macro is already
1492
- // defined in that module rather than checking in the current set of visible
1493
- // modules.
1534
+ // defined in that module rather than checking all visible modules. This is
1535
+ // mainly to cover corner cases where the same controlling macro is used in
1536
+ // different files in multiple modules.
1494
1537
if (M ? PP.isMacroDefinedInLocalModule (ControllingMacro, M)
1495
1538
: PP.isMacroDefined (ControllingMacro)) {
1496
1539
++NumMultiIncludeFileOptzn;
@@ -1499,7 +1542,6 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
1499
1542
}
1500
1543
1501
1544
IsFirstIncludeOfFile = PP.markIncluded (File);
1502
-
1503
1545
return true ;
1504
1546
}
1505
1547
0 commit comments