[all-commits] [llvm/llvm-project] 0cd0aa: [clang][modules] Headers meant to be included mult...

Ian Anderson via All-commits all-commits at lists.llvm.org
Fri Apr 5 10:14:04 PDT 2024


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: 0cd0aa029647c8d1dba5c3d62f92325576796fa2
      https://github.com/llvm/llvm-project/commit/0cd0aa029647c8d1dba5c3d62f92325576796fa2
  Author: Ian Anderson <iana at apple.com>
  Date:   2024-04-05 (Fri, 05 Apr 2024)

  Changed paths:
    M clang/include/clang/Lex/HeaderSearch.h
    M clang/lib/Lex/HeaderSearch.cpp
    M clang/lib/Serialization/ASTReader.cpp
    M clang/test/Modules/builtin-import.mm
    M clang/test/Modules/import-textual-noguard.mm
    M clang/test/Modules/import-textual.mm
    A clang/test/Modules/multiple-import.m

  Log Message:
  -----------
  [clang][modules] Headers meant to be included multiple times can be completely invisible in clang module builds (#83660)

Once a file has been `#import`'ed, it gets stamped as if it was `#pragma
once` and will not be re-entered, even on #include. This means that any
errant #import of a file designed to be included multiple times, such as
<assert.h>, will incorrectly mark it as include-once and break the
multiple include functionality. Normally this isn't a big problem, e.g.
<assert.h> can't have its NDEBUG mode changed after the first #import,
but it is still mostly functional. However, when clang modules are
involved, this can cause the header to be hidden entirely.

Objective-C code most often uses #import for everything, because it's
required for most Objective-C headers to prevent double inclusion and
redeclaration errors. (It's rare for Objective-C headers to use macro
guards or `#pragma once`.) The problem arises when a submodule includes
a multiple-include header. The "already included" state is global across
all modules (which is necessary so that non-modular headers don't get
compiled into multiple translation units and cause redeclaration
errors). If another module or the main file #import's the same header,
it becomes invisible from then on. If the original submodule is not
imported, the include of the header will effectively do nothing and the
header will be invisible. The only way to actually get the header's
declarations is to somehow figure out which submodule consumed the
header, and import that instead. That's basically impossible since it
depends on exactly which modules were built in which order.

#import is a poor indicator of whether a header is actually
include-once, as the #import is external to the header it applies to,
and requires that all inclusions correctly and consistently use #import
vs #include. When modules are enabled, consider a header marked
`textual` in its module as a stronger indicator of multiple-include than
#import's indication of include-once. This will allow headers like
<assert.h> to always be included when modules are enabled, even if
#import is erroneously used somewhere.



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list