1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #ifndef LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H |
15 | #define LLVM_CLANG_LIB_PARSE_RAIIOBJECTSFORPARSER_H |
16 | |
17 | #include "clang/Parse/ParseDiagnostic.h" |
18 | #include "clang/Parse/Parser.h" |
19 | #include "clang/Sema/DelayedDiagnostic.h" |
20 | #include "clang/Sema/ParsedTemplate.h" |
21 | #include "clang/Sema/Sema.h" |
22 | |
23 | namespace clang { |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | class SuppressAccessChecks { |
45 | Sema &S; |
46 | sema::DelayedDiagnosticPool DiagnosticPool; |
47 | Sema::ParsingDeclState State; |
48 | bool Active; |
49 | |
50 | public: |
51 | |
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 | } |
61 | SuppressAccessChecks(SuppressAccessChecks &&Other) |
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 | (0) . __assert_fail ("Active && \"trying to end an inactive suppression\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Parse/RAIIObjectsForParser.h", 69, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(Active && "trying to end an inactive suppression"); |
70 | S.PopParsingDeclaration(State, nullptr); |
71 | Active = false; |
72 | } |
73 | |
74 | void redelay() { |
75 | (0) . __assert_fail ("!Active && \"redelaying without having ended first\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Parse/RAIIObjectsForParser.h", 75, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Active && "redelaying without having ended first"); |
76 | if (!DiagnosticPool.pool_empty()) |
77 | S.redelayDiagnostics(DiagnosticPool); |
78 | assert(DiagnosticPool.pool_empty()); |
79 | } |
80 | |
81 | ~SuppressAccessChecks() { |
82 | if (Active) done(); |
83 | } |
84 | }; |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | class ParsingDeclRAIIObject { |
91 | Sema &Actions; |
92 | sema::DelayedDiagnosticPool DiagnosticPool; |
93 | Sema::ParsingDeclState State; |
94 | bool Popped; |
95 | |
96 | ParsingDeclRAIIObject(const ParsingDeclRAIIObject &) = delete; |
97 | void operator=(const ParsingDeclRAIIObject &) = delete; |
98 | |
99 | public: |
100 | enum NoParent_t { NoParent }; |
101 | ParsingDeclRAIIObject(Parser &P, NoParent_t _) |
102 | : Actions(P.getActions()), DiagnosticPool(nullptr) { |
103 | push(); |
104 | } |
105 | |
106 | |
107 | ParsingDeclRAIIObject(Parser &P, |
108 | const sema::DelayedDiagnosticPool *parentPool) |
109 | : Actions(P.getActions()), DiagnosticPool(parentPool) { |
110 | push(); |
111 | } |
112 | |
113 | |
114 | |
115 | |
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 | |
126 | ~ParsingDeclRAIIObject() { |
127 | abort(); |
128 | } |
129 | |
130 | sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() { |
131 | return DiagnosticPool; |
132 | } |
133 | const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { |
134 | return DiagnosticPool; |
135 | } |
136 | |
137 | |
138 | void reset() { |
139 | abort(); |
140 | push(); |
141 | } |
142 | |
143 | |
144 | |
145 | void abort() { |
146 | pop(nullptr); |
147 | } |
148 | |
149 | void complete(Decl *D) { |
150 | (0) . __assert_fail ("!Popped && \"ParsingDeclaration has already been popped!\"", "/home/seafit/code_projects/clang_source/clang/include/clang/Parse/RAIIObjectsForParser.h", 150, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(!Popped && "ParsingDeclaration has already been popped!"); |
151 | pop(D); |
152 | } |
153 | |
154 | |
155 | |
156 | void abortAndRemember() { |
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 | |
175 | class ParsingDeclSpec : public DeclSpec { |
176 | ParsingDeclRAIIObject ParsingRAII; |
177 | |
178 | public: |
179 | ParsingDeclSpec(Parser &P) |
180 | : DeclSpec(P.getAttrFactory()), |
181 | ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {} |
182 | ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) |
183 | : DeclSpec(P.getAttrFactory()), |
184 | ParsingRAII(P, RAII) {} |
185 | |
186 | const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const { |
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 | |
200 | class ParsingDeclarator : public Declarator { |
201 | ParsingDeclRAIIObject ParsingRAII; |
202 | |
203 | public: |
204 | ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, DeclaratorContext C) |
205 | : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { |
206 | } |
207 | |
208 | const ParsingDeclSpec &getDeclSpec() const { |
209 | return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec()); |
210 | } |
211 | |
212 | ParsingDeclSpec &getMutableDeclSpec() const { |
213 | return const_cast<ParsingDeclSpec&>(getDeclSpec()); |
214 | } |
215 | |
216 | void clear() { |
217 | Declarator::clear(); |
218 | ParsingRAII.reset(); |
219 | } |
220 | |
221 | void complete(Decl *D) { |
222 | ParsingRAII.complete(D); |
223 | } |
224 | }; |
225 | |
226 | |
227 | class ParsingFieldDeclarator : public FieldDeclarator { |
228 | ParsingDeclRAIIObject ParsingRAII; |
229 | |
230 | public: |
231 | ParsingFieldDeclarator(Parser &P, const ParsingDeclSpec &DS) |
232 | : FieldDeclarator(DS), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { |
233 | } |
234 | |
235 | const ParsingDeclSpec &getDeclSpec() const { |
236 | return static_cast<const ParsingDeclSpec&>(D.getDeclSpec()); |
237 | } |
238 | |
239 | ParsingDeclSpec &getMutableDeclSpec() const { |
240 | return const_cast<ParsingDeclSpec&>(getDeclSpec()); |
241 | } |
242 | |
243 | void complete(Decl *D) { |
244 | ParsingRAII.complete(D); |
245 | } |
246 | }; |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | class ExtensionRAIIObject { |
253 | ExtensionRAIIObject(const ExtensionRAIIObject &) = delete; |
254 | void operator=(const ExtensionRAIIObject &) = delete; |
255 | |
256 | DiagnosticsEngine &Diags; |
257 | public: |
258 | ExtensionRAIIObject(DiagnosticsEngine &diags) : Diags(diags) { |
259 | Diags.IncrementAllExtensionsSilenced(); |
260 | } |
261 | |
262 | ~ExtensionRAIIObject() { |
263 | Diags.DecrementAllExtensionsSilenced(); |
264 | } |
265 | }; |
266 | |
267 | |
268 | |
269 | |
270 | class ColonProtectionRAIIObject { |
271 | Parser &P; |
272 | bool OldVal; |
273 | public: |
274 | ColonProtectionRAIIObject(Parser &p, bool Value = true) |
275 | : P(p), OldVal(P.ColonIsSacred) { |
276 | P.ColonIsSacred = Value; |
277 | } |
278 | |
279 | |
280 | |
281 | void restore() { |
282 | P.ColonIsSacred = OldVal; |
283 | } |
284 | |
285 | ~ColonProtectionRAIIObject() { |
286 | restore(); |
287 | } |
288 | }; |
289 | |
290 | |
291 | |
292 | class GreaterThanIsOperatorScope { |
293 | bool &GreaterThanIsOperator; |
294 | bool OldGreaterThanIsOperator; |
295 | public: |
296 | GreaterThanIsOperatorScope(bool >IO, bool Val) |
297 | : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) { |
298 | GreaterThanIsOperator = Val; |
299 | } |
300 | |
301 | ~GreaterThanIsOperatorScope() { |
302 | GreaterThanIsOperator = OldGreaterThanIsOperator; |
303 | } |
304 | }; |
305 | |
306 | class InMessageExpressionRAIIObject { |
307 | bool &InMessageExpression; |
308 | bool OldValue; |
309 | |
310 | public: |
311 | InMessageExpressionRAIIObject(Parser &P, bool Value) |
312 | : InMessageExpression(P.InMessageExpression), |
313 | OldValue(P.InMessageExpression) { |
314 | InMessageExpression = Value; |
315 | } |
316 | |
317 | ~InMessageExpressionRAIIObject() { |
318 | InMessageExpression = OldValue; |
319 | } |
320 | }; |
321 | |
322 | |
323 | |
324 | class ParenBraceBracketBalancer { |
325 | Parser &P; |
326 | unsigned short ParenCount, BracketCount, BraceCount; |
327 | public: |
328 | ParenBraceBracketBalancer(Parser &p) |
329 | : P(p), ParenCount(p.ParenCount), BracketCount(p.BracketCount), |
330 | BraceCount(p.BraceCount) { } |
331 | |
332 | ~ParenBraceBracketBalancer() { |
333 | P.AngleBrackets.clear(P); |
334 | P.ParenCount = ParenCount; |
335 | P.BracketCount = BracketCount; |
336 | P.BraceCount = BraceCount; |
337 | } |
338 | }; |
339 | |
340 | class PoisonSEHIdentifiersRAIIObject { |
341 | PoisonIdentifierRAIIObject Ident_AbnormalTermination; |
342 | PoisonIdentifierRAIIObject Ident_GetExceptionCode; |
343 | PoisonIdentifierRAIIObject Ident_GetExceptionInfo; |
344 | PoisonIdentifierRAIIObject Ident__abnormal_termination; |
345 | PoisonIdentifierRAIIObject Ident__exception_code; |
346 | PoisonIdentifierRAIIObject Ident__exception_info; |
347 | PoisonIdentifierRAIIObject Ident___abnormal_termination; |
348 | PoisonIdentifierRAIIObject Ident___exception_code; |
349 | PoisonIdentifierRAIIObject Ident___exception_info; |
350 | public: |
351 | PoisonSEHIdentifiersRAIIObject(Parser &Self, bool NewValue) |
352 | : Ident_AbnormalTermination(Self.Ident_AbnormalTermination, NewValue), |
353 | Ident_GetExceptionCode(Self.Ident_GetExceptionCode, NewValue), |
354 | Ident_GetExceptionInfo(Self.Ident_GetExceptionInfo, NewValue), |
355 | Ident__abnormal_termination(Self.Ident__abnormal_termination, NewValue), |
356 | Ident__exception_code(Self.Ident__exception_code, NewValue), |
357 | Ident__exception_info(Self.Ident__exception_info, NewValue), |
358 | Ident___abnormal_termination(Self.Ident___abnormal_termination, NewValue), |
359 | Ident___exception_code(Self.Ident___exception_code, NewValue), |
360 | Ident___exception_info(Self.Ident___exception_info, NewValue) { |
361 | } |
362 | }; |
363 | |
364 | |
365 | |
366 | class BalancedDelimiterTracker : public GreaterThanIsOperatorScope { |
367 | Parser& P; |
368 | tok::TokenKind Kind, Close, FinalToken; |
369 | SourceLocation (Parser::*Consumer)(); |
370 | SourceLocation LOpen, LClose; |
371 | |
372 | unsigned short &getDepth() { |
373 | switch (Kind) { |
374 | case tok::l_brace: return P.BraceCount; |
375 | case tok::l_square: return P.BracketCount; |
376 | case tok::l_paren: return P.ParenCount; |
377 | default: llvm_unreachable("Wrong token kind"); |
378 | } |
379 | } |
380 | |
381 | bool diagnoseOverflow(); |
382 | bool diagnoseMissingClose(); |
383 | |
384 | public: |
385 | BalancedDelimiterTracker(Parser& p, tok::TokenKind k, |
386 | tok::TokenKind FinalToken = tok::semi) |
387 | : GreaterThanIsOperatorScope(p.GreaterThanIsOperator, true), |
388 | P(p), Kind(k), FinalToken(FinalToken) |
389 | { |
390 | switch (Kind) { |
391 | default: llvm_unreachable("Unexpected balanced token"); |
392 | case tok::l_brace: |
393 | Close = tok::r_brace; |
394 | Consumer = &Parser::ConsumeBrace; |
395 | break; |
396 | case tok::l_paren: |
397 | Close = tok::r_paren; |
398 | Consumer = &Parser::ConsumeParen; |
399 | break; |
400 | |
401 | case tok::l_square: |
402 | Close = tok::r_square; |
403 | Consumer = &Parser::ConsumeBracket; |
404 | break; |
405 | } |
406 | } |
407 | |
408 | SourceLocation getOpenLocation() const { return LOpen; } |
409 | SourceLocation getCloseLocation() const { return LClose; } |
410 | SourceRange getRange() const { return SourceRange(LOpen, LClose); } |
411 | |
412 | bool consumeOpen() { |
413 | if (!P.Tok.is(Kind)) |
414 | return true; |
415 | |
416 | if (getDepth() < P.getLangOpts().BracketDepth) { |
417 | LOpen = (P.*Consumer)(); |
418 | return false; |
419 | } |
420 | |
421 | return diagnoseOverflow(); |
422 | } |
423 | |
424 | bool expectAndConsume(unsigned DiagID = diag::err_expected, |
425 | const char *Msg = "", |
426 | tok::TokenKind SkipToTok = tok::unknown); |
427 | bool consumeClose() { |
428 | if (P.Tok.is(Close)) { |
429 | LClose = (P.*Consumer)(); |
430 | return false; |
431 | } else if (P.Tok.is(tok::semi) && P.NextToken().is(Close)) { |
432 | SourceLocation SemiLoc = P.ConsumeToken(); |
433 | P.Diag(SemiLoc, diag::err_unexpected_semi) |
434 | << Close << FixItHint::CreateRemoval(SourceRange(SemiLoc, SemiLoc)); |
435 | LClose = (P.*Consumer)(); |
436 | return false; |
437 | } |
438 | |
439 | return diagnoseMissingClose(); |
440 | } |
441 | void skipToEnd(); |
442 | }; |
443 | |
444 | |
445 | |
446 | class DestroyTemplateIdAnnotationsRAIIObj { |
447 | SmallVectorImpl<TemplateIdAnnotation *> &Container; |
448 | |
449 | public: |
450 | DestroyTemplateIdAnnotationsRAIIObj( |
451 | SmallVectorImpl<TemplateIdAnnotation *> &Container) |
452 | : Container(Container) {} |
453 | |
454 | ~DestroyTemplateIdAnnotationsRAIIObj() { |
455 | for (SmallVectorImpl<TemplateIdAnnotation *>::iterator I = |
456 | Container.begin(), |
457 | E = Container.end(); |
458 | I != E; ++I) |
459 | (*I)->Destroy(); |
460 | Container.clear(); |
461 | } |
462 | }; |
463 | } |
464 | |
465 | #endif |
466 | |