1 /**
2 * @file braces.cpp
3 * Adds or removes braces.
4 *
5 * @author Ben Gardner
6 * @license GPL v2+
7 */
8
9 #include "braces.h"
10
11 #include "calculate_closing_brace_position.h"
12 #include "combine_tools.h"
13 #include "newlines.h"
14 #include "prototypes.h"
15
16 constexpr static auto LCURRENT = LBR;
17
18 using namespace uncrustify;
19
20 using std::vector;
21
22
23 //! Converts a single brace into a virtual brace
24 static void convert_brace(chunk_t *br);
25
26
27 //! Converts a single virtual brace into a real brace
28 static void convert_vbrace(chunk_t *br);
29
30
31 static void convert_vbrace_to_brace(void);
32
33
34 //! Go backwards to honor brace newline removal limits
35 static void examine_braces(void);
36
37
38 /**
39 * Step forward and count the number of semi colons at the current level.
40 * Abort if more than 1 or if we enter a preprocessor
41 */
42 static void examine_brace(chunk_t *bopen);
43
44
45 static void move_case_break(void);
46
47
48 static void mod_case_brace(void);
49
50
51 static void mod_full_brace_if_chain(void);
52
53
54 /**
55 * Checks to see if the braces can be removed.
56 * - less than a certain length
57 * - doesn't mess up if/else stuff
58 */
59 static bool can_remove_braces(chunk_t *bopen);
60
61
62 /**
63 * Checks to see if the virtual braces should be converted to real braces.
64 * - over a certain length
65 *
66 * @param vbopen Virtual Brace Open chunk
67 *
68 * @return true (convert to real braces) or false (leave alone)
69 */
70 static bool should_add_braces(chunk_t *vbopen);
71
72
73 /**
74 * Collect the text into txt that contains the full tag name.
75 * Mainly for collecting namespace 'a.b.c' or function 'foo::bar()' names.
76 */
77 static void append_tag_name(unc_text &txt, chunk_t *pc);
78
79
80 //! Remove the case brace, if allowable.
81 static chunk_t *mod_case_brace_remove(chunk_t *br_open);
82
83
84 //! Add the case brace, if allowable.
85 static chunk_t *mod_case_brace_add(chunk_t *cl_colon);
86
87
88 /**
89 * Traverse the if chain and see if all can be removed
90 *
91 * @param br_start chunk pointing to opening brace of if clause
92 */
93 static void process_if_chain(chunk_t *br_start);
94
95
96 /**
97 * Check if parenthesis pair that comes before a brace spans multiple lines
98 *
99 *
100 * @param brace the brace chunk whose predecessing parenthesis will be checked
101 *
102 * @pre the brace chunk cannot be a nullptr,
103 * it needs to be of type CT_BRACE_OPEN or CT_BRACE_CLOSE,
104 * its parent type needs to be one of this types:
105 * CT_IF, CT_ELSEIF, CT_FOR, CT_USING_STMT, CT_WHILE,
106 * CT_FUNC_CLASS_DEF, CT_FUNC_DEF
107 *
108 * @return false: if preconditions are not met,
109 * if an error occurs while counting the newline between the
110 * parenthesis or
111 * when no newlines are found between the parenthesis
112 */
paren_multiline_before_brace(chunk_t * brace)113 static bool paren_multiline_before_brace(chunk_t *brace)
114 {
115 if ( brace == nullptr
116 || ( chunk_is_not_token(brace, CT_BRACE_OPEN)
117 && chunk_is_not_token(brace, CT_BRACE_CLOSE))
118 || ( get_chunk_parent_type(brace) != CT_IF
119 && get_chunk_parent_type(brace) != CT_ELSEIF
120 && get_chunk_parent_type(brace) != CT_FOR
121 && get_chunk_parent_type(brace) != CT_USING_STMT
122 && get_chunk_parent_type(brace) != CT_WHILE
123 && get_chunk_parent_type(brace) != CT_FUNC_CLASS_DEF
124 && get_chunk_parent_type(brace) != CT_FUNC_DEF))
125 {
126 return(false);
127 }
128 const auto paren_t = CT_SPAREN_CLOSE;
129
130 // find parenthesis pair of the if/for/while/...
131 auto paren_close = chunk_get_prev_type(brace, paren_t, brace->level, scope_e::ALL);
132 auto paren_open = chunk_skip_to_match_rev(paren_close, scope_e::ALL);
133
134 if ( paren_close == nullptr
135 || paren_open == nullptr
136 || paren_close == brace
137 || paren_open == paren_close)
138 {
139 return(false);
140 }
141 // determine number of lines in the parenthesis pair spans
142 auto nl_count = size_t{};
143 const auto ret_flag = newlines_between(paren_open, paren_close, nl_count);
144
145 if (!ret_flag)
146 {
147 LOG_FMT(LERR, "%s(%d): newlines_between error\n", __func__, __LINE__);
148 return(false);
149 }
150 // nl_count = 0 -> 1 line
151 return(nl_count > 0);
152 }
153
154
do_braces(void)155 void do_braces(void)
156 {
157 LOG_FUNC_ENTRY();
158 // Mark one-liners
159 // Issue #2232 put this at the beginning
160 chunk_t *pc = chunk_get_head();
161
162 while ((pc = chunk_get_next_ncnnl(pc)) != nullptr)
163 {
164 if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
165 && chunk_is_not_token(pc, CT_VBRACE_OPEN))
166 {
167 continue;
168 }
169 chunk_t *br_open = pc;
170 const c_token_t brc_type = c_token_t(pc->type + 1); // corresponds to closing type
171 // Detect empty bodies
172 chunk_t *tmp = chunk_get_next_ncnnl(pc);
173
174 if (chunk_is_token(tmp, brc_type))
175 {
176 chunk_flags_set(br_open, PCF_EMPTY_BODY);
177 chunk_flags_set(tmp, PCF_EMPTY_BODY);
178 }
179 // Scan for the brace close or a newline
180 tmp = br_open;
181
182 while ((tmp = chunk_get_next_nc(tmp)) != nullptr)
183 {
184 if (chunk_is_newline(tmp))
185 {
186 break;
187 }
188
189 if ( chunk_is_token(tmp, brc_type)
190 && br_open->level == tmp->level)
191 {
192 flag_series(br_open, tmp, PCF_ONE_LINER);
193 break;
194 }
195 }
196 }
197 log_rule_B("mod_full_brace_if_chain");
198 log_rule_B("mod_full_brace_if_chain_only");
199
200 if ( options::mod_full_brace_if_chain()
201 || options::mod_full_brace_if_chain_only())
202 {
203 mod_full_brace_if_chain();
204 }
205 log_rule_B("mod_full_brace_if");
206 log_rule_B("mod_full_brace_do");
207 log_rule_B("mod_full_brace_for");
208 log_rule_B("mod_full_brace_using");
209 log_rule_B("mod_full_brace_while");
210
211 if ((options::mod_full_brace_if() |
212 options::mod_full_brace_do() |
213 options::mod_full_brace_for() |
214 options::mod_full_brace_using() |
215 options::mod_full_brace_while()) & IARF_REMOVE)
216 {
217 examine_braces();
218 }
219 // convert vbraces if needed
220 log_rule_B("mod_full_brace_if");
221 log_rule_B("mod_full_brace_do");
222 log_rule_B("mod_full_brace_for");
223 log_rule_B("mod_full_brace_function");
224 log_rule_B("mod_full_brace_using");
225 log_rule_B("mod_full_brace_while");
226
227 if ((options::mod_full_brace_if() |
228 options::mod_full_brace_do() |
229 options::mod_full_brace_for() |
230 options::mod_full_brace_function() |
231 options::mod_full_brace_using() |
232 options::mod_full_brace_while()) & IARF_ADD)
233 {
234 convert_vbrace_to_brace();
235 }
236 log_rule_B("mod_case_brace");
237
238 if (options::mod_case_brace() != IARF_IGNORE)
239 {
240 mod_case_brace();
241 }
242 log_rule_B("mod_move_case_break");
243
244 if (options::mod_move_case_break())
245 {
246 move_case_break();
247 }
248 } // do_braces
249
250
examine_braces(void)251 static void examine_braces(void)
252 {
253 LOG_FUNC_ENTRY();
254
255 log_rule_B("mod_full_brace_nl_block_rem_mlcond");
256 const auto multiline_block = options::mod_full_brace_nl_block_rem_mlcond();
257
258 log_rule_B("mod_full_brace_if");
259 log_rule_B("mod_full_brace_do");
260 log_rule_B("mod_full_brace_for");
261 log_rule_B("mod_full_brace_using");
262 log_rule_B("mod_full_brace_while");
263
264 for (auto pc = chunk_get_tail(); pc != nullptr;)
265 {
266 auto prev = chunk_get_prev_type(pc, CT_BRACE_OPEN, -1);
267
268 if ( chunk_is_token(pc, CT_BRACE_OPEN)
269 && !pc->flags.test(PCF_IN_PREPROC)
270 && ( ( ( get_chunk_parent_type(pc) == CT_IF
271 || get_chunk_parent_type(pc) == CT_ELSE
272 || get_chunk_parent_type(pc) == CT_ELSEIF)
273 && options::mod_full_brace_if() == IARF_REMOVE)
274 || ( get_chunk_parent_type(pc) == CT_DO
275 && options::mod_full_brace_do() == IARF_REMOVE)
276 || ( get_chunk_parent_type(pc) == CT_FOR
277 && options::mod_full_brace_for() == IARF_REMOVE)
278 || ( get_chunk_parent_type(pc) == CT_USING_STMT
279 && options::mod_full_brace_using() == IARF_REMOVE)
280 || ( get_chunk_parent_type(pc) == CT_WHILE
281 && options::mod_full_brace_while() == IARF_REMOVE)))
282 {
283 if ( multiline_block
284 && paren_multiline_before_brace(pc))
285 {
286 pc = prev;
287 continue;
288 }
289 examine_brace(pc);
290 }
291 pc = prev;
292 }
293 } // examine_braces
294
295
should_add_braces(chunk_t * vbopen)296 static bool should_add_braces(chunk_t *vbopen)
297 {
298 LOG_FUNC_ENTRY();
299 log_rule_B("mod_full_brace_nl");
300 const size_t nl_max = options::mod_full_brace_nl();
301
302 if (nl_max == 0)
303 {
304 return(false);
305 }
306 LOG_FMT(LBRDEL, "%s(%d): start on %zu:\n",
307 __func__, __LINE__, vbopen->orig_line);
308
309 size_t nl_count = 0;
310
311 chunk_t *pc = nullptr;
312
313 for (pc = chunk_get_next_nc(vbopen, scope_e::PREPROC);
314 (pc != nullptr && pc->level > vbopen->level);
315 pc = chunk_get_next_nc(pc, scope_e::PREPROC))
316 {
317 if (chunk_is_newline(pc))
318 {
319 nl_count += pc->nl_count;
320 }
321 }
322
323 if ( pc != nullptr
324 && nl_count > nl_max
325 && vbopen->pp_level == pc->pp_level)
326 {
327 LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
328 __func__, __LINE__, nl_max);
329 return(true);
330 }
331 return(false);
332 }
333
334
can_remove_braces(chunk_t * bopen)335 static bool can_remove_braces(chunk_t *bopen)
336 {
337 LOG_FUNC_ENTRY();
338 LOG_FMT(LBRDEL, "%s(%d): start on line %zu:\n",
339 __func__, __LINE__, bopen->orig_line);
340
341 // Cannot remove braces inside a preprocessor
342 if (bopen->flags.test(PCF_IN_PREPROC))
343 {
344 return(false);
345 }
346 chunk_t *pc = chunk_get_next_ncnnl(bopen, scope_e::PREPROC);
347
348 if (chunk_is_token(pc, CT_BRACE_CLOSE))
349 {
350 // Can't remove empty statement
351 return(false);
352 }
353 const size_t level = bopen->level + 1;
354
355 log_rule_B("mod_full_brace_nl");
356 const size_t nl_max = options::mod_full_brace_nl();
357 chunk_t *prev = nullptr;
358
359 size_t semi_count = 0;
360 bool hit_semi = false;
361 size_t nl_count = 0;
362 size_t if_count = 0;
363 int br_count = 0;
364
365 pc = chunk_get_next_nc(bopen, scope_e::ALL);
366 LOG_FMT(LBRDEL, "%s(%d): - begin with token '%s', orig_line is %zu, orig_col is %zu\n",
367 __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
368
369 while ( pc != nullptr
370 && pc->level >= level)
371 {
372 LOG_FMT(LBRDEL, "%s(%d): test token '%s', orig_line is %zu, orig_col is %zu\n",
373 __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
374
375 if (pc->flags.test(PCF_IN_PREPROC))
376 {
377 // Cannot remove braces that contain a preprocessor
378 return(false);
379 }
380
381 if (chunk_is_newline(pc))
382 {
383 nl_count += pc->nl_count;
384
385 if ( nl_max > 0
386 && nl_count > nl_max)
387 {
388 LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
389 __func__, __LINE__, nl_max);
390 return(false);
391 }
392 }
393 else
394 {
395 if (chunk_is_token(pc, CT_BRACE_OPEN))
396 {
397 br_count++;
398 }
399 else if (chunk_is_token(pc, CT_BRACE_CLOSE))
400 {
401 if (br_count == 0)
402 {
403 fprintf(stderr, "%s(%d): br_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
404 __func__, __LINE__, pc->orig_line, pc->orig_col);
405 log_flush(true);
406 exit(EX_SOFTWARE);
407 }
408 br_count--;
409
410 if (pc->level == level)
411 {
412 // mean a statement in a braces { stmt; }
413 // as a statement with a semicolon { stmt; };
414 ++semi_count;
415 hit_semi = true;
416 }
417 }
418 else if ( ( chunk_is_token(pc, CT_IF)
419 || chunk_is_token(pc, CT_ELSEIF))
420 && br_count == 0)
421 {
422 if_count++;
423 }
424
425 if (pc->level == level)
426 {
427 if ( semi_count > 0
428 && hit_semi)
429 {
430 // should have bailed due to close brace level drop
431 LOG_FMT(LBRDEL, "%s(%d): no close brace\n", __func__, __LINE__);
432 return(false);
433 }
434 LOG_FMT(LBRDEL, "%s(%d): text() '%s', orig_line is %zu, semi_count is %zu\n",
435 __func__, __LINE__, pc->text(), pc->orig_line, semi_count);
436
437 if (chunk_is_token(pc, CT_ELSE))
438 {
439 LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
440 __func__, __LINE__, pc->text(), pc->orig_line);
441 return(false);
442 }
443
444 if ( chunk_is_semicolon(pc)
445 || chunk_is_token(pc, CT_IF)
446 || chunk_is_token(pc, CT_ELSEIF)
447 || chunk_is_token(pc, CT_FOR)
448 || chunk_is_token(pc, CT_DO)
449 || chunk_is_token(pc, CT_WHILE)
450 || chunk_is_token(pc, CT_USING_STMT)
451 || ( chunk_is_token(pc, CT_BRACE_OPEN)
452 && chunk_is_token(prev, CT_FPAREN_CLOSE)))
453 {
454 hit_semi |= chunk_is_semicolon(pc);
455
456 if (++semi_count > 1)
457 {
458 LOG_FMT(LBRDEL, "%s(%d): bailed on %zu because of '%s' on line %zu\n",
459 __func__, __LINE__, bopen->orig_line, pc->text(), pc->orig_line);
460 return(false);
461 }
462 }
463 }
464 }
465 prev = pc;
466 pc = chunk_get_next_nc(pc);
467 }
468
469 if (pc == nullptr)
470 {
471 LOG_FMT(LBRDEL, "%s(%d): pc is nullptr\n", __func__, __LINE__);
472 return(false);
473 }
474
475 if ( chunk_is_token(pc, CT_BRACE_CLOSE)
476 && get_chunk_parent_type(pc) == CT_IF)
477 {
478 chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
479 chunk_t *tmp_prev = chunk_get_prev_ncnnl(pc, scope_e::PREPROC);
480
481 if ( chunk_is_token(next, CT_ELSE)
482 && ( chunk_is_token(tmp_prev, CT_BRACE_CLOSE)
483 || chunk_is_token(tmp_prev, CT_VBRACE_CLOSE))
484 && get_chunk_parent_type(tmp_prev) == CT_IF)
485 {
486 LOG_FMT(LBRDEL, "%s(%d): - bailed on '%s'[%s] on line %zu due to 'if' and 'else' sequence\n",
487 __func__, __LINE__, get_token_name(pc->type), get_token_name(get_chunk_parent_type(pc)),
488 pc->orig_line);
489 return(false);
490 }
491 }
492 LOG_FMT(LBRDEL, "%s(%d): - end on '%s' on line %zu. if_count is %zu semi_count is %zu\n",
493 __func__, __LINE__, get_token_name(pc->type), pc->orig_line, if_count, semi_count);
494
495 return( chunk_is_token(pc, CT_BRACE_CLOSE)
496 && pc->pp_level == bopen->pp_level);
497 } // can_remove_braces
498
499
examine_brace(chunk_t * bopen)500 static void examine_brace(chunk_t *bopen)
501 {
502 LOG_FUNC_ENTRY();
503 LOG_FMT(LBRDEL, "%s(%d): start on orig_line %zu, bopen->level is %zu\n",
504 __func__, __LINE__, bopen->orig_line, bopen->level);
505
506 const size_t level = bopen->level + 1;
507
508 log_rule_B("mod_full_brace_nl");
509 const size_t nl_max = options::mod_full_brace_nl();
510
511 chunk_t *prev = nullptr;
512 size_t semi_count = 0;
513 bool hit_semi = false;
514 size_t nl_count = 0;
515 size_t if_count = 0;
516 int br_count = 0;
517
518 chunk_t *pc = chunk_get_next_nc(bopen);
519
520 while ( pc != nullptr
521 && pc->level >= level)
522 {
523 if (chunk_is_token(pc, CT_NEWLINE))
524 {
525 LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, <Newline>\n",
526 __func__, __LINE__, pc->orig_line, pc->orig_col);
527 }
528 else
529 {
530 LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, text() '%s'\n",
531 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());
532 }
533
534 if (pc->flags.test(PCF_IN_PREPROC))
535 {
536 // Cannot remove braces that contain a preprocessor
537 LOG_FMT(LBRDEL, "%s(%d): PREPROC\n", __func__, __LINE__);
538 return;
539 }
540
541 if (chunk_is_newline(pc))
542 {
543 nl_count += pc->nl_count;
544
545 if ( nl_max > 0
546 && nl_count > nl_max)
547 {
548 LOG_FMT(LBRDEL, "%s(%d): exceeded %zu newlines\n",
549 __func__, __LINE__, nl_max);
550 return;
551 }
552 }
553 else
554 {
555 LOG_FMT(LBRDEL, "%s(%d): for pc->text() '%s', pc->level is %zu, bopen->level is %zu\n",
556 __func__, __LINE__, pc->text(), pc->level, bopen->level);
557
558 if ( chunk_is_token(pc, CT_BRACE_OPEN)
559 && pc->level == bopen->level)
560 {
561 br_count++;
562 LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->level is %zu, bopen->level is %zu\n",
563 __func__, __LINE__, br_count, pc->level, bopen->level);
564 }
565 else if ( chunk_is_token(pc, CT_BRACE_CLOSE)
566 && pc->level == bopen->level)
567 {
568 if (br_count == 0)
569 {
570 fprintf(stderr, "%s(%d): br_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
571 __func__, __LINE__, pc->orig_line, pc->orig_col);
572 log_flush(true);
573 exit(EX_SOFTWARE);
574 }
575 br_count--;
576 LOG_FMT(LBRDEL, "%s(%d): br_count is now %d, pc->level is %zu, bopen->level is %zu\n",
577 __func__, __LINE__, br_count, pc->level, bopen->level);
578
579 if (br_count == 0)
580 {
581 chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
582
583 if ( next == nullptr
584 || chunk_is_not_token(next, CT_BRACE_CLOSE))
585 {
586 LOG_FMT(LBRDEL, "%s(%d): junk after close brace\n", __func__, __LINE__);
587 return;
588 }
589 }
590 }
591 else if ( ( chunk_is_token(pc, CT_IF)
592 || chunk_is_token(pc, CT_ELSEIF))
593 && br_count == 0)
594 {
595 if_count++;
596 }
597 LOG_FMT(LBRDEL, "%s(%d): pc->level is %zu, level is %zu\n",
598 __func__, __LINE__, pc->level, level);
599
600 if (pc->level == level)
601 {
602 if ( semi_count > 0
603 && hit_semi)
604 {
605 // should have bailed due to close brace level drop
606 LOG_FMT(LBRDEL, "%s(%d): no close brace\n", __func__, __LINE__);
607 return;
608 }
609 LOG_FMT(LBRDEL, "%s(%d): text() '%s', orig_line is %zu, semi_count is %zu\n",
610 __func__, __LINE__, pc->text(), pc->orig_line, semi_count);
611
612 if (chunk_is_token(pc, CT_ELSE))
613 {
614 LOG_FMT(LBRDEL, "%s(%d): bailed on '%s' on line %zu\n",
615 __func__, __LINE__, pc->text(), pc->orig_line);
616 return;
617 }
618
619 if (prev != nullptr)
620 {
621 LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', prev->text '%s', prev->type %s\n",
622 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), prev->text(), get_token_name(prev->type));
623 }
624 else
625 {
626 LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', prev is nullptr\n",
627 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());
628 }
629 LOG_FMT(LBRDEL, "%s(%d): for pc->text() '%s', pc->level is %zu, bopen->level is %zu\n",
630 __func__, __LINE__, pc->text(), pc->level, bopen->level);
631
632 if ( chunk_is_semicolon(pc)
633 || chunk_is_token(pc, CT_IF)
634 || chunk_is_token(pc, CT_ELSEIF)
635 || chunk_is_token(pc, CT_FOR)
636 || chunk_is_token(pc, CT_DO)
637 || chunk_is_token(pc, CT_WHILE)
638 || chunk_is_token(pc, CT_SWITCH)
639 || chunk_is_token(pc, CT_USING_STMT)
640 || ( chunk_is_token(pc, CT_BRACE_OPEN)
641 && pc->level == bopen->level)) // Issue #1758
642 {
643 LOG_FMT(LBRDEL, "%s(%d): pc->text() '%s', orig_line is %zu, orig_col is %zu, level is %zu\n",
644 __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, pc->level);
645 hit_semi |= chunk_is_semicolon(pc);
646 semi_count++;
647 LOG_FMT(LBRDEL, "%s(%d): semi_count is %zu\n",
648 __func__, __LINE__, semi_count);
649
650 if (semi_count > 1)
651 {
652 LOG_FMT(LBRDEL, "%s(%d): bailed on %zu because of '%s' on line %zu\n",
653 __func__, __LINE__, bopen->orig_line, pc->text(), pc->orig_line);
654 return;
655 }
656 }
657 }
658 }
659 prev = pc;
660 pc = chunk_get_next(pc); // Issue #1907
661 }
662
663 if (pc == nullptr)
664 {
665 LOG_FMT(LBRDEL, "%s(%d): pc is nullptr\n", __func__, __LINE__);
666 return;
667 }
668 LOG_FMT(LBRDEL, "%s(%d): - end on '%s' on line %zu. if_count is %zu, semi_count is %zu\n",
669 __func__, __LINE__, get_token_name(pc->type), pc->orig_line, if_count, semi_count);
670
671 if (chunk_is_token(pc, CT_BRACE_CLOSE))
672 {
673 chunk_t *next = chunk_get_next_ncnnl(pc);
674
675 if (next != nullptr)
676 {
677 while (chunk_is_token(next, CT_VBRACE_CLOSE))
678 {
679 next = chunk_get_next_ncnnl(next);
680 }
681
682 if (next != nullptr)
683 {
684 LOG_FMT(LBRDEL, "%s(%d): orig_line is %zu, orig_col is %zu, next is '%s'\n",
685 __func__, __LINE__, next->orig_line, next->orig_col, get_token_name(next->type));
686 }
687
688 if ( if_count > 0
689 && ( chunk_is_token(next, CT_ELSE)
690 || chunk_is_token(next, CT_ELSEIF)))
691 {
692 LOG_FMT(LBRDEL, "%s(%d): bailed on because 'else' is next and %zu ifs\n",
693 __func__, __LINE__, if_count);
694 return;
695 }
696 }
697 LOG_FMT(LBRDEL, "%s(%d): semi_count is %zu\n",
698 __func__, __LINE__, semi_count);
699
700 if (semi_count > 0)
701 {
702 LOG_FMT(LBRDEL, "%s(%d): bopen->parent_type is %s\n",
703 __func__, __LINE__, get_token_name(get_chunk_parent_type(bopen)));
704
705 if (get_chunk_parent_type(bopen) == CT_ELSE)
706 {
707 chunk_t *tmp_next = chunk_get_next_ncnnl(bopen);
708
709 if (chunk_is_token(tmp_next, CT_IF))
710 {
711 chunk_t *tmp_prev = chunk_get_prev_ncnnl(bopen);
712 LOG_FMT(LBRDEL, "%s(%d): else-if removing braces on line %zu and %zu\n",
713 __func__, __LINE__, bopen->orig_line, pc->orig_line);
714
715 chunk_del(bopen);
716 chunk_del(pc);
717 newline_del_between(tmp_prev, tmp_next);
718
719 log_rule_B("nl_else_if");
720
721 if (options::nl_else_if() & IARF_ADD)
722 {
723 newline_add_between(tmp_prev, tmp_next);
724 }
725 return;
726 }
727 }
728 // we have a pair of braces with only 1 statement inside
729 LOG_FMT(LBRDEL, "%s(%d): we have a pair of braces with only 1 statement inside\n",
730 __func__, __LINE__);
731 LOG_FMT(LBRDEL, "%s(%d): removing braces on line %zu and %zu\n",
732 __func__, __LINE__, bopen->orig_line, pc->orig_line);
733 convert_brace(bopen);
734 convert_brace(pc);
735 }
736 else
737 {
738 LOG_FMT(LBRDEL, "%s(%d): empty statement\n", __func__, __LINE__);
739 }
740 }
741 else
742 {
743 LOG_FMT(LBRDEL, "%s(%d): not a close brace? - '%s'\n",
744 __func__, __LINE__, pc->text());
745 }
746 } // examine_brace
747
748
convert_brace(chunk_t * br)749 static void convert_brace(chunk_t *br)
750 {
751 LOG_FUNC_ENTRY();
752
753 if ( br == nullptr
754 || br->flags.test(PCF_KEEP_BRACE))
755 {
756 return;
757 }
758 chunk_t *tmp;
759
760 if (chunk_is_token(br, CT_BRACE_OPEN))
761 {
762 set_chunk_type(br, CT_VBRACE_OPEN);
763 br->str.clear();
764 tmp = chunk_get_prev(br);
765
766 if (tmp == nullptr)
767 {
768 return;
769 }
770 }
771 else if (chunk_is_token(br, CT_BRACE_CLOSE))
772 {
773 set_chunk_type(br, CT_VBRACE_CLOSE);
774 br->str.clear();
775 tmp = chunk_get_next(br);
776
777 if (tmp == nullptr)
778 {
779 return;
780 }
781 }
782 else
783 {
784 return;
785 }
786
787 if (chunk_is_newline(tmp))
788 {
789 if (tmp->nl_count > 1)
790 {
791 if (!br->flags.test(PCF_ONE_LINER)) // Issue #2232
792 {
793 if (tmp->nl_count == 0)
794 {
795 fprintf(stderr, "%s(%d): tmp->nl_count is ZERO, cannot be decremented, at line %zu, column %zu\n",
796 __func__, __LINE__, tmp->orig_line, tmp->orig_col);
797 log_flush(true);
798 exit(EX_SOFTWARE);
799 }
800 tmp->nl_count--;
801 LOG_FMT(LBRDEL, "%s(%d): tmp->nl_count is %zu\n",
802 __func__, __LINE__, tmp->nl_count);
803 }
804 }
805 else
806 {
807 // Issue #2219
808 // look for opening brace
809 chunk_t *brace = nullptr;
810
811 if (chunk_is_token(br, CT_VBRACE_OPEN))
812 {
813 brace = tmp;
814 }
815 else if (chunk_is_token(br, CT_VBRACE_CLOSE))
816 {
817 brace = chunk_skip_to_match_rev(br);
818
819 if (brace == nullptr)
820 {
821 brace = chunk_get_prev_type(br, CT_BRACE_OPEN, br->level);
822 }
823 }
824
825 if ( chunk_is_token(br, CT_VBRACE_OPEN)
826 || ( chunk_is_token(br, CT_VBRACE_CLOSE)
827 && brace->orig_line < tmp->orig_line))
828 {
829 if (chunk_safe_to_del_nl(tmp))
830 {
831 chunk_del(tmp);
832 }
833 }
834 }
835 }
836 } // convert_brace
837
838
convert_vbrace(chunk_t * vbr)839 static void convert_vbrace(chunk_t *vbr)
840 {
841 LOG_FUNC_ENTRY();
842
843 if (vbr == nullptr)
844 {
845 return;
846 }
847
848 if (chunk_is_token(vbr, CT_VBRACE_OPEN))
849 {
850 set_chunk_type(vbr, CT_BRACE_OPEN);
851 vbr->str = "{";
852
853 /*
854 * If the next chunk is a preprocessor, then move the open brace after the
855 * preprocessor.
856 */
857 chunk_t *tmp = chunk_get_next(vbr);
858
859 if (chunk_is_token(tmp, CT_PREPROC))
860 {
861 tmp = chunk_get_next(vbr, scope_e::PREPROC);
862 chunk_move_after(vbr, tmp);
863 newline_add_after(vbr);
864 }
865 }
866 else if (chunk_is_token(vbr, CT_VBRACE_CLOSE))
867 {
868 set_chunk_type(vbr, CT_BRACE_CLOSE);
869 vbr->str = "}";
870
871 /*
872 * If the next chunk is a comment, followed by a newline, then
873 * move the brace after the newline and add another newline after
874 * the close brace.
875 */
876 chunk_t *tmp = chunk_get_next(vbr);
877
878 if (chunk_is_comment(tmp))
879 {
880 tmp = chunk_get_next(tmp);
881
882 if (chunk_is_newline(tmp))
883 {
884 chunk_move_after(vbr, tmp);
885 newline_add_after(vbr);
886 }
887 }
888 }
889 } // convert_vbrace
890
891
convert_vbrace_to_brace(void)892 static void convert_vbrace_to_brace(void)
893 {
894 LOG_FUNC_ENTRY();
895
896 // Find every vbrace open
897 log_rule_B("mod_full_brace_if");
898 log_rule_B("mod_full_brace_if_chain");
899 log_rule_B("mod_full_brace_for");
900 log_rule_B("mod_full_brace_do");
901 log_rule_B("mod_full_brace_while");
902 log_rule_B("mod_full_brace_using");
903 log_rule_B("mod_full_brace_function");
904
905 for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc))
906 {
907 if (chunk_is_not_token(pc, CT_VBRACE_OPEN))
908 {
909 continue;
910 }
911 auto const in_preproc = pc->flags.test(PCF_IN_PREPROC);
912
913 if ( ( ( get_chunk_parent_type(pc) == CT_IF
914 || get_chunk_parent_type(pc) == CT_ELSE
915 || get_chunk_parent_type(pc) == CT_ELSEIF)
916 && (options::mod_full_brace_if() & IARF_ADD)
917 && !options::mod_full_brace_if_chain())
918 || ( get_chunk_parent_type(pc) == CT_FOR
919 && (options::mod_full_brace_for() & IARF_ADD))
920 || ( get_chunk_parent_type(pc) == CT_DO
921 && (options::mod_full_brace_do() & IARF_ADD))
922 || ( get_chunk_parent_type(pc) == CT_WHILE
923 && (options::mod_full_brace_while() & IARF_ADD))
924 || ( get_chunk_parent_type(pc) == CT_USING_STMT
925 && (options::mod_full_brace_using() & IARF_ADD))
926 || ( get_chunk_parent_type(pc) == CT_FUNC_DEF
927 && (options::mod_full_brace_function() & IARF_ADD)))
928 {
929 // Find the matching vbrace close
930 chunk_t *vbc = nullptr;
931 chunk_t *tmp = pc;
932
933 while ((tmp = chunk_get_next(tmp)) != nullptr)
934 {
935 if ( in_preproc
936 && !tmp->flags.test(PCF_IN_PREPROC))
937 {
938 // Can't leave a preprocessor
939 break;
940 }
941
942 if ( pc->brace_level == tmp->brace_level
943 && chunk_is_token(tmp, CT_VBRACE_CLOSE)
944 && get_chunk_parent_type(pc) == get_chunk_parent_type(tmp)
945 && ((tmp->flags & PCF_IN_PREPROC) == (pc->flags & PCF_IN_PREPROC)))
946 {
947 vbc = tmp;
948 break;
949 }
950 }
951
952 if (vbc == nullptr)
953 {
954 continue;
955 }
956 // if we found a corresponding virtual closing brace
957 convert_vbrace(pc); // convert both the opening
958 convert_vbrace(vbc); // and closing brace
959 }
960 }
961 } // convert_vbrace_to_brace
962
963
insert_comment_after(chunk_t * ref,c_token_t cmt_type,const unc_text & cmt_text)964 chunk_t *insert_comment_after(chunk_t *ref, c_token_t cmt_type,
965 const unc_text &cmt_text)
966 {
967 LOG_FUNC_ENTRY();
968
969 chunk_t new_cmt = *ref;
970
971 new_cmt.prev = nullptr;
972 new_cmt.next = nullptr;
973 new_cmt.flags = (ref->flags & PCF_COPY_FLAGS);
974 set_chunk_type(&new_cmt, cmt_type);
975 new_cmt.str.clear();
976
977 if (cmt_type == CT_COMMENT_CPP)
978 {
979 new_cmt.str.append("// ");
980 new_cmt.str.append(cmt_text);
981 }
982 else
983 {
984 if (chunk_is_token(ref, CT_PP_ELSE))
985 { // make test c/ 02501 stable
986 new_cmt.str.append(" ");
987 }
988 new_cmt.str.append("/* ");
989 new_cmt.str.append(cmt_text);
990 new_cmt.str.append(" */");
991 }
992 // TODO: expand comment type to cover other comment styles?
993
994 new_cmt.column = ref->column + ref->len() + 1;
995 new_cmt.orig_col = new_cmt.column;
996
997 return(chunk_add_after(&new_cmt, ref));
998 }
999
1000
append_tag_name(unc_text & txt,chunk_t * pc)1001 static void append_tag_name(unc_text &txt, chunk_t *pc)
1002 {
1003 LOG_FUNC_ENTRY();
1004 chunk_t *tmp = pc;
1005
1006 LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
1007 __func__, __LINE__, txt.c_str());
1008
1009 // step backwards over all a::b stuff
1010 while ((tmp = chunk_get_prev_ncnnl(tmp)) != nullptr)
1011 {
1012 if ( chunk_is_not_token(tmp, CT_DC_MEMBER)
1013 && chunk_is_not_token(tmp, CT_MEMBER))
1014 {
1015 break;
1016 }
1017 tmp = chunk_get_prev_ncnnl(tmp);
1018 pc = tmp;
1019
1020 if (!chunk_is_word(tmp))
1021 {
1022 break;
1023 }
1024 }
1025 txt += pc->str;
1026 LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
1027 __func__, __LINE__, txt.c_str());
1028
1029 while ((pc = chunk_get_next_ncnnl(pc)) != nullptr)
1030 {
1031 if ( chunk_is_not_token(pc, CT_DC_MEMBER)
1032 && chunk_is_not_token(pc, CT_MEMBER))
1033 {
1034 break;
1035 }
1036 txt += pc->str;
1037 LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
1038 __func__, __LINE__, txt.c_str());
1039 pc = chunk_get_next_ncnnl(pc);
1040
1041 if (pc != nullptr)
1042 {
1043 txt += pc->str;
1044 LOG_FMT(LMCB, "%s(%d): txt is '%s'\n",
1045 __func__, __LINE__, txt.c_str());
1046 }
1047 }
1048 } // append_tag_name
1049
1050
add_long_closebrace_comment(void)1051 void add_long_closebrace_comment(void)
1052 {
1053 LOG_FUNC_ENTRY();
1054 chunk_t *fcn_pc = nullptr;
1055 chunk_t *sw_pc = nullptr;
1056 chunk_t *ns_pc = nullptr;
1057 chunk_t *cl_pc = nullptr;
1058
1059 for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc))
1060 {
1061 if ( chunk_is_token(pc, CT_FUNC_DEF)
1062 || chunk_is_token(pc, CT_OC_MSG_DECL))
1063 {
1064 fcn_pc = pc;
1065 }
1066 else if (chunk_is_token(pc, CT_SWITCH))
1067 {
1068 // pointless, since it always has the text "switch"
1069 sw_pc = pc;
1070 }
1071 else if (chunk_is_token(pc, CT_NAMESPACE))
1072 {
1073 ns_pc = pc;
1074 }
1075 else if (chunk_is_token(pc, CT_CLASS))
1076 {
1077 cl_pc = pc;
1078 }
1079
1080 if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
1081 || pc->flags.test(PCF_IN_PREPROC))
1082 {
1083 continue;
1084 }
1085 chunk_t *br_open = pc;
1086 size_t nl_count = 0;
1087
1088 chunk_t *tmp = pc;
1089
1090 while ((tmp = chunk_get_next(tmp, scope_e::PREPROC)) != nullptr)
1091 {
1092 if (chunk_is_newline(tmp))
1093 {
1094 nl_count += tmp->nl_count;
1095 continue;
1096 }
1097
1098 // handle only matching closing braces, skip other chunks
1099 if ( tmp->level != br_open->level
1100 || chunk_is_not_token(tmp, CT_BRACE_CLOSE))
1101 {
1102 continue;
1103 }
1104 chunk_t *br_close = tmp;
1105
1106 tmp = chunk_get_next(tmp);
1107
1108 // check for a possible end semicolon
1109 if (chunk_is_token(tmp, CT_SEMICOLON))
1110 {
1111 // set br_close to the semi token,
1112 // as br_close is used to add the coment after it
1113 br_close = tmp;
1114 tmp = chunk_get_next(tmp);
1115 }
1116
1117 // make sure a newline follows in order to not overwrite an already
1118 // existring comment
1119 if ( tmp != nullptr
1120 && !chunk_is_newline(tmp))
1121 {
1122 break;
1123 }
1124 size_t nl_min = 0;
1125 chunk_t *tag_pc = nullptr;
1126 unc_text xstr;
1127
1128 if ( get_chunk_parent_type(br_open) == CT_FUNC_DEF
1129 || get_chunk_parent_type(br_open) == CT_OC_MSG_DECL)
1130 {
1131 log_rule_B("mod_add_long_function_closebrace_comment");
1132 nl_min = options::mod_add_long_function_closebrace_comment();
1133 tag_pc = fcn_pc;
1134
1135 if (tag_pc != nullptr)
1136 {
1137 append_tag_name(xstr, tag_pc);
1138 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1139 __func__, __LINE__, xstr.c_str());
1140 }
1141 }
1142 else if ( get_chunk_parent_type(br_open) == CT_SWITCH
1143 && sw_pc != nullptr)
1144 {
1145 log_rule_B("mod_add_long_switch_closebrace_comment");
1146 nl_min = options::mod_add_long_switch_closebrace_comment();
1147 tag_pc = sw_pc;
1148 xstr = sw_pc->str;
1149 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1150 __func__, __LINE__, xstr.c_str());
1151 }
1152 else if ( get_chunk_parent_type(br_open) == CT_NAMESPACE
1153 && ns_pc != nullptr)
1154 {
1155 log_rule_B("mod_add_long_namespace_closebrace_comment");
1156 nl_min = options::mod_add_long_namespace_closebrace_comment();
1157 tag_pc = ns_pc;
1158 xstr = tag_pc->str; // add 'namespace' to the string
1159 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1160 __func__, __LINE__, xstr.c_str());
1161
1162 // next chunk, normally is going to be the namespace name
1163 // append it with a space to generate "namespace xyz"
1164 chunk_t *tmp_next = chunk_get_next_ncnnl(tag_pc);
1165
1166 if (chunk_is_not_token(tmp_next, CT_BRACE_OPEN)) // anonymous namespace -> ignore
1167 {
1168 xstr.append(" ");
1169 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1170 __func__, __LINE__, xstr.c_str());
1171 append_tag_name(xstr, tmp_next);
1172 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1173 __func__, __LINE__, xstr.c_str());
1174 }
1175 }
1176 else if ( get_chunk_parent_type(br_open) == CT_CLASS
1177 && cl_pc != nullptr
1178 && ( !language_is_set(LANG_CPP) // proceed if not C++
1179 || chunk_is_token(br_close, CT_SEMICOLON))) // else a C++ class needs to end with a semicolon
1180 {
1181 log_rule_B("mod_add_long_class_closebrace_comment");
1182 nl_min = options::mod_add_long_class_closebrace_comment();
1183 tag_pc = cl_pc;
1184 xstr = tag_pc->str;
1185 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1186 __func__, __LINE__, xstr.c_str());
1187
1188 chunk_t *tmp_next = chunk_get_next(cl_pc);
1189
1190 if (tag_pc != nullptr)
1191 {
1192 xstr.append(" ");
1193 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1194 __func__, __LINE__, xstr.c_str());
1195 append_tag_name(xstr, tmp_next);
1196 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1197 __func__, __LINE__, xstr.c_str());
1198 }
1199 }
1200
1201 if ( nl_min > 0
1202 && nl_count >= nl_min
1203 && tag_pc != nullptr)
1204 {
1205 // use the comment style that fits to the selected language
1206 const c_token_t style = language_is_set(LANG_CPP | LANG_CS)
1207 ? CT_COMMENT_CPP : CT_COMMENT;
1208
1209 // Add a comment after the close brace
1210 LOG_FMT(LMCB, "%s(%d): xstr is '%s'\n",
1211 __func__, __LINE__, xstr.c_str());
1212 insert_comment_after(br_close, style, xstr);
1213 }
1214 break;
1215 }
1216 }
1217 } // add_long_closebrace_comment
1218
1219
move_case_break(void)1220 static void move_case_break(void)
1221 {
1222 LOG_FUNC_ENTRY();
1223 chunk_t *prev = nullptr;
1224
1225 for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc))
1226 {
1227 if ( chunk_is_token(pc, CT_BREAK)
1228 && chunk_is_token(prev, CT_BRACE_CLOSE)
1229 && get_chunk_parent_type(prev) == CT_CASE
1230 && chunk_is_newline(chunk_get_prev(pc))
1231 && chunk_is_newline(chunk_get_prev(prev)))
1232 {
1233 chunk_swap_lines(prev, pc);
1234 }
1235 prev = pc;
1236 }
1237 }
1238
1239
mod_case_brace_remove(chunk_t * br_open)1240 static chunk_t *mod_case_brace_remove(chunk_t *br_open)
1241 {
1242 LOG_FUNC_ENTRY();
1243 LOG_FMT(LMCB, "%s(%d): line %zu",
1244 __func__, __LINE__, br_open->orig_line);
1245
1246 // Find the matching brace close
1247 chunk_t *next = chunk_get_next_ncnnl(br_open, scope_e::PREPROC);
1248 chunk_t *br_close = chunk_get_next_type(br_open, CT_BRACE_CLOSE, br_open->level, scope_e::PREPROC);
1249
1250 if (br_close == nullptr)
1251 {
1252 LOG_FMT(LMCB, "%s(%d): - no close\n", __func__, __LINE__);
1253 return(next);
1254 }
1255 // Make sure 'break', 'return', 'goto', 'case' or '}' is after the close brace
1256 chunk_t *pc = chunk_get_next_ncnnl(br_close, scope_e::PREPROC);
1257
1258 if ( pc == nullptr
1259 || ( chunk_is_not_token(pc, CT_BREAK)
1260 && chunk_is_not_token(pc, CT_RETURN)
1261 && chunk_is_not_token(pc, CT_CASE)
1262 && chunk_is_not_token(pc, CT_GOTO)
1263 && chunk_is_not_token(pc, CT_BRACE_CLOSE)))
1264 {
1265 LOG_FMT(LMCB, "%s(%d): - after '%s'\n",
1266 __func__, __LINE__, (pc == nullptr) ? "<null>" : get_token_name(pc->type));
1267 return(next);
1268 }
1269
1270 // scan to make sure there are no definitions at brace level between braces
1271 for (chunk_t *tmp_pc = br_open;
1272 tmp_pc != br_close;
1273 tmp_pc = chunk_get_next_ncnnl(tmp_pc, scope_e::PREPROC))
1274 {
1275 if ( tmp_pc->level == (br_open->level + 1)
1276 && tmp_pc->flags.test(PCF_VAR_DEF))
1277 {
1278 LOG_FMT(LMCB, "%s(%d): - vardef on line %zu: '%s'\n",
1279 __func__, __LINE__, tmp_pc->orig_line, pc->text());
1280 return(next);
1281 }
1282 }
1283
1284 LOG_FMT(LMCB, "%s(%d): - removing braces on lines %zu and %zu\n",
1285 __func__, __LINE__, br_open->orig_line, br_close->orig_line);
1286
1287 for (chunk_t *tmp_pc = br_open;
1288 tmp_pc != br_close;
1289 tmp_pc = chunk_get_next_ncnnl(tmp_pc, scope_e::PREPROC))
1290 {
1291 if (tmp_pc->brace_level == 0)
1292 {
1293 fprintf(stderr, "%s(%d): tmp_pc->brace_level is ZERO, cannot be decremented, at line %zu, column %zu\n",
1294 __func__, __LINE__, tmp_pc->orig_line, tmp_pc->orig_col);
1295 log_flush(true);
1296 exit(EX_SOFTWARE);
1297 }
1298 tmp_pc->brace_level--;
1299
1300 if (tmp_pc->level == 0)
1301 {
1302 fprintf(stderr, "%s(%d): tmp_pc->level is ZERO, cannot be decremented, at line %zu, column %zu\n",
1303 __func__, __LINE__, tmp_pc->orig_line, tmp_pc->orig_col);
1304 log_flush(true);
1305 exit(EX_SOFTWARE);
1306 }
1307 tmp_pc->level--;
1308 }
1309
1310 next = chunk_get_prev(br_open, scope_e::PREPROC);
1311
1312 chunk_del(br_open);
1313 chunk_del(br_close);
1314
1315 return(chunk_get_next(next, scope_e::PREPROC));
1316 } // mod_case_brace_remove
1317
1318
mod_case_brace_add(chunk_t * cl_colon)1319 static chunk_t *mod_case_brace_add(chunk_t *cl_colon)
1320 {
1321 LOG_FUNC_ENTRY();
1322 LOG_FMT(LMCB, "%s(%d): orig_line %zu, orig_col is %zu\n",
1323 __func__, __LINE__, cl_colon->orig_line, cl_colon->orig_col);
1324
1325 chunk_t *pc = cl_colon;
1326 chunk_t *last = nullptr;
1327 // look for the case token to the colon
1328 chunk_t *cas_ = chunk_get_prev_type(cl_colon, CT_CASE, cl_colon->level);
1329 // look for the parent
1330 chunk_t *swit = cas_->parent;
1331 // look for the opening brace of the switch
1332 chunk_t *open = chunk_get_next_type(swit, CT_BRACE_OPEN, swit->level);
1333 // look for the closing brace of the switch
1334 chunk_t *clos = chunk_skip_to_match(open);
1335
1336 // find the end of the case-block
1337 while ((pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC)) != nullptr)
1338 {
1339 LOG_FMT(LMCB, "%s(%d): text() is '%s', orig_line %zu, orig_col is %zu, pp_level is %zu\n",
1340 __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, pc->pp_level);
1341
1342 if (pc->level == cl_colon->level)
1343 {
1344 if (chunk_is_token(pc, CT_CASE))
1345 {
1346 LOG_FMT(LMCB, "%s(%d): text() is '%s', orig_line %zu, orig_col is %zu\n",
1347 __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
1348 last = calculate_closing_brace_position(cl_colon, pc);
1349 break;
1350 }
1351 }
1352 else if (pc->level == cl_colon->level - 1)
1353 {
1354 if (pc == clos)
1355 {
1356 LOG_FMT(LMCB, "%s(%d): text() is '%s', orig_line %zu, orig_col is %zu\n",
1357 __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
1358 // end of switch is reached
1359 last = calculate_closing_brace_position(cl_colon, pc);
1360 LOG_FMT(LMCB, "%s(%d): last->text() is '%s', orig_line %zu, orig_col is %zu\n",
1361 __func__, __LINE__, last->text(), last->orig_line, last->orig_col);
1362 break;
1363 }
1364 }
1365 }
1366
1367 if (last == nullptr)
1368 {
1369 LOG_FMT(LMCB, "%s(%d): - last is nullptr\n", __func__, __LINE__);
1370 chunk_t *next = chunk_get_next_ncnnl(cl_colon, scope_e::PREPROC);
1371 return(next);
1372 }
1373 LOG_FMT(LMCB, "%s(%d): last->text() is '%s', orig_line %zu, orig_col is %zu\n",
1374 __func__, __LINE__, last->text(), last->orig_line, last->orig_col);
1375 LOG_FMT(LMCB, "%s(%d): adding braces after '%s' on line %zu\n",
1376 __func__, __LINE__, cl_colon->text(), cl_colon->orig_line);
1377
1378 chunk_t chunk;
1379
1380 set_chunk_type(&chunk, CT_BRACE_OPEN);
1381 set_chunk_parent(&chunk, CT_CASE);
1382 chunk.orig_line = cl_colon->orig_line;
1383 chunk.orig_col = cl_colon->orig_col;
1384 chunk.level = cl_colon->level;
1385 chunk.pp_level = cl_colon->pp_level;
1386 chunk.brace_level = cl_colon->brace_level;
1387 chunk.flags = pc->flags & PCF_COPY_FLAGS;
1388 chunk.str = "{";
1389 chunk_t *br_open = chunk_add_after(&chunk, cl_colon);
1390
1391 set_chunk_type(&chunk, CT_BRACE_CLOSE);
1392 chunk.orig_line = last->orig_line;
1393 chunk.orig_col = last->orig_col;
1394 chunk.str = "}";
1395 chunk_t *br_close = chunk_add_after(&chunk, last);
1396
1397 for (pc = chunk_get_next(br_open, scope_e::PREPROC);
1398 pc != br_close;
1399 pc = chunk_get_next(pc, scope_e::PREPROC))
1400 {
1401 pc->level++;
1402 pc->brace_level++;
1403 }
1404
1405 return(br_open);
1406 } // mod_case_brace_add
1407
1408
mod_case_brace(void)1409 static void mod_case_brace(void)
1410 {
1411 LOG_FUNC_ENTRY();
1412
1413 chunk_t *pc = chunk_get_head();
1414
1415 // Make sure to start outside of a preprocessor line (see issue #3366)
1416 if (chunk_is_preproc(pc))
1417 {
1418 pc = chunk_get_next_ncnnlnp(pc);
1419 }
1420
1421 while (pc != nullptr)
1422 {
1423 chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
1424
1425 if (next == nullptr)
1426 {
1427 return;
1428 }
1429 log_rule_B("mod_case_brace");
1430
1431 if ( options::mod_case_brace() == IARF_REMOVE
1432 && chunk_is_token(pc, CT_BRACE_OPEN)
1433 && get_chunk_parent_type(pc) == CT_CASE)
1434 {
1435 log_rule_B("mod_case_brace - add");
1436 pc = mod_case_brace_remove(pc);
1437 }
1438 else if ( (options::mod_case_brace() & IARF_ADD)
1439 && chunk_is_token(pc, CT_CASE_COLON)
1440 && chunk_is_not_token(next, CT_BRACE_OPEN)
1441 && chunk_is_not_token(next, CT_BRACE_CLOSE)
1442 && chunk_is_not_token(next, CT_CASE))
1443 {
1444 log_rule_B("mod_case_brace - remove");
1445 pc = mod_case_brace_add(pc);
1446 }
1447 else
1448 {
1449 pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
1450 }
1451 }
1452 } // mod_case_brace
1453
1454
process_if_chain(chunk_t * br_start)1455 static void process_if_chain(chunk_t *br_start)
1456 {
1457 LOG_FUNC_ENTRY();
1458 LOG_FMT(LBRCH, "%s(%d): if starts on line %zu, orig_col is %zu.\n",
1459 __func__, __LINE__, br_start->orig_line, br_start->orig_col);
1460
1461 vector<chunk_t *> braces;
1462
1463 braces.reserve(16);
1464
1465 bool must_have_braces = false;
1466
1467 chunk_t *pc = br_start;
1468
1469 while (pc != nullptr)
1470 {
1471 LOG_FMT(LBRCH, "%s(%d): pc->text() is '%s', orig_line is %zu, orig_col is %zu.\n",
1472 __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col);
1473
1474 if (chunk_is_token(pc, CT_BRACE_OPEN))
1475 {
1476 const bool tmp = can_remove_braces(pc);
1477 LOG_FMT(LBRCH, "%s(%d): braces.size() is %zu, line is %zu, - can%s remove %s\n",
1478 __func__, __LINE__, braces.size(), pc->orig_line, tmp ? "" : "not",
1479 get_token_name(pc->type));
1480
1481 if (!tmp)
1482 {
1483 must_have_braces = true;
1484 }
1485 }
1486 else
1487 {
1488 const bool tmp = should_add_braces(pc);
1489
1490 if (tmp)
1491 {
1492 must_have_braces = true;
1493 }
1494 LOG_FMT(LBRCH, "%s(%d): braces.size() is %zu, line is %zu, - %s %s\n",
1495 __func__, __LINE__, braces.size(), pc->orig_line, tmp ? "should add" : "ignore",
1496 get_token_name(pc->type));
1497 }
1498 braces.push_back(pc);
1499 chunk_t *br_close = chunk_skip_to_match(pc, scope_e::PREPROC);
1500
1501 if (br_close == nullptr)
1502 {
1503 break;
1504 }
1505 braces.push_back(br_close);
1506
1507 pc = chunk_get_next_ncnnl(br_close, scope_e::PREPROC);
1508
1509 if ( pc == nullptr
1510 || chunk_is_not_token(pc, CT_ELSE))
1511 {
1512 break;
1513 }
1514 log_rule_B("mod_full_brace_if_chain_only");
1515
1516 if (options::mod_full_brace_if_chain_only())
1517 {
1518 // There is an 'else' - we want full braces.
1519 must_have_braces = true;
1520 }
1521 pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
1522
1523 if (chunk_is_token(pc, CT_ELSEIF))
1524 {
1525 while ( chunk_is_not_token(pc, CT_VBRACE_OPEN)
1526 && chunk_is_not_token(pc, CT_BRACE_OPEN))
1527 {
1528 pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC);
1529 }
1530 }
1531
1532 if (pc == nullptr)
1533 {
1534 break;
1535 }
1536
1537 if ( chunk_is_not_token(pc, CT_BRACE_OPEN)
1538 && chunk_is_not_token(pc, CT_VBRACE_OPEN))
1539 {
1540 break;
1541 }
1542 }
1543
1544 if (must_have_braces)
1545 {
1546 LOG_FMT(LBRCH, "%s(%d): add braces on lines[%zu]:",
1547 __func__, __LINE__, braces.size());
1548
1549 const auto ite = braces.rend();
1550
1551 for (auto itc = braces.rbegin(); itc != ite; ++itc)
1552 {
1553 const auto brace = *itc;
1554
1555 chunk_flags_set(brace, PCF_KEEP_BRACE);
1556
1557 if ( chunk_is_token(brace, CT_VBRACE_OPEN)
1558 || chunk_is_token(brace, CT_VBRACE_CLOSE))
1559 {
1560 LOG_FMT(LBRCH, "%s(%d): %zu",
1561 __func__, __LINE__, brace->orig_line);
1562 convert_vbrace(brace);
1563 }
1564 else
1565 {
1566 LOG_FMT(LBRCH, "%s(%d): {%zu}",
1567 __func__, __LINE__, brace->orig_line);
1568 }
1569 }
1570
1571 LOG_FMT(LBRCH, "\n");
1572 }
1573 else if (options::mod_full_brace_if_chain())
1574 {
1575 log_rule_B("mod_full_brace_if_chain");
1576 LOG_FMT(LBRCH, "%s(%d): remove braces on lines[%zu]:\n",
1577 __func__, __LINE__, braces.size());
1578
1579 /*
1580 * This might run because either
1581 * mod_full_brace_if_chain or mod_full_brace_if_chain_only
1582 * is used.
1583 * We only want to remove braces if the first one is active.
1584 */
1585 log_rule_B("mod_full_brace_nl_block_rem_mlcond");
1586 const auto multiline_block = options::mod_full_brace_nl_block_rem_mlcond();
1587
1588 LOG_FMT(LBRCH, "%s(%d): remove braces on lines:\n", __func__, __LINE__);
1589
1590 // Issue #2229
1591 const auto ite = braces.end();
1592
1593 for (auto itc = braces.begin(); itc != ite; ++itc)
1594 {
1595 const auto brace = *itc;
1596
1597 if ( ( chunk_is_token(brace, CT_BRACE_OPEN)
1598 || chunk_is_token(brace, CT_BRACE_CLOSE))
1599 && (get_chunk_parent_type(brace) != CT_BRACED_INIT_LIST)
1600 && (multiline_block ? !paren_multiline_before_brace(brace) : true))
1601 {
1602 LOG_FMT(LBRCH, "%s(%d): brace->orig_line is %zu, brace->orig_col is %zu\n",
1603 __func__, __LINE__, brace->orig_line, brace->orig_col);
1604 convert_brace(brace);
1605 }
1606 else
1607 {
1608 LOG_FMT(LBRCH, "%s(%d): brace->orig_line is %zu, brace->orig_col is %zu\n",
1609 __func__, __LINE__, brace->orig_line, brace->orig_col);
1610 }
1611 }
1612 }
1613 } // process_if_chain
1614
1615
mod_full_brace_if_chain(void)1616 static void mod_full_brace_if_chain(void)
1617 {
1618 LOG_FUNC_ENTRY();
1619
1620 for (chunk_t *pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next(pc))
1621 {
1622 if ( ( chunk_is_token(pc, CT_BRACE_OPEN)
1623 || chunk_is_token(pc, CT_VBRACE_OPEN))
1624 && get_chunk_parent_type(pc) == CT_IF)
1625 {
1626 process_if_chain(pc);
1627 }
1628 }
1629 }
1630