File indexing completed on 2026-05-10 08:36:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
0015 #define LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
0016
0017 #include "clang/Basic/DiagnosticParse.h"
0018 #include "clang/Parse/Parser.h"
0019 #include "clang/Sema/DelayedDiagnostic.h"
0020 #include "clang/Sema/ParsedTemplate.h"
0021 #include "clang/Sema/Sema.h"
0022
0023 namespace clang {
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 class SuppressAccessChecks {
0045 Sema &S;
0046 sema::DelayedDiagnosticPool DiagnosticPool;
0047 Sema::ParsingDeclState State;
0048 bool Active;
0049
0050 public:
0051
0052 SuppressAccessChecks(Parser &P, bool activate = true)
0053 : S(P.getActions()), DiagnosticPool(nullptr) {
0054 if (activate) {
0055 State = S.PushParsingDeclaration(DiagnosticPool);
0056 Active = true;
0057 } else {
0058 Active = false;
0059 }
0060 }
0061 SuppressAccessChecks(SuppressAccessChecks &&Other)
0062 : S(Other.S), DiagnosticPool(std::move(Other.DiagnosticPool)),
0063 State(Other.State), Active(Other.Active) {
0064 Other.Active = false;
0065 }
0066 void operator=(SuppressAccessChecks &&Other) = delete;
0067
0068 void done() {
0069 assert(Active && "trying to end an inactive suppression");
0070 S.PopParsingDeclaration(State, nullptr);
0071 Active = false;
0072 }
0073
0074 void redelay() {
0075 assert(!Active && "redelaying without having ended first");
0076 if (!DiagnosticPool.pool_empty())
0077 S.redelayDiagnostics(DiagnosticPool);
0078 assert(DiagnosticPool.pool_empty());
0079 }
0080
0081 ~SuppressAccessChecks() {
0082 if (Active) done();
0083 }
0084 };
0085
0086
0087
0088
0089
0090 class ParsingDeclRAIIObject {
0091 Sema &Actions;
0092 sema::DelayedDiagnosticPool DiagnosticPool;
0093 Sema::ParsingDeclState State;
0094 bool Popped;
0095
0096 ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete;
0097 void operator=(const ParsingDeclRAIIObject &) = delete;
0098
0099 public:
0100 enum NoParent_t { NoParent };
0101 ParsingDeclRAIIObject(Parser &P, NoParent_t _)
0102 : Actions(P.getActions()), DiagnosticPool(nullptr) {
0103 push();
0104 }
0105
0106
0107 ParsingDeclRAIIObject(Parser &P,
0108 const sema::DelayedDiagnosticPool *parentPool)
0109 : Actions(P.getActions()), DiagnosticPool(parentPool) {
0110 push();
0111 }
0112
0113
0114
0115
0116 ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
0117 : Actions(P.getActions()),
0118 DiagnosticPool(other ? other->DiagnosticPool.getParent() : nullptr) {
0119 if (other) {
0120 DiagnosticPool.steal(other->DiagnosticPool);
0121 other->abort();
0122 }
0123 push();
0124 }
0125
0126 ~ParsingDeclRAIIObject() {
0127 abort();
0128 }
0129
0130 sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
0131 return DiagnosticPool;
0132 }
0133 const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
0134 return DiagnosticPool;
0135 }
0136
0137
0138 void reset() {
0139 abort();
0140 push();
0141 }
0142
0143
0144
0145 void abort() {
0146 pop(nullptr);
0147 }
0148
0149 void complete(Decl *D) {
0150 assert(!Popped && "ParsingDeclaration has already been popped!");
0151 pop(D);
0152 }
0153
0154
0155
0156 void abortAndRemember() {
0157 pop(nullptr);
0158 }
0159
0160 private:
0161 void push() {
0162 State = Actions.PushParsingDeclaration(DiagnosticPool);
0163 Popped = false;
0164 }
0165
0166 void pop(Decl *D) {
0167 if (!Popped) {
0168 Actions.PopParsingDeclaration(State, D);
0169 Popped = true;
0170 }
0171 }
0172 };
0173
0174
0175 class ParsingDeclSpec : public DeclSpec {
0176 ParsingDeclRAIIObject ParsingRAII;
0177
0178 public:
0179 ParsingDeclSpec(Parser &P)
0180 : DeclSpec(P.getAttrFactory()),
0181 ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
0182 ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
0183 : DeclSpec(P.getAttrFactory()),
0184 ParsingRAII(P, RAII) {}
0185
0186 const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
0187 return ParsingRAII.getDelayedDiagnosticPool();
0188 }
0189
0190 void complete(Decl *D) {
0191 ParsingRAII.complete(D);
0192 }
0193
0194 void abort() {
0195 ParsingRAII.abort();
0196 }
0197 };
0198
0199
0200 class ParsingDeclarator : public Declarator {
0201 ParsingDeclRAIIObject ParsingRAII;
0202
0203 public:
0204 ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS,
0205 const ParsedAttributes &DeclarationAttrs,
0206 DeclaratorContext C)
0207 : Declarator(DS, DeclarationAttrs, C),
0208 ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
0209
0210 const ParsingDeclSpec &getDeclSpec() const {
0211 return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
0212 }
0213
0214 ParsingDeclSpec &getMutableDeclSpec() const {
0215 return const_cast<ParsingDeclSpec&>(getDeclSpec());
0216 }
0217
0218 void clear() {
0219 Declarator::clear();
0220 ParsingRAII.reset();
0221 }
0222
0223 void complete(Decl *D) {
0224 ParsingRAII.complete(D);
0225 }
0226 };
0227
0228
0229 class ParsingFieldDeclarator : public FieldDeclarator {
0230 ParsingDeclRAIIObject ParsingRAII;
0231
0232 public:
0233 ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS,
0234 const ParsedAttributes &DeclarationAttrs)
0235 : FieldDeclarator(DS, DeclarationAttrs),
0236 ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {}
0237
0238 const ParsingDeclSpec &getDeclSpec() const {
0239 return static_cast<const ParsingDeclSpec&>(D.getDeclSpec());
0240 }
0241
0242 ParsingDeclSpec &getMutableDeclSpec() const {
0243 return const_cast<ParsingDeclSpec&>(getDeclSpec());
0244 }
0245
0246 void complete(Decl *D) {
0247 ParsingRAII.complete(D);
0248 }
0249 };
0250
0251
0252
0253
0254
0255 class ExtensionRAIIObject {
0256 ExtensionRAIIObject(const ExtensionRAIIObject &) = delete;
0257 void operator=(const ExtensionRAIIObject &) = delete;
0258
0259 DiagnosticsEngine &Diags;
0260 public:
0261 ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) {
0262 Diags.IncrementAllExtensionsSilenced();
0263 }
0264
0265 ~ExtensionRAIIObject() {
0266 Diags.DecrementAllExtensionsSilenced();
0267 }
0268 };
0269
0270
0271
0272
0273 class ColonProtectionRAIIObject {
0274 Parser &P;
0275 bool OldVal;
0276 public:
0277 ColonProtectionRAIIObject(Parser &p, bool Value = true)
0278 : P(p), OldVal(P.ColonIsSacred) {
0279 P.ColonIsSacred = Value;
0280 }
0281
0282
0283
0284 void restore() {
0285 P.ColonIsSacred = OldVal;
0286 }
0287
0288 ~ColonProtectionRAIIObject() {
0289 restore();
0290 }
0291 };
0292
0293
0294
0295 class ParsingOpenMPDirectiveRAII {
0296 Parser &P;
0297 bool OldVal;
0298
0299 public:
0300 ParsingOpenMPDirectiveRAII(Parser &P, bool Value = true)
0301 : P(P), OldVal(P.OpenMPDirectiveParsing) {
0302 P.OpenMPDirectiveParsing = Value;
0303 }
0304
0305
0306
0307 void restore() { P.OpenMPDirectiveParsing = OldVal; }
0308
0309 ~ParsingOpenMPDirectiveRAII() { restore(); }
0310 };
0311
0312
0313
0314 class ParsingOpenACCDirectiveRAII {
0315 Parser &P;
0316 bool OldVal;
0317
0318 public:
0319 ParsingOpenACCDirectiveRAII(Parser &P, bool Value = true)
0320 : P(P), OldVal(P.OpenACCDirectiveParsing) {
0321 P.OpenACCDirectiveParsing = Value;
0322 }
0323
0324
0325
0326 void restore() { P.OpenACCDirectiveParsing = OldVal; }
0327
0328 ~ParsingOpenACCDirectiveRAII() { restore(); }
0329 };
0330
0331
0332
0333 class GreaterThanIsOperatorScope {
0334 bool &GreaterThanIsOperator;
0335 bool OldGreaterThanIsOperator;
0336 public:
0337 GreaterThanIsOperatorScope(bool >IO, bool Val)
0338 : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) {
0339 GreaterThanIsOperator = Val;
0340 }
0341
0342 ~GreaterThanIsOperatorScope() {
0343 GreaterThanIsOperator = OldGreaterThanIsOperator;
0344 }
0345 };
0346
0347 class InMessageExpressionRAIIObject {
0348 bool &InMessageExpression;
0349 bool OldValue;
0350
0351 public:
0352 InMessageExpressionRAIIObject(Parser &P, bool Value)
0353 : InMessageExpression(P.InMessageExpression),
0354 OldValue(P.InMessageExpression) {
0355 InMessageExpression = Value;
0356 }
0357
0358 ~InMessageExpressionRAIIObject() {
0359 InMessageExpression = OldValue;
0360 }
0361 };
0362
0363 class OffsetOfStateRAIIObject {
0364 Sema::OffsetOfKind &OffsetOfState;
0365 Sema::OffsetOfKind OldValue;
0366
0367 public:
0368 OffsetOfStateRAIIObject(Parser &P, Sema::OffsetOfKind Value)
0369 : OffsetOfState(P.OffsetOfState), OldValue(P.OffsetOfState) {
0370 OffsetOfState = Value;
0371 }
0372
0373 ~OffsetOfStateRAIIObject() { OffsetOfState = OldValue; }
0374 };
0375
0376
0377
0378 class ParenBraceBracketBalancer {
0379 Parser &P;
0380 unsigned short ParenCount, BracketCount, BraceCount;
0381 public:
0382 ParenBraceBracketBalancer(Parser &p)
0383 : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount),
0384 BraceCount(p.BraceCount) { }
0385
0386 ~ParenBraceBracketBalancer() {
0387 P.AngleBrackets.clear(P);
0388 P.ParenCount = ParenCount;
0389 P.BracketCount = BracketCount;
0390 P.BraceCount = BraceCount;
0391 }
0392 };
0393
0394 class PoisonSEHIdentifiersRAIIObject {
0395 PoisonIdentifierRAIIObject Ident_AbnormalTermination;
0396 PoisonIdentifierRAIIObject Ident_GetExceptionCode;
0397 PoisonIdentifierRAIIObject Ident_GetExceptionInfo;
0398 PoisonIdentifierRAIIObject Ident__abnormal_termination;
0399 PoisonIdentifierRAIIObject Ident__exception_code;
0400 PoisonIdentifierRAIIObject Ident__exception_info;
0401 PoisonIdentifierRAIIObject Ident___abnormal_termination;
0402 PoisonIdentifierRAIIObject Ident___exception_code;
0403 PoisonIdentifierRAIIObject Ident___exception_info;
0404 public:
0405 PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue)
0406 : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue),
0407 Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue),
0408 Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue),
0409 Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue),
0410 Ident__exception_code(Self.Ident__exception_code, NewValue),
0411 Ident__exception_info(Self.Ident__exception_info, NewValue),
0412 Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue),
0413 Ident___exception_code(Self.Ident___exception_code, NewValue),
0414 Ident___exception_info(Self.Ident___exception_info, NewValue) {
0415 }
0416 };
0417
0418
0419
0420 class BalancedDelimiterTracker : public GreaterThanIsOperatorScope {
0421 Parser& P;
0422 tok::TokenKind Kind, Close, FinalToken;
0423 SourceLocation (Parser::*Consumer)();
0424 SourceLocation LOpen, LClose;
0425
0426 unsigned short &getDepth() {
0427 switch (Kind) {
0428 case tok::l_brace: return P.BraceCount;
0429 case tok::l_square: return P.BracketCount;
0430 case tok::l_paren: return P.ParenCount;
0431 default: llvm_unreachable("Wrong token kind");
0432 }
0433 }
0434
0435 bool diagnoseOverflow();
0436 bool diagnoseMissingClose();
0437
0438 public:
0439 BalancedDelimiterTracker(Parser& p, tok::TokenKind k,
0440 tok::TokenKind FinalToken = tok::semi)
0441 : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true),
0442 P(p), Kind(k), FinalToken(FinalToken)
0443 {
0444 switch (Kind) {
0445 default: llvm_unreachable("Unexpected balanced token");
0446 case tok::l_brace:
0447 Close = tok::r_brace;
0448 Consumer = &Parser::ConsumeBrace;
0449 break;
0450 case tok::l_paren:
0451 Close = tok::r_paren;
0452 Consumer = &Parser::ConsumeParen;
0453 break;
0454
0455 case tok::l_square:
0456 Close = tok::r_square;
0457 Consumer = &Parser::ConsumeBracket;
0458 break;
0459 }
0460 }
0461
0462 SourceLocation getOpenLocation() const { return LOpen; }
0463 SourceLocation getCloseLocation() const { return LClose; }
0464 SourceRange getRange() const { return SourceRange(LOpen, LClose); }
0465
0466 bool consumeOpen() {
0467 if (!P.Tok.is(Kind))
0468 return true;
0469
0470 if (getDepth() < P.getLangOpts().BracketDepth) {
0471 LOpen = (P.*Consumer)();
0472 return false;
0473 }
0474
0475 return diagnoseOverflow();
0476 }
0477
0478 bool expectAndConsume(unsigned DiagID = diag::err_expected,
0479 const char *Msg = "",
0480 tok::TokenKind SkipToTok = tok::unknown);
0481 bool consumeClose() {
0482 if (P.Tok.is(Close)) {
0483 LClose = (P.*Consumer)();
0484 return false;
0485 } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) {
0486 SourceLocation SemiLoc = P.ConsumeToken();
0487 P.Diag(SemiLoc, diag::err_unexpected_semi)
0488 << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc));
0489 LClose = (P.*Consumer)();
0490 return false;
0491 }
0492
0493 return diagnoseMissingClose();
0494 }
0495 void skipToEnd();
0496 };
0497 }
0498
0499 #endif