This is an archive of the discontinued LLVM Phabricator instance.

Modules: Simulate diagnostic settings for implicit modules
ClosedPublic

Authored by dexonsmith on Mar 14 2017, 2:57 PM.

Details

Summary

This is a follow-up to r293123 that makes it work with implicit modules.

Some background:

An implicit module build (using Clang's internal build system) uses the same PCM file location for different -Werror levels.

E.g., if a TU has -Werror=format and tries to load a PCM built without -Werror=format, a new PCM will be built in its place (and the new PCM should have the same signature, since r297655). In the other direction, if a TU does not have -Werror=format and tries to load a PCM built with -Werror=format, it should "just work".

The idea is to evolve the PCM toward the strictest -Werror flags that anyone tries.

This commit:

r293123 started serializing the diagnostic state for each PCM, which broke the implicit build model.

This commit filters the diagnostic state to match the current compilation's diagnostic settings.

  • Ignore the module's serialized first diagnostic state. Use this TU's state instead.
  • If a pragma warning was upgraded to error/fatal when generating the PCM (e.g., due to -Werror on the command-line), check whether it should still be upgraded in its current context.

Some feedback I'd like on this approach:

  1. The patch-as-is checks whether pragmas should be demoted to warnings for all AST files, not just implicit modules. I can add a bit of logic to ReadPragmaDiagnosticMappings that limits it to F.Kind == MK_ImplicitModule, but I'm not sure it's necessary. Maybe it hits when reading PCH files, but no tests fail, and I'm not sure this is worse... thoughts?
  2. If ReadDiagState sees a back-reference, it doesn't bother to check whether pragmas should be demoted; it assumes it should match whatever was done with the back-reference.
    • I think this could be exercised with -Werror=X on the command-line and pragmas modifying -WX (first "ignored", then "error", then "warning"). Perhaps I should add a FIXME or a comment, but otherwise I think this is okay to miss...
    • It could be a back-reference to CurDiagState, which current gets (de)serialized before the pragma mappings. If we instead (de)serialize CurDiagState last, I think this one goes away. Is there a problem with that?

Diff Detail

Event Timeline

dexonsmith created this revision.Mar 14 2017, 2:57 PM
dexonsmith edited the summary of this revision. (Show Details)
rsmith accepted this revision.Mar 21 2017, 4:12 PM

LGTM

  • The patch-as-is checks whether pragmas should be demoted to warnings for all AST files, not just implicit modules. I can add a bit of logic to ReadPragmaDiagnosticMappings that limits it to F.Kind == MK_ImplicitModule, but I'm not sure it's necessary. Maybe it hits when reading PCH files, but no tests fail, and I'm not sure this is worse... thoughts?

For the PCH and preamble cases, PCHValidator should check that the diagnostic mappings are the same prior to applying the diagnostic pragmas, so there should never be a case where a warning mapping is upgraded to error/fatal error and wasn't when the PCH was built (or vice versa) except when building with -fno-validate-pch. Even in that case, the emergent behavior here seems mostly OK (you imagine what the PCH would have looked like if it were built with the current compilation's warning flags), except...

If you build a PCH that contains #pragma clang diagnostic warning "-Wfoo" and then use it from a -Werror=foo compilation, it looks like we won't notice that we need to upgrade the warning to an error when replaying the PCH's pragma mappings. This is a corner case of a corner case, though.

  • If ReadDiagState sees a back-reference, it doesn't bother to check whether pragmas should be demoted; it assumes it should match whatever was done with the back-reference. I think this could be exercised with -Werror=X on the command-line and pragmas modifying -WX (first "ignored", then "error", then "warning"). Perhaps I should add a FIXME or a comment, but otherwise I think this is okay to miss...

IIRC we only get backreferences from pragma push/pop (and CurDiagState), and I think the push/pop cases will always have the same upgrade behavior (you can't push inside a module and pop outside it, for instance, so the starting state for the push and pop should be consistent).

It could be a back-reference to CurDiagState, which current gets (de)serialized before the pragma mappings. If we instead (de)serialize CurDiagState last, I think this one goes away. Is there a problem with that?

I don't think so, and putting CurDiagState last seems better in general (it keeps the states in something much more like source order). I think I only put it second for convenience (so I didn't need to check whether I'd just read the last state in order to handle it differently).

clang/include/clang/Basic/DiagnosticIDs.h
119–120

This could do with a documentation comment. Something like "Whether this mapping attempted to map the diagnostic to a warning but was overruled because the diagnostic was already mapped to an error or fatal error."

This revision is now accepted and ready to land.Mar 21 2017, 4:12 PM

Thanks for the review! Somehow I missed it until now (I think I must have an "ignore rsmith" filter set up), but I should find a chance to rebase and commit tomorrow or Monday.

dexonsmith closed this revision.Apr 11 2017, 9:16 PM
dexonsmith marked an inline comment as done.

And committed in:
r297770 c0c27f3 Modules: Optimize bitcode encoding of diagnostic state
r300021 5e5be8e Serialization: Skip check in WritePragmaDiagnosticMappings, NFC
r300024 91f051f Serialization: Emit the final diagnostic state last, almost NFC
r300025 d3992c5 Serialization: Simulate -Werror settings in implicit modules

Thanks again for the review.