On Thu, 22 Feb 2024, Jakub Jelinek wrote: > Hi! > > We aren't able to parse __has_attribute (vendor::attr) (and __has_c_attribute > and __has_cpp_attribute) in strict C < C23 modes. While in -std=gnu* modes > or in -std=c23 there is CPP_SCOPE token, in -std=c* (except for -std=c23) > there are is just a pair of CPP_COLON tokens. > The c-lex.cc hunk adds support for that. > > That leads to a question if we should return 1 or 0 from > __has_attribute (gnu::unused) or not, because while > [[gnu::unused]] is parsed fine in -std=gnu*/-std=c23 modes (sure, with > pedwarn for < C23), we do not parse it at all in -std=c* (except for > -std=c23), we only parse [[__extension__ gnu::unused]] there. While > the __extension__ in there helps to avoid the pedwarn, I think it is > better to be consistent between GNU and strict C < C23 modes and > parse [[gnu::unused]] too; on the other side, I think parsing > [[__extension__ gnu : : unused]] is too weird and undesirable. > > So, the following patch adds a flag during preprocessing at the point > where we normally create CPP_SCOPE tokens out of 2 consecutive colons > on the first CPP_COLON to mark the consecutive case (as we are tight > on the bits, I've reused the PURE_ZERO flag, which is used just by the > C++ FE and only ever set (both C and C++) on CPP_NUMBER tokens, this > new flag has the same value and is only ever used on CPP_COLON tokens) > and instead of checking loose_scope_p argument (i.e. whether it is > [[__extension__ ...]] or not), it just parses CPP_SCOPE or CPP_COLON > with CLONE_SCOPE flag followed by another CPP_COLON the same. > The latter will never appear in >= C23 or -std=gnu* modes, though > guarding its use say with flag_iso && !flag_isoc23 && doesn't really > work because the __extension__ case temporarily clears flag_iso flag.
This patch (the one using COLON_SCOPE, *not* the one using PREV_WHITE) is OK. PREV_WHITE is about whether there is whitespace between the tokens in the macro expansion, for the purposes of stringization - I don't think it's appropriate to use here. For example, given #define COLON() : then [[gnu COLON()COLON() unused]] int x; should preferably not be valid; stringizing the results of expanding COLON()COLON() will produce "::" (PREV_WHITE not set), but that wouldn't be a valid attribute in C23 and I don't think anyone could reasonably expect it to be valid with previous standard versions. -- Joseph S. Myers josmy...@redhat.com