-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Clang] Fix parsing of reversible type traits in template arguments #95969
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1385,6 +1385,15 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename, | |
if (!getLangOpts().ObjC && Next.is(tok::identifier)) | ||
return TPResult::True; | ||
|
||
// If this identifier was reverted from a token ID, and the next token | ||
// is a '(', we assume it to be a use of a type trait, so this | ||
// can never be a type name. | ||
if (Next.is(tok::l_paren) && | ||
Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier() && | ||
isRevertibleTypeTrait(Tok.getIdentifierInfo())) { | ||
Comment on lines
+1391
to
+1393
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can set the correct There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather not mutate anything in this function |
||
return TPResult::False; | ||
} | ||
|
||
if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) { | ||
// Determine whether this is a valid expression. If not, we will hit | ||
// a parse error one way or another. In that case, tell the caller that | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -141,3 +141,15 @@ namespace r360308_regression { | |
return a == b; | ||
} | ||
} | ||
|
||
namespace GH95598 { | ||
template<typename _Tp, bool _IsPtr = __is_pointer(_Tp)> | ||
struct __is_pointer {}; | ||
// expected-warning@-1 {{keyword '__is_pointer' will be made available as an identifier for the remainder of the translation unit}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This diagnostic is very confusing because it implies the name is only available as an identifier when in reality it's available as either an identifier or a keyword. This seems to be the original functionality though: https://godbolt.org/z/WzTs4T31j (based on the changes in 47642d2 which added this diagnostic). So I think your changes are aligned with the original intent of the diagnostic, but I've CCed @zygoloid and @rnk just in case others from this era recall differently. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we've incrementally ended up in a bad place. Here's my memory of what happened: Originally, the idea was: we provide builtins such as But then it turns out that boost uses these things as keywords directly, rather than using the standard library functionality. To keep both that and libstdc++ working at the same time, we treat the keyword followed by an open paren as having the builtin meaning even when the keyword has been reverted to being a non-keyword. And now we're noticing that we also need special behavior in other parts of the parser to treat the keyword followed by an open paren as a special case. I don't think we should be extending this hack further. I've suggested on the libstdc++ bug report that this be fixed in libstdc++ instead, by stopping using our keywords as their type names. Maybe one day we can then remove it entirely. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One thing we could consider doing would be removing the entire "revertible keyword" mechanism, and instead, in the lexer, classifying these tokens as keywords only if the next pp-token is an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @zygoloid https://github.com/itanium-cxx-abi/cxx-abi/blob/07427ac5b6ff0799c47e8c754609cf8220c05cc0/gcc-tinfo2.cc#L373 (never mind, this turns out to have never compiled with Clang in the first place. GCC seems to support There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @zygoloid I prototyped something #96097 One of the test has a default constructor declaration, ie The alternative is to keep status quo or go with the current PR and change the warning to a depreciation warning. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the historical information @zygoloid!
I tend to agree; if we can avoid continuing to extend this hack, I think we should. That said, I'd be curious whether deprecation is highly disruptive or not; my intuition is that we'd struggle with this one because people tend to use boost (and certainly libstdc++) as system headers, and we suppress diagnostics by default in system headers. So I'd expect this deprecation to take a long while before we could remove the hacks due to the long tail of not wanting to break system headers. The ctor situation would be annoying, but I think the ctor and dtor are the only places we'd have to put in a special hack for "got a keyword where we expected an identifier", so perhaps the blast radius is sufficiently limited for that to be a reasonable approach? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are now patches posted for libstdc++ to avoid using our type trait keywords as identifiers. |
||
|
||
template<bool> | ||
struct ts{}; | ||
|
||
template<typename _Tp> | ||
struct is_pointer : ts<__is_pointer(_Tp)> {}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need a comment above this like: