clang 24.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.
90 class ParsingDeclRAIIObject {
91 Sema &Actions;
92 sema::DelayedDiagnosticPool DiagnosticPool;
94 bool Popped;
95
96 ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
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).
116 ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
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
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.
255 class ExtensionRAIIObject {
256 ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
257 void operator=(const ExtensionRAIIObject &) = delete;
258
259 DiagnosticsEngine &Diags;
260 public:
261 ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
262 Diags.IncrementAllExtensionsSilenced();
263 }
264
266 Diags.DecrementAllExtensionsSilenced();
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
291 };
292
294 Parser &P;
295 bool OldVal;
296
297 public:
299 : P(P), OldVal(P.ParsingGenericAssociationType) {
300 P.ParsingGenericAssociationType = Value;
301 }
302
304 delete;
307
308 void restore() { P.ParsingGenericAssociationType = OldVal; }
309
311 };
312
313 /// Activates OpenMP parsing mode to preseve OpenMP specific annotation
314 /// tokens.
316 Parser &P;
317 bool OldVal;
318
319 public:
321 : P(P), OldVal(P.OpenMPDirectiveParsing) {
322 P.OpenMPDirectiveParsing = Value;
323 }
324
325 /// This can be used to restore the state early, before the dtor
326 /// is run.
327 void restore() { P.OpenMPDirectiveParsing = OldVal; }
328
330 };
331
332 /// Activates OpenACC parsing mode to preseve OpenACC specific annotation
333 /// tokens.
335 Parser &P;
336 bool OldVal;
337
338 public:
340 : P(P), OldVal(P.OpenACCDirectiveParsing) {
341 P.OpenACCDirectiveParsing = Value;
342 }
343
344 /// This can be used to restore the state early, before the dtor
345 /// is run.
346 void restore() { P.OpenACCDirectiveParsing = OldVal; }
347
349 };
350
351 /// RAII object that makes '>' behave either as an operator
352 /// or as the closing angle bracket for a template argument list.
354 bool &GreaterThanIsOperator;
355 bool OldGreaterThanIsOperator;
356 public:
357 GreaterThanIsOperatorScope(bool &GTIO, bool Val)
358 : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
359 GreaterThanIsOperator = Val;
360 }
361
363 GreaterThanIsOperator = OldGreaterThanIsOperator;
364 }
365 };
366
368 bool &InMessageExpression;
369 bool OldValue;
370
371 public:
373 : InMessageExpression(P.InMessageExpression),
374 OldValue(P.InMessageExpression) {
375 InMessageExpression = Value;
376 }
377
379 InMessageExpression = OldValue;
380 }
381 };
382
384 OffsetOfKind &OffsetOfState;
385 OffsetOfKind OldValue;
386
387 public:
389 : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) {
390 OffsetOfState = Value;
391 }
392
393 ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; }
394 };
395
396 /// RAII object that makes sure paren/bracket/brace count is correct
397 /// after declaration/statement parsing, even when there's a parsing error.
399 Parser &P;
400 unsigned short ParenCount, BracketCount, BraceCount;
401 public:
403 : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
404 BraceCount(p.BraceCount) { }
405
407 P.AngleBrackets.clear(P);
408 P.ParenCount = ParenCount;
409 P.BracketCount = BracketCount;
410 P.BraceCount = BraceCount;
411 }
412 };
413
415 PoisonIdentifierRAIIObject Ident_AbnormalTermination;
416 PoisonIdentifierRAIIObject Ident_GetExceptionCode;
417 PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
418 PoisonIdentifierRAIIObject Ident__abnormal_termination;
419 PoisonIdentifierRAIIObject Ident__exception_code;
420 PoisonIdentifierRAIIObject Ident__exception_info;
421 PoisonIdentifierRAIIObject Ident___abnormal_termination;
422 PoisonIdentifierRAIIObject Ident___exception_code;
423 PoisonIdentifierRAIIObject Ident___exception_info;
424 public:
426 : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
427 Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
428 Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
429 Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
430 Ident__exception_code(Self.Ident__exception_code, NewValue),
431 Ident__exception_info(Self.Ident__exception_info, NewValue),
432 Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
433 Ident___exception_code(Self.Ident___exception_code, NewValue),
434 Ident___exception_info(Self.Ident___exception_info, NewValue) {
435 }
436 };
437
438 /// RAII class that helps handle the parsing of an open/close delimiter
439 /// pair, such as braces { ... } or parentheses ( ... ).
441 Parser& P;
442 tok::TokenKind Kind, Close, FinalToken;
443 SourceLocation (Parser::*Consumer)();
444 SourceLocation LOpen, LClose;
445
446 unsigned short &getDepth() {
447 switch (Kind) {
448 case tok::l_brace: return P.BraceCount;
449 case tok::l_square: return P.BracketCount;
450 case tok::l_paren: return P.ParenCount;
451 default: llvm_unreachable("Wrong token kind");
452 }
453 }
454
455 bool diagnoseOverflow();
456 bool diagnoseMissingClose();
457
458 public:
460 tok::TokenKind FinalToken = tok::semi)
461 : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
462 P(p), Kind(k), FinalToken(FinalToken)
463 {
464 switch (Kind) {
465 default: llvm_unreachable("Unexpected balanced token");
466 case tok::l_brace:
467 Close = tok::r_brace;
468 Consumer = &Parser::ConsumeBrace;
469 break;
470 case tok::l_paren:
471 Close = tok::r_paren;
472 Consumer = &Parser::ConsumeParen;
473 break;
474
475 case tok::l_square:
476 Close = tok::r_square;
477 Consumer = &Parser::ConsumeBracket;
478 break;
479 }
480 }
481
482 SourceLocation getOpenLocation() const { return LOpen; }
483 SourceLocation getCloseLocation() const { return LClose; }
484 SourceRange getRange() const { return SourceRange(LOpen, LClose); }
485
486 bool consumeOpen() {
487 if (!P.Tok.is(Kind))
488 return true;
489
490 if (getDepth() < P.getLangOpts().BracketDepth) {
491 LOpen = (P.*Consumer)();
492 return false;
493 }
494
495 return diagnoseOverflow();
496 }
497
498 bool expectAndConsume(unsigned DiagID = diag::err_expected,
499 const char *Msg = "",
500 tok::TokenKind SkipToTok = tok::unknown);
502 if (P.Tok.is(Close)) {
503 LClose = (P.*Consumer)();
504 return false;
505 } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
506 SourceLocation SemiLoc = P.ConsumeToken();
507 P.Diag(SemiLoc, diag::err_unexpected_semi)
508 << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
509 LClose = (P.*Consumer)();
510 return false;
511 }
512
513 return diagnoseMissingClose();
514 }
515 void skipToEnd();
516 };
517} // end namespace clang
518
519#endif
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
Definition Parser.cpp:2660
BalancedDelimiterTracker(Parser &p, tok::TokenKind k, tok::TokenKind FinalToken=tok::semi)
SourceLocation getCloseLocation() const
void restore()
restore - This can be used to restore the state early, before the dtor is run.
ColonProtectionRAIIObject(Parser &p, bool Value=true)
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:2102
Declarator(const DeclSpec &DS, const ParsedAttributesView &DeclarationAttrs, DeclaratorContext C)
DS and DeclarationAttrs must outlive the Declarator.
Definition DeclSpec.h:2077
void clear()
Reset the contents of this Declarator.
Definition DeclSpec.h:2165
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:241
ExtensionRAIIObject(DiagnosticsEngine &diags)
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
Definition Diagnostic.h:129
GenericAssociationTypeRAIIObject(const GenericAssociationTypeRAIIObject &)=delete
GenericAssociationTypeRAIIObject & operator=(const GenericAssociationTypeRAIIObject &)=delete
GenericAssociationTypeRAIIObject(Parser &P, bool Value=true)
GreaterThanIsOperatorScope(bool &GTIO, bool Val)
InMessageExpressionRAIIObject(Parser &P, bool Value)
OffsetOfStateRAIIObject(Parser &P, OffsetOfKind Value)
ParsedAttributes - A collection of parsed attributes.
Definition ParsedAttr.h:950
Parser - This implements a parser for the C family of languages.
Definition Parser.h:266
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
ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, const ParsedAttributes &DeclarationAttrs, DeclaratorContext C)
const ParsingDeclSpec & getDeclSpec() const
ParsingDeclSpec & getMutableDeclSpec() const
const ParsingDeclSpec & getDeclSpec() const
ParsingDeclSpec & getMutableDeclSpec() const
ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS, const ParsedAttributes &DeclarationAttrs)
void restore()
This can be used to restore the state early, before the dtor is run.
ParsingOpenACCDirectiveRAII(Parser &P, bool Value=true)
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:863
DelayedDiagnosticsState ParsingDeclState
Definition Sema.h:1407
void PopParsingDeclaration(ParsingDeclState state, Decl *decl)
ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool)
Definition Sema.h:1461
Encodes a location in the source.
A trivial tuple used to represent a source range.
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.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition TokenKinds.h:33
Top level wrappers for InstallAPI frontend operations.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
DeclaratorContext
Definition DeclSpec.h:1905
OffsetOfKind
Definition Sema.h:610
@ Other
Other implicit parameter.
Definition Decl.h:1775
#define true
Definition stdbool.h:25
FieldDeclarator(const DeclSpec &DS, const ParsedAttributes &DeclarationAttrs)
Definition DeclSpec.h:2828