There are a two things that are particularly hard to express in the macro-based system: lists and optional attributes.
Lists are difficult to make work because {"one", "two"}
is multiple preprocessor tokens, ({"one", "two"})
isn't a valid array literal, etc. As a result, I had to create EducationalNotes.def
and a separate set of macros to associate a list of filenames with a diagnostic id for the experimental educational notes feature.
Optional attributes are also annoying to work with because they require either defining a whole bunch of macro variants or explicitly specifying their absence. This isn't a problem today because the only optional tags are PointsToFirstBadToken
and Fatal
, but it does add a useless none
specifier to 95% of diagnostics, and a diagnostic can't be both PointsToFirstBadToken
and Fatal
.
The TableGen format I have in mind looks roughly like this:
def non_nominal_extension:
Error<"non-nominal type %0 cannot be extended", [Type]>,
PointsToFirstBadToken,
EducationalNotes<["nominal-types.md"]>;
Where only the Error
supertype is required.
This can potentially extend in the future to support a lot of the improvements discussed here like:
- user-facing public diagnostic names (
PublicName<"...">
) - an extended diagnostic message format to, for example, surface more detailed type inference info (
ExtendedMessage<[Args...], [{ // C++ to generate an extended message }]>
)
Moving to TableGen makes it much easier to explore these future directions, even if not all of them end up being implemented.