@@ -1307,6 +1307,23 @@ OptionalFileEntryRef HeaderSearch::LookupSubframeworkHeader(
13071307// File Info Management.
13081308// ===----------------------------------------------------------------------===//
13091309
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+
13101327// / Merge the header file info provided by \p OtherHFI into the current
13111328// / header file info (\p HFI)
13121329static void mergeHeaderFileInfo (HeaderFileInfo &HFI,
@@ -1315,7 +1332,8 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
13151332
13161333 HFI.isImport |= OtherHFI.isImport ;
13171334 HFI.isPragmaOnce |= OtherHFI.isPragmaOnce ;
1318- HFI.isModuleHeader |= OtherHFI.isModuleHeader ;
1335+ mergeHeaderFileInfoModuleBits (HFI, OtherHFI.isModuleHeader ,
1336+ OtherHFI.isTextualModuleHeader );
13191337
13201338 if (!HFI.ControllingMacro && !HFI.ControllingMacroID ) {
13211339 HFI.ControllingMacro = OtherHFI.ControllingMacro ;
@@ -1403,94 +1421,146 @@ bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {
14031421void HeaderSearch::MarkFileModuleHeader (FileEntryRef FE,
14041422 ModuleMap::ModuleHeaderRole Role,
14051423 bool isCompilingModuleHeader) {
1406- bool isModularHeader = ModuleMap::isModular (Role);
1407-
14081424 // Don't mark the file info as non-external if there's nothing to change.
14091425 if (!isCompilingModuleHeader) {
1410- if (!isModularHeader )
1426+ if ((Role & ModuleMap::ExcludedHeader) )
14111427 return ;
14121428 auto *HFI = getExistingFileInfo (FE);
14131429 if (HFI && HFI->isModuleHeader )
14141430 return ;
14151431 }
14161432
14171433 auto &HFI = getFileInfo (FE);
1418- HFI.isModuleHeader |= isModularHeader ;
1434+ HFI.mergeModuleMembership (Role) ;
14191435 HFI.isCompilingModuleHeader |= isCompilingModuleHeader;
14201436}
14211437
14221438bool HeaderSearch::ShouldEnterIncludeFile (Preprocessor &PP,
14231439 FileEntryRef File, bool isImport,
14241440 bool ModulesEnabled, Module *M,
14251441 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;
14281457 IsFirstIncludeOfFile = false ;
1429-
1430- // Get information about this file.
14311458 HeaderFileInfo &FileInfo = getFileInfo (File);
14321459
1433- // FIXME: this is a workaround for the lack of proper modules-aware support
1434- // for #import / #pragma once
1435- auto TryEnterImported = [&]() -> bool {
1436- if (!ModulesEnabled)
1460+ auto MaybeReenterImportedFile = [&]() -> bool {
1461+ // Modules add a wrinkle though: what's included isn't necessarily visible.
1462+ // Consider this module.
1463+ // module Example {
1464+ // module A { header "a.h" export * }
1465+ // module B { header "b.h" export * }
1466+ // }
1467+ // b.h includes c.h. The main file includes a.h, which will trigger a module
1468+ // build of Example, and c.h will be included. However, c.h isn't visible to
1469+ // the main file. Normally this is fine, the main file can just include c.h
1470+ // if it needs it. If c.h is in a module, the include will translate into a
1471+ // module import, this function will be skipped, and everything will work as
1472+ // expected. However, if c.h is not in a module (or is `textual`), then this
1473+ // function will run. If c.h is include-once, it will not be entered from
1474+ // the main file and it will still not be visible.
1475+
1476+ // If modules aren't enabled then there's no visibility issue. Always
1477+ // respect `#pragma once`.
1478+ if (!ModulesEnabled || FileInfo.isPragmaOnce )
14371479 return false ;
1480+
14381481 // Ensure FileInfo bits are up to date.
14391482 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- // }
1483+
1484+ // This brings up a subtlety of #import - it's not a very good indicator of
1485+ // include-once. Developers are often unaware of the difference between
1486+ // #include and #import, and tend to use one or the other indiscrimiately.
1487+ // In order to support #include on include-once headers that lack macro
1488+ // guards and `#pragma once` (which is the vast majority of Objective-C
1489+ // headers), if a file is ever included with #import, it's marked as
1490+ // isImport in the HeaderFileInfo and treated as include-once. This allows
1491+ // #include to work in Objective-C.
1492+ // #include <Foundation/Foundation.h>
1493+ // #include <Foundation/NSString.h>
1494+ // Foundation.h has an #import of NSString.h, and so the second #include is
1495+ // skipped even though NSString.h has no `#pragma once` and no macro guard.
14511496 //
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;
1497+ // However, this helpfulness causes problems with modules. If c.h is not an
1498+ // include-once file, but something included it with #import anyway (as is
1499+ // typical in Objective-C code), this include will be skipped and c.h will
1500+ // not be visible. Consider it not include-once if it is a `textual` header
1501+ // in a module.
1502+ if (FileInfo.isTextualModuleHeader )
1503+ return true ;
1504+
1505+ if (FileInfo.isCompilingModuleHeader ) {
1506+ // It's safer to re-enter a file whose module is being built because its
1507+ // declarations will still be scoped to a single module.
1508+ if (FileInfo.isModuleHeader ) {
1509+ // Headers marked as "builtin" are covered by the system module maps
1510+ // rather than the builtin ones. Some versions of the Darwin module fail
1511+ // to mark stdarg.h and stddef.h as textual. Attempt to re-enter these
1512+ // files while building their module to allow them to function properly.
1513+ if (ModMap.isBuiltinHeader (File))
1514+ return true ;
1515+ } else {
1516+ // Files that are excluded from their module can potentially be
1517+ // re-entered from their own module. This might cause redeclaration
1518+ // errors if another module saw this file first, but there's a
1519+ // reasonable chance that its module will build first. However if
1520+ // there's no controlling macro, then trust the #import and assume this
1521+ // really is an include-once file.
1522+ if (FileInfo.getControllingMacro (ExternalLookup))
1523+ return true ;
1524+ }
1525+ }
1526+ // If the include file has a macro guard, then it might still not be
1527+ // re-entered if the controlling macro is visibly defined. e.g. another
1528+ // header in the module being built included this file and local submodule
1529+ // visibility is not enabled.
1530+
1531+ // It might be tempting to re-enter the include-once file if it's not
1532+ // visible in an attempt to make it visible. However this will still cause
1533+ // redeclaration errors against the known-but-not-visible declarations. The
1534+ // include file not being visible will most likely cause "undefined x"
1535+ // errors, but at least there's a slim chance of compilation succeeding.
1536+ return false ;
14691537 };
14701538
1471- // If this is a #import directive, check that we have not already imported
1472- // this header.
14731539 if (isImport) {
1474- // If this has already been imported, don't import it again.
1540+ // As discussed above, record that this file was ever `#import`ed, and treat
1541+ // it as an include-once file from here out.
14751542 FileInfo.isImport = true ;
1476-
1477- // Has this already been #import'ed or #include'd?
1478- if (PP.alreadyIncluded (File) && !TryEnterImported ())
1543+ if (PP.alreadyIncluded (File) && !MaybeReenterImportedFile ())
14791544 return false ;
14801545 } 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 ())
1546+ // isPragmaOnce and isImport are only set after the file has been included
1547+ // at least once. If either are set then this is a repeat #include of an
1548+ // include-once file.
1549+ if (FileInfo.isPragmaOnce ||
1550+ (FileInfo.isImport && !MaybeReenterImportedFile ()))
14841551 return false ;
14851552 }
14861553
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)) {
1554+ // As a final optimization, check for a macro guard and skip entering the file
1555+ // if the controlling macro is defined. The macro guard will effectively erase
1556+ // the file's contents, and the include would have no effect other than to
1557+ // waste time opening and reading a file.
1558+ if (const IdentifierInfo *ControllingMacro =
1559+ FileInfo.getControllingMacro (ExternalLookup)) {
14911560 // 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.
1561+ // defined in that module rather than checking all visible modules. This is
1562+ // mainly to cover corner cases where the same controlling macro is used in
1563+ // different files in multiple modules.
14941564 if (M ? PP.isMacroDefinedInLocalModule (ControllingMacro, M)
14951565 : PP.isMacroDefined (ControllingMacro)) {
14961566 ++NumMultiIncludeFileOptzn;
@@ -1499,7 +1569,6 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
14991569 }
15001570
15011571 IsFirstIncludeOfFile = PP.markIncluded (File);
1502-
15031572 return true ;
15041573}
15051574
0 commit comments