1//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the C++ Declaration portions of the Parser interfaces.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/ASTContext.h"
14#include "clang/AST/DeclTemplate.h"
15#include "clang/AST/PrettyDeclStackTrace.h"
16#include "clang/Basic/AttributeCommonInfo.h"
17#include "clang/Basic/Attributes.h"
18#include "clang/Basic/CharInfo.h"
19#include "clang/Basic/DiagnosticParse.h"
20#include "clang/Basic/TargetInfo.h"
21#include "clang/Basic/TokenKinds.h"
22#include "clang/Lex/LiteralSupport.h"
23#include "clang/Parse/ParseHLSLRootSignature.h"
24#include "clang/Parse/Parser.h"
25#include "clang/Parse/RAIIObjectsForParser.h"
26#include "clang/Sema/DeclSpec.h"
27#include "clang/Sema/EnterExpressionEvaluationContext.h"
28#include "clang/Sema/ParsedTemplate.h"
29#include "clang/Sema/Scope.h"
30#include "clang/Sema/SemaCodeCompletion.h"
31#include "clang/Sema/SemaHLSL.h"
32#include "llvm/Support/TimeProfiler.h"
33#include <optional>
34
35using namespace clang;
36
37Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
38 SourceLocation &DeclEnd,
39 SourceLocation InlineLoc) {
40 assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
41 SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
42 ObjCDeclContextSwitch ObjCDC(*this);
43
44 if (Tok.is(K: tok::code_completion)) {
45 cutOffParsing();
46 Actions.CodeCompletion().CodeCompleteNamespaceDecl(S: getCurScope());
47 return nullptr;
48 }
49
50 SourceLocation IdentLoc;
51 IdentifierInfo *Ident = nullptr;
52 InnerNamespaceInfoList ExtraNSs;
53 SourceLocation FirstNestedInlineLoc;
54
55 ParsedAttributes attrs(AttrFactory);
56
57 while (MaybeParseGNUAttributes(Attrs&: attrs) || isAllowedCXX11AttributeSpecifier()) {
58 if (isAllowedCXX11AttributeSpecifier()) {
59 if (getLangOpts().CPlusPlus11)
60 Diag(Loc: Tok.getLocation(), DiagID: getLangOpts().CPlusPlus17
61 ? diag::warn_cxx14_compat_ns_enum_attribute
62 : diag::ext_ns_enum_attribute)
63 << 0 /*namespace*/;
64 ParseCXX11Attributes(attrs);
65 }
66 }
67
68 if (Tok.is(K: tok::identifier)) {
69 Ident = Tok.getIdentifierInfo();
70 IdentLoc = ConsumeToken(); // eat the identifier.
71 while (Tok.is(K: tok::coloncolon) &&
72 (NextToken().is(K: tok::identifier) ||
73 (NextToken().is(K: tok::kw_inline) &&
74 GetLookAheadToken(N: 2).is(K: tok::identifier)))) {
75
76 InnerNamespaceInfo Info;
77 Info.NamespaceLoc = ConsumeToken();
78
79 if (Tok.is(K: tok::kw_inline)) {
80 Info.InlineLoc = ConsumeToken();
81 if (FirstNestedInlineLoc.isInvalid())
82 FirstNestedInlineLoc = Info.InlineLoc;
83 }
84
85 Info.Ident = Tok.getIdentifierInfo();
86 Info.IdentLoc = ConsumeToken();
87
88 ExtraNSs.push_back(Elt: Info);
89 }
90 }
91
92 DiagnoseAndSkipCXX11Attributes();
93 MaybeParseGNUAttributes(Attrs&: attrs);
94 DiagnoseAndSkipCXX11Attributes();
95
96 SourceLocation attrLoc = attrs.Range.getBegin();
97
98 // A nested namespace definition cannot have attributes.
99 if (!ExtraNSs.empty() && attrLoc.isValid())
100 Diag(Loc: attrLoc, DiagID: diag::err_unexpected_nested_namespace_attribute);
101
102 if (Tok.is(K: tok::equal)) {
103 if (!Ident) {
104 Diag(Tok, DiagID: diag::err_expected) << tok::identifier;
105 // Skip to end of the definition and eat the ';'.
106 SkipUntil(T: tok::semi);
107 return nullptr;
108 }
109 if (!ExtraNSs.empty()) {
110 Diag(Loc: ExtraNSs.front().NamespaceLoc,
111 DiagID: diag::err_unexpected_qualified_namespace_alias)
112 << SourceRange(ExtraNSs.front().NamespaceLoc,
113 ExtraNSs.back().IdentLoc);
114 SkipUntil(T: tok::semi);
115 return nullptr;
116 }
117 if (attrLoc.isValid())
118 Diag(Loc: attrLoc, DiagID: diag::err_unexpected_namespace_attributes_alias);
119 if (InlineLoc.isValid())
120 Diag(Loc: InlineLoc, DiagID: diag::err_inline_namespace_alias)
121 << FixItHint::CreateRemoval(RemoveRange: InlineLoc);
122 Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, AliasLoc: IdentLoc, Alias: Ident, DeclEnd);
123 return Actions.ConvertDeclToDeclGroup(Ptr: NSAlias);
124 }
125
126 BalancedDelimiterTracker T(*this, tok::l_brace);
127 if (T.consumeOpen()) {
128 if (Ident)
129 Diag(Tok, DiagID: diag::err_expected) << tok::l_brace;
130 else
131 Diag(Tok, DiagID: diag::err_expected_either) << tok::identifier << tok::l_brace;
132 return nullptr;
133 }
134
135 if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||
136 getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||
137 getCurScope()->getFnParent()) {
138 Diag(Loc: T.getOpenLocation(), DiagID: diag::err_namespace_nonnamespace_scope);
139 SkipUntil(T: tok::r_brace);
140 return nullptr;
141 }
142
143 if (ExtraNSs.empty()) {
144 // Normal namespace definition, not a nested-namespace-definition.
145 } else if (InlineLoc.isValid()) {
146 Diag(Loc: InlineLoc, DiagID: diag::err_inline_nested_namespace_definition);
147 } else if (getLangOpts().CPlusPlus20) {
148 Diag(Loc: ExtraNSs[0].NamespaceLoc,
149 DiagID: diag::warn_cxx14_compat_nested_namespace_definition);
150 if (FirstNestedInlineLoc.isValid())
151 Diag(Loc: FirstNestedInlineLoc,
152 DiagID: diag::warn_cxx17_compat_inline_nested_namespace_definition);
153 } else if (getLangOpts().CPlusPlus17) {
154 Diag(Loc: ExtraNSs[0].NamespaceLoc,
155 DiagID: diag::warn_cxx14_compat_nested_namespace_definition);
156 if (FirstNestedInlineLoc.isValid())
157 Diag(Loc: FirstNestedInlineLoc, DiagID: diag::ext_inline_nested_namespace_definition);
158 } else {
159 TentativeParsingAction TPA(*this);
160 SkipUntil(T: tok::r_brace, Flags: StopBeforeMatch);
161 Token rBraceToken = Tok;
162 TPA.Revert();
163
164 if (!rBraceToken.is(K: tok::r_brace)) {
165 Diag(Loc: ExtraNSs[0].NamespaceLoc, DiagID: diag::ext_nested_namespace_definition)
166 << SourceRange(ExtraNSs.front().NamespaceLoc,
167 ExtraNSs.back().IdentLoc);
168 } else {
169 std::string NamespaceFix;
170 for (const auto &ExtraNS : ExtraNSs) {
171 NamespaceFix += " { ";
172 if (ExtraNS.InlineLoc.isValid())
173 NamespaceFix += "inline ";
174 NamespaceFix += "namespace ";
175 NamespaceFix += ExtraNS.Ident->getName();
176 }
177
178 std::string RBraces;
179 for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i)
180 RBraces += "} ";
181
182 Diag(Loc: ExtraNSs[0].NamespaceLoc, DiagID: diag::ext_nested_namespace_definition)
183 << FixItHint::CreateReplacement(
184 RemoveRange: SourceRange(ExtraNSs.front().NamespaceLoc,
185 ExtraNSs.back().IdentLoc),
186 Code: NamespaceFix)
187 << FixItHint::CreateInsertion(InsertionLoc: rBraceToken.getLocation(), Code: RBraces);
188 }
189
190 // Warn about nested inline namespaces.
191 if (FirstNestedInlineLoc.isValid())
192 Diag(Loc: FirstNestedInlineLoc, DiagID: diag::ext_inline_nested_namespace_definition);
193 }
194
195 // If we're still good, complain about inline namespaces in non-C++0x now.
196 if (InlineLoc.isValid())
197 Diag(Loc: InlineLoc, DiagID: getLangOpts().CPlusPlus11
198 ? diag::warn_cxx98_compat_inline_namespace
199 : diag::ext_inline_namespace);
200
201 // Enter a scope for the namespace.
202 ParseScope NamespaceScope(this, Scope::DeclScope);
203
204 UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
205 Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
206 S: getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident,
207 LBrace: T.getOpenLocation(), AttrList: attrs, UsingDecl&: ImplicitUsingDirectiveDecl, IsNested: false);
208
209 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl,
210 NamespaceLoc, "parsing namespace");
211
212 // Parse the contents of the namespace. This includes parsing recovery on
213 // any improperly nested namespaces.
214 ParseInnerNamespace(InnerNSs: ExtraNSs, index: 0, InlineLoc, attrs, Tracker&: T);
215
216 // Leave the namespace scope.
217 NamespaceScope.Exit();
218
219 DeclEnd = T.getCloseLocation();
220 Actions.ActOnFinishNamespaceDef(Dcl: NamespcDecl, RBrace: DeclEnd);
221
222 return Actions.ConvertDeclToDeclGroup(Ptr: NamespcDecl,
223 OwnedType: ImplicitUsingDirectiveDecl);
224}
225
226void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
227 unsigned int index, SourceLocation &InlineLoc,
228 ParsedAttributes &attrs,
229 BalancedDelimiterTracker &Tracker) {
230 if (index == InnerNSs.size()) {
231 while (!tryParseMisplacedModuleImport() && Tok.isNot(K: tok::r_brace) &&
232 Tok.isNot(K: tok::eof)) {
233 ParsedAttributes DeclAttrs(AttrFactory);
234 MaybeParseCXX11Attributes(Attrs&: DeclAttrs);
235 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
236 ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs&: EmptyDeclSpecAttrs);
237 }
238
239 // The caller is what called check -- we are simply calling
240 // the close for it.
241 Tracker.consumeClose();
242
243 return;
244 }
245
246 // Handle a nested namespace definition.
247 // FIXME: Preserve the source information through to the AST rather than
248 // desugaring it here.
249 ParseScope NamespaceScope(this, Scope::DeclScope);
250 UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
251 Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
252 S: getCurScope(), InlineLoc: InnerNSs[index].InlineLoc, NamespaceLoc: InnerNSs[index].NamespaceLoc,
253 IdentLoc: InnerNSs[index].IdentLoc, Ident: InnerNSs[index].Ident,
254 LBrace: Tracker.getOpenLocation(), AttrList: attrs, UsingDecl&: ImplicitUsingDirectiveDecl, IsNested: true);
255 assert(!ImplicitUsingDirectiveDecl &&
256 "nested namespace definition cannot define anonymous namespace");
257
258 ParseInnerNamespace(InnerNSs, index: ++index, InlineLoc, attrs, Tracker);
259
260 NamespaceScope.Exit();
261 Actions.ActOnFinishNamespaceDef(Dcl: NamespcDecl, RBrace: Tracker.getCloseLocation());
262}
263
264Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
265 SourceLocation AliasLoc,
266 IdentifierInfo *Alias,
267 SourceLocation &DeclEnd) {
268 assert(Tok.is(tok::equal) && "Not equal token");
269
270 ConsumeToken(); // eat the '='.
271
272 if (Tok.is(K: tok::code_completion)) {
273 cutOffParsing();
274 Actions.CodeCompletion().CodeCompleteNamespaceAliasDecl(S: getCurScope());
275 return nullptr;
276 }
277
278 CXXScopeSpec SS;
279 // Parse (optional) nested-name-specifier.
280 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
281 /*ObjectHasErrors=*/false,
282 /*EnteringContext=*/false,
283 /*MayBePseudoDestructor=*/nullptr,
284 /*IsTypename=*/false,
285 /*LastII=*/nullptr,
286 /*OnlyNamespace=*/true);
287
288 if (Tok.isNot(K: tok::identifier)) {
289 Diag(Tok, DiagID: diag::err_expected_namespace_name);
290 // Skip to end of the definition and eat the ';'.
291 SkipUntil(T: tok::semi);
292 return nullptr;
293 }
294
295 if (SS.isInvalid()) {
296 // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
297 // Skip to end of the definition and eat the ';'.
298 SkipUntil(T: tok::semi);
299 return nullptr;
300 }
301
302 // Parse identifier.
303 IdentifierInfo *Ident = Tok.getIdentifierInfo();
304 SourceLocation IdentLoc = ConsumeToken();
305
306 // Eat the ';'.
307 DeclEnd = Tok.getLocation();
308 if (ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_semi_after_namespace_name))
309 SkipUntil(T: tok::semi);
310
311 return Actions.ActOnNamespaceAliasDef(CurScope: getCurScope(), NamespaceLoc, AliasLoc,
312 Alias, SS, IdentLoc, Ident);
313}
314
315Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
316 assert(isTokenStringLiteral() && "Not a string literal!");
317 ExprResult Lang = ParseUnevaluatedStringLiteralExpression();
318
319 ParseScope LinkageScope(this, Scope::DeclScope);
320 Decl *LinkageSpec =
321 Lang.isInvalid()
322 ? nullptr
323 : Actions.ActOnStartLinkageSpecification(
324 S: getCurScope(), ExternLoc: DS.getSourceRange().getBegin(), LangStr: Lang.get(),
325 LBraceLoc: Tok.is(K: tok::l_brace) ? Tok.getLocation() : SourceLocation());
326
327 ParsedAttributes DeclAttrs(AttrFactory);
328 ParsedAttributes DeclSpecAttrs(AttrFactory);
329
330 while (MaybeParseCXX11Attributes(Attrs&: DeclAttrs) ||
331 MaybeParseGNUAttributes(Attrs&: DeclSpecAttrs))
332 ;
333
334 if (Tok.isNot(K: tok::l_brace)) {
335 // Reset the source range in DS, as the leading "extern"
336 // does not really belong to the inner declaration ...
337 DS.SetRangeStart(SourceLocation());
338 DS.SetRangeEnd(SourceLocation());
339 // ... but anyway remember that such an "extern" was seen.
340 DS.setExternInLinkageSpec(true);
341 ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs, DS: &DS);
342 return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
343 S: getCurScope(), LinkageSpec, RBraceLoc: SourceLocation())
344 : nullptr;
345 }
346
347 DS.abort();
348
349 ProhibitAttributes(Attrs&: DeclAttrs);
350
351 BalancedDelimiterTracker T(*this, tok::l_brace);
352 T.consumeOpen();
353
354 unsigned NestedModules = 0;
355 while (true) {
356 switch (Tok.getKind()) {
357 case tok::annot_module_begin:
358 ++NestedModules;
359 ParseTopLevelDecl();
360 continue;
361
362 case tok::annot_module_end:
363 if (!NestedModules)
364 break;
365 --NestedModules;
366 ParseTopLevelDecl();
367 continue;
368
369 case tok::annot_module_include:
370 ParseTopLevelDecl();
371 continue;
372
373 case tok::eof:
374 break;
375
376 case tok::r_brace:
377 if (!NestedModules)
378 break;
379 [[fallthrough]];
380 default:
381 ParsedAttributes DeclAttrs(AttrFactory);
382 ParsedAttributes DeclSpecAttrs(AttrFactory);
383 while (MaybeParseCXX11Attributes(Attrs&: DeclAttrs) ||
384 MaybeParseGNUAttributes(Attrs&: DeclSpecAttrs))
385 ;
386 ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs);
387 continue;
388 }
389
390 break;
391 }
392
393 T.consumeClose();
394 return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
395 S: getCurScope(), LinkageSpec, RBraceLoc: T.getCloseLocation())
396 : nullptr;
397}
398
399Decl *Parser::ParseExportDeclaration() {
400 assert(Tok.is(tok::kw_export));
401 SourceLocation ExportLoc = ConsumeToken();
402
403 if (Tok.is(K: tok::code_completion)) {
404 cutOffParsing();
405 Actions.CodeCompletion().CodeCompleteOrdinaryName(
406 S: getCurScope(), CompletionContext: PP.isIncrementalProcessingEnabled()
407 ? SemaCodeCompletion::PCC_TopLevelOrExpression
408 : SemaCodeCompletion::PCC_Namespace);
409 return nullptr;
410 }
411
412 ParseScope ExportScope(this, Scope::DeclScope);
413 Decl *ExportDecl = Actions.ActOnStartExportDecl(
414 S: getCurScope(), ExportLoc,
415 LBraceLoc: Tok.is(K: tok::l_brace) ? Tok.getLocation() : SourceLocation());
416
417 if (Tok.isNot(K: tok::l_brace)) {
418 // FIXME: Factor out a ParseExternalDeclarationWithAttrs.
419 ParsedAttributes DeclAttrs(AttrFactory);
420 MaybeParseCXX11Attributes(Attrs&: DeclAttrs);
421 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
422 ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs&: EmptyDeclSpecAttrs);
423 return Actions.ActOnFinishExportDecl(S: getCurScope(), ExportDecl,
424 RBraceLoc: SourceLocation());
425 }
426
427 BalancedDelimiterTracker T(*this, tok::l_brace);
428 T.consumeOpen();
429
430 while (!tryParseMisplacedModuleImport() && Tok.isNot(K: tok::r_brace) &&
431 Tok.isNot(K: tok::eof)) {
432 ParsedAttributes DeclAttrs(AttrFactory);
433 MaybeParseCXX11Attributes(Attrs&: DeclAttrs);
434 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
435 ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs&: EmptyDeclSpecAttrs);
436 }
437
438 T.consumeClose();
439 return Actions.ActOnFinishExportDecl(S: getCurScope(), ExportDecl,
440 RBraceLoc: T.getCloseLocation());
441}
442
443Parser::DeclGroupPtrTy Parser::ParseUsingDirectiveOrDeclaration(
444 DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
445 SourceLocation &DeclEnd, ParsedAttributes &Attrs) {
446 assert(Tok.is(tok::kw_using) && "Not using token");
447 ObjCDeclContextSwitch ObjCDC(*this);
448
449 // Eat 'using'.
450 SourceLocation UsingLoc = ConsumeToken();
451
452 if (Tok.is(K: tok::code_completion)) {
453 cutOffParsing();
454 Actions.CodeCompletion().CodeCompleteUsing(S: getCurScope());
455 return nullptr;
456 }
457
458 // Consume unexpected 'template' keywords.
459 while (Tok.is(K: tok::kw_template)) {
460 SourceLocation TemplateLoc = ConsumeToken();
461 Diag(Loc: TemplateLoc, DiagID: diag::err_unexpected_template_after_using)
462 << FixItHint::CreateRemoval(RemoveRange: TemplateLoc);
463 }
464
465 // 'using namespace' means this is a using-directive.
466 if (Tok.is(K: tok::kw_namespace)) {
467 // Template parameters are always an error here.
468 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {
469 SourceRange R = TemplateInfo.getSourceRange();
470 Diag(Loc: UsingLoc, DiagID: diag::err_templated_using_directive_declaration)
471 << 0 /* directive */ << R << FixItHint::CreateRemoval(RemoveRange: R);
472 }
473
474 Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs&: Attrs);
475 return Actions.ConvertDeclToDeclGroup(Ptr: UsingDir);
476 }
477
478 // Otherwise, it must be a using-declaration or an alias-declaration.
479 return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, Attrs,
480 AS: AS_none);
481}
482
483Decl *Parser::ParseUsingDirective(DeclaratorContext Context,
484 SourceLocation UsingLoc,
485 SourceLocation &DeclEnd,
486 ParsedAttributes &attrs) {
487 assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
488
489 // Eat 'namespace'.
490 SourceLocation NamespcLoc = ConsumeToken();
491
492 if (Tok.is(K: tok::code_completion)) {
493 cutOffParsing();
494 Actions.CodeCompletion().CodeCompleteUsingDirective(S: getCurScope());
495 return nullptr;
496 }
497
498 CXXScopeSpec SS;
499 // Parse (optional) nested-name-specifier.
500 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
501 /*ObjectHasErrors=*/false,
502 /*EnteringContext=*/false,
503 /*MayBePseudoDestructor=*/nullptr,
504 /*IsTypename=*/false,
505 /*LastII=*/nullptr,
506 /*OnlyNamespace=*/true);
507
508 IdentifierInfo *NamespcName = nullptr;
509 SourceLocation IdentLoc = SourceLocation();
510
511 // Parse namespace-name.
512 if (Tok.isNot(K: tok::identifier)) {
513 Diag(Tok, DiagID: diag::err_expected_namespace_name);
514 // If there was invalid namespace name, skip to end of decl, and eat ';'.
515 SkipUntil(T: tok::semi);
516 // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
517 return nullptr;
518 }
519
520 if (SS.isInvalid()) {
521 // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
522 // Skip to end of the definition and eat the ';'.
523 SkipUntil(T: tok::semi);
524 return nullptr;
525 }
526
527 // Parse identifier.
528 NamespcName = Tok.getIdentifierInfo();
529 IdentLoc = ConsumeToken();
530
531 // Parse (optional) attributes (most likely GNU strong-using extension).
532 bool GNUAttr = false;
533 if (Tok.is(K: tok::kw___attribute)) {
534 GNUAttr = true;
535 ParseGNUAttributes(Attrs&: attrs);
536 }
537
538 // Eat ';'.
539 DeclEnd = Tok.getLocation();
540 if (ExpectAndConsume(ExpectedTok: tok::semi,
541 Diag: GNUAttr ? diag::err_expected_semi_after_attribute_list
542 : diag::err_expected_semi_after_namespace_name))
543 SkipUntil(T: tok::semi);
544
545 return Actions.ActOnUsingDirective(CurScope: getCurScope(), UsingLoc, NamespcLoc, SS,
546 IdentLoc, NamespcName, AttrList: attrs);
547}
548
549bool Parser::ParseUsingDeclarator(DeclaratorContext Context,
550 UsingDeclarator &D) {
551 D.clear();
552
553 // Ignore optional 'typename'.
554 // FIXME: This is wrong; we should parse this as a typename-specifier.
555 TryConsumeToken(Expected: tok::kw_typename, Loc&: D.TypenameLoc);
556
557 if (Tok.is(K: tok::kw___super)) {
558 Diag(Loc: Tok.getLocation(), DiagID: diag::err_super_in_using_declaration);
559 return true;
560 }
561
562 // Parse nested-name-specifier.
563 const IdentifierInfo *LastII = nullptr;
564 if (ParseOptionalCXXScopeSpecifier(SS&: D.SS, /*ObjectType=*/nullptr,
565 /*ObjectHasErrors=*/false,
566 /*EnteringContext=*/false,
567 /*MayBePseudoDtor=*/MayBePseudoDestructor: nullptr,
568 /*IsTypename=*/false,
569 /*LastII=*/&LastII,
570 /*OnlyNamespace=*/false,
571 /*InUsingDeclaration=*/true))
572
573 return true;
574 if (D.SS.isInvalid())
575 return true;
576
577 // Parse the unqualified-id. We allow parsing of both constructor and
578 // destructor names and allow the action module to diagnose any semantic
579 // errors.
580 //
581 // C++11 [class.qual]p2:
582 // [...] in a using-declaration that is a member-declaration, if the name
583 // specified after the nested-name-specifier is the same as the identifier
584 // or the simple-template-id's template-name in the last component of the
585 // nested-name-specifier, the name is [...] considered to name the
586 // constructor.
587 if (getLangOpts().CPlusPlus11 && Context == DeclaratorContext::Member &&
588 Tok.is(K: tok::identifier) &&
589 (NextToken().is(K: tok::semi) || NextToken().is(K: tok::comma) ||
590 NextToken().is(K: tok::ellipsis) || NextToken().is(K: tok::l_square) ||
591 NextToken().isRegularKeywordAttribute() ||
592 NextToken().is(K: tok::kw___attribute)) &&
593 D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
594 !D.SS.getScopeRep()->getAsNamespace() &&
595 !D.SS.getScopeRep()->getAsNamespaceAlias()) {
596 SourceLocation IdLoc = ConsumeToken();
597 ParsedType Type =
598 Actions.getInheritingConstructorName(SS&: D.SS, NameLoc: IdLoc, Name: *LastII);
599 D.Name.setConstructorName(ClassType: Type, ClassNameLoc: IdLoc, EndLoc: IdLoc);
600 } else {
601 if (ParseUnqualifiedId(
602 SS&: D.SS, /*ObjectType=*/nullptr,
603 /*ObjectHadErrors=*/false, /*EnteringContext=*/false,
604 /*AllowDestructorName=*/true,
605 /*AllowConstructorName=*/
606 !(Tok.is(K: tok::identifier) && NextToken().is(K: tok::equal)),
607 /*AllowDeductionGuide=*/false, TemplateKWLoc: nullptr, Result&: D.Name))
608 return true;
609 }
610
611 if (TryConsumeToken(Expected: tok::ellipsis, Loc&: D.EllipsisLoc))
612 Diag(Loc: Tok.getLocation(), DiagID: getLangOpts().CPlusPlus17
613 ? diag::warn_cxx17_compat_using_declaration_pack
614 : diag::ext_using_declaration_pack);
615
616 return false;
617}
618
619Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(
620 DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
621 SourceLocation UsingLoc, SourceLocation &DeclEnd,
622 ParsedAttributes &PrefixAttrs, AccessSpecifier AS) {
623 SourceLocation UELoc;
624 bool InInitStatement = Context == DeclaratorContext::SelectionInit ||
625 Context == DeclaratorContext::ForInit;
626
627 if (TryConsumeToken(Expected: tok::kw_enum, Loc&: UELoc) && !InInitStatement) {
628 // C++20 using-enum
629 Diag(Loc: UELoc, DiagID: getLangOpts().CPlusPlus20
630 ? diag::warn_cxx17_compat_using_enum_declaration
631 : diag::ext_using_enum_declaration);
632
633 DiagnoseCXX11AttributeExtension(Attrs&: PrefixAttrs);
634
635 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {
636 SourceRange R = TemplateInfo.getSourceRange();
637 Diag(Loc: UsingLoc, DiagID: diag::err_templated_using_directive_declaration)
638 << 1 /* declaration */ << R << FixItHint::CreateRemoval(RemoveRange: R);
639 SkipUntil(T: tok::semi);
640 return nullptr;
641 }
642 CXXScopeSpec SS;
643 if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/ObjectType: nullptr,
644 /*ObectHasErrors=*/ObjectHasErrors: false,
645 /*EnteringConttext=*/EnteringContext: false,
646 /*MayBePseudoDestructor=*/nullptr,
647 /*IsTypename=*/true,
648 /*IdentifierInfo=*/LastII: nullptr,
649 /*OnlyNamespace=*/false,
650 /*InUsingDeclaration=*/true)) {
651 SkipUntil(T: tok::semi);
652 return nullptr;
653 }
654
655 if (Tok.is(K: tok::code_completion)) {
656 cutOffParsing();
657 Actions.CodeCompletion().CodeCompleteUsing(S: getCurScope());
658 return nullptr;
659 }
660
661 Decl *UED = nullptr;
662
663 // FIXME: identifier and annot_template_id handling is very similar to
664 // ParseBaseTypeSpecifier. It should be factored out into a function.
665 if (Tok.is(K: tok::identifier)) {
666 IdentifierInfo *IdentInfo = Tok.getIdentifierInfo();
667 SourceLocation IdentLoc = ConsumeToken();
668
669 ParsedType Type = Actions.getTypeName(
670 II: *IdentInfo, NameLoc: IdentLoc, S: getCurScope(), SS: &SS, /*isClassName=*/true,
671 /*HasTrailingDot=*/false,
672 /*ObjectType=*/nullptr, /*IsCtorOrDtorName=*/false,
673 /*WantNontrivialTypeSourceInfo=*/true);
674
675 UED = Actions.ActOnUsingEnumDeclaration(
676 CurScope: getCurScope(), AS, UsingLoc, EnumLoc: UELoc, TyLoc: IdentLoc, II: *IdentInfo, Ty: Type, SS: &SS);
677 } else if (Tok.is(K: tok::annot_template_id)) {
678 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(tok: Tok);
679
680 if (TemplateId->mightBeType()) {
681 AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename: ImplicitTypenameContext::No,
682 /*IsClassName=*/true);
683
684 assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
685 TypeResult Type = getTypeAnnotation(Tok);
686 SourceRange Loc = Tok.getAnnotationRange();
687 ConsumeAnnotationToken();
688
689 UED = Actions.ActOnUsingEnumDeclaration(CurScope: getCurScope(), AS, UsingLoc,
690 EnumLoc: UELoc, TyLoc: Loc, II: *TemplateId->Name,
691 Ty: Type.get(), SS: &SS);
692 } else {
693 Diag(Loc: Tok.getLocation(), DiagID: diag::err_using_enum_not_enum)
694 << TemplateId->Name->getName()
695 << SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc);
696 }
697 } else {
698 Diag(Loc: Tok.getLocation(), DiagID: diag::err_using_enum_expect_identifier)
699 << Tok.is(K: tok::kw_enum);
700 SkipUntil(T: tok::semi);
701 return nullptr;
702 }
703
704 if (!UED) {
705 SkipUntil(T: tok::semi);
706 return nullptr;
707 }
708
709 DeclEnd = Tok.getLocation();
710 if (ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_after,
711 DiagMsg: "using-enum declaration"))
712 SkipUntil(T: tok::semi);
713
714 return Actions.ConvertDeclToDeclGroup(Ptr: UED);
715 }
716
717 // Check for misplaced attributes before the identifier in an
718 // alias-declaration.
719 ParsedAttributes MisplacedAttrs(AttrFactory);
720 MaybeParseCXX11Attributes(Attrs&: MisplacedAttrs);
721
722 if (InInitStatement && Tok.isNot(K: tok::identifier))
723 return nullptr;
724
725 UsingDeclarator D;
726 bool InvalidDeclarator = ParseUsingDeclarator(Context, D);
727
728 ParsedAttributes Attrs(AttrFactory);
729 MaybeParseAttributes(WhichAttrKinds: PAKM_GNU | PAKM_CXX11, Attrs);
730
731 // If we had any misplaced attributes from earlier, this is where they
732 // should have been written.
733 if (MisplacedAttrs.Range.isValid()) {
734 auto *FirstAttr =
735 MisplacedAttrs.empty() ? nullptr : &MisplacedAttrs.front();
736 auto &Range = MisplacedAttrs.Range;
737 (FirstAttr && FirstAttr->isRegularKeywordAttribute()
738 ? Diag(Loc: Range.getBegin(), DiagID: diag::err_keyword_not_allowed) << FirstAttr
739 : Diag(Loc: Range.getBegin(), DiagID: diag::err_attributes_not_allowed))
740 << FixItHint::CreateInsertionFromRange(
741 InsertionLoc: Tok.getLocation(), FromRange: CharSourceRange::getTokenRange(R: Range))
742 << FixItHint::CreateRemoval(RemoveRange: Range);
743 Attrs.takeAllFrom(Other&: MisplacedAttrs);
744 }
745
746 // Maybe this is an alias-declaration.
747 if (Tok.is(K: tok::equal) || InInitStatement) {
748 if (InvalidDeclarator) {
749 SkipUntil(T: tok::semi);
750 return nullptr;
751 }
752
753 ProhibitAttributes(Attrs&: PrefixAttrs);
754
755 Decl *DeclFromDeclSpec = nullptr;
756 Scope *CurScope = getCurScope();
757 if (CurScope)
758 CurScope->setFlags(Scope::ScopeFlags::TypeAliasScope |
759 CurScope->getFlags());
760
761 Decl *AD = ParseAliasDeclarationAfterDeclarator(
762 TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, OwnedType: &DeclFromDeclSpec);
763
764 if (!AD)
765 return nullptr;
766
767 return Actions.ConvertDeclToDeclGroup(Ptr: AD, OwnedType: DeclFromDeclSpec);
768 }
769
770 DiagnoseCXX11AttributeExtension(Attrs&: PrefixAttrs);
771
772 // Diagnose an attempt to declare a templated using-declaration.
773 // In C++11, alias-declarations can be templates:
774 // template <...> using id = type;
775 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {
776 SourceRange R = TemplateInfo.getSourceRange();
777 Diag(Loc: UsingLoc, DiagID: diag::err_templated_using_directive_declaration)
778 << 1 /* declaration */ << R << FixItHint::CreateRemoval(RemoveRange: R);
779
780 // Unfortunately, we have to bail out instead of recovering by
781 // ignoring the parameters, just in case the nested name specifier
782 // depends on the parameters.
783 return nullptr;
784 }
785
786 SmallVector<Decl *, 8> DeclsInGroup;
787 while (true) {
788 // Parse (optional) attributes.
789 MaybeParseAttributes(WhichAttrKinds: PAKM_GNU | PAKM_CXX11, Attrs);
790 DiagnoseCXX11AttributeExtension(Attrs);
791 Attrs.addAll(B: PrefixAttrs.begin(), E: PrefixAttrs.end());
792
793 if (InvalidDeclarator)
794 SkipUntil(T1: tok::comma, T2: tok::semi, Flags: StopBeforeMatch);
795 else {
796 // "typename" keyword is allowed for identifiers only,
797 // because it may be a type definition.
798 if (D.TypenameLoc.isValid() &&
799 D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
800 Diag(Loc: D.Name.getSourceRange().getBegin(),
801 DiagID: diag::err_typename_identifiers_only)
802 << FixItHint::CreateRemoval(RemoveRange: SourceRange(D.TypenameLoc));
803 // Proceed parsing, but discard the typename keyword.
804 D.TypenameLoc = SourceLocation();
805 }
806
807 Decl *UD = Actions.ActOnUsingDeclaration(CurScope: getCurScope(), AS, UsingLoc,
808 TypenameLoc: D.TypenameLoc, SS&: D.SS, Name&: D.Name,
809 EllipsisLoc: D.EllipsisLoc, AttrList: Attrs);
810 if (UD)
811 DeclsInGroup.push_back(Elt: UD);
812 }
813
814 if (!TryConsumeToken(Expected: tok::comma))
815 break;
816
817 // Parse another using-declarator.
818 Attrs.clear();
819 InvalidDeclarator = ParseUsingDeclarator(Context, D);
820 }
821
822 if (DeclsInGroup.size() > 1)
823 Diag(Loc: Tok.getLocation(),
824 DiagID: getLangOpts().CPlusPlus17
825 ? diag::warn_cxx17_compat_multi_using_declaration
826 : diag::ext_multi_using_declaration);
827
828 // Eat ';'.
829 DeclEnd = Tok.getLocation();
830 if (ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_after,
831 DiagMsg: !Attrs.empty() ? "attributes list"
832 : UELoc.isValid() ? "using-enum declaration"
833 : "using declaration"))
834 SkipUntil(T: tok::semi);
835
836 return Actions.BuildDeclaratorGroup(Group: DeclsInGroup);
837}
838
839Decl *Parser::ParseAliasDeclarationAfterDeclarator(
840 const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
841 UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,
842 ParsedAttributes &Attrs, Decl **OwnedType) {
843 if (ExpectAndConsume(ExpectedTok: tok::equal)) {
844 SkipUntil(T: tok::semi);
845 return nullptr;
846 }
847
848 Diag(Loc: Tok.getLocation(), DiagID: getLangOpts().CPlusPlus11
849 ? diag::warn_cxx98_compat_alias_declaration
850 : diag::ext_alias_declaration);
851
852 // Type alias templates cannot be specialized.
853 int SpecKind = -1;
854 if (TemplateInfo.Kind == ParsedTemplateKind::Template &&
855 D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId)
856 SpecKind = 0;
857 if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitSpecialization)
858 SpecKind = 1;
859 if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation)
860 SpecKind = 2;
861 if (SpecKind != -1) {
862 SourceRange Range;
863 if (SpecKind == 0)
864 Range = SourceRange(D.Name.TemplateId->LAngleLoc,
865 D.Name.TemplateId->RAngleLoc);
866 else
867 Range = TemplateInfo.getSourceRange();
868 Diag(Loc: Range.getBegin(), DiagID: diag::err_alias_declaration_specialization)
869 << SpecKind << Range;
870 SkipUntil(T: tok::semi);
871 return nullptr;
872 }
873
874 // Name must be an identifier.
875 if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {
876 Diag(Loc: D.Name.StartLocation, DiagID: diag::err_alias_declaration_not_identifier);
877 // No removal fixit: can't recover from this.
878 SkipUntil(T: tok::semi);
879 return nullptr;
880 } else if (D.TypenameLoc.isValid())
881 Diag(Loc: D.TypenameLoc, DiagID: diag::err_alias_declaration_not_identifier)
882 << FixItHint::CreateRemoval(
883 RemoveRange: SourceRange(D.TypenameLoc, D.SS.isNotEmpty() ? D.SS.getEndLoc()
884 : D.TypenameLoc));
885 else if (D.SS.isNotEmpty())
886 Diag(Loc: D.SS.getBeginLoc(), DiagID: diag::err_alias_declaration_not_identifier)
887 << FixItHint::CreateRemoval(RemoveRange: D.SS.getRange());
888 if (D.EllipsisLoc.isValid())
889 Diag(Loc: D.EllipsisLoc, DiagID: diag::err_alias_declaration_pack_expansion)
890 << FixItHint::CreateRemoval(RemoveRange: SourceRange(D.EllipsisLoc));
891
892 Decl *DeclFromDeclSpec = nullptr;
893 TypeResult TypeAlias =
894 ParseTypeName(Range: nullptr,
895 Context: TemplateInfo.Kind != ParsedTemplateKind::NonTemplate ? DeclaratorContext::AliasTemplate
896 : DeclaratorContext::AliasDecl,
897 AS, OwnedType: &DeclFromDeclSpec, Attrs: &Attrs);
898 if (OwnedType)
899 *OwnedType = DeclFromDeclSpec;
900
901 // Eat ';'.
902 DeclEnd = Tok.getLocation();
903 if (ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_after,
904 DiagMsg: !Attrs.empty() ? "attributes list"
905 : "alias declaration"))
906 SkipUntil(T: tok::semi);
907
908 TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
909 MultiTemplateParamsArg TemplateParamsArg(
910 TemplateParams ? TemplateParams->data() : nullptr,
911 TemplateParams ? TemplateParams->size() : 0);
912 return Actions.ActOnAliasDeclaration(CurScope: getCurScope(), AS, TemplateParams: TemplateParamsArg,
913 UsingLoc, Name&: D.Name, AttrList: Attrs, Type: TypeAlias,
914 DeclFromDeclSpec);
915}
916
917static FixItHint getStaticAssertNoMessageFixIt(const Expr *AssertExpr,
918 SourceLocation EndExprLoc) {
919 if (const auto *BO = dyn_cast_or_null<BinaryOperator>(Val: AssertExpr)) {
920 if (BO->getOpcode() == BO_LAnd &&
921 isa<StringLiteral>(Val: BO->getRHS()->IgnoreImpCasts()))
922 return FixItHint::CreateReplacement(RemoveRange: BO->getOperatorLoc(), Code: ",");
923 }
924 return FixItHint::CreateInsertion(InsertionLoc: EndExprLoc, Code: ", \"\"");
925}
926
927Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {
928 assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) &&
929 "Not a static_assert declaration");
930
931 // Save the token name used for static assertion.
932 const char *TokName = Tok.getName();
933
934 if (Tok.is(K: tok::kw__Static_assert))
935 diagnoseUseOfC11Keyword(Tok);
936 else if (Tok.is(K: tok::kw_static_assert)) {
937 if (!getLangOpts().CPlusPlus) {
938 if (getLangOpts().C23)
939 Diag(Tok, DiagID: diag::warn_c23_compat_keyword) << Tok.getName();
940 } else
941 Diag(Tok, DiagID: diag::warn_cxx98_compat_static_assert);
942 }
943
944 SourceLocation StaticAssertLoc = ConsumeToken();
945
946 BalancedDelimiterTracker T(*this, tok::l_paren);
947 if (T.consumeOpen()) {
948 Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
949 SkipMalformedDecl();
950 return nullptr;
951 }
952
953 EnterExpressionEvaluationContext ConstantEvaluated(
954 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
955 ExprResult AssertExpr(ParseConstantExpressionInExprEvalContext());
956 if (AssertExpr.isInvalid()) {
957 SkipMalformedDecl();
958 return nullptr;
959 }
960
961 ExprResult AssertMessage;
962 if (Tok.is(K: tok::r_paren)) {
963 unsigned DiagVal;
964 if (getLangOpts().CPlusPlus17)
965 DiagVal = diag::warn_cxx14_compat_static_assert_no_message;
966 else if (getLangOpts().CPlusPlus)
967 DiagVal = diag::ext_cxx_static_assert_no_message;
968 else if (getLangOpts().C23)
969 DiagVal = diag::warn_c17_compat_static_assert_no_message;
970 else
971 DiagVal = diag::ext_c_static_assert_no_message;
972 Diag(Tok, DiagID: DiagVal) << getStaticAssertNoMessageFixIt(AssertExpr: AssertExpr.get(),
973 EndExprLoc: Tok.getLocation());
974 } else {
975 if (ExpectAndConsume(ExpectedTok: tok::comma)) {
976 SkipUntil(T: tok::semi);
977 return nullptr;
978 }
979
980 bool ParseAsExpression = false;
981 if (getLangOpts().CPlusPlus11) {
982 for (unsigned I = 0;; ++I) {
983 const Token &T = GetLookAheadToken(N: I);
984 if (T.is(K: tok::r_paren))
985 break;
986 if (!tokenIsLikeStringLiteral(Tok: T, LO: getLangOpts()) || T.hasUDSuffix()) {
987 ParseAsExpression = true;
988 break;
989 }
990 }
991 }
992
993 if (ParseAsExpression) {
994 Diag(Tok,
995 DiagID: getLangOpts().CPlusPlus26
996 ? diag::warn_cxx20_compat_static_assert_user_generated_message
997 : diag::ext_cxx_static_assert_user_generated_message);
998 AssertMessage = ParseConstantExpressionInExprEvalContext();
999 } else if (tokenIsLikeStringLiteral(Tok, LO: getLangOpts()))
1000 AssertMessage = ParseUnevaluatedStringLiteralExpression();
1001 else {
1002 Diag(Tok, DiagID: diag::err_expected_string_literal)
1003 << /*Source='static_assert'*/ 1;
1004 SkipMalformedDecl();
1005 return nullptr;
1006 }
1007
1008 if (AssertMessage.isInvalid()) {
1009 SkipMalformedDecl();
1010 return nullptr;
1011 }
1012 }
1013
1014 if (T.consumeClose())
1015 return nullptr;
1016
1017 DeclEnd = Tok.getLocation();
1018 ExpectAndConsumeSemi(DiagID: diag::err_expected_semi_after_static_assert, TokenUsed: TokName);
1019
1020 return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr: AssertExpr.get(),
1021 AssertMessageExpr: AssertMessage.get(),
1022 RParenLoc: T.getCloseLocation());
1023}
1024
1025SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
1026 assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype) &&
1027 "Not a decltype specifier");
1028
1029 ExprResult Result;
1030 SourceLocation StartLoc = Tok.getLocation();
1031 SourceLocation EndLoc;
1032
1033 if (Tok.is(K: tok::annot_decltype)) {
1034 Result = getExprAnnotation(Tok);
1035 EndLoc = Tok.getAnnotationEndLoc();
1036 // Unfortunately, we don't know the LParen source location as the annotated
1037 // token doesn't have it.
1038 DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc));
1039 ConsumeAnnotationToken();
1040 if (Result.isInvalid()) {
1041 DS.SetTypeSpecError();
1042 return EndLoc;
1043 }
1044 } else {
1045 if (Tok.getIdentifierInfo()->isStr(Str: "decltype"))
1046 Diag(Tok, DiagID: diag::warn_cxx98_compat_decltype);
1047
1048 ConsumeToken();
1049
1050 BalancedDelimiterTracker T(*this, tok::l_paren);
1051 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after, Msg: "decltype",
1052 SkipToTok: tok::r_paren)) {
1053 DS.SetTypeSpecError();
1054 return T.getOpenLocation() == Tok.getLocation() ? StartLoc
1055 : T.getOpenLocation();
1056 }
1057
1058 // Check for C++1y 'decltype(auto)'.
1059 if (Tok.is(K: tok::kw_auto) && NextToken().is(K: tok::r_paren)) {
1060 // the typename-specifier in a function-style cast expression may
1061 // be 'auto' since C++23.
1062 Diag(Loc: Tok.getLocation(),
1063 DiagID: getLangOpts().CPlusPlus14
1064 ? diag::warn_cxx11_compat_decltype_auto_type_specifier
1065 : diag::ext_decltype_auto_type_specifier);
1066 ConsumeToken();
1067 } else {
1068 // Parse the expression
1069
1070 // C++11 [dcl.type.simple]p4:
1071 // The operand of the decltype specifier is an unevaluated operand.
1072 EnterExpressionEvaluationContext Unevaluated(
1073 Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
1074 Sema::ExpressionEvaluationContextRecord::EK_Decltype);
1075 Result = ParseExpression();
1076 if (Result.isInvalid()) {
1077 DS.SetTypeSpecError();
1078 if (SkipUntil(T: tok::r_paren, Flags: StopAtSemi | StopBeforeMatch)) {
1079 EndLoc = ConsumeParen();
1080 } else {
1081 if (PP.isBacktrackEnabled() && Tok.is(K: tok::semi)) {
1082 // Backtrack to get the location of the last token before the semi.
1083 PP.RevertCachedTokens(N: 2);
1084 ConsumeToken(); // the semi.
1085 EndLoc = ConsumeAnyToken();
1086 assert(Tok.is(tok::semi));
1087 } else {
1088 EndLoc = Tok.getLocation();
1089 }
1090 }
1091 return EndLoc;
1092 }
1093
1094 Result = Actions.ActOnDecltypeExpression(E: Result.get());
1095 }
1096
1097 // Match the ')'
1098 T.consumeClose();
1099 DS.setTypeArgumentRange(T.getRange());
1100 if (T.getCloseLocation().isInvalid()) {
1101 DS.SetTypeSpecError();
1102 // FIXME: this should return the location of the last token
1103 // that was consumed (by "consumeClose()")
1104 return T.getCloseLocation();
1105 }
1106
1107 if (Result.isInvalid()) {
1108 DS.SetTypeSpecError();
1109 return T.getCloseLocation();
1110 }
1111
1112 EndLoc = T.getCloseLocation();
1113 }
1114 assert(!Result.isInvalid());
1115
1116 const char *PrevSpec = nullptr;
1117 unsigned DiagID;
1118 const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
1119 // Check for duplicate type specifiers (e.g. "int decltype(a)").
1120 if (Result.get() ? DS.SetTypeSpecType(T: DeclSpec::TST_decltype, Loc: StartLoc,
1121 PrevSpec, DiagID, Rep: Result.get(), policy: Policy)
1122 : DS.SetTypeSpecType(T: DeclSpec::TST_decltype_auto, Loc: StartLoc,
1123 PrevSpec, DiagID, Policy)) {
1124 Diag(Loc: StartLoc, DiagID) << PrevSpec;
1125 DS.SetTypeSpecError();
1126 }
1127 return EndLoc;
1128}
1129
1130void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
1131 SourceLocation StartLoc,
1132 SourceLocation EndLoc) {
1133 // make sure we have a token we can turn into an annotation token
1134 if (PP.isBacktrackEnabled()) {
1135 PP.RevertCachedTokens(N: 1);
1136 if (DS.getTypeSpecType() == TST_error) {
1137 // We encountered an error in parsing 'decltype(...)' so lets annotate all
1138 // the tokens in the backtracking cache - that we likely had to skip over
1139 // to get to a token that allows us to resume parsing, such as a
1140 // semi-colon.
1141 EndLoc = PP.getLastCachedTokenLocation();
1142 }
1143 } else
1144 PP.EnterToken(Tok, /*IsReinject*/ true);
1145
1146 Tok.setKind(tok::annot_decltype);
1147 setExprAnnotation(Tok,
1148 ER: DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr()
1149 : DS.getTypeSpecType() == TST_decltype_auto ? ExprResult()
1150 : ExprError());
1151 Tok.setAnnotationEndLoc(EndLoc);
1152 Tok.setLocation(StartLoc);
1153 PP.AnnotateCachedTokens(Tok);
1154}
1155
1156SourceLocation Parser::ParsePackIndexingType(DeclSpec &DS) {
1157 assert(Tok.isOneOf(tok::annot_pack_indexing_type, tok::identifier) &&
1158 "Expected an identifier");
1159
1160 TypeResult Type;
1161 SourceLocation StartLoc;
1162 SourceLocation EllipsisLoc;
1163 const char *PrevSpec;
1164 unsigned DiagID;
1165 const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
1166
1167 if (Tok.is(K: tok::annot_pack_indexing_type)) {
1168 StartLoc = Tok.getLocation();
1169 SourceLocation EndLoc;
1170 Type = getTypeAnnotation(Tok);
1171 EndLoc = Tok.getAnnotationEndLoc();
1172 // Unfortunately, we don't know the LParen source location as the annotated
1173 // token doesn't have it.
1174 DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc));
1175 ConsumeAnnotationToken();
1176 if (Type.isInvalid()) {
1177 DS.SetTypeSpecError();
1178 return EndLoc;
1179 }
1180 DS.SetTypeSpecType(T: DeclSpec::TST_typename_pack_indexing, Loc: StartLoc, PrevSpec,
1181 DiagID, Rep: Type, Policy);
1182 return EndLoc;
1183 }
1184 if (!NextToken().is(K: tok::ellipsis) ||
1185 !GetLookAheadToken(N: 2).is(K: tok::l_square)) {
1186 DS.SetTypeSpecError();
1187 return Tok.getEndLoc();
1188 }
1189
1190 ParsedType Ty = Actions.getTypeName(II: *Tok.getIdentifierInfo(),
1191 NameLoc: Tok.getLocation(), S: getCurScope());
1192 if (!Ty) {
1193 DS.SetTypeSpecError();
1194 return Tok.getEndLoc();
1195 }
1196 Type = Ty;
1197
1198 StartLoc = ConsumeToken();
1199 EllipsisLoc = ConsumeToken();
1200 BalancedDelimiterTracker T(*this, tok::l_square);
1201 T.consumeOpen();
1202 ExprResult IndexExpr = ParseConstantExpression();
1203 T.consumeClose();
1204
1205 DS.SetRangeStart(StartLoc);
1206 DS.SetRangeEnd(T.getCloseLocation());
1207
1208 if (!IndexExpr.isUsable()) {
1209 ASTContext &C = Actions.getASTContext();
1210 IndexExpr = IntegerLiteral::Create(C, V: C.MakeIntValue(Value: 0, Type: C.getSizeType()),
1211 type: C.getSizeType(), l: SourceLocation());
1212 }
1213
1214 DS.SetTypeSpecType(T: DeclSpec::TST_typename, Loc: StartLoc, PrevSpec, DiagID, Rep: Type,
1215 Policy);
1216 DS.SetPackIndexingExpr(EllipsisLoc, Pack: IndexExpr.get());
1217 return T.getCloseLocation();
1218}
1219
1220void Parser::AnnotateExistingIndexedTypeNamePack(ParsedType T,
1221 SourceLocation StartLoc,
1222 SourceLocation EndLoc) {
1223 // make sure we have a token we can turn into an annotation token
1224 if (PP.isBacktrackEnabled()) {
1225 PP.RevertCachedTokens(N: 1);
1226 if (!T) {
1227 // We encountered an error in parsing 'decltype(...)' so lets annotate all
1228 // the tokens in the backtracking cache - that we likely had to skip over
1229 // to get to a token that allows us to resume parsing, such as a
1230 // semi-colon.
1231 EndLoc = PP.getLastCachedTokenLocation();
1232 }
1233 } else
1234 PP.EnterToken(Tok, /*IsReinject*/ true);
1235
1236 Tok.setKind(tok::annot_pack_indexing_type);
1237 setTypeAnnotation(Tok, T);
1238 Tok.setAnnotationEndLoc(EndLoc);
1239 Tok.setLocation(StartLoc);
1240 PP.AnnotateCachedTokens(Tok);
1241}
1242
1243DeclSpec::TST Parser::TypeTransformTokToDeclSpec() {
1244 switch (Tok.getKind()) {
1245#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \
1246 case tok::kw___##Trait: \
1247 return DeclSpec::TST_##Trait;
1248#include "clang/Basic/TransformTypeTraits.def"
1249 default:
1250 llvm_unreachable("passed in an unhandled type transformation built-in");
1251 }
1252}
1253
1254bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) {
1255 if (!NextToken().is(K: tok::l_paren)) {
1256 Tok.setKind(tok::identifier);
1257 return false;
1258 }
1259 DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec();
1260 SourceLocation StartLoc = ConsumeToken();
1261
1262 BalancedDelimiterTracker T(*this, tok::l_paren);
1263 if (T.expectAndConsume(DiagID: diag::err_expected_lparen_after, Msg: Tok.getName(),
1264 SkipToTok: tok::r_paren))
1265 return true;
1266
1267 TypeResult Result = ParseTypeName();
1268 if (Result.isInvalid()) {
1269 SkipUntil(T: tok::r_paren, Flags: StopAtSemi);
1270 return true;
1271 }
1272
1273 T.consumeClose();
1274 if (T.getCloseLocation().isInvalid())
1275 return true;
1276
1277 const char *PrevSpec = nullptr;
1278 unsigned DiagID;
1279 if (DS.SetTypeSpecType(T: TypeTransformTST, Loc: StartLoc, PrevSpec, DiagID,
1280 Rep: Result.get(),
1281 Policy: Actions.getASTContext().getPrintingPolicy()))
1282 Diag(Loc: StartLoc, DiagID) << PrevSpec;
1283 DS.setTypeArgumentRange(T.getRange());
1284 return true;
1285}
1286
1287TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
1288 SourceLocation &EndLocation) {
1289 // Ignore attempts to use typename
1290 if (Tok.is(K: tok::kw_typename)) {
1291 Diag(Tok, DiagID: diag::err_expected_class_name_not_template)
1292 << FixItHint::CreateRemoval(RemoveRange: Tok.getLocation());
1293 ConsumeToken();
1294 }
1295
1296 // Parse optional nested-name-specifier
1297 CXXScopeSpec SS;
1298 if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
1299 /*ObjectHasErrors=*/false,
1300 /*EnteringContext=*/false))
1301 return true;
1302
1303 BaseLoc = Tok.getLocation();
1304
1305 // Parse decltype-specifier
1306 // tok == kw_decltype is just error recovery, it can only happen when SS
1307 // isn't empty
1308 if (Tok.isOneOf(Ks: tok::kw_decltype, Ks: tok::annot_decltype)) {
1309 if (SS.isNotEmpty())
1310 Diag(Loc: SS.getBeginLoc(), DiagID: diag::err_unexpected_scope_on_base_decltype)
1311 << FixItHint::CreateRemoval(RemoveRange: SS.getRange());
1312 // Fake up a Declarator to use with ActOnTypeName.
1313 DeclSpec DS(AttrFactory);
1314
1315 EndLocation = ParseDecltypeSpecifier(DS);
1316
1317 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
1318 DeclaratorContext::TypeName);
1319 return Actions.ActOnTypeName(D&: DeclaratorInfo);
1320 }
1321
1322 if (Tok.is(K: tok::annot_pack_indexing_type)) {
1323 DeclSpec DS(AttrFactory);
1324 ParsePackIndexingType(DS);
1325 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
1326 DeclaratorContext::TypeName);
1327 return Actions.ActOnTypeName(D&: DeclaratorInfo);
1328 }
1329
1330 // Check whether we have a template-id that names a type.
1331 // FIXME: identifier and annot_template_id handling in ParseUsingDeclaration
1332 // work very similarly. It should be refactored into a separate function.
1333 if (Tok.is(K: tok::annot_template_id)) {
1334 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(tok: Tok);
1335 if (TemplateId->mightBeType()) {
1336 AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename: ImplicitTypenameContext::No,
1337 /*IsClassName=*/true);
1338
1339 assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
1340 TypeResult Type = getTypeAnnotation(Tok);
1341 EndLocation = Tok.getAnnotationEndLoc();
1342 ConsumeAnnotationToken();
1343 return Type;
1344 }
1345
1346 // Fall through to produce an error below.
1347 }
1348
1349 if (Tok.isNot(K: tok::identifier)) {
1350 Diag(Tok, DiagID: diag::err_expected_class_name);
1351 return true;
1352 }
1353
1354 IdentifierInfo *Id = Tok.getIdentifierInfo();
1355 SourceLocation IdLoc = ConsumeToken();
1356
1357 if (Tok.is(K: tok::less)) {
1358 // It looks the user intended to write a template-id here, but the
1359 // template-name was wrong. Try to fix that.
1360 // FIXME: Invoke ParseOptionalCXXScopeSpecifier in a "'template' is neither
1361 // required nor permitted" mode, and do this there.
1362 TemplateNameKind TNK = TNK_Non_template;
1363 TemplateTy Template;
1364 if (!Actions.DiagnoseUnknownTemplateName(II: *Id, IILoc: IdLoc, S: getCurScope(), SS: &SS,
1365 SuggestedTemplate&: Template, SuggestedKind&: TNK)) {
1366 Diag(Loc: IdLoc, DiagID: diag::err_unknown_template_name) << Id;
1367 }
1368
1369 // Form the template name
1370 UnqualifiedId TemplateName;
1371 TemplateName.setIdentifier(Id, IdLoc);
1372
1373 // Parse the full template-id, then turn it into a type.
1374 if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateKWLoc: SourceLocation(),
1375 TemplateName))
1376 return true;
1377 if (Tok.is(K: tok::annot_template_id) &&
1378 takeTemplateIdAnnotation(tok: Tok)->mightBeType())
1379 AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename: ImplicitTypenameContext::No,
1380 /*IsClassName=*/true);
1381
1382 // If we didn't end up with a typename token, there's nothing more we
1383 // can do.
1384 if (Tok.isNot(K: tok::annot_typename))
1385 return true;
1386
1387 // Retrieve the type from the annotation token, consume that token, and
1388 // return.
1389 EndLocation = Tok.getAnnotationEndLoc();
1390 TypeResult Type = getTypeAnnotation(Tok);
1391 ConsumeAnnotationToken();
1392 return Type;
1393 }
1394
1395 // We have an identifier; check whether it is actually a type.
1396 IdentifierInfo *CorrectedII = nullptr;
1397 ParsedType Type = Actions.getTypeName(
1398 II: *Id, NameLoc: IdLoc, S: getCurScope(), SS: &SS, /*isClassName=*/true, HasTrailingDot: false, ObjectType: nullptr,
1399 /*IsCtorOrDtorName=*/false,
1400 /*WantNontrivialTypeSourceInfo=*/true,
1401 /*IsClassTemplateDeductionContext=*/false, AllowImplicitTypename: ImplicitTypenameContext::No,
1402 CorrectedII: &CorrectedII);
1403 if (!Type) {
1404 Diag(Loc: IdLoc, DiagID: diag::err_expected_class_name);
1405 return true;
1406 }
1407
1408 // Consume the identifier.
1409 EndLocation = IdLoc;
1410
1411 // Fake up a Declarator to use with ActOnTypeName.
1412 DeclSpec DS(AttrFactory);
1413 DS.SetRangeStart(IdLoc);
1414 DS.SetRangeEnd(EndLocation);
1415 DS.getTypeSpecScope() = SS;
1416
1417 const char *PrevSpec = nullptr;
1418 unsigned DiagID;
1419 DS.SetTypeSpecType(T: TST_typename, Loc: IdLoc, PrevSpec, DiagID, Rep: Type,
1420 Policy: Actions.getASTContext().getPrintingPolicy());
1421
1422 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),
1423 DeclaratorContext::TypeName);
1424 return Actions.ActOnTypeName(D&: DeclaratorInfo);
1425}
1426
1427void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
1428 while (Tok.isOneOf(Ks: tok::kw___single_inheritance,
1429 Ks: tok::kw___multiple_inheritance,
1430 Ks: tok::kw___virtual_inheritance)) {
1431 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1432 auto Kind = Tok.getKind();
1433 SourceLocation AttrNameLoc = ConsumeToken();
1434 attrs.addNew(attrName: AttrName, attrRange: AttrNameLoc, scope: AttributeScopeInfo(), args: nullptr, numArgs: 0, form: Kind);
1435 }
1436}
1437
1438void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) {
1439 while (Tok.is(K: tok::kw__Nullable)) {
1440 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1441 auto Kind = Tok.getKind();
1442 SourceLocation AttrNameLoc = ConsumeToken();
1443 attrs.addNew(attrName: AttrName, attrRange: AttrNameLoc, scope: AttributeScopeInfo(), args: nullptr, numArgs: 0, form: Kind);
1444 }
1445}
1446
1447bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
1448 // This switch enumerates the valid "follow" set for type-specifiers.
1449 switch (Tok.getKind()) {
1450 default:
1451 if (Tok.isRegularKeywordAttribute())
1452 return true;
1453 break;
1454 case tok::semi: // struct foo {...} ;
1455 case tok::star: // struct foo {...} * P;
1456 case tok::amp: // struct foo {...} & R = ...
1457 case tok::ampamp: // struct foo {...} && R = ...
1458 case tok::identifier: // struct foo {...} V ;
1459 case tok::r_paren: //(struct foo {...} ) {4}
1460 case tok::coloncolon: // struct foo {...} :: a::b;
1461 case tok::annot_cxxscope: // struct foo {...} a:: b;
1462 case tok::annot_typename: // struct foo {...} a ::b;
1463 case tok::annot_template_id: // struct foo {...} a<int> ::b;
1464 case tok::kw_decltype: // struct foo {...} decltype (a)::b;
1465 case tok::l_paren: // struct foo {...} ( x);
1466 case tok::comma: // __builtin_offsetof(struct foo{...} ,
1467 case tok::kw_operator: // struct foo operator ++() {...}
1468 case tok::kw___declspec: // struct foo {...} __declspec(...)
1469 case tok::l_square: // void f(struct f [ 3])
1470 case tok::ellipsis: // void f(struct f ... [Ns])
1471 // FIXME: we should emit semantic diagnostic when declaration
1472 // attribute is in type attribute position.
1473 case tok::kw___attribute: // struct foo __attribute__((used)) x;
1474 case tok::annot_pragma_pack: // struct foo {...} _Pragma(pack(pop));
1475 // struct foo {...} _Pragma(section(...));
1476 case tok::annot_pragma_ms_pragma:
1477 // struct foo {...} _Pragma(vtordisp(pop));
1478 case tok::annot_pragma_ms_vtordisp:
1479 // struct foo {...} _Pragma(pointers_to_members(...));
1480 case tok::annot_pragma_ms_pointers_to_members:
1481 return true;
1482 case tok::colon:
1483 return CouldBeBitfield || // enum E { ... } : 2;
1484 ColonIsSacred; // _Generic(..., enum E : 2);
1485 // Microsoft compatibility
1486 case tok::kw___cdecl: // struct foo {...} __cdecl x;
1487 case tok::kw___fastcall: // struct foo {...} __fastcall x;
1488 case tok::kw___stdcall: // struct foo {...} __stdcall x;
1489 case tok::kw___thiscall: // struct foo {...} __thiscall x;
1490 case tok::kw___vectorcall: // struct foo {...} __vectorcall x;
1491 // We will diagnose these calling-convention specifiers on non-function
1492 // declarations later, so claim they are valid after a type specifier.
1493 return getLangOpts().MicrosoftExt;
1494 // Type qualifiers
1495 case tok::kw_const: // struct foo {...} const x;
1496 case tok::kw_volatile: // struct foo {...} volatile x;
1497 case tok::kw_restrict: // struct foo {...} restrict x;
1498 case tok::kw__Atomic: // struct foo {...} _Atomic x;
1499 case tok::kw___unaligned: // struct foo {...} __unaligned *x;
1500 // Function specifiers
1501 // Note, no 'explicit'. An explicit function must be either a conversion
1502 // operator or a constructor. Either way, it can't have a return type.
1503 case tok::kw_inline: // struct foo inline f();
1504 case tok::kw_virtual: // struct foo virtual f();
1505 case tok::kw_friend: // struct foo friend f();
1506 // Storage-class specifiers
1507 case tok::kw_static: // struct foo {...} static x;
1508 case tok::kw_extern: // struct foo {...} extern x;
1509 case tok::kw_typedef: // struct foo {...} typedef x;
1510 case tok::kw_register: // struct foo {...} register x;
1511 case tok::kw_auto: // struct foo {...} auto x;
1512 case tok::kw_mutable: // struct foo {...} mutable x;
1513 case tok::kw_thread_local: // struct foo {...} thread_local x;
1514 case tok::kw_constexpr: // struct foo {...} constexpr x;
1515 case tok::kw_consteval: // struct foo {...} consteval x;
1516 case tok::kw_constinit: // struct foo {...} constinit x;
1517 // As shown above, type qualifiers and storage class specifiers absolutely
1518 // can occur after class specifiers according to the grammar. However,
1519 // almost no one actually writes code like this. If we see one of these,
1520 // it is much more likely that someone missed a semi colon and the
1521 // type/storage class specifier we're seeing is part of the *next*
1522 // intended declaration, as in:
1523 //
1524 // struct foo { ... }
1525 // typedef int X;
1526 //
1527 // We'd really like to emit a missing semicolon error instead of emitting
1528 // an error on the 'int' saying that you can't have two type specifiers in
1529 // the same declaration of X. Because of this, we look ahead past this
1530 // token to see if it's a type specifier. If so, we know the code is
1531 // otherwise invalid, so we can produce the expected semi error.
1532 if (!isKnownToBeTypeSpecifier(Tok: NextToken()))
1533 return true;
1534 break;
1535 case tok::r_brace: // struct bar { struct foo {...} }
1536 // Missing ';' at end of struct is accepted as an extension in C mode.
1537 if (!getLangOpts().CPlusPlus)
1538 return true;
1539 break;
1540 case tok::greater:
1541 // template<class T = class X>
1542 return getLangOpts().CPlusPlus;
1543 }
1544 return false;
1545}
1546
1547void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
1548 SourceLocation StartLoc, DeclSpec &DS,
1549 ParsedTemplateInfo &TemplateInfo,
1550 AccessSpecifier AS, bool EnteringContext,
1551 DeclSpecContext DSC,
1552 ParsedAttributes &Attributes) {
1553 DeclSpec::TST TagType;
1554 if (TagTokKind == tok::kw_struct)
1555 TagType = DeclSpec::TST_struct;
1556 else if (TagTokKind == tok::kw___interface)
1557 TagType = DeclSpec::TST_interface;
1558 else if (TagTokKind == tok::kw_class)
1559 TagType = DeclSpec::TST_class;
1560 else {
1561 assert(TagTokKind == tok::kw_union && "Not a class specifier");
1562 TagType = DeclSpec::TST_union;
1563 }
1564
1565 if (Tok.is(K: tok::code_completion)) {
1566 // Code completion for a struct, class, or union name.
1567 cutOffParsing();
1568 Actions.CodeCompletion().CodeCompleteTag(S: getCurScope(), TagSpec: TagType);
1569 return;
1570 }
1571
1572 // C++20 [temp.class.spec] 13.7.5/10
1573 // The usual access checking rules do not apply to non-dependent names
1574 // used to specify template arguments of the simple-template-id of the
1575 // partial specialization.
1576 // C++20 [temp.spec] 13.9/6:
1577 // The usual access checking rules do not apply to names in a declaration
1578 // of an explicit instantiation or explicit specialization...
1579 const bool shouldDelayDiagsInTag =
1580 (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate);
1581 SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);
1582
1583 ParsedAttributes attrs(AttrFactory);
1584 // If attributes exist after tag, parse them.
1585 for (;;) {
1586 MaybeParseAttributes(WhichAttrKinds: PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, Attrs&: attrs);
1587 // Parse inheritance specifiers.
1588 if (Tok.isOneOf(Ks: tok::kw___single_inheritance,
1589 Ks: tok::kw___multiple_inheritance,
1590 Ks: tok::kw___virtual_inheritance)) {
1591 ParseMicrosoftInheritanceClassAttributes(attrs);
1592 continue;
1593 }
1594 if (Tok.is(K: tok::kw__Nullable)) {
1595 ParseNullabilityClassAttributes(attrs);
1596 continue;
1597 }
1598 break;
1599 }
1600
1601 // Source location used by FIXIT to insert misplaced
1602 // C++11 attributes
1603 SourceLocation AttrFixitLoc = Tok.getLocation();
1604
1605 if (TagType == DeclSpec::TST_struct && Tok.isNot(K: tok::identifier) &&
1606 !Tok.isAnnotation() && Tok.getIdentifierInfo() &&
1607 Tok.isOneOf(
1608#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,
1609#include "clang/Basic/TransformTypeTraits.def"
1610 Ks: tok::kw___is_abstract,
1611 Ks: tok::kw___is_aggregate,
1612 Ks: tok::kw___is_arithmetic,
1613 Ks: tok::kw___is_array,
1614 Ks: tok::kw___is_assignable,
1615 Ks: tok::kw___is_base_of,
1616 Ks: tok::kw___is_bounded_array,
1617 Ks: tok::kw___is_class,
1618 Ks: tok::kw___is_complete_type,
1619 Ks: tok::kw___is_compound,
1620 Ks: tok::kw___is_const,
1621 Ks: tok::kw___is_constructible,
1622 Ks: tok::kw___is_convertible,
1623 Ks: tok::kw___is_convertible_to,
1624 Ks: tok::kw___is_destructible,
1625 Ks: tok::kw___is_empty,
1626 Ks: tok::kw___is_enum,
1627 Ks: tok::kw___is_floating_point,
1628 Ks: tok::kw___is_final,
1629 Ks: tok::kw___is_function,
1630 Ks: tok::kw___is_fundamental,
1631 Ks: tok::kw___is_integral,
1632 Ks: tok::kw___is_interface_class,
1633 Ks: tok::kw___is_literal,
1634 Ks: tok::kw___is_lvalue_expr,
1635 Ks: tok::kw___is_lvalue_reference,
1636 Ks: tok::kw___is_member_function_pointer,
1637 Ks: tok::kw___is_member_object_pointer,
1638 Ks: tok::kw___is_member_pointer,
1639 Ks: tok::kw___is_nothrow_assignable,
1640 Ks: tok::kw___is_nothrow_constructible,
1641 Ks: tok::kw___is_nothrow_convertible,
1642 Ks: tok::kw___is_nothrow_destructible,
1643 Ks: tok::kw___is_object,
1644 Ks: tok::kw___is_pod,
1645 Ks: tok::kw___is_pointer,
1646 Ks: tok::kw___is_polymorphic,
1647 Ks: tok::kw___is_reference,
1648 Ks: tok::kw___is_rvalue_expr,
1649 Ks: tok::kw___is_rvalue_reference,
1650 Ks: tok::kw___is_same,
1651 Ks: tok::kw___is_scalar,
1652 Ks: tok::kw___is_scoped_enum,
1653 Ks: tok::kw___is_sealed,
1654 Ks: tok::kw___is_signed,
1655 Ks: tok::kw___is_standard_layout,
1656 Ks: tok::kw___is_trivial,
1657 Ks: tok::kw___is_trivially_equality_comparable,
1658 Ks: tok::kw___is_trivially_assignable,
1659 Ks: tok::kw___is_trivially_constructible,
1660 Ks: tok::kw___is_trivially_copyable,
1661 Ks: tok::kw___is_unbounded_array,
1662 Ks: tok::kw___is_union,
1663 Ks: tok::kw___is_unsigned,
1664 Ks: tok::kw___is_void,
1665 Ks: tok::kw___is_volatile
1666 ))
1667 // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
1668 // name of struct templates, but some are keywords in GCC >= 4.3
1669 // and Clang. Therefore, when we see the token sequence "struct
1670 // X", make X into a normal identifier rather than a keyword, to
1671 // allow libstdc++ 4.2 and libc++ to work properly.
1672 TryKeywordIdentFallback(DisableKeyword: true);
1673
1674 struct PreserveAtomicIdentifierInfoRAII {
1675 PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled)
1676 : AtomicII(nullptr) {
1677 if (!Enabled)
1678 return;
1679 assert(Tok.is(tok::kw__Atomic));
1680 AtomicII = Tok.getIdentifierInfo();
1681 AtomicII->revertTokenIDToIdentifier();
1682 Tok.setKind(tok::identifier);
1683 }
1684 ~PreserveAtomicIdentifierInfoRAII() {
1685 if (!AtomicII)
1686 return;
1687 AtomicII->revertIdentifierToTokenID(TK: tok::kw__Atomic);
1688 }
1689 IdentifierInfo *AtomicII;
1690 };
1691
1692 // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
1693 // implementation for VS2013 uses _Atomic as an identifier for one of the
1694 // classes in <atomic>. When we are parsing 'struct _Atomic', don't consider
1695 // '_Atomic' to be a keyword. We are careful to undo this so that clang can
1696 // use '_Atomic' in its own header files.
1697 bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat &&
1698 Tok.is(K: tok::kw__Atomic) &&
1699 TagType == DeclSpec::TST_struct;
1700 PreserveAtomicIdentifierInfoRAII AtomicTokenGuard(
1701 Tok, ShouldChangeAtomicToIdentifier);
1702
1703 // Parse the (optional) nested-name-specifier.
1704 CXXScopeSpec &SS = DS.getTypeSpecScope();
1705 if (getLangOpts().CPlusPlus) {
1706 // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it
1707 // is a base-specifier-list.
1708 ColonProtectionRAIIObject X(*this);
1709
1710 CXXScopeSpec Spec;
1711 if (TemplateInfo.TemplateParams)
1712 Spec.setTemplateParamLists(*TemplateInfo.TemplateParams);
1713
1714 bool HasValidSpec = true;
1715 if (ParseOptionalCXXScopeSpecifier(SS&: Spec, /*ObjectType=*/nullptr,
1716 /*ObjectHasErrors=*/false,
1717 EnteringContext)) {
1718 DS.SetTypeSpecError();
1719 HasValidSpec = false;
1720 }
1721 if (Spec.isSet())
1722 if (Tok.isNot(K: tok::identifier) && Tok.isNot(K: tok::annot_template_id)) {
1723 Diag(Tok, DiagID: diag::err_expected) << tok::identifier;
1724 HasValidSpec = false;
1725 }
1726 if (HasValidSpec)
1727 SS = Spec;
1728 }
1729
1730 TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
1731
1732 auto RecoverFromUndeclaredTemplateName = [&](IdentifierInfo *Name,
1733 SourceLocation NameLoc,
1734 SourceRange TemplateArgRange,
1735 bool KnownUndeclared) {
1736 Diag(Loc: NameLoc, DiagID: diag::err_explicit_spec_non_template)
1737 << (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation)
1738 << TagTokKind << Name << TemplateArgRange << KnownUndeclared;
1739
1740 // Strip off the last template parameter list if it was empty, since
1741 // we've removed its template argument list.
1742 if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
1743 if (TemplateParams->size() > 1) {
1744 TemplateParams->pop_back();
1745 } else {
1746 TemplateParams = nullptr;
1747 TemplateInfo.Kind = ParsedTemplateKind::NonTemplate;
1748 }
1749 } else if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation) {
1750 // Pretend this is just a forward declaration.
1751 TemplateParams = nullptr;
1752 TemplateInfo.Kind = ParsedTemplateKind::NonTemplate;
1753 TemplateInfo.TemplateLoc = SourceLocation();
1754 TemplateInfo.ExternLoc = SourceLocation();
1755 }
1756 };
1757
1758 // Parse the (optional) class name or simple-template-id.
1759 IdentifierInfo *Name = nullptr;
1760 SourceLocation NameLoc;
1761 TemplateIdAnnotation *TemplateId = nullptr;
1762 if (Tok.is(K: tok::identifier)) {
1763 Name = Tok.getIdentifierInfo();
1764 NameLoc = ConsumeToken();
1765 DS.SetRangeEnd(NameLoc);
1766
1767 if (Tok.is(K: tok::less) && getLangOpts().CPlusPlus) {
1768 // The name was supposed to refer to a template, but didn't.
1769 // Eat the template argument list and try to continue parsing this as
1770 // a class (or template thereof).
1771 TemplateArgList TemplateArgs;
1772 SourceLocation LAngleLoc, RAngleLoc;
1773 if (ParseTemplateIdAfterTemplateName(ConsumeLastToken: true, LAngleLoc, TemplateArgs,
1774 RAngleLoc)) {
1775 // We couldn't parse the template argument list at all, so don't
1776 // try to give any location information for the list.
1777 LAngleLoc = RAngleLoc = SourceLocation();
1778 }
1779 RecoverFromUndeclaredTemplateName(
1780 Name, NameLoc, SourceRange(LAngleLoc, RAngleLoc), false);
1781 }
1782 } else if (Tok.is(K: tok::annot_template_id)) {
1783 TemplateId = takeTemplateIdAnnotation(tok: Tok);
1784 NameLoc = ConsumeAnnotationToken();
1785
1786 if (TemplateId->Kind == TNK_Undeclared_template) {
1787 // Try to resolve the template name to a type template. May update Kind.
1788 Actions.ActOnUndeclaredTypeTemplateName(
1789 S: getCurScope(), Name&: TemplateId->Template, TNK&: TemplateId->Kind, NameLoc, II&: Name);
1790 if (TemplateId->Kind == TNK_Undeclared_template) {
1791 RecoverFromUndeclaredTemplateName(
1792 Name, NameLoc,
1793 SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc), true);
1794 TemplateId = nullptr;
1795 }
1796 }
1797
1798 if (TemplateId && !TemplateId->mightBeType()) {
1799 // The template-name in the simple-template-id refers to
1800 // something other than a type template. Give an appropriate
1801 // error message and skip to the ';'.
1802 SourceRange Range(NameLoc);
1803 if (SS.isNotEmpty())
1804 Range.setBegin(SS.getBeginLoc());
1805
1806 // FIXME: Name may be null here.
1807 Diag(Loc: TemplateId->LAngleLoc, DiagID: diag::err_template_spec_syntax_non_template)
1808 << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;
1809
1810 DS.SetTypeSpecError();
1811 SkipUntil(T: tok::semi, Flags: StopBeforeMatch);
1812 return;
1813 }
1814 }
1815
1816 // There are four options here.
1817 // - If we are in a trailing return type, this is always just a reference,
1818 // and we must not try to parse a definition. For instance,
1819 // [] () -> struct S { };
1820 // does not define a type.
1821 // - If we have 'struct foo {...', 'struct foo :...',
1822 // 'struct foo final :' or 'struct foo final {', then this is a definition.
1823 // - If we have 'struct foo;', then this is either a forward declaration
1824 // or a friend declaration, which have to be treated differently.
1825 // - Otherwise we have something like 'struct foo xyz', a reference.
1826 //
1827 // We also detect these erroneous cases to provide better diagnostic for
1828 // C++11 attributes parsing.
1829 // - attributes follow class name:
1830 // struct foo [[]] {};
1831 // - attributes appear before or after 'final':
1832 // struct foo [[]] final [[]] {};
1833 //
1834 // However, in type-specifier-seq's, things look like declarations but are
1835 // just references, e.g.
1836 // new struct s;
1837 // or
1838 // &T::operator struct s;
1839 // For these, DSC is DeclSpecContext::DSC_type_specifier or
1840 // DeclSpecContext::DSC_alias_declaration.
1841
1842 // If there are attributes after class name, parse them.
1843 MaybeParseCXX11Attributes(Attrs&: Attributes);
1844
1845 const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
1846 TagUseKind TUK;
1847
1848 // C++26 [class.mem.general]p10: If a name-declaration matches the
1849 // syntactic requirements of friend-type-declaration, it is a
1850 // friend-type-declaration.
1851 if (getLangOpts().CPlusPlus && DS.isFriendSpecifiedFirst() &&
1852 Tok.isOneOf(Ks: tok::comma, Ks: tok::ellipsis))
1853 TUK = TagUseKind::Friend;
1854 else if (isDefiningTypeSpecifierContext(DSC, IsCPlusPlus: getLangOpts().CPlusPlus) ==
1855 AllowDefiningTypeSpec::No ||
1856 (getLangOpts().OpenMP && OpenMPDirectiveParsing))
1857 TUK = TagUseKind::Reference;
1858 else if (Tok.is(K: tok::l_brace) ||
1859 (DSC != DeclSpecContext::DSC_association &&
1860 getLangOpts().CPlusPlus && Tok.is(K: tok::colon)) ||
1861 (isClassCompatibleKeyword() &&
1862 (NextToken().is(K: tok::l_brace) || NextToken().is(K: tok::colon) ||
1863 isClassCompatibleKeyword(Tok: NextToken())))) {
1864 if (DS.isFriendSpecified()) {
1865 // C++ [class.friend]p2:
1866 // A class shall not be defined in a friend declaration.
1867 Diag(Loc: Tok.getLocation(), DiagID: diag::err_friend_decl_defines_type)
1868 << SourceRange(DS.getFriendSpecLoc());
1869
1870 // Skip everything up to the semicolon, so that this looks like a proper
1871 // friend class (or template thereof) declaration.
1872 SkipUntil(T: tok::semi, Flags: StopBeforeMatch);
1873 TUK = TagUseKind::Friend;
1874 } else {
1875 // Okay, this is a class definition.
1876 TUK = TagUseKind::Definition;
1877 }
1878 } else if (isClassCompatibleKeyword() &&
1879 (NextToken().is(K: tok::l_square) ||
1880 NextToken().is(K: tok::kw_alignas) ||
1881 NextToken().isRegularKeywordAttribute() ||
1882 isCXX11VirtSpecifier(Tok: NextToken()) != VirtSpecifiers::VS_None ||
1883 isCXX2CTriviallyRelocatableKeyword())) {
1884 // We can't tell if this is a definition or reference
1885 // until we skipped the 'final' and C++11 attribute specifiers.
1886 TentativeParsingAction PA(*this);
1887
1888 // Skip the 'final', abstract'... keywords.
1889 while (isClassCompatibleKeyword())
1890 ConsumeToken();
1891
1892 // Skip C++11 attribute specifiers.
1893 while (true) {
1894 if (Tok.is(K: tok::l_square) && NextToken().is(K: tok::l_square)) {
1895 ConsumeBracket();
1896 if (!SkipUntil(T: tok::r_square, Flags: StopAtSemi))
1897 break;
1898 } else if (Tok.is(K: tok::kw_alignas) && NextToken().is(K: tok::l_paren)) {
1899 ConsumeToken();
1900 ConsumeParen();
1901 if (!SkipUntil(T: tok::r_paren, Flags: StopAtSemi))
1902 break;
1903 } else if (Tok.isRegularKeywordAttribute()) {
1904 bool TakesArgs = doesKeywordAttributeTakeArgs(Kind: Tok.getKind());
1905 ConsumeToken();
1906 if (TakesArgs) {
1907 BalancedDelimiterTracker T(*this, tok::l_paren);
1908 if (!T.consumeOpen())
1909 T.skipToEnd();
1910 }
1911 } else {
1912 break;
1913 }
1914 }
1915
1916 if (Tok.isOneOf(Ks: tok::l_brace, Ks: tok::colon))
1917 TUK = TagUseKind::Definition;
1918 else
1919 TUK = TagUseKind::Reference;
1920
1921 PA.Revert();
1922 } else if (!isTypeSpecifier(DSC) &&
1923 (Tok.is(K: tok::semi) ||
1924 (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(CouldBeBitfield: false)))) {
1925 TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration;
1926 if (Tok.isNot(K: tok::semi)) {
1927 const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
1928 // A semicolon was missing after this declaration. Diagnose and recover.
1929 ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_after,
1930 DiagMsg: DeclSpec::getSpecifierName(T: TagType, Policy: PPol));
1931 PP.EnterToken(Tok, /*IsReinject*/ true);
1932 Tok.setKind(tok::semi);
1933 }
1934 } else
1935 TUK = TagUseKind::Reference;
1936
1937 // Forbid misplaced attributes. In cases of a reference, we pass attributes
1938 // to caller to handle.
1939 if (TUK != TagUseKind::Reference) {
1940 // If this is not a reference, then the only possible
1941 // valid place for C++11 attributes to appear here
1942 // is between class-key and class-name. If there are
1943 // any attributes after class-name, we try a fixit to move
1944 // them to the right place.
1945 SourceRange AttrRange = Attributes.Range;
1946 if (AttrRange.isValid()) {
1947 auto *FirstAttr = Attributes.empty() ? nullptr : &Attributes.front();
1948 auto Loc = AttrRange.getBegin();
1949 (FirstAttr && FirstAttr->isRegularKeywordAttribute()
1950 ? Diag(Loc, DiagID: diag::err_keyword_not_allowed) << FirstAttr
1951 : Diag(Loc, DiagID: diag::err_attributes_not_allowed))
1952 << AttrRange
1953 << FixItHint::CreateInsertionFromRange(
1954 InsertionLoc: AttrFixitLoc, FromRange: CharSourceRange(AttrRange, true))
1955 << FixItHint::CreateRemoval(RemoveRange: AttrRange);
1956
1957 // Recover by adding misplaced attributes to the attribute list
1958 // of the class so they can be applied on the class later.
1959 attrs.takeAllFrom(Other&: Attributes);
1960 }
1961 }
1962
1963 if (!Name && !TemplateId &&
1964 (DS.getTypeSpecType() == DeclSpec::TST_error ||
1965 TUK != TagUseKind::Definition)) {
1966 if (DS.getTypeSpecType() != DeclSpec::TST_error) {
1967 // We have a declaration or reference to an anonymous class.
1968 Diag(Loc: StartLoc, DiagID: diag::err_anon_type_definition)
1969 << DeclSpec::getSpecifierName(T: TagType, Policy);
1970 }
1971
1972 // If we are parsing a definition and stop at a base-clause, continue on
1973 // until the semicolon. Continuing from the comma will just trick us into
1974 // thinking we are seeing a variable declaration.
1975 if (TUK == TagUseKind::Definition && Tok.is(K: tok::colon))
1976 SkipUntil(T: tok::semi, Flags: StopBeforeMatch);
1977 else
1978 SkipUntil(T: tok::comma, Flags: StopAtSemi);
1979 return;
1980 }
1981
1982 // Create the tag portion of the class or class template.
1983 DeclResult TagOrTempResult = true; // invalid
1984 TypeResult TypeResult = true; // invalid
1985
1986 bool Owned = false;
1987 SkipBodyInfo SkipBody;
1988 if (TemplateId) {
1989 // Explicit specialization, class template partial specialization,
1990 // or explicit instantiation.
1991 ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
1992 TemplateId->NumArgs);
1993 if (TemplateId->isInvalid()) {
1994 // Can't build the declaration.
1995 } else if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation &&
1996 TUK == TagUseKind::Declaration) {
1997 // This is an explicit instantiation of a class template.
1998 ProhibitCXX11Attributes(Attrs&: attrs, AttrDiagID: diag::err_attributes_not_allowed,
1999 KeywordDiagId: diag::err_keyword_not_allowed,
2000 /*DiagnoseEmptyAttrs=*/true);
2001
2002 TagOrTempResult = Actions.ActOnExplicitInstantiation(
2003 S: getCurScope(), ExternLoc: TemplateInfo.ExternLoc, TemplateLoc: TemplateInfo.TemplateLoc,
2004 TagSpec: TagType, KWLoc: StartLoc, SS, Template: TemplateId->Template,
2005 TemplateNameLoc: TemplateId->TemplateNameLoc, LAngleLoc: TemplateId->LAngleLoc, TemplateArgs: TemplateArgsPtr,
2006 RAngleLoc: TemplateId->RAngleLoc, Attr: attrs);
2007
2008 // Friend template-ids are treated as references unless
2009 // they have template headers, in which case they're ill-formed
2010 // (FIXME: "template <class T> friend class A<T>::B<int>;").
2011 // We diagnose this error in ActOnClassTemplateSpecialization.
2012 } else if (TUK == TagUseKind::Reference ||
2013 (TUK == TagUseKind::Friend &&
2014 TemplateInfo.Kind == ParsedTemplateKind::NonTemplate)) {
2015 ProhibitCXX11Attributes(Attrs&: attrs, AttrDiagID: diag::err_attributes_not_allowed,
2016 KeywordDiagId: diag::err_keyword_not_allowed,
2017 /*DiagnoseEmptyAttrs=*/true);
2018 TypeResult = Actions.ActOnTagTemplateIdType(
2019 TUK, TagSpec: TagType, TagLoc: StartLoc, SS, TemplateKWLoc: TemplateId->TemplateKWLoc,
2020 TemplateD: TemplateId->Template, TemplateLoc: TemplateId->TemplateNameLoc,
2021 LAngleLoc: TemplateId->LAngleLoc, TemplateArgsIn: TemplateArgsPtr, RAngleLoc: TemplateId->RAngleLoc);
2022 } else {
2023 // This is an explicit specialization or a class template
2024 // partial specialization.
2025 TemplateParameterLists FakedParamLists;
2026 if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation) {
2027 // This looks like an explicit instantiation, because we have
2028 // something like
2029 //
2030 // template class Foo<X>
2031 //
2032 // but it actually has a definition. Most likely, this was
2033 // meant to be an explicit specialization, but the user forgot
2034 // the '<>' after 'template'.
2035 // It this is friend declaration however, since it cannot have a
2036 // template header, it is most likely that the user meant to
2037 // remove the 'template' keyword.
2038 assert((TUK == TagUseKind::Definition || TUK == TagUseKind::Friend) &&
2039 "Expected a definition here");
2040
2041 if (TUK == TagUseKind::Friend) {
2042 Diag(Loc: DS.getFriendSpecLoc(), DiagID: diag::err_friend_explicit_instantiation);
2043 TemplateParams = nullptr;
2044 } else {
2045 SourceLocation LAngleLoc =
2046 PP.getLocForEndOfToken(Loc: TemplateInfo.TemplateLoc);
2047 Diag(Loc: TemplateId->TemplateNameLoc,
2048 DiagID: diag::err_explicit_instantiation_with_definition)
2049 << SourceRange(TemplateInfo.TemplateLoc)
2050 << FixItHint::CreateInsertion(InsertionLoc: LAngleLoc, Code: "<>");
2051
2052 // Create a fake template parameter list that contains only
2053 // "template<>", so that we treat this construct as a class
2054 // template specialization.
2055 FakedParamLists.push_back(Elt: Actions.ActOnTemplateParameterList(
2056 Depth: 0, ExportLoc: SourceLocation(), TemplateLoc: TemplateInfo.TemplateLoc, LAngleLoc, Params: {},
2057 RAngleLoc: LAngleLoc, RequiresClause: nullptr));
2058 TemplateParams = &FakedParamLists;
2059 }
2060 }
2061
2062 // Build the class template specialization.
2063 TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
2064 S: getCurScope(), TagSpec: TagType, TUK, KWLoc: StartLoc, ModulePrivateLoc: DS.getModulePrivateSpecLoc(),
2065 SS, TemplateId&: *TemplateId, Attr: attrs,
2066 TemplateParameterLists: MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
2067 : nullptr,
2068 TemplateParams ? TemplateParams->size() : 0),
2069 SkipBody: &SkipBody);
2070 }
2071 } else if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation &&
2072 TUK == TagUseKind::Declaration) {
2073 // Explicit instantiation of a member of a class template
2074 // specialization, e.g.,
2075 //
2076 // template struct Outer<int>::Inner;
2077 //
2078 ProhibitAttributes(Attrs&: attrs);
2079
2080 TagOrTempResult = Actions.ActOnExplicitInstantiation(
2081 S: getCurScope(), ExternLoc: TemplateInfo.ExternLoc, TemplateLoc: TemplateInfo.TemplateLoc,
2082 TagSpec: TagType, KWLoc: StartLoc, SS, Name, NameLoc, Attr: attrs);
2083 } else if (TUK == TagUseKind::Friend &&
2084 TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {
2085 ProhibitCXX11Attributes(Attrs&: attrs, AttrDiagID: diag::err_attributes_not_allowed,
2086 KeywordDiagId: diag::err_keyword_not_allowed,
2087 /*DiagnoseEmptyAttrs=*/true);
2088
2089 // Consume '...' first so we error on the ',' after it if there is one.
2090 SourceLocation EllipsisLoc;
2091 TryConsumeToken(Expected: tok::ellipsis, Loc&: EllipsisLoc);
2092
2093 // CWG 2917: In a template-declaration whose declaration is a
2094 // friend-type-declaration, the friend-type-specifier-list shall
2095 // consist of exactly one friend-type-specifier.
2096 //
2097 // Essentially, the following is obviously nonsense, so disallow it:
2098 //
2099 // template <typename>
2100 // friend class S, int;
2101 //
2102 if (Tok.is(K: tok::comma)) {
2103 Diag(Loc: Tok.getLocation(),
2104 DiagID: diag::err_friend_template_decl_multiple_specifiers);
2105 SkipUntil(T: tok::semi, Flags: StopBeforeMatch);
2106 }
2107
2108 TagOrTempResult = Actions.ActOnTemplatedFriendTag(
2109 S: getCurScope(), FriendLoc: DS.getFriendSpecLoc(), TagSpec: TagType, TagLoc: StartLoc, SS, Name,
2110 NameLoc, EllipsisLoc, Attr: attrs,
2111 TempParamLists: MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr,
2112 TemplateParams ? TemplateParams->size() : 0));
2113 } else {
2114 if (TUK != TagUseKind::Declaration && TUK != TagUseKind::Definition)
2115 ProhibitCXX11Attributes(Attrs&: attrs, AttrDiagID: diag::err_attributes_not_allowed,
2116 KeywordDiagId: diag::err_keyword_not_allowed,
2117 /* DiagnoseEmptyAttrs=*/true);
2118
2119 if (TUK == TagUseKind::Definition &&
2120 TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation) {
2121 // If the declarator-id is not a template-id, issue a diagnostic and
2122 // recover by ignoring the 'template' keyword.
2123 Diag(Tok, DiagID: diag::err_template_defn_explicit_instantiation)
2124 << 1 << FixItHint::CreateRemoval(RemoveRange: TemplateInfo.TemplateLoc);
2125 TemplateParams = nullptr;
2126 }
2127
2128 bool IsDependent = false;
2129
2130 // Don't pass down template parameter lists if this is just a tag
2131 // reference. For example, we don't need the template parameters here:
2132 // template <class T> class A *makeA(T t);
2133 MultiTemplateParamsArg TParams;
2134 if (TUK != TagUseKind::Reference && TemplateParams)
2135 TParams =
2136 MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());
2137
2138 stripTypeAttributesOffDeclSpec(Attrs&: attrs, DS, TUK);
2139
2140 // Declaration or definition of a class type
2141 TagOrTempResult = Actions.ActOnTag(
2142 S: getCurScope(), TagSpec: TagType, TUK, KWLoc: StartLoc, SS, Name, NameLoc, Attr: attrs, AS,
2143 ModulePrivateLoc: DS.getModulePrivateSpecLoc(), TemplateParameterLists: TParams, OwnedDecl&: Owned, IsDependent,
2144 ScopedEnumKWLoc: SourceLocation(), ScopedEnumUsesClassTag: false, UnderlyingType: clang::TypeResult(),
2145 IsTypeSpecifier: DSC == DeclSpecContext::DSC_type_specifier,
2146 IsTemplateParamOrArg: DSC == DeclSpecContext::DSC_template_param ||
2147 DSC == DeclSpecContext::DSC_template_type_arg,
2148 OOK: OffsetOfState, SkipBody: &SkipBody);
2149
2150 // If ActOnTag said the type was dependent, try again with the
2151 // less common call.
2152 if (IsDependent) {
2153 assert(TUK == TagUseKind::Reference || TUK == TagUseKind::Friend);
2154 TypeResult = Actions.ActOnDependentTag(S: getCurScope(), TagSpec: TagType, TUK, SS,
2155 Name, TagLoc: StartLoc, NameLoc);
2156 }
2157 }
2158
2159 // If this is an elaborated type specifier in function template,
2160 // and we delayed diagnostics before,
2161 // just merge them into the current pool.
2162 if (shouldDelayDiagsInTag) {
2163 diagsFromTag.done();
2164 if (TUK == TagUseKind::Reference &&
2165 TemplateInfo.Kind == ParsedTemplateKind::Template)
2166 diagsFromTag.redelay();
2167 }
2168
2169 // If there is a body, parse it and inform the actions module.
2170 if (TUK == TagUseKind::Definition) {
2171 assert(Tok.is(tok::l_brace) ||
2172 (getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
2173 isClassCompatibleKeyword());
2174 if (SkipBody.ShouldSkip)
2175 SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType,
2176 TagDecl: TagOrTempResult.get());
2177 else if (getLangOpts().CPlusPlus)
2178 ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, Attrs&: attrs, TagType,
2179 TagDecl: TagOrTempResult.get());
2180 else {
2181 Decl *D =
2182 SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get();
2183 // Parse the definition body.
2184 ParseStructUnionBody(StartLoc, TagType, TagDecl: cast<RecordDecl>(Val: D));
2185 if (SkipBody.CheckSameAsPrevious &&
2186 !Actions.ActOnDuplicateDefinition(S: getCurScope(),
2187 Prev: TagOrTempResult.get(), SkipBody)) {
2188 DS.SetTypeSpecError();
2189 return;
2190 }
2191 }
2192 }
2193
2194 if (!TagOrTempResult.isInvalid())
2195 // Delayed processing of attributes.
2196 Actions.ProcessDeclAttributeDelayed(D: TagOrTempResult.get(), AttrList: attrs);
2197
2198 const char *PrevSpec = nullptr;
2199 unsigned DiagID;
2200 bool Result;
2201 if (!TypeResult.isInvalid()) {
2202 Result = DS.SetTypeSpecType(T: DeclSpec::TST_typename, TagKwLoc: StartLoc,
2203 TagNameLoc: NameLoc.isValid() ? NameLoc : StartLoc,
2204 PrevSpec, DiagID, Rep: TypeResult.get(), Policy);
2205 } else if (!TagOrTempResult.isInvalid()) {
2206 Result = DS.SetTypeSpecType(
2207 T: TagType, TagKwLoc: StartLoc, TagNameLoc: NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,
2208 DiagID, Rep: TagOrTempResult.get(), Owned, Policy);
2209 } else {
2210 DS.SetTypeSpecError();
2211 return;
2212 }
2213
2214 if (Result)
2215 Diag(Loc: StartLoc, DiagID) << PrevSpec;
2216
2217 // At this point, we've successfully parsed a class-specifier in 'definition'
2218 // form (e.g. "struct foo { int x; }". While we could just return here, we're
2219 // going to look at what comes after it to improve error recovery. If an
2220 // impossible token occurs next, we assume that the programmer forgot a ; at
2221 // the end of the declaration and recover that way.
2222 //
2223 // Also enforce C++ [temp]p3:
2224 // In a template-declaration which defines a class, no declarator
2225 // is permitted.
2226 //
2227 // After a type-specifier, we don't expect a semicolon. This only happens in
2228 // C, since definitions are not permitted in this context in C++.
2229 if (TUK == TagUseKind::Definition &&
2230 (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) &&
2231 (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate || !isValidAfterTypeSpecifier(CouldBeBitfield: false))) {
2232 if (Tok.isNot(K: tok::semi)) {
2233 const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
2234 ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_after,
2235 DiagMsg: DeclSpec::getSpecifierName(T: TagType, Policy: PPol));
2236 // Push this token back into the preprocessor and change our current token
2237 // to ';' so that the rest of the code recovers as though there were an
2238 // ';' after the definition.
2239 PP.EnterToken(Tok, /*IsReinject=*/true);
2240 Tok.setKind(tok::semi);
2241 }
2242 }
2243}
2244
2245void Parser::ParseBaseClause(Decl *ClassDecl) {
2246 assert(Tok.is(tok::colon) && "Not a base clause");
2247 ConsumeToken();
2248
2249 // Build up an array of parsed base specifiers.
2250 SmallVector<CXXBaseSpecifier *, 8> BaseInfo;
2251
2252 while (true) {
2253 // Parse a base-specifier.
2254 BaseResult Result = ParseBaseSpecifier(ClassDecl);
2255 if (!Result.isUsable()) {
2256 // Skip the rest of this base specifier, up until the comma or
2257 // opening brace.
2258 SkipUntil(T1: tok::comma, T2: tok::l_brace, Flags: StopAtSemi | StopBeforeMatch);
2259 } else {
2260 // Add this to our array of base specifiers.
2261 BaseInfo.push_back(Elt: Result.get());
2262 }
2263
2264 // If the next token is a comma, consume it and keep reading
2265 // base-specifiers.
2266 if (!TryConsumeToken(Expected: tok::comma))
2267 break;
2268 }
2269
2270 // Attach the base specifiers
2271 Actions.ActOnBaseSpecifiers(ClassDecl, Bases: BaseInfo);
2272}
2273
2274BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
2275 bool IsVirtual = false;
2276 SourceLocation StartLoc = Tok.getLocation();
2277
2278 ParsedAttributes Attributes(AttrFactory);
2279 MaybeParseCXX11Attributes(Attrs&: Attributes);
2280
2281 // Parse the 'virtual' keyword.
2282 if (TryConsumeToken(Expected: tok::kw_virtual))
2283 IsVirtual = true;
2284
2285 CheckMisplacedCXX11Attribute(Attrs&: Attributes, CorrectLocation: StartLoc);
2286
2287 // Parse an (optional) access specifier.
2288 AccessSpecifier Access = getAccessSpecifierIfPresent();
2289 if (Access != AS_none) {
2290 ConsumeToken();
2291 if (getLangOpts().HLSL)
2292 Diag(Loc: Tok.getLocation(), DiagID: diag::ext_hlsl_access_specifiers);
2293 }
2294
2295 CheckMisplacedCXX11Attribute(Attrs&: Attributes, CorrectLocation: StartLoc);
2296
2297 // Parse the 'virtual' keyword (again!), in case it came after the
2298 // access specifier.
2299 if (Tok.is(K: tok::kw_virtual)) {
2300 SourceLocation VirtualLoc = ConsumeToken();
2301 if (IsVirtual) {
2302 // Complain about duplicate 'virtual'
2303 Diag(Loc: VirtualLoc, DiagID: diag::err_dup_virtual)
2304 << FixItHint::CreateRemoval(RemoveRange: VirtualLoc);
2305 }
2306
2307 IsVirtual = true;
2308 }
2309
2310 if (getLangOpts().HLSL && IsVirtual)
2311 Diag(Loc: Tok.getLocation(), DiagID: diag::err_hlsl_virtual_inheritance);
2312
2313 CheckMisplacedCXX11Attribute(Attrs&: Attributes, CorrectLocation: StartLoc);
2314
2315 // Parse the class-name.
2316
2317 // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
2318 // implementation for VS2013 uses _Atomic as an identifier for one of the
2319 // classes in <atomic>. Treat '_Atomic' to be an identifier when we are
2320 // parsing the class-name for a base specifier.
2321 if (getLangOpts().MSVCCompat && Tok.is(K: tok::kw__Atomic) &&
2322 NextToken().is(K: tok::less))
2323 Tok.setKind(tok::identifier);
2324
2325 SourceLocation EndLocation;
2326 SourceLocation BaseLoc;
2327 TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation);
2328 if (BaseType.isInvalid())
2329 return true;
2330
2331 // Parse the optional ellipsis (for a pack expansion). The ellipsis is
2332 // actually part of the base-specifier-list grammar productions, but we
2333 // parse it here for convenience.
2334 SourceLocation EllipsisLoc;
2335 TryConsumeToken(Expected: tok::ellipsis, Loc&: EllipsisLoc);
2336
2337 // Find the complete source range for the base-specifier.
2338 SourceRange Range(StartLoc, EndLocation);
2339
2340 // Notify semantic analysis that we have parsed a complete
2341 // base-specifier.
2342 return Actions.ActOnBaseSpecifier(classdecl: ClassDecl, SpecifierRange: Range, Attrs: Attributes, Virtual: IsVirtual,
2343 Access, basetype: BaseType.get(), BaseLoc,
2344 EllipsisLoc);
2345}
2346
2347AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
2348 switch (Tok.getKind()) {
2349 default:
2350 return AS_none;
2351 case tok::kw_private:
2352 return AS_private;
2353 case tok::kw_protected:
2354 return AS_protected;
2355 case tok::kw_public:
2356 return AS_public;
2357 }
2358}
2359
2360void Parser::HandleMemberFunctionDeclDelays(Declarator &DeclaratorInfo,
2361 Decl *ThisDecl) {
2362 DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo();
2363 // If there was a late-parsed exception-specification, we'll need a
2364 // late parse
2365 bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed;
2366
2367 if (!NeedLateParse) {
2368 // Look ahead to see if there are any default args
2369 for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
2370 const auto *Param = cast<ParmVarDecl>(Val: FTI.Params[ParamIdx].Param);
2371 if (Param->hasUnparsedDefaultArg()) {
2372 NeedLateParse = true;
2373 break;
2374 }
2375 }
2376 }
2377
2378 if (NeedLateParse) {
2379 // Push this method onto the stack of late-parsed method
2380 // declarations.
2381 auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
2382 getCurrentClass().LateParsedDeclarations.push_back(Elt: LateMethod);
2383
2384 // Push tokens for each parameter. Those that do not have defaults will be
2385 // NULL. We need to track all the parameters so that we can push them into
2386 // scope for later parameters and perhaps for the exception specification.
2387 LateMethod->DefaultArgs.reserve(N: FTI.NumParams);
2388 for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)
2389 LateMethod->DefaultArgs.push_back(Elt: LateParsedDefaultArgument(
2390 FTI.Params[ParamIdx].Param,
2391 std::move(FTI.Params[ParamIdx].DefaultArgTokens)));
2392
2393 // Stash the exception-specification tokens in the late-pased method.
2394 if (FTI.getExceptionSpecType() == EST_Unparsed) {
2395 LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
2396 FTI.ExceptionSpecTokens = nullptr;
2397 }
2398 }
2399}
2400
2401VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
2402 if (!getLangOpts().CPlusPlus || Tok.isNot(K: tok::identifier))
2403 return VirtSpecifiers::VS_None;
2404
2405 const IdentifierInfo *II = Tok.getIdentifierInfo();
2406
2407 // Initialize the contextual keywords.
2408 if (!Ident_final) {
2409 Ident_final = &PP.getIdentifierTable().get(Name: "final");
2410 if (getLangOpts().GNUKeywords)
2411 Ident_GNU_final = &PP.getIdentifierTable().get(Name: "__final");
2412 if (getLangOpts().MicrosoftExt) {
2413 Ident_sealed = &PP.getIdentifierTable().get(Name: "sealed");
2414 Ident_abstract = &PP.getIdentifierTable().get(Name: "abstract");
2415 }
2416 Ident_override = &PP.getIdentifierTable().get(Name: "override");
2417 }
2418
2419 if (II == Ident_override)
2420 return VirtSpecifiers::VS_Override;
2421
2422 if (II == Ident_sealed)
2423 return VirtSpecifiers::VS_Sealed;
2424
2425 if (II == Ident_abstract)
2426 return VirtSpecifiers::VS_Abstract;
2427
2428 if (II == Ident_final)
2429 return VirtSpecifiers::VS_Final;
2430
2431 if (II == Ident_GNU_final)
2432 return VirtSpecifiers::VS_GNU_Final;
2433
2434 return VirtSpecifiers::VS_None;
2435}
2436
2437void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
2438 bool IsInterface,
2439 SourceLocation FriendLoc) {
2440 while (true) {
2441 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
2442 if (Specifier == VirtSpecifiers::VS_None)
2443 return;
2444
2445 if (FriendLoc.isValid()) {
2446 Diag(Loc: Tok.getLocation(), DiagID: diag::err_friend_decl_spec)
2447 << VirtSpecifiers::getSpecifierName(VS: Specifier)
2448 << FixItHint::CreateRemoval(RemoveRange: Tok.getLocation())
2449 << SourceRange(FriendLoc, FriendLoc);
2450 ConsumeToken();
2451 continue;
2452 }
2453
2454 // C++ [class.mem]p8:
2455 // A virt-specifier-seq shall contain at most one of each virt-specifier.
2456 const char *PrevSpec = nullptr;
2457 if (VS.SetSpecifier(VS: Specifier, Loc: Tok.getLocation(), PrevSpec))
2458 Diag(Loc: Tok.getLocation(), DiagID: diag::err_duplicate_virt_specifier)
2459 << PrevSpec << FixItHint::CreateRemoval(RemoveRange: Tok.getLocation());
2460
2461 if (IsInterface && (Specifier == VirtSpecifiers::VS_Final ||
2462 Specifier == VirtSpecifiers::VS_Sealed)) {
2463 Diag(Loc: Tok.getLocation(), DiagID: diag::err_override_control_interface)
2464 << VirtSpecifiers::getSpecifierName(VS: Specifier);
2465 } else if (Specifier == VirtSpecifiers::VS_Sealed) {
2466 Diag(Loc: Tok.getLocation(), DiagID: diag::ext_ms_sealed_keyword);
2467 } else if (Specifier == VirtSpecifiers::VS_Abstract) {
2468 Diag(Loc: Tok.getLocation(), DiagID: diag::ext_ms_abstract_keyword);
2469 } else if (Specifier == VirtSpecifiers::VS_GNU_Final) {
2470 Diag(Loc: Tok.getLocation(), DiagID: diag::ext_warn_gnu_final);
2471 } else {
2472 Diag(Loc: Tok.getLocation(),
2473 DiagID: getLangOpts().CPlusPlus11
2474 ? diag::warn_cxx98_compat_override_control_keyword
2475 : diag::ext_override_control_keyword)
2476 << VirtSpecifiers::getSpecifierName(VS: Specifier);
2477 }
2478 ConsumeToken();
2479 }
2480}
2481
2482bool Parser::isCXX11FinalKeyword() const {
2483 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
2484 return Specifier == VirtSpecifiers::VS_Final ||
2485 Specifier == VirtSpecifiers::VS_GNU_Final ||
2486 Specifier == VirtSpecifiers::VS_Sealed;
2487}
2488
2489bool Parser::isCXX2CTriviallyRelocatableKeyword(Token Tok) const {
2490 if (!getLangOpts().CPlusPlus || Tok.isNot(K: tok::identifier))
2491 return false;
2492 if (!Ident_trivially_relocatable_if_eligible)
2493 Ident_trivially_relocatable_if_eligible =
2494 &PP.getIdentifierTable().get(Name: "trivially_relocatable_if_eligible");
2495 IdentifierInfo *II = Tok.getIdentifierInfo();
2496 return II == Ident_trivially_relocatable_if_eligible;
2497}
2498
2499bool Parser::isCXX2CTriviallyRelocatableKeyword() const {
2500 return isCXX2CTriviallyRelocatableKeyword(Tok);
2501}
2502
2503void Parser::ParseCXX2CTriviallyRelocatableSpecifier(SourceLocation &TRS) {
2504 assert(isCXX2CTriviallyRelocatableKeyword() &&
2505 "expected a trivially_relocatable specifier");
2506
2507 Diag(Loc: Tok.getLocation(), DiagID: getLangOpts().CPlusPlus26
2508 ? diag::warn_relocatable_keyword
2509 : diag::ext_relocatable_keyword)
2510 << /*relocatable*/ 0;
2511
2512 TRS = ConsumeToken();
2513}
2514
2515bool Parser::isCXX2CReplaceableKeyword(Token Tok) const {
2516 if (!getLangOpts().CPlusPlus || Tok.isNot(K: tok::identifier))
2517 return false;
2518 if (!Ident_replaceable_if_eligible)
2519 Ident_replaceable_if_eligible =
2520 &PP.getIdentifierTable().get(Name: "replaceable_if_eligible");
2521 IdentifierInfo *II = Tok.getIdentifierInfo();
2522 return II == Ident_replaceable_if_eligible;
2523}
2524
2525bool Parser::isCXX2CReplaceableKeyword() const {
2526 return isCXX2CReplaceableKeyword(Tok);
2527}
2528
2529void Parser::ParseCXX2CReplaceableSpecifier(SourceLocation &MRS) {
2530 assert(isCXX2CReplaceableKeyword() &&
2531 "expected a replaceable_if_eligible specifier");
2532
2533 Diag(Loc: Tok.getLocation(), DiagID: getLangOpts().CPlusPlus26
2534 ? diag::warn_relocatable_keyword
2535 : diag::ext_relocatable_keyword)
2536 << /*replaceable*/ 1;
2537
2538 MRS = ConsumeToken();
2539}
2540
2541bool Parser::isClassCompatibleKeyword(Token Tok) const {
2542 if (isCXX2CTriviallyRelocatableKeyword(Tok) || isCXX2CReplaceableKeyword(Tok))
2543 return true;
2544 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
2545 return Specifier == VirtSpecifiers::VS_Final ||
2546 Specifier == VirtSpecifiers::VS_GNU_Final ||
2547 Specifier == VirtSpecifiers::VS_Sealed ||
2548 Specifier == VirtSpecifiers::VS_Abstract;
2549}
2550
2551bool Parser::isClassCompatibleKeyword() const {
2552 return isClassCompatibleKeyword(Tok);
2553}
2554
2555/// Parse a C++ member-declarator up to, but not including, the optional
2556/// brace-or-equal-initializer or pure-specifier.
2557bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
2558 Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,
2559 LateParsedAttrList &LateParsedAttrs) {
2560 // member-declarator:
2561 // declarator virt-specifier-seq[opt] pure-specifier[opt]
2562 // declarator requires-clause
2563 // declarator brace-or-equal-initializer[opt]
2564 // identifier attribute-specifier-seq[opt] ':' constant-expression
2565 // brace-or-equal-initializer[opt]
2566 // ':' constant-expression
2567 //
2568 // NOTE: the latter two productions are a proposed bugfix rather than the
2569 // current grammar rules as of C++20.
2570 if (Tok.isNot(K: tok::colon))
2571 ParseDeclarator(D&: DeclaratorInfo);
2572 else
2573 DeclaratorInfo.SetIdentifier(Id: nullptr, IdLoc: Tok.getLocation());
2574
2575 if (getLangOpts().HLSL)
2576 MaybeParseHLSLAnnotations(D&: DeclaratorInfo, EndLoc: nullptr,
2577 /*CouldBeBitField*/ true);
2578
2579 if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(Expected: tok::colon)) {
2580 assert(DeclaratorInfo.isPastIdentifier() &&
2581 "don't know where identifier would go yet?");
2582 BitfieldSize = ParseConstantExpression();
2583 if (BitfieldSize.isInvalid())
2584 SkipUntil(T: tok::comma, Flags: StopAtSemi | StopBeforeMatch);
2585 } else if (Tok.is(K: tok::kw_requires)) {
2586 ParseTrailingRequiresClause(D&: DeclaratorInfo);
2587 } else {
2588 ParseOptionalCXX11VirtSpecifierSeq(
2589 VS, IsInterface: getCurrentClass().IsInterface,
2590 FriendLoc: DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
2591 if (!VS.isUnset())
2592 MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(D&: DeclaratorInfo,
2593 VS);
2594 }
2595
2596 // If a simple-asm-expr is present, parse it.
2597 if (Tok.is(K: tok::kw_asm)) {
2598 SourceLocation Loc;
2599 ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, EndLoc: &Loc));
2600 if (AsmLabel.isInvalid())
2601 SkipUntil(T: tok::comma, Flags: StopAtSemi | StopBeforeMatch);
2602
2603 DeclaratorInfo.setAsmLabel(AsmLabel.get());
2604 DeclaratorInfo.SetRangeEnd(Loc);
2605 }
2606
2607 // If attributes exist after the declarator, but before an '{', parse them.
2608 // However, this does not apply for [[]] attributes (which could show up
2609 // before or after the __attribute__ attributes).
2610 DiagnoseAndSkipCXX11Attributes();
2611 MaybeParseGNUAttributes(D&: DeclaratorInfo, LateAttrs: &LateParsedAttrs);
2612 DiagnoseAndSkipCXX11Attributes();
2613
2614 // For compatibility with code written to older Clang, also accept a
2615 // virt-specifier *after* the GNU attributes.
2616 if (BitfieldSize.isUnset() && VS.isUnset()) {
2617 ParseOptionalCXX11VirtSpecifierSeq(
2618 VS, IsInterface: getCurrentClass().IsInterface,
2619 FriendLoc: DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
2620 if (!VS.isUnset()) {
2621 // If we saw any GNU-style attributes that are known to GCC followed by a
2622 // virt-specifier, issue a GCC-compat warning.
2623 for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())
2624 if (AL.isKnownToGCC() && !AL.isCXX11Attribute())
2625 Diag(Loc: AL.getLoc(), DiagID: diag::warn_gcc_attribute_location);
2626
2627 MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(D&: DeclaratorInfo,
2628 VS);
2629 }
2630 }
2631
2632 // If this has neither a name nor a bit width, something has gone seriously
2633 // wrong. Skip until the semi-colon or }.
2634 if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
2635 // If so, skip until the semi-colon or a }.
2636 SkipUntil(T: tok::r_brace, Flags: StopAtSemi | StopBeforeMatch);
2637 return true;
2638 }
2639 return false;
2640}
2641
2642void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
2643 Declarator &D, VirtSpecifiers &VS) {
2644 DeclSpec DS(AttrFactory);
2645
2646 // GNU-style and C++11 attributes are not allowed here, but they will be
2647 // handled by the caller. Diagnose everything else.
2648 ParseTypeQualifierListOpt(
2649 DS, AttrReqs: AR_NoAttributesParsed, /*AtomicOrPtrauthAllowed=*/false,
2650 /*IdentifierRequired=*/false, CodeCompletionHandler: [&]() {
2651 Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D, VS: &VS);
2652 });
2653 D.ExtendWithDeclSpec(DS);
2654
2655 if (D.isFunctionDeclarator()) {
2656 auto &Function = D.getFunctionTypeInfo();
2657 if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
2658 auto DeclSpecCheck = [&](DeclSpec::TQ TypeQual, StringRef FixItName,
2659 SourceLocation SpecLoc) {
2660 FixItHint Insertion;
2661 auto &MQ = Function.getOrCreateMethodQualifiers();
2662 if (!(MQ.getTypeQualifiers() & TypeQual)) {
2663 std::string Name(FixItName.data());
2664 Name += " ";
2665 Insertion = FixItHint::CreateInsertion(InsertionLoc: VS.getFirstLocation(), Code: Name);
2666 MQ.SetTypeQual(T: TypeQual, Loc: SpecLoc);
2667 }
2668 Diag(Loc: SpecLoc, DiagID: diag::err_declspec_after_virtspec)
2669 << FixItName
2670 << VirtSpecifiers::getSpecifierName(VS: VS.getLastSpecifier())
2671 << FixItHint::CreateRemoval(RemoveRange: SpecLoc) << Insertion;
2672 };
2673 DS.forEachQualifier(Handle: DeclSpecCheck);
2674 }
2675
2676 // Parse ref-qualifiers.
2677 bool RefQualifierIsLValueRef = true;
2678 SourceLocation RefQualifierLoc;
2679 if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {
2680 const char *Name = (RefQualifierIsLValueRef ? "& " : "&& ");
2681 FixItHint Insertion =
2682 FixItHint::CreateInsertion(InsertionLoc: VS.getFirstLocation(), Code: Name);
2683 Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef;
2684 Function.RefQualifierLoc = RefQualifierLoc;
2685
2686 Diag(Loc: RefQualifierLoc, DiagID: diag::err_declspec_after_virtspec)
2687 << (RefQualifierIsLValueRef ? "&" : "&&")
2688 << VirtSpecifiers::getSpecifierName(VS: VS.getLastSpecifier())
2689 << FixItHint::CreateRemoval(RemoveRange: RefQualifierLoc) << Insertion;
2690 D.SetRangeEnd(RefQualifierLoc);
2691 }
2692 }
2693}
2694
2695Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(
2696 AccessSpecifier AS, ParsedAttributes &AccessAttrs,
2697 ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) {
2698 assert(getLangOpts().CPlusPlus &&
2699 "ParseCXXClassMemberDeclaration should only be called in C++ mode");
2700 if (Tok.is(K: tok::at)) {
2701 if (getLangOpts().ObjC && NextToken().isObjCAtKeyword(objcKey: tok::objc_defs))
2702 Diag(Tok, DiagID: diag::err_at_defs_cxx);
2703 else
2704 Diag(Tok, DiagID: diag::err_at_in_class);
2705
2706 ConsumeToken();
2707 SkipUntil(T: tok::r_brace, Flags: StopAtSemi);
2708 return nullptr;
2709 }
2710
2711 // Turn on colon protection early, while parsing declspec, although there is
2712 // nothing to protect there. It prevents from false errors if error recovery
2713 // incorrectly determines where the declspec ends, as in the example:
2714 // struct A { enum class B { C }; };
2715 // const int C = 4;
2716 // struct D { A::B : C; };
2717 ColonProtectionRAIIObject X(*this);
2718
2719 // Access declarations.
2720 bool MalformedTypeSpec = false;
2721 if (TemplateInfo.Kind == ParsedTemplateKind::NonTemplate &&
2722 Tok.isOneOf(Ks: tok::identifier, Ks: tok::coloncolon, Ks: tok::kw___super)) {
2723 if (TryAnnotateCXXScopeToken())
2724 MalformedTypeSpec = true;
2725
2726 bool isAccessDecl;
2727 if (Tok.isNot(K: tok::annot_cxxscope))
2728 isAccessDecl = false;
2729 else if (NextToken().is(K: tok::identifier))
2730 isAccessDecl = GetLookAheadToken(N: 2).is(K: tok::semi);
2731 else
2732 isAccessDecl = NextToken().is(K: tok::kw_operator);
2733
2734 if (isAccessDecl) {
2735 // Collect the scope specifier token we annotated earlier.
2736 CXXScopeSpec SS;
2737 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
2738 /*ObjectHasErrors=*/false,
2739 /*EnteringContext=*/false);
2740
2741 if (SS.isInvalid()) {
2742 SkipUntil(T: tok::semi);
2743 return nullptr;
2744 }
2745
2746 // Try to parse an unqualified-id.
2747 SourceLocation TemplateKWLoc;
2748 UnqualifiedId Name;
2749 if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,
2750 /*ObjectHadErrors=*/false, EnteringContext: false, AllowDestructorName: true, AllowConstructorName: true,
2751 AllowDeductionGuide: false, TemplateKWLoc: &TemplateKWLoc, Result&: Name)) {
2752 SkipUntil(T: tok::semi);
2753 return nullptr;
2754 }
2755
2756 // TODO: recover from mistakenly-qualified operator declarations.
2757 if (ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_after,
2758 DiagMsg: "access declaration")) {
2759 SkipUntil(T: tok::semi);
2760 return nullptr;
2761 }
2762
2763 // FIXME: We should do something with the 'template' keyword here.
2764 return DeclGroupPtrTy::make(P: DeclGroupRef(Actions.ActOnUsingDeclaration(
2765 CurScope: getCurScope(), AS, /*UsingLoc*/ SourceLocation(),
2766 /*TypenameLoc*/ SourceLocation(), SS, Name,
2767 /*EllipsisLoc*/ SourceLocation(),
2768 /*AttrList*/ ParsedAttributesView())));
2769 }
2770 }
2771
2772 // static_assert-declaration. A templated static_assert declaration is
2773 // diagnosed in Parser::ParseDeclarationAfterTemplate.
2774 if (TemplateInfo.Kind == ParsedTemplateKind::NonTemplate &&
2775 Tok.isOneOf(Ks: tok::kw_static_assert, Ks: tok::kw__Static_assert)) {
2776 SourceLocation DeclEnd;
2777 return DeclGroupPtrTy::make(
2778 P: DeclGroupRef(ParseStaticAssertDeclaration(DeclEnd)));
2779 }
2780
2781 if (Tok.is(K: tok::kw_template)) {
2782 assert(!TemplateInfo.TemplateParams &&
2783 "Nested template improperly parsed?");
2784 ObjCDeclContextSwitch ObjCDC(*this);
2785 SourceLocation DeclEnd;
2786 return ParseTemplateDeclarationOrSpecialization(Context: DeclaratorContext::Member,
2787 DeclEnd, AccessAttrs, AS);
2788 }
2789
2790 // Handle: member-declaration ::= '__extension__' member-declaration
2791 if (Tok.is(K: tok::kw___extension__)) {
2792 // __extension__ silences extension warnings in the subexpression.
2793 ExtensionRAIIObject O(Diags); // Use RAII to do this.
2794 ConsumeToken();
2795 return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,
2796 TemplateDiags);
2797 }
2798
2799 ParsedAttributes DeclAttrs(AttrFactory);
2800 // Optional C++11 attribute-specifier
2801 MaybeParseCXX11Attributes(Attrs&: DeclAttrs);
2802
2803 // The next token may be an OpenMP pragma annotation token. That would
2804 // normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in
2805 // this case, it came from an *attribute* rather than a pragma. Handle it now.
2806 if (Tok.is(K: tok::annot_attr_openmp))
2807 return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs&: DeclAttrs);
2808
2809 if (Tok.is(K: tok::kw_using)) {
2810 // Eat 'using'.
2811 SourceLocation UsingLoc = ConsumeToken();
2812
2813 // Consume unexpected 'template' keywords.
2814 while (Tok.is(K: tok::kw_template)) {
2815 SourceLocation TemplateLoc = ConsumeToken();
2816 Diag(Loc: TemplateLoc, DiagID: diag::err_unexpected_template_after_using)
2817 << FixItHint::CreateRemoval(RemoveRange: TemplateLoc);
2818 }
2819
2820 if (Tok.is(K: tok::kw_namespace)) {
2821 Diag(Loc: UsingLoc, DiagID: diag::err_using_namespace_in_class);
2822 SkipUntil(T: tok::semi, Flags: StopBeforeMatch);
2823 return nullptr;
2824 }
2825 SourceLocation DeclEnd;
2826 // Otherwise, it must be a using-declaration or an alias-declaration.
2827 return ParseUsingDeclaration(Context: DeclaratorContext::Member, TemplateInfo,
2828 UsingLoc, DeclEnd, PrefixAttrs&: DeclAttrs, AS);
2829 }
2830
2831 ParsedAttributes DeclSpecAttrs(AttrFactory);
2832 // Hold late-parsed attributes so we can attach a Decl to them later.
2833 LateParsedAttrList CommonLateParsedAttrs;
2834
2835 while (MaybeParseCXX11Attributes(Attrs&: DeclAttrs) ||
2836 MaybeParseGNUAttributes(Attrs&: DeclSpecAttrs, LateAttrs: &CommonLateParsedAttrs) ||
2837 MaybeParseMicrosoftAttributes(Attrs&: DeclSpecAttrs))
2838 ;
2839
2840 SourceLocation DeclStart;
2841 if (DeclAttrs.Range.isValid()) {
2842 DeclStart = DeclSpecAttrs.Range.isInvalid()
2843 ? DeclAttrs.Range.getBegin()
2844 : std::min(a: DeclAttrs.Range.getBegin(),
2845 b: DeclSpecAttrs.Range.getBegin());
2846 } else {
2847 DeclStart = DeclSpecAttrs.Range.getBegin();
2848 }
2849
2850 // decl-specifier-seq:
2851 // Parse the common declaration-specifiers piece.
2852 ParsingDeclSpec DS(*this, TemplateDiags);
2853 DS.takeAttributesFrom(attrs&: DeclSpecAttrs);
2854
2855 if (MalformedTypeSpec)
2856 DS.SetTypeSpecError();
2857
2858 // Turn off usual access checking for templates explicit specialization
2859 // and instantiation.
2860 // C++20 [temp.spec] 13.9/6.
2861 // This disables the access checking rules for member function template
2862 // explicit instantiation and explicit specialization.
2863 bool IsTemplateSpecOrInst =
2864 (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation ||
2865 TemplateInfo.Kind == ParsedTemplateKind::ExplicitSpecialization);
2866 SuppressAccessChecks diagsFromTag(*this, IsTemplateSpecOrInst);
2867
2868 ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC: DeclSpecContext::DSC_class,
2869 LateAttrs: &CommonLateParsedAttrs);
2870
2871 if (IsTemplateSpecOrInst)
2872 diagsFromTag.done();
2873
2874 // Turn off colon protection that was set for declspec.
2875 X.restore();
2876
2877 if (DeclStart.isValid())
2878 DS.SetRangeStart(DeclStart);
2879
2880 // If we had a free-standing type definition with a missing semicolon, we
2881 // may get this far before the problem becomes obvious.
2882 if (DS.hasTagDefinition() &&
2883 TemplateInfo.Kind == ParsedTemplateKind::NonTemplate &&
2884 DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSContext: DeclSpecContext::DSC_class,
2885 LateAttrs: &CommonLateParsedAttrs))
2886 return nullptr;
2887
2888 MultiTemplateParamsArg TemplateParams(
2889 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data()
2890 : nullptr,
2891 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
2892
2893 if (TryConsumeToken(Expected: tok::semi)) {
2894 if (DS.isFriendSpecified())
2895 ProhibitAttributes(Attrs&: DeclAttrs);
2896
2897 RecordDecl *AnonRecord = nullptr;
2898 Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
2899 S: getCurScope(), AS, DS, DeclAttrs, TemplateParams, IsExplicitInstantiation: false, AnonRecord);
2900 Actions.ActOnDefinedDeclarationSpecifier(D: TheDecl);
2901 DS.complete(D: TheDecl);
2902 if (AnonRecord) {
2903 Decl *decls[] = {AnonRecord, TheDecl};
2904 return Actions.BuildDeclaratorGroup(Group: decls);
2905 }
2906 return Actions.ConvertDeclToDeclGroup(Ptr: TheDecl);
2907 }
2908
2909 if (DS.hasTagDefinition())
2910 Actions.ActOnDefinedDeclarationSpecifier(D: DS.getRepAsDecl());
2911
2912 // Handle C++26's variadic friend declarations. These don't even have
2913 // declarators, so we get them out of the way early here.
2914 if (DS.isFriendSpecifiedFirst() && Tok.isOneOf(Ks: tok::comma, Ks: tok::ellipsis)) {
2915 Diag(Loc: Tok.getLocation(), DiagID: getLangOpts().CPlusPlus26
2916 ? diag::warn_cxx23_variadic_friends
2917 : diag::ext_variadic_friends);
2918
2919 SourceLocation FriendLoc = DS.getFriendSpecLoc();
2920 SmallVector<Decl *> Decls;
2921
2922 // Handles a single friend-type-specifier.
2923 auto ParsedFriendDecl = [&](ParsingDeclSpec &DeclSpec) {
2924 SourceLocation VariadicLoc;
2925 TryConsumeToken(Expected: tok::ellipsis, Loc&: VariadicLoc);
2926
2927 RecordDecl *AnonRecord = nullptr;
2928 Decl *D = Actions.ParsedFreeStandingDeclSpec(
2929 S: getCurScope(), AS, DS&: DeclSpec, DeclAttrs, TemplateParams, IsExplicitInstantiation: false,
2930 AnonRecord, EllipsisLoc: VariadicLoc);
2931 DeclSpec.complete(D);
2932 if (!D) {
2933 SkipUntil(T1: tok::semi, T2: tok::r_brace);
2934 return true;
2935 }
2936
2937 Decls.push_back(Elt: D);
2938 return false;
2939 };
2940
2941 if (ParsedFriendDecl(DS))
2942 return nullptr;
2943
2944 while (TryConsumeToken(Expected: tok::comma)) {
2945 ParsingDeclSpec DeclSpec(*this, TemplateDiags);
2946 const char *PrevSpec = nullptr;
2947 unsigned DiagId = 0;
2948 DeclSpec.SetFriendSpec(Loc: FriendLoc, PrevSpec, DiagID&: DiagId);
2949 ParseDeclarationSpecifiers(DS&: DeclSpec, TemplateInfo, AS,
2950 DSC: DeclSpecContext::DSC_class, LateAttrs: nullptr);
2951 if (ParsedFriendDecl(DeclSpec))
2952 return nullptr;
2953 }
2954
2955 ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_semi_after_stmt,
2956 DiagMsg: "friend declaration");
2957
2958 return Actions.BuildDeclaratorGroup(Group: Decls);
2959 }
2960
2961 // Befriending a concept is invalid and would already fail if
2962 // we did nothing here, but this allows us to issue a more
2963 // helpful diagnostic.
2964 if (Tok.is(K: tok::kw_concept)) {
2965 Diag(
2966 Loc: Tok.getLocation(),
2967 DiagID: DS.isFriendSpecified() || NextToken().is(K: tok::kw_friend)
2968 ? llvm::to_underlying(E: diag::err_friend_concept)
2969 : llvm::to_underlying(
2970 E: diag::
2971 err_concept_decls_may_only_appear_in_global_namespace_scope));
2972 SkipUntil(T1: tok::semi, T2: tok::r_brace, Flags: StopBeforeMatch);
2973 return nullptr;
2974 }
2975
2976 ParsingDeclarator DeclaratorInfo(*this, DS, DeclAttrs,
2977 DeclaratorContext::Member);
2978 if (TemplateInfo.TemplateParams)
2979 DeclaratorInfo.setTemplateParameterLists(TemplateParams);
2980 VirtSpecifiers VS;
2981
2982 // Hold late-parsed attributes so we can attach a Decl to them later.
2983 LateParsedAttrList LateParsedAttrs;
2984
2985 SourceLocation EqualLoc;
2986 SourceLocation PureSpecLoc;
2987
2988 auto TryConsumePureSpecifier = [&](bool AllowDefinition) {
2989 if (Tok.isNot(K: tok::equal))
2990 return false;
2991
2992 auto &Zero = NextToken();
2993 SmallString<8> Buffer;
2994 if (Zero.isNot(K: tok::numeric_constant) ||
2995 PP.getSpelling(Tok: Zero, Buffer) != "0")
2996 return false;
2997
2998 auto &After = GetLookAheadToken(N: 2);
2999 if (!After.isOneOf(Ks: tok::semi, Ks: tok::comma) &&
3000 !(AllowDefinition &&
3001 After.isOneOf(Ks: tok::l_brace, Ks: tok::colon, Ks: tok::kw_try)))
3002 return false;
3003
3004 EqualLoc = ConsumeToken();
3005 PureSpecLoc = ConsumeToken();
3006 return true;
3007 };
3008
3009 SmallVector<Decl *, 8> DeclsInGroup;
3010 ExprResult BitfieldSize;
3011 ExprResult TrailingRequiresClause;
3012 bool ExpectSemi = true;
3013
3014 // C++20 [temp.spec] 13.9/6.
3015 // This disables the access checking rules for member function template
3016 // explicit instantiation and explicit specialization.
3017 SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);
3018
3019 // Parse the first declarator.
3020 if (ParseCXXMemberDeclaratorBeforeInitializer(
3021 DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) {
3022 TryConsumeToken(Expected: tok::semi);
3023 return nullptr;
3024 }
3025
3026 if (IsTemplateSpecOrInst)
3027 SAC.done();
3028
3029 // Check for a member function definition.
3030 if (BitfieldSize.isUnset()) {
3031 // MSVC permits pure specifier on inline functions defined at class scope.
3032 // Hence check for =0 before checking for function definition.
3033 if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction())
3034 TryConsumePureSpecifier(/*AllowDefinition*/ true);
3035
3036 FunctionDefinitionKind DefinitionKind = FunctionDefinitionKind::Declaration;
3037 // function-definition:
3038 //
3039 // In C++11, a non-function declarator followed by an open brace is a
3040 // braced-init-list for an in-class member initialization, not an
3041 // erroneous function definition.
3042 if (Tok.is(K: tok::l_brace) && !getLangOpts().CPlusPlus11) {
3043 DefinitionKind = FunctionDefinitionKind::Definition;
3044 } else if (DeclaratorInfo.isFunctionDeclarator()) {
3045 if (Tok.isOneOf(Ks: tok::l_brace, Ks: tok::colon, Ks: tok::kw_try)) {
3046 DefinitionKind = FunctionDefinitionKind::Definition;
3047 } else if (Tok.is(K: tok::equal)) {
3048 const Token &KW = NextToken();
3049 if (KW.is(K: tok::kw_default))
3050 DefinitionKind = FunctionDefinitionKind::Defaulted;
3051 else if (KW.is(K: tok::kw_delete))
3052 DefinitionKind = FunctionDefinitionKind::Deleted;
3053 else if (KW.is(K: tok::code_completion)) {
3054 cutOffParsing();
3055 Actions.CodeCompletion().CodeCompleteAfterFunctionEquals(
3056 D&: DeclaratorInfo);
3057 return nullptr;
3058 }
3059 }
3060 }
3061 DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);
3062
3063 // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
3064 // to a friend declaration, that declaration shall be a definition.
3065 if (DeclaratorInfo.isFunctionDeclarator() &&
3066 DefinitionKind == FunctionDefinitionKind::Declaration &&
3067 DS.isFriendSpecified()) {
3068 // Diagnose attributes that appear before decl specifier:
3069 // [[]] friend int foo();
3070 ProhibitAttributes(Attrs&: DeclAttrs);
3071 }
3072
3073 if (DefinitionKind != FunctionDefinitionKind::Declaration) {
3074 if (!DeclaratorInfo.isFunctionDeclarator()) {
3075 Diag(Loc: DeclaratorInfo.getIdentifierLoc(), DiagID: diag::err_func_def_no_params);
3076 ConsumeBrace();
3077 SkipUntil(T: tok::r_brace);
3078
3079 // Consume the optional ';'
3080 TryConsumeToken(Expected: tok::semi);
3081
3082 return nullptr;
3083 }
3084
3085 if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
3086 Diag(Loc: DeclaratorInfo.getIdentifierLoc(),
3087 DiagID: diag::err_function_declared_typedef);
3088
3089 // Recover by treating the 'typedef' as spurious.
3090 DS.ClearStorageClassSpecs();
3091 }
3092
3093 Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, D&: DeclaratorInfo,
3094 TemplateInfo, VS, PureSpecLoc);
3095
3096 if (FunDecl) {
3097 for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
3098 CommonLateParsedAttrs[i]->addDecl(D: FunDecl);
3099 }
3100 for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
3101 LateParsedAttrs[i]->addDecl(D: FunDecl);
3102 }
3103 }
3104 LateParsedAttrs.clear();
3105
3106 // Consume the ';' - it's optional unless we have a delete or default
3107 if (Tok.is(K: tok::semi))
3108 ConsumeExtraSemi(Kind: ExtraSemiKind::AfterMemberFunctionDefinition);
3109
3110 return DeclGroupPtrTy::make(P: DeclGroupRef(FunDecl));
3111 }
3112 }
3113
3114 // member-declarator-list:
3115 // member-declarator
3116 // member-declarator-list ',' member-declarator
3117
3118 while (true) {
3119 InClassInitStyle HasInClassInit = ICIS_NoInit;
3120 bool HasStaticInitializer = false;
3121 if (Tok.isOneOf(Ks: tok::equal, Ks: tok::l_brace) && PureSpecLoc.isInvalid()) {
3122 // DRXXXX: Anonymous bit-fields cannot have a brace-or-equal-initializer.
3123 if (BitfieldSize.isUsable() && !DeclaratorInfo.hasName()) {
3124 // Diagnose the error and pretend there is no in-class initializer.
3125 Diag(Tok, DiagID: diag::err_anon_bitfield_member_init);
3126 SkipUntil(T: tok::comma, Flags: StopAtSemi | StopBeforeMatch);
3127 } else if (DeclaratorInfo.isDeclarationOfFunction()) {
3128 // It's a pure-specifier.
3129 if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false))
3130 // Parse it as an expression so that Sema can diagnose it.
3131 HasStaticInitializer = true;
3132 } else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
3133 DeclSpec::SCS_static &&
3134 DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
3135 DeclSpec::SCS_typedef &&
3136 !DS.isFriendSpecified() &&
3137 TemplateInfo.Kind == ParsedTemplateKind::NonTemplate) {
3138 // It's a default member initializer.
3139 if (BitfieldSize.get())
3140 Diag(Tok, DiagID: getLangOpts().CPlusPlus20
3141 ? diag::warn_cxx17_compat_bitfield_member_init
3142 : diag::ext_bitfield_member_init);
3143 HasInClassInit = Tok.is(K: tok::equal) ? ICIS_CopyInit : ICIS_ListInit;
3144 } else {
3145 HasStaticInitializer = true;
3146 }
3147 }
3148
3149 // NOTE: If Sema is the Action module and declarator is an instance field,
3150 // this call will *not* return the created decl; It will return null.
3151 // See Sema::ActOnCXXMemberDeclarator for details.
3152
3153 NamedDecl *ThisDecl = nullptr;
3154 if (DS.isFriendSpecified()) {
3155 // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
3156 // to a friend declaration, that declaration shall be a definition.
3157 //
3158 // Diagnose attributes that appear in a friend member function declarator:
3159 // friend int foo [[]] ();
3160 for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())
3161 if (AL.isCXX11Attribute() || AL.isRegularKeywordAttribute()) {
3162 auto Loc = AL.getRange().getBegin();
3163 (AL.isRegularKeywordAttribute()
3164 ? Diag(Loc, DiagID: diag::err_keyword_not_allowed) << AL
3165 : Diag(Loc, DiagID: diag::err_attributes_not_allowed))
3166 << AL.getRange();
3167 }
3168
3169 ThisDecl = Actions.ActOnFriendFunctionDecl(S: getCurScope(), D&: DeclaratorInfo,
3170 TemplateParams);
3171 } else {
3172 ThisDecl = Actions.ActOnCXXMemberDeclarator(
3173 S: getCurScope(), AS, D&: DeclaratorInfo, TemplateParameterLists: TemplateParams, BitfieldWidth: BitfieldSize.get(),
3174 VS, InitStyle: HasInClassInit);
3175
3176 if (VarTemplateDecl *VT =
3177 ThisDecl ? dyn_cast<VarTemplateDecl>(Val: ThisDecl) : nullptr)
3178 // Re-direct this decl to refer to the templated decl so that we can
3179 // initialize it.
3180 ThisDecl = VT->getTemplatedDecl();
3181
3182 if (ThisDecl)
3183 Actions.ProcessDeclAttributeList(S: getCurScope(), D: ThisDecl, AttrList: AccessAttrs);
3184 }
3185
3186 // Error recovery might have converted a non-static member into a static
3187 // member.
3188 if (HasInClassInit != ICIS_NoInit &&
3189 DeclaratorInfo.getDeclSpec().getStorageClassSpec() ==
3190 DeclSpec::SCS_static) {
3191 HasInClassInit = ICIS_NoInit;
3192 HasStaticInitializer = true;
3193 }
3194
3195 if (PureSpecLoc.isValid() && VS.getAbstractLoc().isValid()) {
3196 Diag(Loc: PureSpecLoc, DiagID: diag::err_duplicate_virt_specifier) << "abstract";
3197 }
3198 if (ThisDecl && PureSpecLoc.isValid())
3199 Actions.ActOnPureSpecifier(D: ThisDecl, PureSpecLoc);
3200 else if (ThisDecl && VS.getAbstractLoc().isValid())
3201 Actions.ActOnPureSpecifier(D: ThisDecl, PureSpecLoc: VS.getAbstractLoc());
3202
3203 // Handle the initializer.
3204 if (HasInClassInit != ICIS_NoInit) {
3205 // The initializer was deferred; parse it and cache the tokens.
3206 Diag(Tok, DiagID: getLangOpts().CPlusPlus11
3207 ? diag::warn_cxx98_compat_nonstatic_member_init
3208 : diag::ext_nonstatic_member_init);
3209
3210 if (DeclaratorInfo.isArrayOfUnknownBound()) {
3211 // C++11 [dcl.array]p3: An array bound may also be omitted when the
3212 // declarator is followed by an initializer.
3213 //
3214 // A brace-or-equal-initializer for a member-declarator is not an
3215 // initializer in the grammar, so this is ill-formed.
3216 Diag(Tok, DiagID: diag::err_incomplete_array_member_init);
3217 SkipUntil(T: tok::comma, Flags: StopAtSemi | StopBeforeMatch);
3218
3219 // Avoid later warnings about a class member of incomplete type.
3220 if (ThisDecl)
3221 ThisDecl->setInvalidDecl();
3222 } else
3223 ParseCXXNonStaticMemberInitializer(VarD: ThisDecl);
3224 } else if (HasStaticInitializer) {
3225 // Normal initializer.
3226 ExprResult Init = ParseCXXMemberInitializer(
3227 D: ThisDecl, IsFunction: DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
3228
3229 if (Init.isInvalid()) {
3230 if (ThisDecl)
3231 Actions.ActOnUninitializedDecl(dcl: ThisDecl);
3232 SkipUntil(T: tok::comma, Flags: StopAtSemi | StopBeforeMatch);
3233 } else if (ThisDecl)
3234 Actions.AddInitializerToDecl(dcl: ThisDecl, init: Init.get(),
3235 DirectInit: EqualLoc.isInvalid());
3236 } else if (ThisDecl && DeclaratorInfo.isStaticMember())
3237 // No initializer.
3238 Actions.ActOnUninitializedDecl(dcl: ThisDecl);
3239
3240 if (ThisDecl) {
3241 if (!ThisDecl->isInvalidDecl()) {
3242 // Set the Decl for any late parsed attributes
3243 for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i)
3244 CommonLateParsedAttrs[i]->addDecl(D: ThisDecl);
3245
3246 for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i)
3247 LateParsedAttrs[i]->addDecl(D: ThisDecl);
3248 }
3249 Actions.FinalizeDeclaration(D: ThisDecl);
3250 DeclsInGroup.push_back(Elt: ThisDecl);
3251
3252 if (DeclaratorInfo.isFunctionDeclarator() &&
3253 DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
3254 DeclSpec::SCS_typedef)
3255 HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);
3256 }
3257 LateParsedAttrs.clear();
3258
3259 DeclaratorInfo.complete(D: ThisDecl);
3260
3261 // If we don't have a comma, it is either the end of the list (a ';')
3262 // or an error, bail out.
3263 SourceLocation CommaLoc;
3264 if (!TryConsumeToken(Expected: tok::comma, Loc&: CommaLoc))
3265 break;
3266
3267 if (Tok.isAtStartOfLine() &&
3268 !MightBeDeclarator(Context: DeclaratorContext::Member)) {
3269 // This comma was followed by a line-break and something which can't be
3270 // the start of a declarator. The comma was probably a typo for a
3271 // semicolon.
3272 Diag(Loc: CommaLoc, DiagID: diag::err_expected_semi_declaration)
3273 << FixItHint::CreateReplacement(RemoveRange: CommaLoc, Code: ";");
3274 ExpectSemi = false;
3275 break;
3276 }
3277
3278 // C++23 [temp.pre]p5:
3279 // In a template-declaration, explicit specialization, or explicit
3280 // instantiation the init-declarator-list in the declaration shall
3281 // contain at most one declarator.
3282 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate &&
3283 DeclaratorInfo.isFirstDeclarator()) {
3284 Diag(Loc: CommaLoc, DiagID: diag::err_multiple_template_declarators)
3285 << TemplateInfo.Kind;
3286 }
3287
3288 // Parse the next declarator.
3289 DeclaratorInfo.clear();
3290 VS.clear();
3291 BitfieldSize = ExprResult(/*Invalid=*/false);
3292 EqualLoc = PureSpecLoc = SourceLocation();
3293 DeclaratorInfo.setCommaLoc(CommaLoc);
3294
3295 // GNU attributes are allowed before the second and subsequent declarator.
3296 // However, this does not apply for [[]] attributes (which could show up
3297 // before or after the __attribute__ attributes).
3298 DiagnoseAndSkipCXX11Attributes();
3299 MaybeParseGNUAttributes(D&: DeclaratorInfo);
3300 DiagnoseAndSkipCXX11Attributes();
3301
3302 if (ParseCXXMemberDeclaratorBeforeInitializer(
3303 DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs))
3304 break;
3305 }
3306
3307 if (ExpectSemi &&
3308 ExpectAndConsume(ExpectedTok: tok::semi, Diag: diag::err_expected_semi_decl_list)) {
3309 // Skip to end of block or statement.
3310 SkipUntil(T: tok::r_brace, Flags: StopAtSemi | StopBeforeMatch);
3311 // If we stopped at a ';', eat it.
3312 TryConsumeToken(Expected: tok::semi);
3313 return nullptr;
3314 }
3315
3316 return Actions.FinalizeDeclaratorGroup(S: getCurScope(), DS, Group: DeclsInGroup);
3317}
3318
3319ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
3320 SourceLocation &EqualLoc) {
3321 assert(Tok.isOneOf(tok::equal, tok::l_brace) &&
3322 "Data member initializer not starting with '=' or '{'");
3323
3324 bool IsFieldInitialization = isa_and_present<FieldDecl>(Val: D);
3325
3326 EnterExpressionEvaluationContext Context(
3327 Actions,
3328 IsFieldInitialization
3329 ? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed
3330 : Sema::ExpressionEvaluationContext::PotentiallyEvaluated,
3331 D);
3332
3333 // CWG2760
3334 // Default member initializers used to initialize a base or member subobject
3335 // [...] are considered to be part of the function body
3336 Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
3337 IsFieldInitialization;
3338
3339 if (TryConsumeToken(Expected: tok::equal, Loc&: EqualLoc)) {
3340 if (Tok.is(K: tok::kw_delete)) {
3341 // In principle, an initializer of '= delete p;' is legal, but it will
3342 // never type-check. It's better to diagnose it as an ill-formed
3343 // expression than as an ill-formed deleted non-function member. An
3344 // initializer of '= delete p, foo' will never be parsed, because a
3345 // top-level comma always ends the initializer expression.
3346 const Token &Next = NextToken();
3347 if (IsFunction || Next.isOneOf(Ks: tok::semi, Ks: tok::comma, Ks: tok::eof)) {
3348 if (IsFunction)
3349 Diag(Loc: ConsumeToken(), DiagID: diag::err_default_delete_in_multiple_declaration)
3350 << 1 /* delete */;
3351 else
3352 Diag(Loc: ConsumeToken(), DiagID: diag::err_deleted_non_function);
3353 SkipDeletedFunctionBody();
3354 return ExprError();
3355 }
3356 } else if (Tok.is(K: tok::kw_default)) {
3357 if (IsFunction)
3358 Diag(Tok, DiagID: diag::err_default_delete_in_multiple_declaration)
3359 << 0 /* default */;
3360 else
3361 Diag(Loc: ConsumeToken(), DiagID: diag::err_default_special_members)
3362 << getLangOpts().CPlusPlus20;
3363 return ExprError();
3364 }
3365 }
3366 if (const auto *PD = dyn_cast_or_null<MSPropertyDecl>(Val: D)) {
3367 Diag(Tok, DiagID: diag::err_ms_property_initializer) << PD;
3368 return ExprError();
3369 }
3370 return ParseInitializer();
3371}
3372
3373void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
3374 SourceLocation AttrFixitLoc,
3375 unsigned TagType, Decl *TagDecl) {
3376 // Skip the optional 'final' keyword.
3377 while (isClassCompatibleKeyword())
3378 ConsumeToken();
3379
3380 // Diagnose any C++11 attributes after 'final' keyword.
3381 // We deliberately discard these attributes.
3382 ParsedAttributes Attrs(AttrFactory);
3383 CheckMisplacedCXX11Attribute(Attrs, CorrectLocation: AttrFixitLoc);
3384
3385 // This can only happen if we had malformed misplaced attributes;
3386 // we only get called if there is a colon or left-brace after the
3387 // attributes.
3388 if (Tok.isNot(K: tok::colon) && Tok.isNot(K: tok::l_brace))
3389 return;
3390
3391 // Skip the base clauses. This requires actually parsing them, because
3392 // otherwise we can't be sure where they end (a left brace may appear
3393 // within a template argument).
3394 if (Tok.is(K: tok::colon)) {
3395 // Enter the scope of the class so that we can correctly parse its bases.
3396 ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope);
3397 ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,
3398 TagType == DeclSpec::TST_interface);
3399 auto OldContext =
3400 Actions.ActOnTagStartSkippedDefinition(S: getCurScope(), TD: TagDecl);
3401
3402 // Parse the bases but don't attach them to the class.
3403 ParseBaseClause(ClassDecl: nullptr);
3404
3405 Actions.ActOnTagFinishSkippedDefinition(Context: OldContext);
3406
3407 if (!Tok.is(K: tok::l_brace)) {
3408 Diag(Loc: PP.getLocForEndOfToken(Loc: PrevTokLocation),
3409 DiagID: diag::err_expected_lbrace_after_base_specifiers);
3410 return;
3411 }
3412 }
3413
3414 // Skip the body.
3415 assert(Tok.is(tok::l_brace));
3416 BalancedDelimiterTracker T(*this, tok::l_brace);
3417 T.consumeOpen();
3418 T.skipToEnd();
3419
3420 // Parse and discard any trailing attributes.
3421 if (Tok.is(K: tok::kw___attribute)) {
3422 ParsedAttributes Attrs(AttrFactory);
3423 MaybeParseGNUAttributes(Attrs);
3424 }
3425}
3426
3427Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
3428 AccessSpecifier &AS, ParsedAttributes &AccessAttrs, DeclSpec::TST TagType,
3429 Decl *TagDecl) {
3430 ParenBraceBracketBalancer BalancerRAIIObj(*this);
3431
3432 switch (Tok.getKind()) {
3433 case tok::kw___if_exists:
3434 case tok::kw___if_not_exists:
3435 ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS&: AS);
3436 return nullptr;
3437
3438 case tok::semi:
3439 // Check for extraneous top-level semicolon.
3440 ConsumeExtraSemi(Kind: ExtraSemiKind::InsideStruct, T: TagType);
3441 return nullptr;
3442
3443 // Handle pragmas that can appear as member declarations.
3444 case tok::annot_pragma_vis:
3445 HandlePragmaVisibility();
3446 return nullptr;
3447 case tok::annot_pragma_pack:
3448 HandlePragmaPack();
3449 return nullptr;
3450 case tok::annot_pragma_align:
3451 HandlePragmaAlign();
3452 return nullptr;
3453 case tok::annot_pragma_ms_pointers_to_members:
3454 HandlePragmaMSPointersToMembers();
3455 return nullptr;
3456 case tok::annot_pragma_ms_pragma:
3457 HandlePragmaMSPragma();
3458 return nullptr;
3459 case tok::annot_pragma_ms_vtordisp:
3460 HandlePragmaMSVtorDisp();
3461 return nullptr;
3462 case tok::annot_pragma_dump:
3463 HandlePragmaDump();
3464 return nullptr;
3465
3466 case tok::kw_namespace:
3467 // If we see a namespace here, a close brace was missing somewhere.
3468 DiagnoseUnexpectedNamespace(Context: cast<NamedDecl>(Val: TagDecl));
3469 return nullptr;
3470
3471 case tok::kw_private:
3472 // FIXME: We don't accept GNU attributes on access specifiers in OpenCL mode
3473 // yet.
3474 if (getLangOpts().OpenCL && !NextToken().is(K: tok::colon)) {
3475 ParsedTemplateInfo TemplateInfo;
3476 return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo);
3477 }
3478 [[fallthrough]];
3479 case tok::kw_public:
3480 case tok::kw_protected: {
3481 if (getLangOpts().HLSL)
3482 Diag(Loc: Tok.getLocation(), DiagID: diag::ext_hlsl_access_specifiers);
3483 AccessSpecifier NewAS = getAccessSpecifierIfPresent();
3484 assert(NewAS != AS_none);
3485 // Current token is a C++ access specifier.
3486 AS = NewAS;
3487 SourceLocation ASLoc = Tok.getLocation();
3488 unsigned TokLength = Tok.getLength();
3489 ConsumeToken();
3490 AccessAttrs.clear();
3491 MaybeParseGNUAttributes(Attrs&: AccessAttrs);
3492
3493 SourceLocation EndLoc;
3494 if (TryConsumeToken(Expected: tok::colon, Loc&: EndLoc)) {
3495 } else if (TryConsumeToken(Expected: tok::semi, Loc&: EndLoc)) {
3496 Diag(Loc: EndLoc, DiagID: diag::err_expected)
3497 << tok::colon << FixItHint::CreateReplacement(RemoveRange: EndLoc, Code: ":");
3498 } else {
3499 EndLoc = ASLoc.getLocWithOffset(Offset: TokLength);
3500 Diag(Loc: EndLoc, DiagID: diag::err_expected)
3501 << tok::colon << FixItHint::CreateInsertion(InsertionLoc: EndLoc, Code: ":");
3502 }
3503
3504 // The Microsoft extension __interface does not permit non-public
3505 // access specifiers.
3506 if (TagType == DeclSpec::TST_interface && AS != AS_public) {
3507 Diag(Loc: ASLoc, DiagID: diag::err_access_specifier_interface) << (AS == AS_protected);
3508 }
3509
3510 if (Actions.ActOnAccessSpecifier(Access: NewAS, ASLoc, ColonLoc: EndLoc, Attrs: AccessAttrs)) {
3511 // found another attribute than only annotations
3512 AccessAttrs.clear();
3513 }
3514
3515 return nullptr;
3516 }
3517
3518 case tok::annot_attr_openmp:
3519 case tok::annot_pragma_openmp:
3520 return ParseOpenMPDeclarativeDirectiveWithExtDecl(
3521 AS, Attrs&: AccessAttrs, /*Delayed=*/true, TagType, TagDecl);
3522 case tok::annot_pragma_openacc:
3523 return ParseOpenACCDirectiveDecl(AS, Attrs&: AccessAttrs, TagType, TagDecl);
3524
3525 default:
3526 if (tok::isPragmaAnnotation(K: Tok.getKind())) {
3527 Diag(Loc: Tok.getLocation(), DiagID: diag::err_pragma_misplaced_in_decl)
3528 << DeclSpec::getSpecifierName(
3529 T: TagType, Policy: Actions.getASTContext().getPrintingPolicy());
3530 ConsumeAnnotationToken();
3531 return nullptr;
3532 }
3533 ParsedTemplateInfo TemplateInfo;
3534 return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo);
3535 }
3536}
3537
3538void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
3539 SourceLocation AttrFixitLoc,
3540 ParsedAttributes &Attrs,
3541 unsigned TagType, Decl *TagDecl) {
3542 assert((TagType == DeclSpec::TST_struct ||
3543 TagType == DeclSpec::TST_interface ||
3544 TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) &&
3545 "Invalid TagType!");
3546
3547 llvm::TimeTraceScope TimeScope("ParseClass", [&]() {
3548 if (auto *TD = dyn_cast_or_null<NamedDecl>(Val: TagDecl))
3549 return TD->getQualifiedNameAsString();
3550 return std::string("<anonymous>");
3551 });
3552
3553 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
3554 "parsing struct/union/class body");
3555
3556 // Determine whether this is a non-nested class. Note that local
3557 // classes are *not* considered to be nested classes.
3558 bool NonNestedClass = true;
3559 if (!ClassStack.empty()) {
3560 for (const Scope *S = getCurScope(); S; S = S->getParent()) {
3561 if (S->isClassScope()) {
3562 // We're inside a class scope, so this is a nested class.
3563 NonNestedClass = false;
3564
3565 // The Microsoft extension __interface does not permit nested classes.
3566 if (getCurrentClass().IsInterface) {
3567 Diag(Loc: RecordLoc, DiagID: diag::err_invalid_member_in_interface)
3568 << /*ErrorType=*/6
3569 << (isa<NamedDecl>(Val: TagDecl)
3570 ? cast<NamedDecl>(Val: TagDecl)->getQualifiedNameAsString()
3571 : "(anonymous)");
3572 }
3573 break;
3574 }
3575
3576 if (S->isFunctionScope())
3577 // If we're in a function or function template then this is a local
3578 // class rather than a nested class.
3579 break;
3580 }
3581 }
3582
3583 // Enter a scope for the class.
3584 ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope);
3585
3586 // Note that we are parsing a new (potentially-nested) class definition.
3587 ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass,
3588 TagType == DeclSpec::TST_interface);
3589
3590 if (TagDecl)
3591 Actions.ActOnTagStartDefinition(S: getCurScope(), TagDecl);
3592
3593 SourceLocation FinalLoc;
3594 SourceLocation AbstractLoc;
3595 bool IsFinalSpelledSealed = false;
3596 bool IsAbstract = false;
3597 SourceLocation TriviallyRelocatable;
3598 SourceLocation Replaceable;
3599
3600 // Parse the optional 'final' keyword.
3601 if (getLangOpts().CPlusPlus && Tok.is(K: tok::identifier)) {
3602 while (true) {
3603 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
3604 if (Specifier == VirtSpecifiers::VS_None) {
3605 if (isCXX2CTriviallyRelocatableKeyword(Tok)) {
3606 if (TriviallyRelocatable.isValid()) {
3607 auto Skipped = Tok;
3608 ConsumeToken();
3609 Diag(Tok: Skipped, DiagID: diag::err_duplicate_class_relocation_specifier)
3610 << /*trivial_relocatable*/ 0 << TriviallyRelocatable;
3611 } else {
3612 ParseCXX2CTriviallyRelocatableSpecifier(TRS&: TriviallyRelocatable);
3613 }
3614 continue;
3615 }
3616 if (isCXX2CReplaceableKeyword(Tok)) {
3617 if (Replaceable.isValid()) {
3618 auto Skipped = Tok;
3619 ConsumeToken();
3620 Diag(Tok: Skipped, DiagID: diag::err_duplicate_class_relocation_specifier)
3621 << /*replaceable*/ 1 << Replaceable;
3622 } else {
3623 ParseCXX2CReplaceableSpecifier(MRS&: Replaceable);
3624 }
3625 continue;
3626 }
3627 break;
3628 }
3629 if (isCXX11FinalKeyword()) {
3630 if (FinalLoc.isValid()) {
3631 auto Skipped = ConsumeToken();
3632 Diag(Loc: Skipped, DiagID: diag::err_duplicate_class_virt_specifier)
3633 << VirtSpecifiers::getSpecifierName(VS: Specifier);
3634 } else {
3635 FinalLoc = ConsumeToken();
3636 if (Specifier == VirtSpecifiers::VS_Sealed)
3637 IsFinalSpelledSealed = true;
3638 }
3639 } else {
3640 if (AbstractLoc.isValid()) {
3641 auto Skipped = ConsumeToken();
3642 Diag(Loc: Skipped, DiagID: diag::err_duplicate_class_virt_specifier)
3643 << VirtSpecifiers::getSpecifierName(VS: Specifier);
3644 } else {
3645 AbstractLoc = ConsumeToken();
3646 IsAbstract = true;
3647 }
3648 }
3649 if (TagType == DeclSpec::TST_interface)
3650 Diag(Loc: FinalLoc, DiagID: diag::err_override_control_interface)
3651 << VirtSpecifiers::getSpecifierName(VS: Specifier);
3652 else if (Specifier == VirtSpecifiers::VS_Final)
3653 Diag(Loc: FinalLoc, DiagID: getLangOpts().CPlusPlus11
3654 ? diag::warn_cxx98_compat_override_control_keyword
3655 : diag::ext_override_control_keyword)
3656 << VirtSpecifiers::getSpecifierName(VS: Specifier);
3657 else if (Specifier == VirtSpecifiers::VS_Sealed)
3658 Diag(Loc: FinalLoc, DiagID: diag::ext_ms_sealed_keyword);
3659 else if (Specifier == VirtSpecifiers::VS_Abstract)
3660 Diag(Loc: AbstractLoc, DiagID: diag::ext_ms_abstract_keyword);
3661 else if (Specifier == VirtSpecifiers::VS_GNU_Final)
3662 Diag(Loc: FinalLoc, DiagID: diag::ext_warn_gnu_final);
3663 }
3664 assert((FinalLoc.isValid() || AbstractLoc.isValid() ||
3665 TriviallyRelocatable.isValid() || Replaceable.isValid()) &&
3666 "not a class definition");
3667
3668 // Parse any C++11 attributes after 'final' keyword.
3669 // These attributes are not allowed to appear here,
3670 // and the only possible place for them to appertain
3671 // to the class would be between class-key and class-name.
3672 CheckMisplacedCXX11Attribute(Attrs, CorrectLocation: AttrFixitLoc);
3673
3674 // ParseClassSpecifier() does only a superficial check for attributes before
3675 // deciding to call this method. For example, for
3676 // `class C final alignas ([l) {` it will decide that this looks like a
3677 // misplaced attribute since it sees `alignas '(' ')'`. But the actual
3678 // attribute parsing code will try to parse the '[' as a constexpr lambda
3679 // and consume enough tokens that the alignas parsing code will eat the
3680 // opening '{'. So bail out if the next token isn't one we expect.
3681 if (!Tok.is(K: tok::colon) && !Tok.is(K: tok::l_brace)) {
3682 if (TagDecl)
3683 Actions.ActOnTagDefinitionError(S: getCurScope(), TagDecl);
3684 return;
3685 }
3686 }
3687
3688 if (Tok.is(K: tok::colon)) {
3689 ParseScope InheritanceScope(this, getCurScope()->getFlags() |
3690 Scope::ClassInheritanceScope);
3691
3692 ParseBaseClause(ClassDecl: TagDecl);
3693 if (!Tok.is(K: tok::l_brace)) {
3694 bool SuggestFixIt = false;
3695 SourceLocation BraceLoc = PP.getLocForEndOfToken(Loc: PrevTokLocation);
3696 if (Tok.isAtStartOfLine()) {
3697 switch (Tok.getKind()) {
3698 case tok::kw_private:
3699 case tok::kw_protected:
3700 case tok::kw_public:
3701 SuggestFixIt = NextToken().getKind() == tok::colon;
3702 break;
3703 case tok::kw_static_assert:
3704 case tok::r_brace:
3705 case tok::kw_using:
3706 // base-clause can have simple-template-id; 'template' can't be there
3707 case tok::kw_template:
3708 SuggestFixIt = true;
3709 break;
3710 case tok::identifier:
3711 SuggestFixIt = isConstructorDeclarator(Unqualified: true);
3712 break;
3713 default:
3714 SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
3715 break;
3716 }
3717 }
3718 DiagnosticBuilder LBraceDiag =
3719 Diag(Loc: BraceLoc, DiagID: diag::err_expected_lbrace_after_base_specifiers);
3720 if (SuggestFixIt) {
3721 LBraceDiag << FixItHint::CreateInsertion(InsertionLoc: BraceLoc, Code: " {");
3722 // Try recovering from missing { after base-clause.
3723 PP.EnterToken(Tok, /*IsReinject*/ true);
3724 Tok.setKind(tok::l_brace);
3725 } else {
3726 if (TagDecl)
3727 Actions.ActOnTagDefinitionError(S: getCurScope(), TagDecl);
3728 return;
3729 }
3730 }
3731 }
3732
3733 assert(Tok.is(tok::l_brace));
3734 BalancedDelimiterTracker T(*this, tok::l_brace);
3735 T.consumeOpen();
3736
3737 if (TagDecl)
3738 Actions.ActOnStartCXXMemberDeclarations(
3739 S: getCurScope(), TagDecl, FinalLoc, IsFinalSpelledSealed, IsAbstract,
3740 TriviallyRelocatable, Replaceable, LBraceLoc: T.getOpenLocation());
3741
3742 // C++ 11p3: Members of a class defined with the keyword class are private
3743 // by default. Members of a class defined with the keywords struct or union
3744 // are public by default.
3745 // HLSL: In HLSL members of a class are public by default.
3746 AccessSpecifier CurAS;
3747 if (TagType == DeclSpec::TST_class && !getLangOpts().HLSL)
3748 CurAS = AS_private;
3749 else
3750 CurAS = AS_public;
3751 ParsedAttributes AccessAttrs(AttrFactory);
3752
3753 if (TagDecl) {
3754 // While we still have something to read, read the member-declarations.
3755 while (!tryParseMisplacedModuleImport() && Tok.isNot(K: tok::r_brace) &&
3756 Tok.isNot(K: tok::eof)) {
3757 // Each iteration of this loop reads one member-declaration.
3758 ParseCXXClassMemberDeclarationWithPragmas(
3759 AS&: CurAS, AccessAttrs, TagType: static_cast<DeclSpec::TST>(TagType), TagDecl);
3760 MaybeDestroyTemplateIds();
3761 }
3762 T.consumeClose();
3763 } else {
3764 SkipUntil(T: tok::r_brace);
3765 }
3766
3767 // If attributes exist after class contents, parse them.
3768 ParsedAttributes attrs(AttrFactory);
3769 MaybeParseGNUAttributes(Attrs&: attrs);
3770
3771 if (TagDecl)
3772 Actions.ActOnFinishCXXMemberSpecification(S: getCurScope(), RLoc: RecordLoc, TagDecl,
3773 LBrac: T.getOpenLocation(),
3774 RBrac: T.getCloseLocation(), AttrList: attrs);
3775
3776 // C++11 [class.mem]p2:
3777 // Within the class member-specification, the class is regarded as complete
3778 // within function bodies, default arguments, exception-specifications, and
3779 // brace-or-equal-initializers for non-static data members (including such
3780 // things in nested classes).
3781 if (TagDecl && NonNestedClass) {
3782 // We are not inside a nested class. This class and its nested classes
3783 // are complete and we can parse the delayed portions of method
3784 // declarations and the lexed inline method definitions, along with any
3785 // delayed attributes.
3786
3787 SourceLocation SavedPrevTokLocation = PrevTokLocation;
3788 ParseLexedPragmas(Class&: getCurrentClass());
3789 ParseLexedAttributes(Class&: getCurrentClass());
3790 ParseLexedMethodDeclarations(Class&: getCurrentClass());
3791
3792 // We've finished with all pending member declarations.
3793 Actions.ActOnFinishCXXMemberDecls();
3794
3795 ParseLexedMemberInitializers(Class&: getCurrentClass());
3796 ParseLexedMethodDefs(Class&: getCurrentClass());
3797 PrevTokLocation = SavedPrevTokLocation;
3798
3799 // We've finished parsing everything, including default argument
3800 // initializers.
3801 Actions.ActOnFinishCXXNonNestedClass();
3802 }
3803
3804 if (TagDecl)
3805 Actions.ActOnTagFinishDefinition(S: getCurScope(), TagDecl, BraceRange: T.getRange());
3806
3807 // Leave the class scope.
3808 ParsingDef.Pop();
3809 ClassScope.Exit();
3810}
3811
3812void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) {
3813 assert(Tok.is(tok::kw_namespace));
3814
3815 // FIXME: Suggest where the close brace should have gone by looking
3816 // at indentation changes within the definition body.
3817 Diag(Loc: D->getLocation(), DiagID: diag::err_missing_end_of_definition) << D;
3818 Diag(Loc: Tok.getLocation(), DiagID: diag::note_missing_end_of_definition_before) << D;
3819
3820 // Push '};' onto the token stream to recover.
3821 PP.EnterToken(Tok, /*IsReinject*/ true);
3822
3823 Tok.startToken();
3824 Tok.setLocation(PP.getLocForEndOfToken(Loc: PrevTokLocation));
3825 Tok.setKind(tok::semi);
3826 PP.EnterToken(Tok, /*IsReinject*/ true);
3827
3828 Tok.setKind(tok::r_brace);
3829}
3830
3831void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
3832 assert(Tok.is(tok::colon) &&
3833 "Constructor initializer always starts with ':'");
3834
3835 // Poison the SEH identifiers so they are flagged as illegal in constructor
3836 // initializers.
3837 PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);
3838 SourceLocation ColonLoc = ConsumeToken();
3839
3840 SmallVector<CXXCtorInitializer *, 4> MemInitializers;
3841 bool AnyErrors = false;
3842
3843 do {
3844 if (Tok.is(K: tok::code_completion)) {
3845 cutOffParsing();
3846 Actions.CodeCompletion().CodeCompleteConstructorInitializer(
3847 Constructor: ConstructorDecl, Initializers: MemInitializers);
3848 return;
3849 }
3850
3851 MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
3852 if (!MemInit.isInvalid())
3853 MemInitializers.push_back(Elt: MemInit.get());
3854 else
3855 AnyErrors = true;
3856
3857 if (Tok.is(K: tok::comma))
3858 ConsumeToken();
3859 else if (Tok.is(K: tok::l_brace))
3860 break;
3861 // If the previous initializer was valid and the next token looks like a
3862 // base or member initializer, assume that we're just missing a comma.
3863 else if (!MemInit.isInvalid() &&
3864 Tok.isOneOf(Ks: tok::identifier, Ks: tok::coloncolon)) {
3865 SourceLocation Loc = PP.getLocForEndOfToken(Loc: PrevTokLocation);
3866 Diag(Loc, DiagID: diag::err_ctor_init_missing_comma)
3867 << FixItHint::CreateInsertion(InsertionLoc: Loc, Code: ", ");
3868 } else {
3869 // Skip over garbage, until we get to '{'. Don't eat the '{'.
3870 if (!MemInit.isInvalid())
3871 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected_either)
3872 << tok::l_brace << tok::comma;
3873 SkipUntil(T: tok::l_brace, Flags: StopAtSemi | StopBeforeMatch);
3874 break;
3875 }
3876 } while (true);
3877
3878 Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, MemInits: MemInitializers,
3879 AnyErrors);
3880}
3881
3882MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
3883 // parse '::'[opt] nested-name-specifier[opt]
3884 CXXScopeSpec SS;
3885 if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
3886 /*ObjectHasErrors=*/false,
3887 /*EnteringContext=*/false))
3888 return true;
3889
3890 // : identifier
3891 IdentifierInfo *II = nullptr;
3892 SourceLocation IdLoc = Tok.getLocation();
3893 // : declype(...)
3894 DeclSpec DS(AttrFactory);
3895 // : template_name<...>
3896 TypeResult TemplateTypeTy;
3897
3898 if (Tok.is(K: tok::identifier)) {
3899 // Get the identifier. This may be a member name or a class name,
3900 // but we'll let the semantic analysis determine which it is.
3901 II = Tok.getIdentifierInfo();
3902 ConsumeToken();
3903 } else if (Tok.is(K: tok::annot_decltype)) {
3904 // Get the decltype expression, if there is one.
3905 // Uses of decltype will already have been converted to annot_decltype by
3906 // ParseOptionalCXXScopeSpecifier at this point.
3907 // FIXME: Can we get here with a scope specifier?
3908 ParseDecltypeSpecifier(DS);
3909 } else if (Tok.is(K: tok::annot_pack_indexing_type)) {
3910 // Uses of T...[N] will already have been converted to
3911 // annot_pack_indexing_type by ParseOptionalCXXScopeSpecifier at this point.
3912 ParsePackIndexingType(DS);
3913 } else {
3914 TemplateIdAnnotation *TemplateId = Tok.is(K: tok::annot_template_id)
3915 ? takeTemplateIdAnnotation(tok: Tok)
3916 : nullptr;
3917 if (TemplateId && TemplateId->mightBeType()) {
3918 AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename: ImplicitTypenameContext::No,
3919 /*IsClassName=*/true);
3920 assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
3921 TemplateTypeTy = getTypeAnnotation(Tok);
3922 ConsumeAnnotationToken();
3923 } else {
3924 Diag(Tok, DiagID: diag::err_expected_member_or_base_name);
3925 return true;
3926 }
3927 }
3928
3929 // Parse the '('.
3930 if (getLangOpts().CPlusPlus11 && Tok.is(K: tok::l_brace)) {
3931 Diag(Tok, DiagID: diag::warn_cxx98_compat_generalized_initializer_lists);
3932
3933 // FIXME: Add support for signature help inside initializer lists.
3934 ExprResult InitList = ParseBraceInitializer();
3935 if (InitList.isInvalid())
3936 return true;
3937
3938 SourceLocation EllipsisLoc;
3939 TryConsumeToken(Expected: tok::ellipsis, Loc&: EllipsisLoc);
3940
3941 if (TemplateTypeTy.isInvalid())
3942 return true;
3943 return Actions.ActOnMemInitializer(ConstructorD: ConstructorDecl, S: getCurScope(), SS, MemberOrBase: II,
3944 TemplateTypeTy: TemplateTypeTy.get(), DS, IdLoc,
3945 InitList: InitList.get(), EllipsisLoc);
3946 } else if (Tok.is(K: tok::l_paren)) {
3947 BalancedDelimiterTracker T(*this, tok::l_paren);
3948 T.consumeOpen();
3949
3950 // Parse the optional expression-list.
3951 ExprVector ArgExprs;
3952 auto RunSignatureHelp = [&] {
3953 if (TemplateTypeTy.isInvalid())
3954 return QualType();
3955 QualType PreferredType =
3956 Actions.CodeCompletion().ProduceCtorInitMemberSignatureHelp(
3957 ConstructorDecl, SS, TemplateTypeTy: TemplateTypeTy.get(), ArgExprs, II,
3958 OpenParLoc: T.getOpenLocation(), /*Braced=*/false);
3959 CalledSignatureHelp = true;
3960 return PreferredType;
3961 };
3962 if (Tok.isNot(K: tok::r_paren) && ParseExpressionList(Exprs&: ArgExprs, ExpressionStarts: [&] {
3963 PreferredType.enterFunctionArgument(Tok: Tok.getLocation(),
3964 ComputeType: RunSignatureHelp);
3965 })) {
3966 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
3967 RunSignatureHelp();
3968 SkipUntil(T: tok::r_paren, Flags: StopAtSemi);
3969 return true;
3970 }
3971
3972 T.consumeClose();
3973
3974 SourceLocation EllipsisLoc;
3975 TryConsumeToken(Expected: tok::ellipsis, Loc&: EllipsisLoc);
3976
3977 if (TemplateTypeTy.isInvalid())
3978 return true;
3979 return Actions.ActOnMemInitializer(
3980 ConstructorD: ConstructorDecl, S: getCurScope(), SS, MemberOrBase: II, TemplateTypeTy: TemplateTypeTy.get(), DS, IdLoc,
3981 LParenLoc: T.getOpenLocation(), Args: ArgExprs, RParenLoc: T.getCloseLocation(), EllipsisLoc);
3982 }
3983
3984 if (TemplateTypeTy.isInvalid())
3985 return true;
3986
3987 if (getLangOpts().CPlusPlus11)
3988 return Diag(Tok, DiagID: diag::err_expected_either) << tok::l_paren << tok::l_brace;
3989 else
3990 return Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
3991}
3992
3993ExceptionSpecificationType Parser::tryParseExceptionSpecification(
3994 bool Delayed, SourceRange &SpecificationRange,
3995 SmallVectorImpl<ParsedType> &DynamicExceptions,
3996 SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
3997 ExprResult &NoexceptExpr, CachedTokens *&ExceptionSpecTokens) {
3998 ExceptionSpecificationType Result = EST_None;
3999 ExceptionSpecTokens = nullptr;
4000
4001 // Handle delayed parsing of exception-specifications.
4002 if (Delayed) {
4003 if (Tok.isNot(K: tok::kw_throw) && Tok.isNot(K: tok::kw_noexcept))
4004 return EST_None;
4005
4006 // Consume and cache the starting token.
4007 bool IsNoexcept = Tok.is(K: tok::kw_noexcept);
4008 Token StartTok = Tok;
4009 SpecificationRange = SourceRange(ConsumeToken());
4010
4011 // Check for a '('.
4012 if (!Tok.is(K: tok::l_paren)) {
4013 // If this is a bare 'noexcept', we're done.
4014 if (IsNoexcept) {
4015 Diag(Tok, DiagID: diag::warn_cxx98_compat_noexcept_decl);
4016 NoexceptExpr = nullptr;
4017 return EST_BasicNoexcept;
4018 }
4019
4020 Diag(Tok, DiagID: diag::err_expected_lparen_after) << "throw";
4021 return EST_DynamicNone;
4022 }
4023
4024 // Cache the tokens for the exception-specification.
4025 ExceptionSpecTokens = new CachedTokens;
4026 ExceptionSpecTokens->push_back(Elt: StartTok); // 'throw' or 'noexcept'
4027 ExceptionSpecTokens->push_back(Elt: Tok); // '('
4028 SpecificationRange.setEnd(ConsumeParen()); // '('
4029
4030 ConsumeAndStoreUntil(T1: tok::r_paren, Toks&: *ExceptionSpecTokens,
4031 /*StopAtSemi=*/true,
4032 /*ConsumeFinalToken=*/true);
4033 SpecificationRange.setEnd(ExceptionSpecTokens->back().getLocation());
4034
4035 return EST_Unparsed;
4036 }
4037
4038 // See if there's a dynamic specification.
4039 if (Tok.is(K: tok::kw_throw)) {
4040 Result = ParseDynamicExceptionSpecification(
4041 SpecificationRange, Exceptions&: DynamicExceptions, Ranges&: DynamicExceptionRanges);
4042 assert(DynamicExceptions.size() == DynamicExceptionRanges.size() &&
4043 "Produced different number of exception types and ranges.");
4044 }
4045
4046 // If there's no noexcept specification, we're done.
4047 if (Tok.isNot(K: tok::kw_noexcept))
4048 return Result;
4049
4050 Diag(Tok, DiagID: diag::warn_cxx98_compat_noexcept_decl);
4051
4052 // If we already had a dynamic specification, parse the noexcept for,
4053 // recovery, but emit a diagnostic and don't store the results.
4054 SourceRange NoexceptRange;
4055 ExceptionSpecificationType NoexceptType = EST_None;
4056
4057 SourceLocation KeywordLoc = ConsumeToken();
4058 if (Tok.is(K: tok::l_paren)) {
4059 // There is an argument.
4060 BalancedDelimiterTracker T(*this, tok::l_paren);
4061 T.consumeOpen();
4062
4063 EnterExpressionEvaluationContext ConstantEvaluated(
4064 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
4065 NoexceptExpr = ParseConstantExpressionInExprEvalContext();
4066
4067 T.consumeClose();
4068 if (!NoexceptExpr.isInvalid()) {
4069 NoexceptExpr =
4070 Actions.ActOnNoexceptSpec(NoexceptExpr: NoexceptExpr.get(), EST&: NoexceptType);
4071 NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
4072 } else {
4073 NoexceptType = EST_BasicNoexcept;
4074 }
4075 } else {
4076 // There is no argument.
4077 NoexceptType = EST_BasicNoexcept;
4078 NoexceptRange = SourceRange(KeywordLoc, KeywordLoc);
4079 }
4080
4081 if (Result == EST_None) {
4082 SpecificationRange = NoexceptRange;
4083 Result = NoexceptType;
4084
4085 // If there's a dynamic specification after a noexcept specification,
4086 // parse that and ignore the results.
4087 if (Tok.is(K: tok::kw_throw)) {
4088 Diag(Loc: Tok.getLocation(), DiagID: diag::err_dynamic_and_noexcept_specification);
4089 ParseDynamicExceptionSpecification(SpecificationRange&: NoexceptRange, Exceptions&: DynamicExceptions,
4090 Ranges&: DynamicExceptionRanges);
4091 }
4092 } else {
4093 Diag(Loc: Tok.getLocation(), DiagID: diag::err_dynamic_and_noexcept_specification);
4094 }
4095
4096 return Result;
4097}
4098
4099static void diagnoseDynamicExceptionSpecification(Parser &P, SourceRange Range,
4100 bool IsNoexcept) {
4101 if (P.getLangOpts().CPlusPlus11) {
4102 const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";
4103 P.Diag(Loc: Range.getBegin(), DiagID: P.getLangOpts().CPlusPlus17 && !IsNoexcept
4104 ? diag::ext_dynamic_exception_spec
4105 : diag::warn_exception_spec_deprecated)
4106 << Range;
4107 P.Diag(Loc: Range.getBegin(), DiagID: diag::note_exception_spec_deprecated)
4108 << Replacement << FixItHint::CreateReplacement(RemoveRange: Range, Code: Replacement);
4109 }
4110}
4111
4112ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
4113 SourceRange &SpecificationRange, SmallVectorImpl<ParsedType> &Exceptions,
4114 SmallVectorImpl<SourceRange> &Ranges) {
4115 assert(Tok.is(tok::kw_throw) && "expected throw");
4116
4117 SpecificationRange.setBegin(ConsumeToken());
4118 BalancedDelimiterTracker T(*this, tok::l_paren);
4119 if (T.consumeOpen()) {
4120 Diag(Tok, DiagID: diag::err_expected_lparen_after) << "throw";
4121 SpecificationRange.setEnd(SpecificationRange.getBegin());
4122 return EST_DynamicNone;
4123 }
4124
4125 // Parse throw(...), a Microsoft extension that means "this function
4126 // can throw anything".
4127 if (Tok.is(K: tok::ellipsis)) {
4128 SourceLocation EllipsisLoc = ConsumeToken();
4129 if (!getLangOpts().MicrosoftExt)
4130 Diag(Loc: EllipsisLoc, DiagID: diag::ext_ellipsis_exception_spec);
4131 T.consumeClose();
4132 SpecificationRange.setEnd(T.getCloseLocation());
4133 diagnoseDynamicExceptionSpecification(P&: *this, Range: SpecificationRange, IsNoexcept: false);
4134 return EST_MSAny;
4135 }
4136
4137 // Parse the sequence of type-ids.
4138 SourceRange Range;
4139 while (Tok.isNot(K: tok::r_paren)) {
4140 TypeResult Res(ParseTypeName(Range: &Range));
4141
4142 if (Tok.is(K: tok::ellipsis)) {
4143 // C++0x [temp.variadic]p5:
4144 // - In a dynamic-exception-specification (15.4); the pattern is a
4145 // type-id.
4146 SourceLocation Ellipsis = ConsumeToken();
4147 Range.setEnd(Ellipsis);
4148 if (!Res.isInvalid())
4149 Res = Actions.ActOnPackExpansion(Type: Res.get(), EllipsisLoc: Ellipsis);
4150 }
4151
4152 if (!Res.isInvalid()) {
4153 Exceptions.push_back(Elt: Res.get());
4154 Ranges.push_back(Elt: Range);
4155 }
4156
4157 if (!TryConsumeToken(Expected: tok::comma))
4158 break;
4159 }
4160
4161 T.consumeClose();
4162 SpecificationRange.setEnd(T.getCloseLocation());
4163 diagnoseDynamicExceptionSpecification(P&: *this, Range: SpecificationRange,
4164 IsNoexcept: Exceptions.empty());
4165 return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;
4166}
4167
4168TypeResult Parser::ParseTrailingReturnType(SourceRange &Range,
4169 bool MayBeFollowedByDirectInit) {
4170 assert(Tok.is(tok::arrow) && "expected arrow");
4171
4172 ConsumeToken();
4173
4174 return ParseTypeName(Range: &Range, Context: MayBeFollowedByDirectInit
4175 ? DeclaratorContext::TrailingReturnVar
4176 : DeclaratorContext::TrailingReturn);
4177}
4178
4179void Parser::ParseTrailingRequiresClause(Declarator &D) {
4180 assert(Tok.is(tok::kw_requires) && "expected requires");
4181
4182 SourceLocation RequiresKWLoc = ConsumeToken();
4183
4184 // C++23 [basic.scope.namespace]p1:
4185 // For each non-friend redeclaration or specialization whose target scope
4186 // is or is contained by the scope, the portion after the declarator-id,
4187 // class-head-name, or enum-head-name is also included in the scope.
4188 // C++23 [basic.scope.class]p1:
4189 // For each non-friend redeclaration or specialization whose target scope
4190 // is or is contained by the scope, the portion after the declarator-id,
4191 // class-head-name, or enum-head-name is also included in the scope.
4192 //
4193 // FIXME: We should really be calling ParseTrailingRequiresClause in
4194 // ParseDirectDeclarator, when we are already in the declarator scope.
4195 // This would also correctly suppress access checks for specializations
4196 // and explicit instantiations, which we currently do not do.
4197 CXXScopeSpec &SS = D.getCXXScopeSpec();
4198 DeclaratorScopeObj DeclScopeObj(*this, SS);
4199 if (SS.isValid() && Actions.ShouldEnterDeclaratorScope(S: getCurScope(), SS))
4200 DeclScopeObj.EnterDeclaratorScope();
4201
4202 ExprResult TrailingRequiresClause;
4203 ParseScope ParamScope(this, Scope::DeclScope |
4204 Scope::FunctionDeclarationScope |
4205 Scope::FunctionPrototypeScope);
4206
4207 Actions.ActOnStartTrailingRequiresClause(S: getCurScope(), D);
4208
4209 std::optional<Sema::CXXThisScopeRAII> ThisScope;
4210 InitCXXThisScopeForDeclaratorIfRelevant(D, DS: D.getDeclSpec(), ThisScope);
4211
4212 TrailingRequiresClause =
4213 ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);
4214
4215 TrailingRequiresClause =
4216 Actions.ActOnFinishTrailingRequiresClause(ConstraintExpr: TrailingRequiresClause);
4217
4218 if (!D.isDeclarationOfFunction()) {
4219 Diag(Loc: RequiresKWLoc,
4220 DiagID: diag::err_requires_clause_on_declarator_not_declaring_a_function);
4221 return;
4222 }
4223
4224 if (TrailingRequiresClause.isInvalid())
4225 SkipUntil(Toks: {tok::l_brace, tok::arrow, tok::kw_try, tok::comma, tok::colon},
4226 Flags: StopAtSemi | StopBeforeMatch);
4227 else
4228 D.setTrailingRequiresClause(TrailingRequiresClause.get());
4229
4230 // Did the user swap the trailing return type and requires clause?
4231 if (D.isFunctionDeclarator() && Tok.is(K: tok::arrow) &&
4232 D.getDeclSpec().getTypeSpecType() == TST_auto) {
4233 SourceLocation ArrowLoc = Tok.getLocation();
4234 SourceRange Range;
4235 TypeResult TrailingReturnType =
4236 ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit=*/false);
4237
4238 if (!TrailingReturnType.isInvalid()) {
4239 Diag(Loc: ArrowLoc,
4240 DiagID: diag::err_requires_clause_must_appear_after_trailing_return)
4241 << Range;
4242 auto &FunctionChunk = D.getFunctionTypeInfo();
4243 FunctionChunk.HasTrailingReturnType = TrailingReturnType.isUsable();
4244 FunctionChunk.TrailingReturnType = TrailingReturnType.get();
4245 FunctionChunk.TrailingReturnTypeLoc = Range.getBegin();
4246 } else
4247 SkipUntil(Toks: {tok::equal, tok::l_brace, tok::arrow, tok::kw_try, tok::comma},
4248 Flags: StopAtSemi | StopBeforeMatch);
4249 }
4250}
4251
4252Sema::ParsingClassState Parser::PushParsingClass(Decl *ClassDecl,
4253 bool NonNestedClass,
4254 bool IsInterface) {
4255 assert((NonNestedClass || !ClassStack.empty()) &&
4256 "Nested class without outer class");
4257 ClassStack.push(x: new ParsingClass(ClassDecl, NonNestedClass, IsInterface));
4258 return Actions.PushParsingClass();
4259}
4260
4261void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
4262 for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I)
4263 delete Class->LateParsedDeclarations[I];
4264 delete Class;
4265}
4266
4267void Parser::PopParsingClass(Sema::ParsingClassState state) {
4268 assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");
4269
4270 Actions.PopParsingClass(state);
4271
4272 ParsingClass *Victim = ClassStack.top();
4273 ClassStack.pop();
4274 if (Victim->TopLevelClass) {
4275 // Deallocate all of the nested classes of this class,
4276 // recursively: we don't need to keep any of this information.
4277 DeallocateParsedClasses(Class: Victim);
4278 return;
4279 }
4280 assert(!ClassStack.empty() && "Missing top-level class?");
4281
4282 if (Victim->LateParsedDeclarations.empty()) {
4283 // The victim is a nested class, but we will not need to perform
4284 // any processing after the definition of this class since it has
4285 // no members whose handling was delayed. Therefore, we can just
4286 // remove this nested class.
4287 DeallocateParsedClasses(Class: Victim);
4288 return;
4289 }
4290
4291 // This nested class has some members that will need to be processed
4292 // after the top-level class is completely defined. Therefore, add
4293 // it to the list of nested classes within its parent.
4294 assert(getCurScope()->isClassScope() &&
4295 "Nested class outside of class scope?");
4296 ClassStack.top()->LateParsedDeclarations.push_back(
4297 Elt: new LateParsedClass(this, Victim));
4298}
4299
4300IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(
4301 SourceLocation &Loc, SemaCodeCompletion::AttributeCompletion Completion,
4302 const IdentifierInfo *Scope) {
4303 switch (Tok.getKind()) {
4304 default:
4305 // Identifiers and keywords have identifier info attached.
4306 if (!Tok.isAnnotation()) {
4307 if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
4308 Loc = ConsumeToken();
4309 return II;
4310 }
4311 }
4312 return nullptr;
4313
4314 case tok::code_completion:
4315 cutOffParsing();
4316 Actions.CodeCompletion().CodeCompleteAttribute(
4317 Syntax: getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C23,
4318 Completion, Scope);
4319 return nullptr;
4320
4321 case tok::numeric_constant: {
4322 // If we got a numeric constant, check to see if it comes from a macro that
4323 // corresponds to the predefined __clang__ macro. If it does, warn the user
4324 // and recover by pretending they said _Clang instead.
4325 if (Tok.getLocation().isMacroID()) {
4326 SmallString<8> ExpansionBuf;
4327 SourceLocation ExpansionLoc =
4328 PP.getSourceManager().getExpansionLoc(Loc: Tok.getLocation());
4329 StringRef Spelling = PP.getSpelling(loc: ExpansionLoc, buffer&: ExpansionBuf);
4330 if (Spelling == "__clang__") {
4331 SourceRange TokRange(
4332 ExpansionLoc,
4333 PP.getSourceManager().getExpansionLoc(Loc: Tok.getEndLoc()));
4334 Diag(Tok, DiagID: diag::warn_wrong_clang_attr_namespace)
4335 << FixItHint::CreateReplacement(RemoveRange: TokRange, Code: "_Clang");
4336 Loc = ConsumeToken();
4337 return &PP.getIdentifierTable().get(Name: "_Clang");
4338 }
4339 }
4340 return nullptr;
4341 }
4342
4343 case tok::ampamp: // 'and'
4344 case tok::pipe: // 'bitor'
4345 case tok::pipepipe: // 'or'
4346 case tok::caret: // 'xor'
4347 case tok::tilde: // 'compl'
4348 case tok::amp: // 'bitand'
4349 case tok::ampequal: // 'and_eq'
4350 case tok::pipeequal: // 'or_eq'
4351 case tok::caretequal: // 'xor_eq'
4352 case tok::exclaim: // 'not'
4353 case tok::exclaimequal: // 'not_eq'
4354 // Alternative tokens do not have identifier info, but their spelling
4355 // starts with an alphabetical character.
4356 SmallString<8> SpellingBuf;
4357 SourceLocation SpellingLoc =
4358 PP.getSourceManager().getSpellingLoc(Loc: Tok.getLocation());
4359 StringRef Spelling = PP.getSpelling(loc: SpellingLoc, buffer&: SpellingBuf);
4360 if (isLetter(c: Spelling[0])) {
4361 Loc = ConsumeToken();
4362 return &PP.getIdentifierTable().get(Name: Spelling);
4363 }
4364 return nullptr;
4365 }
4366}
4367
4368void Parser::ParseOpenMPAttributeArgs(const IdentifierInfo *AttrName,
4369 CachedTokens &OpenMPTokens) {
4370 // Both 'sequence' and 'directive' attributes require arguments, so parse the
4371 // open paren for the argument list.
4372 BalancedDelimiterTracker T(*this, tok::l_paren);
4373 if (T.consumeOpen()) {
4374 Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
4375 return;
4376 }
4377
4378 if (AttrName->isStr(Str: "directive")) {
4379 // If the attribute is named `directive`, we can consume its argument list
4380 // and push the tokens from it into the cached token stream for a new OpenMP
4381 // pragma directive.
4382 Token OMPBeginTok;
4383 OMPBeginTok.startToken();
4384 OMPBeginTok.setKind(tok::annot_attr_openmp);
4385 OMPBeginTok.setLocation(Tok.getLocation());
4386 OpenMPTokens.push_back(Elt: OMPBeginTok);
4387
4388 ConsumeAndStoreUntil(T1: tok::r_paren, Toks&: OpenMPTokens, /*StopAtSemi=*/false,
4389 /*ConsumeFinalToken*/ false);
4390 Token OMPEndTok;
4391 OMPEndTok.startToken();
4392 OMPEndTok.setKind(tok::annot_pragma_openmp_end);
4393 OMPEndTok.setLocation(Tok.getLocation());
4394 OpenMPTokens.push_back(Elt: OMPEndTok);
4395 } else {
4396 assert(AttrName->isStr("sequence") &&
4397 "Expected either 'directive' or 'sequence'");
4398 // If the attribute is named 'sequence', its argument is a list of one or
4399 // more OpenMP attributes (either 'omp::directive' or 'omp::sequence',
4400 // where the 'omp::' is optional).
4401 do {
4402 // We expect to see one of the following:
4403 // * An identifier (omp) for the attribute namespace followed by ::
4404 // * An identifier (directive) or an identifier (sequence).
4405 SourceLocation IdentLoc;
4406 const IdentifierInfo *Ident = TryParseCXX11AttributeIdentifier(Loc&: IdentLoc);
4407
4408 // If there is an identifier and it is 'omp', a double colon is required
4409 // followed by the actual identifier we're after.
4410 if (Ident && Ident->isStr(Str: "omp") && !ExpectAndConsume(ExpectedTok: tok::coloncolon))
4411 Ident = TryParseCXX11AttributeIdentifier(Loc&: IdentLoc);
4412
4413 // If we failed to find an identifier (scoped or otherwise), or we found
4414 // an unexpected identifier, diagnose.
4415 if (!Ident || (!Ident->isStr(Str: "directive") && !Ident->isStr(Str: "sequence"))) {
4416 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected_sequence_or_directive);
4417 SkipUntil(T: tok::r_paren, Flags: StopBeforeMatch);
4418 continue;
4419 }
4420 // We read an identifier. If the identifier is one of the ones we
4421 // expected, we can recurse to parse the args.
4422 ParseOpenMPAttributeArgs(AttrName: Ident, OpenMPTokens);
4423
4424 // There may be a comma to signal that we expect another directive in the
4425 // sequence.
4426 } while (TryConsumeToken(Expected: tok::comma));
4427 }
4428 // Parse the closing paren for the argument list.
4429 T.consumeClose();
4430}
4431
4432static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
4433 IdentifierInfo *ScopeName) {
4434 switch (
4435 ParsedAttr::getParsedKind(Name: AttrName, Scope: ScopeName, SyntaxUsed: ParsedAttr::AS_CXX11)) {
4436 case ParsedAttr::AT_CarriesDependency:
4437 case ParsedAttr::AT_Deprecated:
4438 case ParsedAttr::AT_FallThrough:
4439 case ParsedAttr::AT_CXX11NoReturn:
4440 case ParsedAttr::AT_NoUniqueAddress:
4441 case ParsedAttr::AT_Likely:
4442 case ParsedAttr::AT_Unlikely:
4443 return true;
4444 case ParsedAttr::AT_WarnUnusedResult:
4445 return !ScopeName && AttrName->getName() == "nodiscard";
4446 case ParsedAttr::AT_Unused:
4447 return !ScopeName && AttrName->getName() == "maybe_unused";
4448 default:
4449 return false;
4450 }
4451}
4452
4453bool Parser::ParseCXXAssumeAttributeArg(
4454 ParsedAttributes &Attrs, IdentifierInfo *AttrName,
4455 SourceLocation AttrNameLoc, IdentifierInfo *ScopeName,
4456 SourceLocation ScopeLoc, SourceLocation *EndLoc, ParsedAttr::Form Form) {
4457 assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
4458 BalancedDelimiterTracker T(*this, tok::l_paren);
4459 T.consumeOpen();
4460
4461 // [dcl.attr.assume]: The expression is potentially evaluated.
4462 EnterExpressionEvaluationContext Unevaluated(
4463 Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
4464
4465 TentativeParsingAction TPA(*this);
4466 ExprResult Res = ParseConditionalExpression();
4467 if (Res.isInvalid()) {
4468 TPA.Commit();
4469 SkipUntil(T1: tok::r_paren, T2: tok::r_square, Flags: StopAtSemi | StopBeforeMatch);
4470 if (Tok.is(K: tok::r_paren))
4471 T.consumeClose();
4472 return true;
4473 }
4474
4475 if (!Tok.isOneOf(Ks: tok::r_paren, Ks: tok::r_square)) {
4476 // Emit a better diagnostic if this is an otherwise valid expression that
4477 // is not allowed here.
4478 TPA.Revert();
4479 Res = ParseExpression();
4480 if (!Res.isInvalid()) {
4481 auto *E = Res.get();
4482 Diag(Loc: E->getExprLoc(), DiagID: diag::err_assume_attr_expects_cond_expr)
4483 << AttrName << FixItHint::CreateInsertion(InsertionLoc: E->getBeginLoc(), Code: "(")
4484 << FixItHint::CreateInsertion(InsertionLoc: PP.getLocForEndOfToken(Loc: E->getEndLoc()),
4485 Code: ")")
4486 << E->getSourceRange();
4487 }
4488
4489 T.consumeClose();
4490 return true;
4491 }
4492
4493 TPA.Commit();
4494 ArgsUnion Assumption = Res.get();
4495 auto RParen = Tok.getLocation();
4496 T.consumeClose();
4497 Attrs.addNew(attrName: AttrName, attrRange: SourceRange(AttrNameLoc, RParen),
4498 scope: AttributeScopeInfo(ScopeName, ScopeLoc), args: &Assumption, numArgs: 1, form: Form);
4499
4500 if (EndLoc)
4501 *EndLoc = RParen;
4502
4503 return false;
4504}
4505
4506bool Parser::ParseCXX11AttributeArgs(
4507 IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
4508 ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,
4509 SourceLocation ScopeLoc, CachedTokens &OpenMPTokens) {
4510 assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
4511 SourceLocation LParenLoc = Tok.getLocation();
4512 const LangOptions &LO = getLangOpts();
4513 ParsedAttr::Form Form =
4514 LO.CPlusPlus ? ParsedAttr::Form::CXX11() : ParsedAttr::Form::C23();
4515
4516 // Try parsing microsoft attributes
4517 if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) {
4518 if (hasAttribute(Syntax: AttributeCommonInfo::Syntax::AS_Microsoft, Scope: ScopeName,
4519 Attr: AttrName, Target: getTargetInfo(), LangOpts: getLangOpts()))
4520 Form = ParsedAttr::Form::Microsoft();
4521 }
4522
4523 // If the attribute isn't known, we will not attempt to parse any
4524 // arguments.
4525 if (Form.getSyntax() != ParsedAttr::AS_Microsoft &&
4526 !hasAttribute(Syntax: LO.CPlusPlus ? AttributeCommonInfo::Syntax::AS_CXX11
4527 : AttributeCommonInfo::Syntax::AS_C23,
4528 Scope: ScopeName, Attr: AttrName, Target: getTargetInfo(), LangOpts: getLangOpts())) {
4529 // Eat the left paren, then skip to the ending right paren.
4530 ConsumeParen();
4531 SkipUntil(T: tok::r_paren);
4532 return false;
4533 }
4534
4535 if (ScopeName && (ScopeName->isStr(Str: "gnu") || ScopeName->isStr(Str: "__gnu__"))) {
4536 // GNU-scoped attributes have some special cases to handle GNU-specific
4537 // behaviors.
4538 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
4539 ScopeLoc, Form, D: nullptr);
4540 return true;
4541 }
4542
4543 // [[omp::directive]] and [[omp::sequence]] need special handling.
4544 if (ScopeName && ScopeName->isStr(Str: "omp") &&
4545 (AttrName->isStr(Str: "directive") || AttrName->isStr(Str: "sequence"))) {
4546 Diag(Loc: AttrNameLoc, DiagID: getLangOpts().OpenMP >= 51
4547 ? diag::warn_omp51_compat_attributes
4548 : diag::ext_omp_attributes);
4549
4550 ParseOpenMPAttributeArgs(AttrName, OpenMPTokens);
4551
4552 // We claim that an attribute was parsed and added so that one is not
4553 // created for us by the caller.
4554 return true;
4555 }
4556
4557 unsigned NumArgs;
4558 // Some Clang-scoped attributes have some special parsing behavior.
4559 if (ScopeName && (ScopeName->isStr(Str: "clang") || ScopeName->isStr(Str: "_Clang")))
4560 NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,
4561 ScopeName, ScopeLoc, Form);
4562 // So does C++23's assume() attribute.
4563 else if (!ScopeName && AttrName->isStr(Str: "assume")) {
4564 if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, ScopeName: nullptr,
4565 ScopeLoc: SourceLocation{}, EndLoc, Form))
4566 return true;
4567 NumArgs = 1;
4568 } else
4569 NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
4570 ScopeName, ScopeLoc, Form);
4571
4572 if (!Attrs.empty() &&
4573 IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
4574 ParsedAttr &Attr = Attrs.back();
4575
4576 // Ignore attributes that don't exist for the target.
4577 if (!Attr.existsInTarget(Target: getTargetInfo())) {
4578 Actions.DiagnoseUnknownAttribute(AL: Attr);
4579 Attr.setInvalid(true);
4580 return true;
4581 }
4582
4583 // If the attribute is a standard or built-in attribute and we are
4584 // parsing an argument list, we need to determine whether this attribute
4585 // was allowed to have an argument list (such as [[deprecated]]), and how
4586 // many arguments were parsed (so we can diagnose on [[deprecated()]]).
4587 if (Attr.getMaxArgs() && !NumArgs) {
4588 // The attribute was allowed to have arguments, but none were provided
4589 // even though the attribute parsed successfully. This is an error.
4590 Diag(Loc: LParenLoc, DiagID: diag::err_attribute_requires_arguments) << AttrName;
4591 Attr.setInvalid(true);
4592 } else if (!Attr.getMaxArgs()) {
4593 // The attribute parsed successfully, but was not allowed to have any
4594 // arguments. It doesn't matter whether any were provided -- the
4595 // presence of the argument list (even if empty) is diagnosed.
4596 Diag(Loc: LParenLoc, DiagID: diag::err_cxx11_attribute_forbids_arguments)
4597 << AttrName
4598 << FixItHint::CreateRemoval(RemoveRange: SourceRange(LParenLoc, *EndLoc));
4599 Attr.setInvalid(true);
4600 }
4601 }
4602 return true;
4603}
4604
4605void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
4606 CachedTokens &OpenMPTokens,
4607 SourceLocation *EndLoc) {
4608 if (Tok.is(K: tok::kw_alignas)) {
4609 // alignas is a valid token in C23 but it is not an attribute, it's a type-
4610 // specifier-qualifier, which means it has different parsing behavior. We
4611 // handle this in ParseDeclarationSpecifiers() instead of here in C. We
4612 // should not get here for C any longer.
4613 assert(getLangOpts().CPlusPlus && "'alignas' is not an attribute in C");
4614 Diag(Loc: Tok.getLocation(), DiagID: diag::warn_cxx98_compat_alignas);
4615 ParseAlignmentSpecifier(Attrs, endLoc: EndLoc);
4616 return;
4617 }
4618
4619 if (Tok.isRegularKeywordAttribute()) {
4620 SourceLocation Loc = Tok.getLocation();
4621 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
4622 ParsedAttr::Form Form = ParsedAttr::Form(Tok.getKind());
4623 bool TakesArgs = doesKeywordAttributeTakeArgs(Kind: Tok.getKind());
4624 ConsumeToken();
4625 if (TakesArgs) {
4626 if (!Tok.is(K: tok::l_paren))
4627 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected_lparen_after) << AttrName;
4628 else
4629 ParseAttributeArgsCommon(AttrName, AttrNameLoc: Loc, Attrs, EndLoc,
4630 /*ScopeName*/ nullptr,
4631 /*ScopeLoc*/ Loc, Form);
4632 } else
4633 Attrs.addNew(attrName: AttrName, attrRange: Loc, scope: AttributeScopeInfo(), args: nullptr, numArgs: 0, form: Form);
4634 return;
4635 }
4636
4637 assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) &&
4638 "Not a double square bracket attribute list");
4639
4640 SourceLocation OpenLoc = Tok.getLocation();
4641 if (getLangOpts().CPlusPlus) {
4642 Diag(Loc: OpenLoc, DiagID: getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_attribute
4643 : diag::warn_ext_cxx11_attributes);
4644 } else {
4645 Diag(Loc: OpenLoc, DiagID: getLangOpts().C23 ? diag::warn_pre_c23_compat_attributes
4646 : diag::warn_ext_c23_attributes);
4647 }
4648
4649 ConsumeBracket();
4650 checkCompoundToken(FirstTokLoc: OpenLoc, FirstTokKind: tok::l_square, Op: CompoundToken::AttrBegin);
4651 ConsumeBracket();
4652
4653 SourceLocation CommonScopeLoc;
4654 IdentifierInfo *CommonScopeName = nullptr;
4655 if (Tok.is(K: tok::kw_using)) {
4656 Diag(Loc: Tok.getLocation(), DiagID: getLangOpts().CPlusPlus17
4657 ? diag::warn_cxx14_compat_using_attribute_ns
4658 : diag::ext_using_attribute_ns);
4659 ConsumeToken();
4660
4661 CommonScopeName = TryParseCXX11AttributeIdentifier(
4662 Loc&: CommonScopeLoc, Completion: SemaCodeCompletion::AttributeCompletion::Scope);
4663 if (!CommonScopeName) {
4664 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected) << tok::identifier;
4665 SkipUntil(T1: tok::r_square, T2: tok::colon, Flags: StopBeforeMatch);
4666 }
4667 if (!TryConsumeToken(Expected: tok::colon) && CommonScopeName)
4668 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected) << tok::colon;
4669 }
4670
4671 bool AttrParsed = false;
4672 while (!Tok.isOneOf(Ks: tok::r_square, Ks: tok::semi, Ks: tok::eof)) {
4673 if (AttrParsed) {
4674 // If we parsed an attribute, a comma is required before parsing any
4675 // additional attributes.
4676 if (ExpectAndConsume(ExpectedTok: tok::comma)) {
4677 SkipUntil(T: tok::r_square, Flags: StopAtSemi | StopBeforeMatch);
4678 continue;
4679 }
4680 AttrParsed = false;
4681 }
4682
4683 // Eat all remaining superfluous commas before parsing the next attribute.
4684 while (TryConsumeToken(Expected: tok::comma))
4685 ;
4686
4687 SourceLocation ScopeLoc, AttrLoc;
4688 IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;
4689
4690 AttrName = TryParseCXX11AttributeIdentifier(
4691 Loc&: AttrLoc, Completion: SemaCodeCompletion::AttributeCompletion::Attribute,
4692 Scope: CommonScopeName);
4693 if (!AttrName)
4694 // Break out to the "expected ']'" diagnostic.
4695 break;
4696
4697 // scoped attribute
4698 if (TryConsumeToken(Expected: tok::coloncolon)) {
4699 ScopeName = AttrName;
4700 ScopeLoc = AttrLoc;
4701
4702 AttrName = TryParseCXX11AttributeIdentifier(
4703 Loc&: AttrLoc, Completion: SemaCodeCompletion::AttributeCompletion::Attribute,
4704 Scope: ScopeName);
4705 if (!AttrName) {
4706 Diag(Loc: Tok.getLocation(), DiagID: diag::err_expected) << tok::identifier;
4707 SkipUntil(T1: tok::r_square, T2: tok::comma, Flags: StopAtSemi | StopBeforeMatch);
4708 continue;
4709 }
4710 }
4711
4712 if (CommonScopeName) {
4713 if (ScopeName) {
4714 Diag(Loc: ScopeLoc, DiagID: diag::err_using_attribute_ns_conflict)
4715 << SourceRange(CommonScopeLoc);
4716 } else {
4717 ScopeName = CommonScopeName;
4718 ScopeLoc = CommonScopeLoc;
4719 }
4720 }
4721
4722 // Parse attribute arguments
4723 if (Tok.is(K: tok::l_paren))
4724 AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrNameLoc: AttrLoc, Attrs, EndLoc,
4725 ScopeName, ScopeLoc, OpenMPTokens);
4726
4727 if (!AttrParsed) {
4728 Attrs.addNew(attrName: AttrName,
4729 attrRange: SourceRange(ScopeLoc.isValid() && CommonScopeLoc.isInvalid()
4730 ? ScopeLoc
4731 : AttrLoc,
4732 AttrLoc),
4733 scope: AttributeScopeInfo(ScopeName, ScopeLoc, CommonScopeLoc),
4734 args: nullptr, numArgs: 0,
4735 form: getLangOpts().CPlusPlus ? ParsedAttr::Form::CXX11()
4736 : ParsedAttr::Form::C23());
4737 AttrParsed = true;
4738 }
4739
4740 if (TryConsumeToken(Expected: tok::ellipsis))
4741 Diag(Tok, DiagID: diag::err_cxx11_attribute_forbids_ellipsis) << AttrName;
4742 }
4743
4744 // If we hit an error and recovered by parsing up to a semicolon, eat the
4745 // semicolon and don't issue further diagnostics about missing brackets.
4746 if (Tok.is(K: tok::semi)) {
4747 ConsumeToken();
4748 return;
4749 }
4750
4751 SourceLocation CloseLoc = Tok.getLocation();
4752 if (ExpectAndConsume(ExpectedTok: tok::r_square))
4753 SkipUntil(T: tok::r_square);
4754 else if (Tok.is(K: tok::r_square))
4755 checkCompoundToken(FirstTokLoc: CloseLoc, FirstTokKind: tok::r_square, Op: CompoundToken::AttrEnd);
4756 if (EndLoc)
4757 *EndLoc = Tok.getLocation();
4758 if (ExpectAndConsume(ExpectedTok: tok::r_square))
4759 SkipUntil(T: tok::r_square);
4760}
4761
4762void Parser::ParseCXX11Attributes(ParsedAttributes &Attrs) {
4763 SourceLocation StartLoc = Tok.getLocation();
4764 SourceLocation EndLoc = StartLoc;
4765
4766 do {
4767 ParseCXX11AttributeSpecifier(Attrs, EndLoc: &EndLoc);
4768 } while (isAllowedCXX11AttributeSpecifier());
4769
4770 Attrs.Range = SourceRange(StartLoc, EndLoc);
4771}
4772
4773void Parser::DiagnoseAndSkipCXX11Attributes() {
4774 auto Keyword =
4775 Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr;
4776 // Start and end location of an attribute or an attribute list.
4777 SourceLocation StartLoc = Tok.getLocation();
4778 SourceLocation EndLoc = SkipCXX11Attributes();
4779
4780 if (EndLoc.isValid()) {
4781 SourceRange Range(StartLoc, EndLoc);
4782 (Keyword ? Diag(Loc: StartLoc, DiagID: diag::err_keyword_not_allowed) << Keyword
4783 : Diag(Loc: StartLoc, DiagID: diag::err_attributes_not_allowed))
4784 << Range;
4785 }
4786}
4787
4788SourceLocation Parser::SkipCXX11Attributes() {
4789 SourceLocation EndLoc;
4790
4791 if (isCXX11AttributeSpecifier() == CXX11AttributeKind::NotAttributeSpecifier)
4792 return EndLoc;
4793
4794 do {
4795 if (Tok.is(K: tok::l_square)) {
4796 BalancedDelimiterTracker T(*this, tok::l_square);
4797 T.consumeOpen();
4798 T.skipToEnd();
4799 EndLoc = T.getCloseLocation();
4800 } else if (Tok.isRegularKeywordAttribute() &&
4801 !doesKeywordAttributeTakeArgs(Kind: Tok.getKind())) {
4802 EndLoc = Tok.getLocation();
4803 ConsumeToken();
4804 } else {
4805 assert((Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute()) &&
4806 "not an attribute specifier");
4807 ConsumeToken();
4808 BalancedDelimiterTracker T(*this, tok::l_paren);
4809 if (!T.consumeOpen())
4810 T.skipToEnd();
4811 EndLoc = T.getCloseLocation();
4812 }
4813 } while (isCXX11AttributeSpecifier() !=
4814 CXX11AttributeKind::NotAttributeSpecifier);
4815
4816 return EndLoc;
4817}
4818
4819void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) {
4820 assert(Tok.is(tok::identifier) && "Not a Microsoft attribute list");
4821 IdentifierInfo *UuidIdent = Tok.getIdentifierInfo();
4822 assert(UuidIdent->getName() == "uuid" && "Not a Microsoft attribute list");
4823
4824 SourceLocation UuidLoc = Tok.getLocation();
4825 ConsumeToken();
4826
4827 // Ignore the left paren location for now.
4828 BalancedDelimiterTracker T(*this, tok::l_paren);
4829 if (T.consumeOpen()) {
4830 Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
4831 return;
4832 }
4833
4834 ArgsVector ArgExprs;
4835 if (isTokenStringLiteral()) {
4836 // Easy case: uuid("...") -- quoted string.
4837 ExprResult StringResult = ParseUnevaluatedStringLiteralExpression();
4838 if (StringResult.isInvalid())
4839 return;
4840 ArgExprs.push_back(Elt: StringResult.get());
4841 } else {
4842 // something like uuid({000000A0-0000-0000-C000-000000000049}) -- no
4843 // quotes in the parens. Just append the spelling of all tokens encountered
4844 // until the closing paren.
4845
4846 SmallString<42> StrBuffer; // 2 "", 36 bytes UUID, 2 optional {}, 1 nul
4847 StrBuffer += "\"";
4848
4849 // Since none of C++'s keywords match [a-f]+, accepting just tok::l_brace,
4850 // tok::r_brace, tok::minus, tok::identifier (think C000) and
4851 // tok::numeric_constant (0000) should be enough. But the spelling of the
4852 // uuid argument is checked later anyways, so there's no harm in accepting
4853 // almost anything here.
4854 // cl is very strict about whitespace in this form and errors out if any
4855 // is present, so check the space flags on the tokens.
4856 SourceLocation StartLoc = Tok.getLocation();
4857 while (Tok.isNot(K: tok::r_paren)) {
4858 if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {
4859 Diag(Tok, DiagID: diag::err_attribute_uuid_malformed_guid);
4860 SkipUntil(T: tok::r_paren, Flags: StopAtSemi);
4861 return;
4862 }
4863 SmallString<16> SpellingBuffer;
4864 SpellingBuffer.resize(N: Tok.getLength() + 1);
4865 bool Invalid = false;
4866 StringRef TokSpelling = PP.getSpelling(Tok, Buffer&: SpellingBuffer, Invalid: &Invalid);
4867 if (Invalid) {
4868 SkipUntil(T: tok::r_paren, Flags: StopAtSemi);
4869 return;
4870 }
4871 StrBuffer += TokSpelling;
4872 ConsumeAnyToken();
4873 }
4874 StrBuffer += "\"";
4875
4876 if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {
4877 Diag(Tok, DiagID: diag::err_attribute_uuid_malformed_guid);
4878 ConsumeParen();
4879 return;
4880 }
4881
4882 // Pretend the user wrote the appropriate string literal here.
4883 // ActOnStringLiteral() copies the string data into the literal, so it's
4884 // ok that the Token points to StrBuffer.
4885 Token Toks[1];
4886 Toks[0].startToken();
4887 Toks[0].setKind(tok::string_literal);
4888 Toks[0].setLocation(StartLoc);
4889 Toks[0].setLiteralData(StrBuffer.data());
4890 Toks[0].setLength(StrBuffer.size());
4891 StringLiteral *UuidString =
4892 cast<StringLiteral>(Val: Actions.ActOnUnevaluatedStringLiteral(StringToks: Toks).get());
4893 ArgExprs.push_back(Elt: UuidString);
4894 }
4895
4896 if (!T.consumeClose()) {
4897 Attrs.addNew(attrName: UuidIdent, attrRange: SourceRange(UuidLoc, T.getCloseLocation()),
4898 scope: AttributeScopeInfo(), args: ArgExprs.data(), numArgs: ArgExprs.size(),
4899 form: ParsedAttr::Form::Microsoft());
4900 }
4901}
4902
4903void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) {
4904 assert(Tok.is(tok::identifier) &&
4905 "Expected an identifier to denote which MS attribute to consider");
4906 IdentifierInfo *RootSignatureIdent = Tok.getIdentifierInfo();
4907 assert(RootSignatureIdent->getName() == "RootSignature" &&
4908 "Expected RootSignature identifier for root signature attribute");
4909
4910 SourceLocation RootSignatureLoc = Tok.getLocation();
4911 ConsumeToken();
4912
4913 // Ignore the left paren location for now.
4914 BalancedDelimiterTracker T(*this, tok::l_paren);
4915 if (T.consumeOpen()) {
4916 Diag(Tok, DiagID: diag::err_expected) << tok::l_paren;
4917 return;
4918 }
4919
4920 auto ProcessStringLiteral = [this]() -> std::optional<StringLiteral *> {
4921 if (!isTokenStringLiteral())
4922 return std::nullopt;
4923
4924 ExprResult StringResult = ParseUnevaluatedStringLiteralExpression();
4925 if (StringResult.isInvalid())
4926 return std::nullopt;
4927
4928 if (auto Lit = dyn_cast<StringLiteral>(Val: StringResult.get()))
4929 return Lit;
4930
4931 return std::nullopt;
4932 };
4933
4934 auto StrLiteral = ProcessStringLiteral();
4935 if (!StrLiteral.has_value()) {
4936 Diag(Tok, DiagID: diag::err_expected_string_literal)
4937 << /*in attributes...*/ 4 << RootSignatureIdent->getName();
4938 SkipUntil(T: tok::r_paren, Flags: StopAtSemi | StopBeforeMatch);
4939 T.consumeClose();
4940 return;
4941 }
4942
4943 // Construct our identifier
4944 StringLiteral *Signature = StrLiteral.value();
4945 auto [DeclIdent, Found] =
4946 Actions.HLSL().ActOnStartRootSignatureDecl(Signature: Signature->getString());
4947 // If we haven't found an already defined DeclIdent then parse the root
4948 // signature string and construct the in-memory elements
4949 if (!Found) {
4950 // Invoke the root signature parser to construct the in-memory constructs
4951 SmallVector<hlsl::RootSignatureElement> RootElements;
4952 hlsl::RootSignatureParser Parser(getLangOpts().HLSLRootSigVer, RootElements,
4953 Signature, PP);
4954 if (Parser.parse()) {
4955 T.consumeClose();
4956 return;
4957 }
4958
4959 // Construct the declaration.
4960 Actions.HLSL().ActOnFinishRootSignatureDecl(Loc: RootSignatureLoc, DeclIdent,
4961 Elements: RootElements);
4962 }
4963
4964 // Create the arg for the ParsedAttr
4965 IdentifierLoc *ILoc = ::new (Actions.getASTContext())
4966 IdentifierLoc(RootSignatureLoc, DeclIdent);
4967
4968 ArgsVector Args = {ILoc};
4969
4970 if (!T.consumeClose())
4971 Attrs.addNew(attrName: RootSignatureIdent,
4972 attrRange: SourceRange(RootSignatureLoc, T.getCloseLocation()),
4973 scope: AttributeScopeInfo(), args: Args.data(), numArgs: Args.size(),
4974 form: ParsedAttr::Form::Microsoft());
4975}
4976
4977void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs) {
4978 assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");
4979
4980 SourceLocation StartLoc = Tok.getLocation();
4981 SourceLocation EndLoc = StartLoc;
4982 do {
4983 // FIXME: If this is actually a C++11 attribute, parse it as one.
4984 BalancedDelimiterTracker T(*this, tok::l_square);
4985 T.consumeOpen();
4986
4987 // Skip most ms attributes except for a specific list.
4988 while (true) {
4989 SkipUntil(T1: tok::r_square, T2: tok::identifier,
4990 Flags: StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);
4991 if (Tok.is(K: tok::code_completion)) {
4992 cutOffParsing();
4993 Actions.CodeCompletion().CodeCompleteAttribute(
4994 Syntax: AttributeCommonInfo::AS_Microsoft,
4995 Completion: SemaCodeCompletion::AttributeCompletion::Attribute,
4996 /*Scope=*/nullptr);
4997 break;
4998 }
4999 if (Tok.isNot(K: tok::identifier)) // ']', but also eof
5000 break;
5001 if (Tok.getIdentifierInfo()->getName() == "uuid")
5002 ParseMicrosoftUuidAttributeArgs(Attrs);
5003 else if (Tok.getIdentifierInfo()->getName() == "RootSignature")
5004 ParseHLSLRootSignatureAttributeArgs(Attrs);
5005 else {
5006 IdentifierInfo *II = Tok.getIdentifierInfo();
5007 SourceLocation NameLoc = Tok.getLocation();
5008 ConsumeToken();
5009 ParsedAttr::Kind AttrKind =
5010 ParsedAttr::getParsedKind(Name: II, Scope: nullptr, SyntaxUsed: ParsedAttr::AS_Microsoft);
5011 // For HLSL we want to handle all attributes, but for MSVC compat, we
5012 // silently ignore unknown Microsoft attributes.
5013 if (getLangOpts().HLSL || AttrKind != ParsedAttr::UnknownAttribute) {
5014 bool AttrParsed = false;
5015 if (Tok.is(K: tok::l_paren)) {
5016 CachedTokens OpenMPTokens;
5017 AttrParsed =
5018 ParseCXX11AttributeArgs(AttrName: II, AttrNameLoc: NameLoc, Attrs, EndLoc: &EndLoc, ScopeName: nullptr,
5019 ScopeLoc: SourceLocation(), OpenMPTokens);
5020 ReplayOpenMPAttributeTokens(OpenMPTokens);
5021 }
5022 if (!AttrParsed) {
5023 Attrs.addNew(attrName: II, attrRange: NameLoc, scope: AttributeScopeInfo(), args: nullptr, numArgs: 0,
5024 form: ParsedAttr::Form::Microsoft());
5025 }
5026 }
5027 }
5028 }
5029
5030 T.consumeClose();
5031 EndLoc = T.getCloseLocation();
5032 } while (Tok.is(K: tok::l_square));
5033
5034 Attrs.Range = SourceRange(StartLoc, EndLoc);
5035}
5036
5037void Parser::ParseMicrosoftIfExistsClassDeclaration(
5038 DeclSpec::TST TagType, ParsedAttributes &AccessAttrs,
5039 AccessSpecifier &CurAS) {
5040 IfExistsCondition Result;
5041 if (ParseMicrosoftIfExistsCondition(Result))
5042 return;
5043
5044 BalancedDelimiterTracker Braces(*this, tok::l_brace);
5045 if (Braces.consumeOpen()) {
5046 Diag(Tok, DiagID: diag::err_expected) << tok::l_brace;
5047 return;
5048 }
5049
5050 switch (Result.Behavior) {
5051 case IfExistsBehavior::Parse:
5052 // Parse the declarations below.
5053 break;
5054
5055 case IfExistsBehavior::Dependent:
5056 Diag(Loc: Result.KeywordLoc, DiagID: diag::warn_microsoft_dependent_exists)
5057 << Result.IsIfExists;
5058 // Fall through to skip.
5059 [[fallthrough]];
5060
5061 case IfExistsBehavior::Skip:
5062 Braces.skipToEnd();
5063 return;
5064 }
5065
5066 while (Tok.isNot(K: tok::r_brace) && !isEofOrEom()) {
5067 // __if_exists, __if_not_exists can nest.
5068 if (Tok.isOneOf(Ks: tok::kw___if_exists, Ks: tok::kw___if_not_exists)) {
5069 ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS);
5070 continue;
5071 }
5072
5073 // Check for extraneous top-level semicolon.
5074 if (Tok.is(K: tok::semi)) {
5075 ConsumeExtraSemi(Kind: ExtraSemiKind::InsideStruct, T: TagType);
5076 continue;
5077 }
5078
5079 AccessSpecifier AS = getAccessSpecifierIfPresent();
5080 if (AS != AS_none) {
5081 // Current token is a C++ access specifier.
5082 CurAS = AS;
5083 SourceLocation ASLoc = Tok.getLocation();
5084 ConsumeToken();
5085 if (Tok.is(K: tok::colon))
5086 Actions.ActOnAccessSpecifier(Access: AS, ASLoc, ColonLoc: Tok.getLocation(),
5087 Attrs: ParsedAttributesView{});
5088 else
5089 Diag(Tok, DiagID: diag::err_expected) << tok::colon;
5090 ConsumeToken();
5091 continue;
5092 }
5093
5094 ParsedTemplateInfo TemplateInfo;
5095 // Parse all the comma separated declarators.
5096 ParseCXXClassMemberDeclaration(AS: CurAS, AccessAttrs, TemplateInfo);
5097 }
5098
5099 Braces.consumeClose();
5100}
5101

source code of clang/lib/Parse/ParseDeclCXX.cpp