[clang] [Clang] Implement C++26’s P2893R3 ‘Variadic friends’ (PR #101448)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 13 03:09:15 PDT 2024
================
@@ -3048,6 +3087,66 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(
if (DS.hasTagDefinition())
Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl());
+ // Handle C++26's variadic friend declarations. These don't even have
+ // declarators, so we get them out of the way early here.
+ if (DS.isFriendSpecifiedFirst() && Tok.isOneOf(tok::comma, tok::ellipsis)) {
+ SourceLocation FriendLoc = DS.getFriendSpecLoc();
+ SmallVector<Decl *> Decls;
+ auto DiagnoseCompat = [&, Diagnosed = false]() mutable {
+ if (Diagnosed)
+ return;
+ Diagnosed = true;
+ Diag(Tok.getLocation(), getLangOpts().CPlusPlus26
+ ? diag::warn_cxx23_variadic_friends
+ : diag::ext_variadic_friends);
+ };
+
+ // Handles a single friend-type-specifier.
+ auto ParsedFriendDecl = [&](ParsingDeclSpec &DeclSpec) {
+ bool Variadic = Tok.is(tok::ellipsis);
+ RecordDecl *AnonRecord = nullptr;
+ Decl *D = Actions.ParsedFreeStandingDeclSpec(
+ getCurScope(), AS, DeclSpec, DeclAttrs, TemplateParams, false,
+ AnonRecord, Variadic ? Tok.getLocation() : SourceLocation());
+ DeclSpec.complete(D);
+ if (!D) {
+ SkipUntil(tok::semi, tok::r_brace);
+ return true;
+ }
+
+ // Eat the '...'.
+ if (Variadic) {
+ DiagnoseCompat();
+ ConsumeToken();
+ }
+
+ Decls.push_back(D);
+ return false;
+ };
+
+ if (ParsedFriendDecl(DS))
+ return nullptr;
+
+ if (Tok.is(tok::comma))
+ DiagnoseCompat();
+
+ while (TryConsumeToken(tok::comma)) {
+ ParsingDeclSpec DeclSpec(*this, TemplateDiags);
+ const char *PrevSpec = nullptr;
+ unsigned DiagId = 0;
+ DeclSpec.SetFriendSpec(FriendLoc, PrevSpec, DiagId);
+ ParseDeclarationSpecifiers(DeclSpec, TemplateInfo, AS,
+ DeclSpecContext::DSC_class, nullptr);
+ if (ParsedFriendDecl(DeclSpec))
+ return nullptr;
+ }
----------------
Sirraide wrote:
I’ve cleaned up the code around this a bit, but I’m not sure I can restructure this to a do while loop because the argument to `ParsedFriendDecl` in the loop is different (and I don’t think you can reuse a `ParsingDeclSpec`, or can you?)
https://github.com/llvm/llvm-project/pull/101448
More information about the cfe-commits
mailing list