clang 18.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 }
66 void operator=(SuppressAccessChecks &&Other) = delete;
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 /// RAII object that makes '>' behave either as an operator
313 /// or as the closing angle bracket for a template argument list.
315 bool &GreaterThanIsOperator;
316 bool OldGreaterThanIsOperator;
317 public:
318 GreaterThanIsOperatorScope(bool &GTIO, bool Val)
319 : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
320 GreaterThanIsOperator = Val;
321 }
322
324 GreaterThanIsOperator = OldGreaterThanIsOperator;
325 }
326 };
327
329 bool &InMessageExpression;
330 bool OldValue;
331
332 public:
334 : InMessageExpression(P.InMessageExpression),
335 OldValue(P.InMessageExpression) {
336 InMessageExpression = Value;
337 }
338
340 InMessageExpression = OldValue;
341 }
342 };
343
345 Sema::OffsetOfKind &OffsetOfState;
346 Sema::OffsetOfKind OldValue;
347
348 public:
350 : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) {
351 OffsetOfState = Value;
352 }
353
354 ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; }
355 };
356
357 /// RAII object that makes sure paren/bracket/brace count is correct
358 /// after declaration/statement parsing, even when there's a parsing error.
360 Parser &P;
361 unsigned short ParenCount, BracketCount, BraceCount;
362 public:
364 : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
365 BraceCount(p.BraceCount) { }
366
368 P.AngleBrackets.clear(P);
369 P.ParenCount = ParenCount;
370 P.BracketCount = BracketCount;
371 P.BraceCount = BraceCount;
372 }
373 };
374
376 PoisonIdentifierRAIIObject Ident_AbnormalTermination;
377 PoisonIdentifierRAIIObject Ident_GetExceptionCode;
378 PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
379 PoisonIdentifierRAIIObject Ident__abnormal_termination;
380 PoisonIdentifierRAIIObject Ident__exception_code;
381 PoisonIdentifierRAIIObject Ident__exception_info;
382 PoisonIdentifierRAIIObject Ident___abnormal_termination;
383 PoisonIdentifierRAIIObject Ident___exception_code;
384 PoisonIdentifierRAIIObject Ident___exception_info;
385 public:
387 : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
388 Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
389 Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
390 Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
391 Ident__exception_code(Self.Ident__exception_code, NewValue),
392 Ident__exception_info(Self.Ident__exception_info, NewValue),
393 Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
394 Ident___exception_code(Self.Ident___exception_code, NewValue),
395 Ident___exception_info(Self.Ident___exception_info, NewValue) {
396 }
397 };
398
399 /// RAII class that helps handle the parsing of an open/close delimiter
400 /// pair, such as braces { ... } or parentheses ( ... ).
402 Parser& P;
403 tok::TokenKind Kind, Close, FinalToken;
404 SourceLocation (Parser::*Consumer)();
405 SourceLocation LOpen, LClose;
406
407 unsigned short &getDepth() {
408 switch (Kind) {
409 case tok::l_brace: return P.BraceCount;
410 case tok::l_square: return P.BracketCount;
411 case tok::l_paren: return P.ParenCount;
412 default: llvm_unreachable("Wrong token kind");
413 }
414 }
415
416 bool diagnoseOverflow();
417 bool diagnoseMissingClose();
418
419 public:
421 tok::TokenKind FinalToken = tok::semi)
422 : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
423 P(p), Kind(k), FinalToken(FinalToken)
424 {
425 switch (Kind) {
426 default: llvm_unreachable("Unexpected balanced token");
427 case tok::l_brace:
428 Close = tok::r_brace;
429 Consumer = &Parser::ConsumeBrace;
430 break;
431 case tok::l_paren:
432 Close = tok::r_paren;
433 Consumer = &Parser::ConsumeParen;
434 break;
435
436 case tok::l_square:
437 Close = tok::r_square;
438 Consumer = &Parser::ConsumeBracket;
439 break;
440 }
441 }
442
443 SourceLocation getOpenLocation() const { return LOpen; }
444 SourceLocation getCloseLocation() const { return LClose; }
445 SourceRange getRange() const { return SourceRange(LOpen, LClose); }
446
447 bool consumeOpen() {
448 if (!P.Tok.is(Kind))
449 return true;
450
451 if (getDepth() < P.getLangOpts().BracketDepth) {
452 LOpen = (P.*Consumer)();
453 return false;
454 }
455
456 return diagnoseOverflow();
457 }
458
459 bool expectAndConsume(unsigned DiagID = diag::err_expected,
460 const char *Msg = "",
461 tok::TokenKind SkipToTok = tok::unknown);
463 if (P.Tok.is(Close)) {
464 LClose = (P.*Consumer)();
465 return false;
466 } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
467 SourceLocation SemiLoc = P.ConsumeToken();
468 P.Diag(SemiLoc, diag::err_unexpected_semi)
469 << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
470 LClose = (P.*Consumer)();
471 return false;
472 }
473
474 return diagnoseMissingClose();
475 }
476 void skipToEnd();
477 };
478} // end namespace clang
479
480#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:2718
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:83
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1850
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition: DeclSpec.h:1986
void clear()
Reset the contents of this Declarator.
Definition: DeclSpec.h:2049
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
void DecrementAllExtensionsSilenced()
Definition: Diagnostic.h:785
void IncrementAllExtensionsSilenced()
Counter bumped when an extension block is/ encountered.
Definition: Diagnostic.h:784
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:935
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:53
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 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:356
void PopParsingDeclaration(ParsingDeclState state, Decl *decl)
ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool)
Definition: Sema.h:5413
OffsetOfKind
Definition: Sema.h:3377
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
@ C
Languages that the frontend can parse and compile.
DeclaratorContext
Definition: DeclSpec.h:1800
Definition: Format.h:5078
#define true
Definition: stdbool.h:21
This little struct is used to capture information about structure field declarators,...
Definition: DeclSpec.h:2686