This is an archive of the discontinued LLVM Phabricator instance.

[clang] Add `// expected-maybe-no-diagnostics` comment to VerifyDiagnosticConsumer
AcceptedPublic

Authored by Endill on May 24 2023, 5:22 AM.

Details

Summary

This patch introduces a // expected-maybe-not-diagnostics that silence warnings about missing // expected-no-diagnostic, but doesn't conflict with neither // expected-error directives nor // expected-no-diagnostics.

I go into details in the Discourse thread about why we need this, and why we need this in the form implemented.

Diff Detail

Event Timeline

Endill created this revision.May 24 2023, 5:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 24 2023, 5:22 AM
Endill requested review of this revision.May 24 2023, 5:22 AM
Herald added a project: Restricted Project. · View Herald TranscriptMay 24 2023, 5:22 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

This patch introduces a // expected-maybe-not-diagnostic that silence

typo in the summary, it introduces // expected-maybe-no-diagnostics

To save other reviewers some clicking around, the reason why this is being proposed is because we want to use the split-file utility to separate monolithic DR tests into individual test cases to keep them hermetic. We could require each individual test within the greater file to specify // expected-no-diagnostics, but that adds quite a bit of noise to the test file due to how often those comments need to repeat. The idea behind this patch is that we can use one // expected-maybe-no-diagnostics marking in a header file that is force included on the RUN lines for the file. This way, each split off file says "if you get no diagnostics, that's fine". In the case where the file legitimately has no diagnostics, we pass that test. But in the case where the file does expect diagnostics, we avoid the "expected no diagnostics, but got diagnostics" failure mode. This allows us to continue to group DRs by number instead of by whether they expect diagnostics or not.

clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
279
Endill edited the summary of this revision. (Show Details)May 24 2023, 9:18 AM
Endill updated this revision to Diff 525216.May 24 2023, 9:24 AM

Add missing comma after enum item

Endill marked an inline comment as done.EditedMay 24 2023, 9:26 AM

Thank you for providing a nice explanation!

jdenny added a subscriber: jdenny.May 25 2023, 7:45 AM

Thanks for working on this. I've been wanting something like it too. In downstream work, I've used a hack that seems to accomplish the same thing but probably shouldn't: expected-error 0 {{}}.

Anyway, please add documentation for the new directive here: https://clang.llvm.org/doxygen/classclang_1_1VerifyDiagnosticConsumer.html#details

clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

This continue skips the prefix checking below, which is important when there are multiple prefixes active (e.g., -verify=foo,bar). That is, any old BOGUS-maybe-no-diagnostics will be effective then.

clang/test/Frontend/verify-maybe-no-diagnostics.c
39

Please test this case:

#ifdef TEST_C3
// expected-maybe-no-diagnostics
#error test_c3
#endif

That is, does Clang actually fail in this case as expected because there's an error and no corresponding expected-error directive? Or does it ignore the error because of the expected-maybe-no-diagnostics directive?

52–53

So expected-no-diagnostics overrides expected-maybe-no-diagnostics. In your use case, omitting one or the other is not always possible?

105

This diagnostic is confusing. Should we add "except 'expected-maybe-no-diagnostics'"?

Endill updated this revision to Diff 526013.May 26 2023, 3:49 AM
Endill edited the summary of this revision. (Show Details)

Address feedback
Docs contributed by @aaron.ballman

Thank you for the review!

clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

This should be fixed now. Thank you for spotting this!

clang/test/Frontend/verify-maybe-no-diagnostics.c
39

Added C2 and C4 tests that should cover that.

That is, does Clang actually fail in this case as expected because there's an error and no corresponding expected-error directive? Or does it ignore the error because of the expected-maybe-no-diagnostics directive?

It works like there's no // expected-maybe-no-diagnostics. That is, failing because there's no matching expected-error directive for an error produced.

52–53

Yes, it works the way you describe.
In our case, // expected-maybe-no-diagnostic comes into hundreds of test cases from force include. It's very much possible for us to ensure that only one of them is present, by banning expected-no-diagnostics.

expected-maybe-no-diagnostic is by design low-priority and no-friction directive, contrary to strict nature of all other directives. That's why it could be very easily overridden.

105

As I mentioned in another comment, maybe-no-diagnostics has the lowest priority, and doesn't have strict and declarative nature, unlike any other directive. That's why it should never be expected (and ideally very rarely used).

The purpose of all the tests I added is to ensure expected-no-diagnostic doesn't affect existing directives and their interaction in any way.

jdenny added inline comments.May 26 2023, 8:06 AM
clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
186–202

Thanks for adding documentation.

I feel that this edit makes the behavior a little clearer, and it clarifies what happens when "expected-no-diagnostics" and "expected-maybe-no-diagnostics" are combined.

Also, the original text had:

but they do not fail automatically due to a combination of "expected-no-diagnostics" and "expected-*" within the same test

That reads to me like it's ok to combine "expected-no-diagnostics" and "expected-*" directives specifying diagnostics. Hopefully this edit clarifies that point.

clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

Thanks for the fix. Please add a test so this bug doesn't pop up again.

472–473

Shouldn't expected-maybe-no-diagnostics have this too so that expected-maybe-no-diagnostics-re is skipped? Please add a test.

clang/test/Frontend/verify-maybe-no-diagnostics.c
105

I don't see how that addresses my concern. Maybe it's because, after the latest edits, phab shifted my comment to the wrong test. I was originally commenting on this:

'expected-no-diagnostics' directive cannot follow other expected directives

This message is now incorrect. expected-no-diagnostics can follow expected-maybe-no-diagnostics. What if we reword as follows?

'expected-no-diagnostics' directive cannot follow directives that expect diagnostics

Endill updated this revision to Diff 526101.May 26 2023, 9:49 AM

Address feedback

Endill added inline comments.May 26 2023, 9:54 AM
clang/include/clang/Frontend/VerifyDiagnosticConsumer.h
186–202

Yeah, it's better the way you propose.

clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

Done as A2 test

472–473

You're right, there's no good reason for us not to do the same. Though I don't like that we silently skip over not-too-sensical // expected-no-diagnostics-re. I'll prepare a follow-up patch that makes -re a hard error for those two special directives.

Tested in A3

clang/test/Frontend/verify-maybe-no-diagnostics.c
105

Sorry, I misunderstood your initial comment. It's fixed now.

jdenny accepted this revision.May 26 2023, 10:13 AM

Thanks for addressing all my concerns.

LGTM except for a test issue I just commented on.

clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

Does A2 trigger the original bug? I think there must be multiple prefixes for this fix to matter.

This revision is now accepted and ready to land.May 26 2023, 10:13 AM

Thank you for your time!

clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469
jdenny added inline comments.May 27 2023, 7:21 AM
clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

I downloaded this version of your patch: https://reviews.llvm.org/D151320?vs=on&id=525216. That version has the bug discussed in this comment thread.

I applied that patch and added test A2. A2 passed. That means A2 does not reproduce the bug it was intended to reproduce.

Then I changed A2 to have -verify=foo,bar. A2 then failed because it then reproduced the bug. (And of course with the current version of your patch, it passes because you've fixed the bug.)

Please add such a test.

Endill updated this revision to Diff 526277.May 27 2023, 10:42 AM

Replace A2 test with E1-E3 tests

Endill added inline comments.May 27 2023, 10:48 AM
clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

I replaced A2 test with more comprehensive E set of tests.

Surprisingly to me, -verify and -verify=foo,bar work quite differently because of PH.Search() call 40 lines above. I can't say I have full understanding what's going on, so I wrote a more comprehensive set of tests. Does this address your concern?

jdenny accepted this revision.May 27 2023, 11:03 AM
jdenny added inline comments.
clang/lib/Frontend/VerifyDiagnosticConsumer.cpp
469

Surprisingly to me, -verify and -verify=foo,bar work quite differently because of PH.Search() call 40 lines above. I can't say I have full understanding what's going on,

That line is optimized for the case of a single prefix: it ignores text without that prefix. If there are multiple prefixes, then it searches for a more general pattern and waits until the std::binary_search call below to worry about the prefix.

so I wrote a more comprehensive set of tests. Does this address your concern?

Yes, and thanks for the extra testing.