This is an archive of the discontinued LLVM Phabricator instance.

Enforce module decl-use restrictions and private header restrictions in textual headers
ClosedPublic

Authored by rsmith on Aug 26 2022, 8:08 PM.

Details

Summary

Per the documentation, these restrictions were intended to apply to textual headers but previously this didn't work because we decided there was no requesting module when the #include was in a textual header.

A -cc1 flag is provided to restore the old behavior for transitionary purposes.

Diff Detail

Event Timeline

rsmith created this revision.Aug 26 2022, 8:08 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 26 2022, 8:08 PM
rsmith requested review of this revision.Aug 26 2022, 8:08 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 26 2022, 8:08 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript
rsmith edited the summary of this revision. (Show Details)Aug 26 2022, 8:08 PM
rsmith updated this revision to Diff 456077.Aug 26 2022, 8:13 PM

Add release notes.

The changes look reasonable to me, though if you think the flag is a temporary one, we might want to consider changes to document that explicitly.

clang/docs/ReleaseNotes.rst
126 ↗(On Diff #456077)

You should mention -fno-modules-validate-textual-header-includes here so that users know there's a transition flag available. Do you expect we'd like to remove that flag in the future, or do you expect we'll need to carry it around "forever"?

rsmith updated this revision to Diff 457742.Sep 2 2022, 6:05 PM

Document the flag to undo the behavior, and mention that it's going away.

clang/docs/ReleaseNotes.rst
126 ↗(On Diff #456077)

I'm hopeful that we only need to keep the flag around while the affected users are transitioning. We know we need it inside Google because with this patch we find a bunch of layering issues that we thought we were already diagnosing, but weren't; I don't know how many other Clang users are actually making use of this part of the module maps functionality. My aim would be to remove the flag after the next release, if possible.

Extended documentation to mention the flag and that it's going away.

aaron.ballman accepted this revision.Sep 6 2022, 8:50 AM

LGTM with a suggestion to also document the command line reference. Thanks!

clang/include/clang/Driver/Options.td
2290
This revision is now accepted and ready to land.Sep 6 2022, 8:50 AM
rsmith updated this revision to Diff 458312.Sep 6 2022, 4:32 PM
rsmith edited the summary of this revision. (Show Details)
  • Help text update from Aaron.
This revision was landed with ongoing or failed builds.Sep 6 2022, 5:14 PM
This revision was automatically updated to reflect the committed changes.

Hi @rsmith, this commit makes it possible for HeaderInfo::LookupFile() to be called with different RequestingModule within single CompilerInstance. This is problematic, since some modules may see headers other modules can't (due to [no_undeclared_includes]). This can permanently mess up contents of the lookup cache (HeaderSearch::LookupFileCache) that uses only the lookup name as the key. You can see the minimal reproducer below. On our side, we can work around this by using -fno-modules-validate-textual-header-includes, but I think this will need to be fixed before that options goes away.

// RUN: rm -rf %t
// RUN: split-file %s %t

//--- include/module.modulemap
module A [no_undeclared_includes] { textual header "A.h" }
module B { header "B.h" }
//--- include/A.h
#if __has_include(<B.h>)
#error Even textual headers within module A now inherit [no_undeclared_includes] \
       and thus do not have that include.
#endif
//--- include/B.h

//--- tu.c
#if !__has_include(<B.h>)
#error Main TU does have that include.
#endif

#include "A.h"

#if !__has_include(<B.h>)
#error Main TU still has that include.
// We hit the above because the unsuccessful __has_include check in A.h taints
// lookup cache (HeaderSearch::LookupFileCache) of this CompilerInstance.
#endif

// RUN: %clang_cc1 -I %t/include -fmodules -fimplicit-module-maps \
// RUN:   -fmodules-cache-path=%t/cache -fsyntax-only %t/tu.c

Hi @rsmith, this commit makes it possible for HeaderInfo::LookupFile() to be called with different RequestingModule within single CompilerInstance. This is problematic, since some modules may see headers other modules can't (due to [no_undeclared_includes]). This can permanently mess up contents of the lookup cache (HeaderSearch::LookupFileCache) that uses only the lookup name as the key.

Hm, interesting. I wonder if this was (subtly) broken before, given that it was previously possible to call LookupFile with different RequestingModules in a single compilation -- once with a null RequestingModule and once with the compilation's current module. In any case, presumably we should either ensure that the cached data is independent of the requesting module (eg, apply the decluse restriction after computing the iterator pair), or add the requesting module to the key, or only cache data for one specific value of RequestingModule. Maybe the simplest thing would be to use a single-item LRU cache here -- store the RequestingModule in the cached result and ignore the existing cached result if it doesn't match the current RequestingModule.