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