Avoid assuming input corresponds to valid source code (PR c/97131).
[gcc.git] / gcc / c-family / c-indentation.c
1 /* Implementation of -Wmisleading-indentation
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "c-common.h"
25 #include "c-indentation.h"
26 #include "selftest.h"
27 #include "diagnostic.h"
28
29 /* Round up VIS_COLUMN to nearest tab stop. */
30
31 static unsigned int
32 next_tab_stop (unsigned int vis_column, unsigned int tab_width)
33 {
34 vis_column = ((vis_column + tab_width) / tab_width) * tab_width;
35 return vis_column;
36 }
37
38 /* Convert libcpp's notion of a column (a 1-based char count) to
39 the "visual column" (0-based column, respecting tabs), by reading the
40 relevant line.
41
42 Returns true if a conversion was possible, writing the result to OUT,
43 otherwise returns false. If FIRST_NWS is not NULL, then write to it
44 the visual column corresponding to the first non-whitespace character
45 on the line (up to or before EXPLOC). */
46
47 static bool
48 get_visual_column (expanded_location exploc, location_t loc,
49 unsigned int *out,
50 unsigned int *first_nws,
51 unsigned int tab_width)
52 {
53 /* PR c++/68819: if the column number is zero, we presumably
54 had a location_t > LINE_MAP_MAX_LOCATION_WITH_COLS, and so
55 we have no column information.
56 Act as if no conversion was possible, triggering the
57 error-handling path in the caller. */
58 if (!exploc.column)
59 {
60 static bool issued_note = false;
61 if (!issued_note)
62 {
63 /* Notify the user the first time this happens. */
64 issued_note = true;
65 inform (loc,
66 "%<-Wmisleading-indentation%> is disabled from this point"
67 " onwards, since column-tracking was disabled due to"
68 " the size of the code/headers");
69 if (!flag_large_source_files)
70 inform (loc,
71 "adding %<-flarge-source-files%> will allow for more"
72 " column-tracking support, at the expense of compilation"
73 " time and memory");
74 }
75 return false;
76 }
77
78 char_span line = location_get_source_line (exploc.file, exploc.line);
79 if (!line)
80 return false;
81 if ((size_t)exploc.column > line.length ())
82 return false;
83 unsigned int vis_column = 0;
84 for (int i = 1; i < exploc.column; i++)
85 {
86 unsigned char ch = line[i - 1];
87
88 if (first_nws != NULL && !ISSPACE (ch))
89 {
90 *first_nws = vis_column;
91 first_nws = NULL;
92 }
93
94 if (ch == '\t')
95 vis_column = next_tab_stop (vis_column, tab_width);
96 else
97 vis_column++;
98 }
99
100 if (first_nws != NULL)
101 *first_nws = vis_column;
102
103 *out = vis_column;
104 return true;
105 }
106
107 /* Attempt to determine the first non-whitespace character in line LINE_NUM
108 of source line FILE.
109
110 If this is possible, return true and write its "visual column" to
111 *FIRST_NWS.
112 Otherwise, return false, leaving *FIRST_NWS untouched. */
113
114 static bool
115 get_first_nws_vis_column (const char *file, int line_num,
116 unsigned int *first_nws,
117 unsigned int tab_width)
118 {
119 gcc_assert (first_nws);
120
121 char_span line = location_get_source_line (file, line_num);
122 if (!line)
123 return false;
124 unsigned int vis_column = 0;
125 for (size_t i = 1; i < line.length (); i++)
126 {
127 unsigned char ch = line[i - 1];
128
129 if (!ISSPACE (ch))
130 {
131 *first_nws = vis_column;
132 return true;
133 }
134
135 if (ch == '\t')
136 vis_column = next_tab_stop (vis_column, tab_width);
137 else
138 vis_column++;
139 }
140
141 /* No non-whitespace characters found. */
142 return false;
143 }
144
145 /* Determine if there is an unindent/outdent between
146 BODY_EXPLOC and NEXT_STMT_EXPLOC, to ensure that we don't
147 issue a warning for cases like the following:
148
149 (1) Preprocessor logic
150
151 if (flagA)
152 foo ();
153 ^ BODY_EXPLOC
154 #if SOME_CONDITION_THAT_DOES_NOT_HOLD
155 if (flagB)
156 #endif
157 bar ();
158 ^ NEXT_STMT_EXPLOC
159
160 "bar ();" is visually aligned below "foo ();" and
161 is (as far as the parser sees) the next token, but
162 this isn't misleading to a human reader.
163
164 (2) Empty macro with bad indentation
165
166 In the following, the
167 "if (i > 0)"
168 is poorly indented, and ought to be on the same column as
169 "engine_ref_debug(e, 0, -1)"
170 However, it is not misleadingly indented, due to the presence
171 of that macro.
172
173 #define engine_ref_debug(X, Y, Z)
174
175 if (locked)
176 i = foo (0);
177 else
178 i = foo (1);
179 engine_ref_debug(e, 0, -1)
180 if (i > 0)
181 return 1;
182
183 Return true if such an unindent/outdent is detected. */
184
185 static bool
186 detect_intervening_unindent (const char *file,
187 int body_line,
188 int next_stmt_line,
189 unsigned int vis_column,
190 unsigned int tab_width)
191 {
192 gcc_assert (file);
193 gcc_assert (next_stmt_line > body_line);
194
195 for (int line = body_line + 1; line < next_stmt_line; line++)
196 {
197 unsigned int line_vis_column;
198 if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width))
199 if (line_vis_column < vis_column)
200 return true;
201 }
202
203 /* Not found. */
204 return false;
205 }
206
207
208 /* Helper function for warn_for_misleading_indentation; see
209 description of that function below. */
210
211 static bool
212 should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
213 const token_indent_info &body_tinfo,
214 const token_indent_info &next_tinfo)
215 {
216 /* Don't attempt to compare indentation if #line or # 44 "file"-style
217 directives are present, suggesting generated code.
218
219 All bets are off if these are present: the file that the #line
220 directive could have an entirely different coding layout to C/C++
221 (e.g. .md files).
222
223 To determine if a #line is present, in theory we could look for a
224 map with reason == LC_RENAME_VERBATIM. However, if there has
225 subsequently been a long line requiring a column number larger than
226 that representable by the original LC_RENAME_VERBATIM map, then
227 we'll have a map with reason LC_RENAME.
228 Rather than attempting to search all of the maps for a
229 LC_RENAME_VERBATIM, instead we have libcpp set a flag whenever one
230 is seen, and we check for the flag here.
231 */
232 if (line_table->seen_line_directive)
233 return false;
234
235 /* We can't usefully warn about do-while and switch statements since the
236 bodies of these statements are always explicitly delimited at both ends,
237 so control flow is quite obvious. */
238 if (guard_tinfo.keyword == RID_DO
239 || guard_tinfo.keyword == RID_SWITCH)
240 return false;
241
242 /* If the token following the body is a close brace or an "else"
243 then while indentation may be sloppy, there is not much ambiguity
244 about control flow, e.g.
245
246 if (foo) <- GUARD
247 bar (); <- BODY
248 else baz (); <- NEXT
249
250 {
251 while (foo) <- GUARD
252 bar (); <- BODY
253 } <- NEXT
254 baz ();
255 */
256 enum cpp_ttype next_tok_type = next_tinfo.type;
257 if (next_tok_type == CPP_CLOSE_BRACE
258 || next_tinfo.keyword == RID_ELSE)
259 return false;
260
261 /* Likewise, if the body of the guard is a compound statement then control
262 flow is quite visually explicit regardless of the code's possibly poor
263 indentation, e.g.
264
265 while (foo) <- GUARD
266 { <- BODY
267 bar ();
268 }
269 baz (); <- NEXT
270
271 Things only get muddy when the body of the guard does not have
272 braces, e.g.
273
274 if (foo) <- GUARD
275 bar (); <- BODY
276 baz (); <- NEXT
277 */
278 enum cpp_ttype body_type = body_tinfo.type;
279 if (body_type == CPP_OPEN_BRACE)
280 return false;
281
282 /* Don't warn here about spurious semicolons. */
283 if (next_tok_type == CPP_SEMICOLON)
284 return false;
285
286 location_t guard_loc = guard_tinfo.location;
287 location_t body_loc = body_tinfo.location;
288 location_t next_stmt_loc = next_tinfo.location;
289
290 /* Resolve each token location to the respective macro expansion
291 point that produced the token. */
292 if (linemap_location_from_macro_expansion_p (line_table, guard_loc))
293 guard_loc = linemap_resolve_location (line_table, guard_loc,
294 LRK_MACRO_EXPANSION_POINT, NULL);
295 if (linemap_location_from_macro_expansion_p (line_table, body_loc))
296 body_loc = linemap_resolve_location (line_table, body_loc,
297 LRK_MACRO_EXPANSION_POINT, NULL);
298 if (linemap_location_from_macro_expansion_p (line_table, next_stmt_loc))
299 next_stmt_loc = linemap_resolve_location (line_table, next_stmt_loc,
300 LRK_MACRO_EXPANSION_POINT, NULL);
301
302 /* When all three tokens are produced from a single macro expansion, we
303 instead consider their loci inside that macro's definition. */
304 if (guard_loc == body_loc && body_loc == next_stmt_loc)
305 {
306 const line_map *guard_body_common_map
307 = first_map_in_common (line_table,
308 guard_tinfo.location, body_tinfo.location,
309 &guard_loc, &body_loc);
310 const line_map *body_next_common_map
311 = first_map_in_common (line_table,
312 body_tinfo.location, next_tinfo.location,
313 &body_loc, &next_stmt_loc);
314
315 /* Punt on complicated nesting of macros. */
316 if (guard_body_common_map != body_next_common_map)
317 return false;
318
319 guard_loc = linemap_resolve_location (line_table, guard_loc,
320 LRK_MACRO_DEFINITION_LOCATION, NULL);
321 body_loc = linemap_resolve_location (line_table, body_loc,
322 LRK_MACRO_DEFINITION_LOCATION, NULL);
323 next_stmt_loc = linemap_resolve_location (line_table, next_stmt_loc,
324 LRK_MACRO_DEFINITION_LOCATION,
325 NULL);
326 }
327
328 /* Give up if the loci are not all distinct. */
329 if (guard_loc == body_loc || body_loc == next_stmt_loc)
330 return false;
331
332 expanded_location body_exploc = expand_location (body_loc);
333 expanded_location next_stmt_exploc = expand_location (next_stmt_loc);
334 expanded_location guard_exploc = expand_location (guard_loc);
335
336 const unsigned int tab_width = global_dc->tabstop;
337
338 /* They must be in the same file. */
339 if (next_stmt_exploc.file != body_exploc.file)
340 return false;
341
342 /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
343 the location of the guard.
344
345 Cases where we want to issue a warning:
346
347 if (flag)
348 foo (); bar ();
349 ^ WARN HERE
350
351 if (flag) foo (); bar ();
352 ^ WARN HERE
353
354
355 if (flag) ; {
356 ^ WARN HERE
357
358 if (flag)
359 ; {
360 ^ WARN HERE
361
362 Cases where we don't want to issue a warning:
363
364 various_code (); if (flag) foo (); bar (); more_code ();
365 ^ DON'T WARN HERE. */
366 if (next_stmt_exploc.line == body_exploc.line)
367 {
368 if (guard_exploc.file != body_exploc.file)
369 return true;
370 if (guard_exploc.line < body_exploc.line)
371 /* The guard is on a line before a line that contains both
372 the body and the next stmt. */
373 return true;
374 else if (guard_exploc.line == body_exploc.line)
375 {
376 /* They're all on the same line. */
377 gcc_assert (guard_exploc.file == next_stmt_exploc.file);
378 gcc_assert (guard_exploc.line == next_stmt_exploc.line);
379 unsigned int guard_vis_column;
380 unsigned int guard_line_first_nws;
381 if (!get_visual_column (guard_exploc, guard_loc,
382 &guard_vis_column,
383 &guard_line_first_nws, tab_width))
384 return false;
385 /* Heuristic: only warn if the guard is the first thing
386 on its line. */
387 if (guard_vis_column == guard_line_first_nws)
388 return true;
389 }
390 }
391
392 /* If NEXT_STMT_LOC is on a line after BODY_LOC, consider
393 their relative locations, and of the guard.
394
395 Cases where we want to issue a warning:
396 if (flag)
397 foo ();
398 bar ();
399 ^ WARN HERE
400
401 Cases where we don't want to issue a warning:
402 if (flag)
403 foo ();
404 bar ();
405 ^ DON'T WARN HERE (autogenerated code?)
406
407 if (flagA)
408 foo ();
409 #if SOME_CONDITION_THAT_DOES_NOT_HOLD
410 if (flagB)
411 #endif
412 bar ();
413 ^ DON'T WARN HERE
414
415 if (flag)
416 ;
417 foo ();
418 ^ DON'T WARN HERE
419
420 #define emit
421 if (flag)
422 foo ();
423 emit bar ();
424 ^ DON'T WARN HERE
425
426 */
427 if (next_stmt_exploc.line > body_exploc.line)
428 {
429 /* Determine if GUARD_LOC and NEXT_STMT_LOC are aligned on the same
430 "visual column"... */
431 unsigned int next_stmt_vis_column;
432 unsigned int next_stmt_line_first_nws;
433 unsigned int body_vis_column;
434 unsigned int body_line_first_nws;
435 unsigned int guard_vis_column;
436 unsigned int guard_line_first_nws;
437 /* If we can't determine it, don't issue a warning. This is sometimes
438 the case for input files containing #line directives, and these
439 are often for autogenerated sources (e.g. from .md files), where
440 it's not clear that it's meaningful to look at indentation. */
441 if (!get_visual_column (next_stmt_exploc, next_stmt_loc,
442 &next_stmt_vis_column,
443 &next_stmt_line_first_nws, tab_width))
444 return false;
445 if (!get_visual_column (body_exploc, body_loc,
446 &body_vis_column,
447 &body_line_first_nws, tab_width))
448 return false;
449 if (!get_visual_column (guard_exploc, guard_loc,
450 &guard_vis_column,
451 &guard_line_first_nws, tab_width))
452 return false;
453
454 /* If the line where the next stmt starts has non-whitespace
455 on it before the stmt, then don't warn:
456 #define emit
457 if (flag)
458 foo ();
459 emit bar ();
460 ^ DON'T WARN HERE
461 (PR c/69122). */
462 if (next_stmt_line_first_nws < next_stmt_vis_column)
463 return false;
464
465 if ((body_type != CPP_SEMICOLON
466 && next_stmt_vis_column == body_vis_column)
467 /* As a special case handle the case where the body is a semicolon
468 that may be hidden by a preceding comment, e.g. */
469
470 // if (p)
471 // /* blah */;
472 // foo (1);
473
474 /* by looking instead at the column of the first non-whitespace
475 character on the body line. */
476 || (body_type == CPP_SEMICOLON
477 && body_exploc.line > guard_exploc.line
478 && body_line_first_nws != body_vis_column
479 && next_stmt_vis_column > guard_line_first_nws))
480 {
481 /* Don't warn if they are aligned on the same column
482 as the guard itself (suggesting autogenerated code that doesn't
483 bother indenting at all).
484 For "else" clauses, we consider the column of the first
485 non-whitespace character on the guard line instead of the column
486 of the actual guard token itself because it is more sensible.
487 Consider:
488
489 if (p) {
490 foo (1);
491 } else // GUARD
492 foo (2); // BODY
493 foo (3); // NEXT
494
495 and:
496
497 if (p)
498 foo (1);
499 } else // GUARD
500 foo (2); // BODY
501 foo (3); // NEXT
502
503 If we just used the column of the "else" token, we would warn on
504 the first example and not warn on the second. But we want the
505 exact opposite to happen: to not warn on the first example (which
506 is probably autogenerated) and to warn on the second (whose
507 indentation is misleading). Using the column of the first
508 non-whitespace character on the guard line makes that
509 happen. */
510 unsigned int guard_column = (guard_tinfo.keyword == RID_ELSE
511 ? guard_line_first_nws
512 : guard_vis_column);
513 if (guard_column == body_vis_column)
514 return false;
515
516 /* We may have something like:
517
518 if (p)
519 {
520 foo (1);
521 } else // GUARD
522 foo (2); // BODY
523 foo (3); // NEXT
524
525 in which case the columns are not aligned but the code is not
526 misleadingly indented. If the column of the body isn't indented
527 more than the guard line then don't warn. */
528 if (body_vis_column <= guard_line_first_nws)
529 return false;
530
531 /* Don't warn if there is an unindent between the two statements. */
532 int vis_column = MIN (next_stmt_vis_column, body_vis_column);
533 if (detect_intervening_unindent (body_exploc.file, body_exploc.line,
534 next_stmt_exploc.line,
535 vis_column, tab_width))
536 return false;
537
538 /* Otherwise, they are visually aligned: issue a warning. */
539 return true;
540 }
541
542 /* Also issue a warning for code having the form:
543
544 if (flag);
545 foo ();
546
547 while (flag);
548 {
549 ...
550 }
551
552 for (...);
553 {
554 ...
555 }
556
557 if (flag)
558 ;
559 else if (flag);
560 foo ();
561
562 where the semicolon at the end of each guard is most likely spurious.
563
564 But do not warn on:
565
566 for (..);
567 foo ();
568
569 where the next statement is aligned with the guard.
570 */
571 if (body_type == CPP_SEMICOLON)
572 {
573 if (body_exploc.line == guard_exploc.line)
574 {
575 if (next_stmt_vis_column > guard_line_first_nws
576 || (next_tok_type == CPP_OPEN_BRACE
577 && next_stmt_vis_column == guard_line_first_nws))
578 return true;
579 }
580 }
581 }
582
583 return false;
584 }
585
586 /* Return the string identifier corresponding to the given guard token. */
587
588 const char *
589 guard_tinfo_to_string (enum rid keyword)
590 {
591 switch (keyword)
592 {
593 case RID_FOR:
594 return "for";
595 case RID_ELSE:
596 return "else";
597 case RID_IF:
598 return "if";
599 case RID_WHILE:
600 return "while";
601 case RID_DO:
602 return "do";
603 case RID_SWITCH:
604 return "switch";
605 default:
606 gcc_unreachable ();
607 }
608 }
609
610 /* Called by the C/C++ frontends when we have a guarding statement at
611 GUARD_LOC containing a statement at BODY_LOC, where the block wasn't
612 written using braces, like this:
613
614 if (flag)
615 foo ();
616
617 along with the location of the next token, at NEXT_STMT_LOC,
618 so that we can detect followup statements that are within
619 the same "visual block" as the guarded statement, but which
620 aren't logically grouped within the guarding statement, such
621 as:
622
623 GUARD_LOC
624 |
625 V
626 if (flag)
627 foo (); <- BODY_LOC
628 bar (); <- NEXT_STMT_LOC
629
630 In the above, "bar ();" isn't guarded by the "if", but
631 is indented to misleadingly suggest that it is in the same
632 block as "foo ();".
633
634 GUARD_KIND identifies the kind of clause e.g. "if", "else" etc. */
635
636 void
637 warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
638 const token_indent_info &body_tinfo,
639 const token_indent_info &next_tinfo)
640 {
641 /* Early reject for the case where -Wmisleading-indentation is disabled,
642 to avoid doing work only to have the warning suppressed inside the
643 diagnostic machinery. */
644 if (!warn_misleading_indentation)
645 return;
646
647 if (should_warn_for_misleading_indentation (guard_tinfo,
648 body_tinfo,
649 next_tinfo))
650 {
651 auto_diagnostic_group d;
652 if (warning_at (guard_tinfo.location, OPT_Wmisleading_indentation,
653 "this %qs clause does not guard...",
654 guard_tinfo_to_string (guard_tinfo.keyword)))
655 inform (next_tinfo.location,
656 "...this statement, but the latter is misleadingly indented"
657 " as if it were guarded by the %qs",
658 guard_tinfo_to_string (guard_tinfo.keyword));
659 }
660 }
661
662 #if CHECKING_P
663
664 namespace selftest {
665
666 /* Verify that next_tab_stop works as expected. */
667
668 static void
669 test_next_tab_stop ()
670 {
671 const unsigned int tab_width = 8;
672
673 ASSERT_EQ (next_tab_stop (0, tab_width), 8);
674 ASSERT_EQ (next_tab_stop (1, tab_width), 8);
675 ASSERT_EQ (next_tab_stop (7, tab_width), 8);
676
677 ASSERT_EQ (next_tab_stop (8, tab_width), 16);
678 ASSERT_EQ (next_tab_stop (9, tab_width), 16);
679 ASSERT_EQ (next_tab_stop (15, tab_width), 16);
680
681 ASSERT_EQ (next_tab_stop (16, tab_width), 24);
682 ASSERT_EQ (next_tab_stop (17, tab_width), 24);
683 ASSERT_EQ (next_tab_stop (23, tab_width), 24);
684 }
685
686 /* Verify that the given call to get_visual_column succeeds, with
687 the given results. */
688
689 static void
690 assert_get_visual_column_succeeds (const location &loc,
691 const char *file, int line, int column,
692 const unsigned int tab_width,
693 unsigned int expected_visual_column,
694 unsigned int expected_first_nws)
695 {
696 expanded_location exploc;
697 exploc.file = file;
698 exploc.line = line;
699 exploc.column = column;
700 exploc.data = NULL;
701 exploc.sysp = false;
702 unsigned int actual_visual_column;
703 unsigned int actual_first_nws;
704 bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
705 &actual_visual_column,
706 &actual_first_nws, tab_width);
707 ASSERT_TRUE_AT (loc, result);
708 ASSERT_EQ_AT (loc, actual_visual_column, expected_visual_column);
709 ASSERT_EQ_AT (loc, actual_first_nws, expected_first_nws);
710 }
711
712 /* Verify that the given call to get_visual_column succeeds, with
713 the given results. */
714
715 #define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILENAME, LINE, COLUMN, \
716 TAB_WIDTH, \
717 EXPECTED_VISUAL_COLUMN, \
718 EXPECTED_FIRST_NWS) \
719 SELFTEST_BEGIN_STMT \
720 assert_get_visual_column_succeeds (SELFTEST_LOCATION, \
721 FILENAME, LINE, COLUMN, \
722 TAB_WIDTH, \
723 EXPECTED_VISUAL_COLUMN, \
724 EXPECTED_FIRST_NWS); \
725 SELFTEST_END_STMT
726
727 /* Verify that the given call to get_visual_column fails gracefully. */
728
729 static void
730 assert_get_visual_column_fails (const location &loc,
731 const char *file, int line, int column,
732 const unsigned int tab_width)
733 {
734 expanded_location exploc;
735 exploc.file = file;
736 exploc.line = line;
737 exploc.column = column;
738 exploc.data = NULL;
739 exploc.sysp = false;
740 unsigned int actual_visual_column;
741 unsigned int actual_first_nws;
742 bool result = get_visual_column (exploc, UNKNOWN_LOCATION,
743 &actual_visual_column,
744 &actual_first_nws, tab_width);
745 ASSERT_FALSE_AT (loc, result);
746 }
747
748 /* Verify that the given call to get_visual_column fails gracefully. */
749
750 #define ASSERT_GET_VISUAL_COLUMN_FAILS(FILENAME, LINE, COLUMN, \
751 TAB_WIDTH) \
752 SELFTEST_BEGIN_STMT \
753 assert_get_visual_column_fails (SELFTEST_LOCATION, \
754 FILENAME, LINE, COLUMN, \
755 TAB_WIDTH); \
756 SELFTEST_END_STMT
757
758 /* Verify that get_visual_column works as expected. */
759
760 static void
761 test_get_visual_column ()
762 {
763 /* Create a tempfile with a mixture of tabs and spaces.
764
765 Both lines have either a space or a tab, then " line N",
766 for 8 characters in total.
767
768 1-based "columns" (w.r.t. to line 1):
769 .....................0000000001111.
770 .....................1234567890123. */
771 const char *content = (" line 1\n"
772 "\t line 2\n");
773 line_table_test ltt;
774 temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
775
776 const unsigned int tab_width = 8;
777 const char *file = tmp.get_filename ();
778
779 /* Line 1 (space-based indentation). */
780 {
781 const int line = 1;
782 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
783 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 1, 1);
784 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 2, 2);
785 /* first_nws should have stopped increasing. */
786 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 3, 2);
787 /* Verify the end-of-line boundary. */
788 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 7, 2);
789 ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
790 }
791
792 /* Line 2 (tab-based indentation). */
793 {
794 const int line = 2;
795 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
796 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 8, 8);
797 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 9, 9);
798 /* first_nws should have stopped increasing. */
799 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 10, 9);
800 /* Verify the end-of-line boundary. */
801 ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 14, 9);
802 ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
803 }
804 }
805
806 /* Run all of the selftests within this file. */
807
808 void
809 c_indentation_c_tests ()
810 {
811 test_next_tab_stop ();
812 test_get_visual_column ();
813 }
814
815 } // namespace selftest
816
817 #endif /* CHECKING_P */