This is an archive of the discontinued LLVM Phabricator instance.

[clang] Extend pragma dump to support expressions
ClosedPublic

Authored by Endill on Feb 15 2023, 9:56 AM.

Details

Reviewers
aaron.ballman
Group Reviewers
Restricted Project
Commits
rG467ed2798772: [clang] Extend pragma dump to support expressions
Summary

Extend #pragma clang __debug dump to support not only single identifier, but an expression as well. This makes it possible to test ADL and overload resolution directly, without being creative to make them observable via diagnostics (e.g. when over.match.best is involved). This implementation has a known limitation of not supporting dependent expressions properly, but it's quite useful even without such support.

Diff Detail

Event Timeline

Endill created this revision.Feb 15 2023, 9:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 15 2023, 9:56 AM
Endill requested review of this revision.Feb 15 2023, 9:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 15 2023, 9:56 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Thanks for this! You should add test coverage for the changes, especially around things like dependent expressions, ADL use, etc. Also, the changes need a release note and the new functionality should be explicitly documented.

clang/lib/Parse/ParsePragma.cpp
723–727

I think you should have another variant of ActOnPragmaDump that does the actual dumping, instead of doing it from the parser. I think we should not try to dump a dependent expression (to support those, I think we need to create a new AST node for the pragma so that we can transform it from TreeTransform.h and perform the dump on the non-dependent expression -- not certain if we want to handle that now, or if we want it to be an error to use this pragma with a dependent expression).

Thank you for reviewing this!

You should add test coverage for the changes, especially around things like dependent expressions, ADL use, etc. Also, the changes need a release note and the new functionality should be explicitly documented.

Despite having a dozen of #pragma __debug directives, none of them are tested neither mentioned in any kind of documentation, including release notes. Are you sure about this? If so, what is the right place to put them into?

clang/lib/Parse/ParsePragma.cpp
723–727

I think you should have another variant of ActOnPragmaDump that does the actual dumping, instead of doing it from the parser.

Would it be fine to do it like this: Actions.ActOnPragmaDump(E), where E is the result of ParseExpression()?

I think we should not try to dump a dependent expression (to support those, I think we need to create a new AST node for the pragma so that we can transform it from TreeTransform.h and perform the dump on the non-dependent expression -- not certain if we want to handle that now, or if we want it to be an error to use this pragma with a dependent expression).

As I mentioned in summary, dependent expressions are out of scope of this patch. How can I test whether expression is dependent?

Despite having a dozen of #pragma __debug directives, none of them are tested neither mentioned in any kind of documentation, including release notes. Are you sure about this? If so, what is the right place to put them into?

Yeah, we've been very bad about documenting our implementation-defined behaviors and I've been on a push to change that moving forward for about the past year or so. You don't have to document all of the debug pragmas by any means, but getting some basic documentation up for the pragma being worked on is good incremental progress. I'd recommend adding the tests to clang/test/Preprocessor and adding the documentation to clang\docs\LanguageExtensions.rst.

clang/lib/Parse/ParsePragma.cpp
723–727

I think you should have another variant of ActOnPragmaDump that does the actual dumping, instead of doing it from the parser.

Would it be fine to do it like this: Actions.ActOnPragmaDump(E), where E is the result of ParseExpression()?

I think it'd make sense to do Actions.ActOnPragmaDump(Tok.getLocation(), ParseExpression()); so that we have the location of the pragma token itself in addition to the expression result for the argument.

As I mentioned in summary, dependent expressions are out of scope of this patch. How can I test whether expression is dependent?

Expr::isValueDependent() and Expr::isTypeDependent()

Endill updated this revision to Diff 504673.Mar 13 2023, 8:35 AM
  • Diagnose dependent expressions
  • Move AST dumping from parser to sema
  • Add documentation
  • Add tests

You should also add a release note to clang/docs/ReleaseNotes.rst so users know about the new functionality.

clang/docs/LanguageExtensions.rst
4926
4930–4937
clang/include/clang/Basic/DiagnosticLexKinds.td
658–661

We can use a select here so we only need one new diagnostic.

This should be moved to DiagnosticParseKinds.td because it's emitted from the parser, not the lexer.

clang/lib/Parse/ParsePragma.cpp
15–16
730–735
clang/test/AST/ast-dump-lookups.cpp
101

You should add the newline back to the end of the file.

I'd also like to see a test case where the expression has errors, like:

#pragma clang __debug dump this is nonsense

and where the expression causes an instantiation:

template <typename T>
struct S {
  static constexpr const T *str = "string";
};

template <>
struct S<wchar_t> {
  static constexpr const wchar_t *str = L"wide string";
};

void func() {
  #pragma clang __debug dump S<wchar_t>::str;
}

Thank you for review!

clang/lib/Parse/ParsePragma.cpp
15–16

I'm using warn_pragma_debug_unexpected_argument and warn_pragma_debug_missing_argument from there as well, and not just added diagnostics. What should I do about that? Copying them over to DiagnosticParseKinds.td doesn't work.

730–735

I see quite a lot of items inside ExprDependence. Are you sure we don't miss any corner cases by using isValueDependent() to select between value- and type-dependent diagnostic text?

aaron.ballman added inline comments.Mar 22 2023, 6:02 AM
clang/lib/Parse/ParsePragma.cpp
15–16

Ah, those should move into DiagnosticCommonKinds.td under the // Parse && Lex heading, then they should be available from here as well without the extra include.

730–735

I was trying to think of a case where we'd run into problems, but I can't come up with one, so I believe we're fine here.

Endill added inline comments.Mar 23 2023, 4:27 AM
clang/lib/Parse/ParsePragma.cpp
730–735

Apparently, we should do it the other way round, because An id-expression is value-dependent if: — it is type-dependent (temp.dep.constexpr/2.2). I observe that in one of the tests I added, T{} is TypeValueInstantiation.

Endill updated this revision to Diff 507843.Mar 23 2023, 12:08 PM
  • Handle expressions as unevaluated operands
  • Numerous fixes to documentation wording
  • Add release notes entry
  • Prevent generic "unknown argument" diagnostic from being issued when other more specific diagnostics have been emitted
  • Add more tests
This revision is now accepted and ready to land.Mar 24 2023, 6:20 AM
This revision was landed with ongoing or failed builds.Mar 24 2023, 7:36 AM
This revision was automatically updated to reflect the committed changes.