clang 19.0.0git
RAIIObjectsForParser.h
Go to the documentation of this file.
1//===--- RAIIObjectsForParser.h - RAII helpers for the parser ---*- 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 defines and implements the some simple RAII objects that are used
10// by the parser to manage bits in recursion.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
15#define LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
16
18#include "clang/Parse/Parser.h"
21#include "clang/Sema/Sema.h"
22
23namespace clang {
24 // TODO: move ParsingClassDefinition here.
25 // TODO: move TentativeParsingAction here.
26
27 /// A RAII object used to temporarily suppress access-like
28 /// checking. Access-like checks are those associated with
29 /// controlling the use of a declaration, like C++ access control
30 /// errors and deprecation warnings. They are contextually
31 /// dependent, in that they can only be resolved with full
32 /// information about what's being declared. They are also
33 /// suppressed in certain contexts, like the template arguments of
34 /// an explicit instantiation. However, those suppression contexts
35 /// cannot necessarily be fully determined in advance; for
36 /// example, something starting like this:
37 /// template <> class std::vector<A::PrivateType>
38 /// might be the entirety of an explicit instantiation:
39 /// template <> class std::vector<A::PrivateType>;
40 /// or just an elaborated type specifier:
41 /// template <> class std::vector<A::PrivateType> make_vector<>();
42 /// Therefore this class collects all the diagnostics and permits
43 /// them to be re-delayed in a new context.
45 Sema &S;
46 sema::DelayedDiagnosticPool DiagnosticPool;
48 bool Active;
49
50 public:
51 /// Begin suppressing access-like checks
52 SuppressAccessChecks(Parser &P, bool activate = true)
53 : S(P.getActions()), DiagnosticPool(nullptr) {
54 if (activate) {
55 State = S.PushParsingDeclaration(DiagnosticPool);
56 Active = true;
57 } else {
58 Active = false;
59 }
60 }
62 : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
63 State(Other.State), Active(Other.Active) {
64 Other.Active = false;
65 }
67
68 void done() {
69 assert(Active && "trying to end an inactive suppression");
70 S.PopParsingDeclaration(State, nullptr);
71 Active = false;
72 }
73
74 void redelay() {
75 assert(!Active && "redelaying without having ended first");
76 if (!DiagnosticPool.pool_empty())
77 S.redelayDiagnostics(DiagnosticPool);
78 assert(DiagnosticPool.pool_empty());
79 }
80
82 if (Active) done();
83 }
84 };
85
86 /// RAII object used to inform the actions that we're
87 /// currently parsing a declaration. This is active when parsing a
88 /// variable's initializer, but not when parsing the body of a
89 /// class or function definition.
91 Sema &Actions;
92 sema::DelayedDiagnosticPool DiagnosticPool;
94 bool Popped;
95
97 void operator=(const ParsingDeclRAIIObject &) = delete;
98
99 public:
102 : Actions(P.getActions()), DiagnosticPool(nullptr) {
103 push();
104 }
105
106 /// Creates a RAII object whose pool is optionally parented by another.
108 const sema::DelayedDiagnosticPool *parentPool)
109 : Actions(P.getActions()), DiagnosticPool(parentPool) {
110 push();
111 }
112
113 /// Creates a RAII object and, optionally, initialize its
114 /// diagnostics pool by stealing the diagnostics from another
115 /// RAII object (which is assumed to be the current top pool).
117 : Actions(P.getActions()),
118 DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
119 if (other) {
120 DiagnosticPool.steal(other->DiagnosticPool);
121 other->abort();
122 }
123 push();
124 }
125
127 abort();
128 }
129
131 return DiagnosticPool;
132 }
134 return DiagnosticPool;
135 }
136
137 /// Resets the RAII object for a new declaration.
138 void reset() {
139 abort();
140 push();
141 }
142
143 /// Signals that the context was completed without an appropriate
144 /// declaration being parsed.
145 void abort() {
146 pop(nullptr);
147 }
148
149 void complete(Decl *D) {
150 assert(!Popped && "ParsingDeclaration has already been popped!");
151 pop(D);
152 }
153
154 /// Unregister this object from Sema, but remember all the
155 /// diagnostics that were emitted into it.
157 pop(nullptr);
158 }
159
160 private:
161 void push() {
162 State = Actions.PushParsingDeclaration(DiagnosticPool);
163 Popped = false;
164 }
165
166 void pop(Decl *D) {
167 if (!Popped) {
168 Actions.PopParsingDeclaration(State, D);
169 Popped = true;
170 }
171 }
172 };
173
174 /// A class for parsing a DeclSpec.
175 class ParsingDeclSpec : public DeclSpec {
176 ParsingDeclRAIIObject ParsingRAII;
177
178 public:
180 : DeclSpec(P.getAttrFactory()),
181 ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
183 : DeclSpec(P.getAttrFactory()),
184 ParsingRAII(P, RAII) {}
185
187 return ParsingRAII.getDelayedDiagnosticPool();
188 }
189
190 void complete(Decl *D) {
191 ParsingRAII.complete(D);
192 }
193
194 void abort() {
195 ParsingRAII.abort();
196 }
197 };
198
199 /// A class for parsing a declarator.
201 ParsingDeclRAIIObject ParsingRAII;
202
203 public:
205 const ParsedAttributes &DeclarationAttrs,
207 : Declarator(DS, DeclarationAttrs, C),
208 ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
209
211 return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
212 }
213
215 return const_cast<ParsingDeclSpec&>(getDeclSpec());
216 }
217
218 void clear() {
220 ParsingRAII.reset();
221 }
222
223 void complete(Decl *D) {
224 ParsingRAII.complete(D);
225 }
226 };
227
228 /// A class for parsing a field declarator.
230 ParsingDeclRAIIObject ParsingRAII;
231
232 public:
234 const ParsedAttributes &DeclarationAttrs)
235 : FieldDeclarator(DS, DeclarationAttrs),
236 ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
237
239 return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
240 }
241
243 return const_cast<ParsingDeclSpec&>(getDeclSpec());
244 }
245
246 void complete(Decl *D) {
247 ParsingRAII.complete(D);
248 }
249 };
250
251 /// ExtensionRAIIObject - This saves the state of extension warnings when
252 /// constructed and disables them. When destructed, it restores them back to
253 /// the way they used to be. This is used to handle __extension__ in the
254 /// parser.
257 void operator=(const ExtensionRAIIObject &) = delete;
258
259 DiagnosticsEngine &Diags;
260 public:
261 ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
263 }
264
267 }
268 };
269
270 /// ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and
271 /// restores it when destroyed. This says that "foo:" should not be
272 /// considered a possible typo for "foo::" for error recovery purposes.
274 Parser &P;
275 bool OldVal;
276 public:
278 : P(p), OldVal(P.ColonIsSacred) {
279 P.ColonIsSacred = Value;
280 }
281
282 /// restore - This can be used to restore the state early, before the dtor
283 /// is run.
284 void restore() {
285 P.ColonIsSacred = OldVal;
286 }
287
289 restore();
290 }
291 };
292
293 /// Activates OpenMP parsing mode to preseve OpenMP specific annotation
294 /// tokens.
296 Parser &P;
297 bool OldVal;
298
299 public:
301 : P(P), OldVal(P.OpenMPDirectiveParsing) {
302 P.OpenMPDirectiveParsing = Value;
303 }
304
305 /// This can be used to restore the state early, before the dtor
306 /// is run.
307 void restore() { P.OpenMPDirectiveParsing = OldVal; }
308
310 };
311
312 /// Activates OpenACC parsing mode to preseve OpenACC specific annotation
313 /// tokens.
315 Parser &P;
316 bool OldVal;
317
318 public:
320 : P(P), OldVal(P.OpenACCDirectiveParsing) {
321 P.OpenACCDirectiveParsing = Value;
322 }
323
324 /// This can be used to restore the state early, before the dtor
325 /// is run.
326 void restore() { P.OpenACCDirectiveParsing = OldVal; }
327
329 };
330
331 /// RAII object that makes '>' behave either as an operator
332 /// or as the closing angle bracket for a template argument list.
334 bool &GreaterThanIsOperator;
335 bool OldGreaterThanIsOperator;
336 public:
337 GreaterThanIsOperatorScope(bool &GTIO, bool Val)
338 : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
339 GreaterThanIsOperator = Val;
340 }
341
343 GreaterThanIsOperator = OldGreaterThanIsOperator;
344 }
345 };
346
348 bool &InMessageExpression;
349 bool OldValue;
350
351 public:
353 : InMessageExpression(P.InMessageExpression),
354 OldValue(P.InMessageExpression) {
355 InMessageExpression = Value;
356 }
357
359 InMessageExpression = OldValue;
360 }
361 };
362
364 Sema::OffsetOfKind &OffsetOfState;
365 Sema::OffsetOfKind OldValue;
366
367 public:
369 : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) {
370 OffsetOfState = Value;
371 }
372
373 ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; }
374 };
375
376 /// RAII object that makes sure paren/bracket/brace count is correct
377 /// after declaration/statement parsing, even when there's a parsing error.
379 Parser &P;
380 unsigned short ParenCount, BracketCount, BraceCount;
381 public:
383 : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
384 BraceCount(p.BraceCount) { }
385
387 P.AngleBrackets.clear(P);
388 P.ParenCount = ParenCount;
389 P.BracketCount = BracketCount;
390 P.BraceCount = BraceCount;
391 }
392 };
393
395 PoisonIdentifierRAIIObject Ident_AbnormalTermination;
396 PoisonIdentifierRAIIObject Ident_GetExceptionCode;
397 PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
398 PoisonIdentifierRAIIObject Ident__abnormal_termination;
399 PoisonIdentifierRAIIObject Ident__exception_code;
400 PoisonIdentifierRAIIObject Ident__exception_info;
401 PoisonIdentifierRAIIObject Ident___abnormal_termination;
402 PoisonIdentifierRAIIObject Ident___exception_code;
403 PoisonIdentifierRAIIObject Ident___exception_info;
404 public:
406 : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
407 Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
408 Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
409 Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
410 Ident__exception_code(Self.Ident__exception_code, NewValue),
411 Ident__exception_info(Self.Ident__exception_info, NewValue),
412 Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
413 Ident___exception_code(Self.Ident___exception_code, NewValue),
414 Ident___exception_info(Self.Ident___exception_info, NewValue) {
415 }
416 };
417
418 /// RAII class that helps handle the parsing of an open/close delimiter
419 /// pair, such as braces { ... } or parentheses ( ... ).
421 Parser& P;
422 tok::TokenKind Kind, Close, FinalToken;
423 SourceLocation (Parser::*Consumer)();
424 SourceLocation LOpen, LClose;
425
426 unsigned short &getDepth() {
427 switch (Kind) {
428 case tok::l_brace: return P.BraceCount;
429 case tok::l_square: return P.BracketCount;
430 case tok::l_paren: return P.ParenCount;
431 default: llvm_unreachable("Wrong token kind");
432 }
433 }
434
435 bool diagnoseOverflow();
436 bool diagnoseMissingClose();
437
438 public:
440 tok::TokenKind FinalToken = tok::semi)
441 : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
442 P(p), Kind(k), FinalToken(FinalToken)
443 {
444 switch (Kind) {
445 default: llvm_unreachable("Unexpected balanced token");
446 case tok::l_brace:
447 Close = tok::r_brace;
448 Consumer = &Parser::ConsumeBrace;
449 break;
450 case tok::l_paren:
451 Close = tok::r_paren;
452 Consumer = &Parser::ConsumeParen;
453 break;
454
455 case tok::l_square:
456 Close = tok::r_square;
457 Consumer = &Parser::ConsumeBracket;
458 break;
459 }
460 }
461
462 SourceLocation getOpenLocation() const { return LOpen; }
463 SourceLocation getCloseLocation() const { return LClose; }
464 SourceRange getRange() const { return SourceRange(LOpen, LClose); }
465
466 bool consumeOpen() {
467 if (!P.Tok.is(Kind))
468 return true;
469
470 if (getDepth() < P.getLangOpts().BracketDepth) {
471 LOpen = (P.*Consumer)();
472 return false;
473 }
474
475 return diagnoseOverflow();
476 }
477
478 bool expectAndConsume(unsigned DiagID = diag::err_expected,
479 const char *Msg = "",
480 tok::TokenKind SkipToTok = tok::unknown);
482 if (P.Tok.is(Close)) {
483 LClose = (P.*Consumer)();
484 return false;
485 } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
486 SourceLocation SemiLoc = P.ConsumeToken();
487 P.Diag(SemiLoc, diag::err_unexpected_semi)
488 << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
489 LClose = (P.*Consumer)();
490 return false;
491 }
492
493 return diagnoseMissingClose();
494 }
495 void skipToEnd();
496 };
497} // end namespace clang
498
499#endif
StringRef P
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
Definition: Parser.cpp:2764
SourceLocation getOpenLocation() const
BalancedDelimiterTracker(Parser &p, tok::TokenKind k, tok::TokenKind FinalToken=tok::semi)
SourceLocation getCloseLocation() const
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed.
void restore()
restore - This can be used to restore the state early, before the dtor is run.
ColonProtectionRAIIObject(Parser &p, bool Value=true)
Captures information about "declaration specifiers".
Definition: DeclSpec.h:246
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:85
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1899
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition: DeclSpec.h:2046
void clear()
Reset the contents of this Declarator.
Definition: DeclSpec.h:2109
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
void DecrementAllExtensionsSilenced()
Definition: Diagnostic.h:790
void IncrementAllExtensionsSilenced()
Counter bumped when an extension block is/ encountered.
Definition: Diagnostic.h:789
ExtensionRAIIObject - This saves the state of extension warnings when constructed and disables them.
ExtensionRAIIObject(DiagnosticsEngine &diags)
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition: Diagnostic.h:123
RAII object that makes '>' behave either as an operator or as the closing angle bracket for a templat...
GreaterThanIsOperatorScope(bool &GTIO, bool Val)
InMessageExpressionRAIIObject(Parser &P, bool Value)
OffsetOfStateRAIIObject(Parser &P, Sema::OffsetOfKind Value)
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...
ParsedAttributes - A collection of parsed attributes.
Definition: ParsedAttr.h:951
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:54
RAII object used to inform the actions that we're currently parsing a declaration.
ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
Creates a RAII object and, optionally, initialize its diagnostics pool by stealing the diagnostics fr...
ParsingDeclRAIIObject(Parser &P, const sema::DelayedDiagnosticPool *parentPool)
Creates a RAII object whose pool is optionally parented by another.
void abort()
Signals that the context was completed without an appropriate declaration being parsed.
void abortAndRemember()
Unregister this object from Sema, but remember all the diagnostics that were emitted into it.
const sema::DelayedDiagnosticPool & getDelayedDiagnosticPool() const
sema::DelayedDiagnosticPool & getDelayedDiagnosticPool()
ParsingDeclRAIIObject(Parser &P, NoParent_t _)
void reset()
Resets the RAII object for a new declaration.
A class for parsing a DeclSpec.
ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
const sema::DelayedDiagnosticPool & getDelayedDiagnosticPool() const
A class for parsing a declarator.
ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, const ParsedAttributes &DeclarationAttrs, DeclaratorContext C)
const ParsingDeclSpec & getDeclSpec() const
ParsingDeclSpec & getMutableDeclSpec() const
A class for parsing a field declarator.
const ParsingDeclSpec & getDeclSpec() const
ParsingDeclSpec & getMutableDeclSpec() const
ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS, const ParsedAttributes &DeclarationAttrs)
Activates OpenACC parsing mode to preseve OpenACC specific annotation tokens.
void restore()
This can be used to restore the state early, before the dtor is run.
ParsingOpenACCDirectiveRAII(Parser &P, bool Value=true)
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
void restore()
This can be used to restore the state early, before the dtor is run.
ParsingOpenMPDirectiveRAII(Parser &P, bool Value=true)
An RAII object for [un]poisoning an identifier within a scope.
PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:426
void PopParsingDeclaration(ParsingDeclState state, Decl *decl)
ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool)
Definition: Sema.h:1158
OffsetOfKind
Definition: Sema.h:3325
Encodes a location in the source.
A trivial tuple used to represent a source range.
A RAII object used to temporarily suppress access-like checking.
void operator=(SuppressAccessChecks &&Other)=delete
SuppressAccessChecks(Parser &P, bool activate=true)
Begin suppressing access-like checks.
SuppressAccessChecks(SuppressAccessChecks &&Other)
A collection of diagnostics which were delayed.
void steal(DelayedDiagnosticPool &pool)
Steal the diagnostics from the given pool.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition: TokenKinds.h:25
The JSON file list parser is used to communicate input to InstallAPI.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
DeclaratorContext
Definition: DeclSpec.h:1849
@ Other
Other implicit parameter.
Definition: Format.h:5304
#define true
Definition: stdbool.h:21
This little struct is used to capture information about structure field declarators,...
Definition: DeclSpec.h:2769