Skip to content

Commit b4b904e

Browse files
committed
[Diagnostic] Fixed add ftabstop to -Wmisleading-indentation
Summary: this allow much better support of codebases like the linux kernel that mix tabs and spaces. -ftabstop=//Width// allow specifying how large tabs are considered to be. Reviewers: xbolva00, aaron.ballman, rsmith Reviewed By: aaron.ballman Subscribers: mstorsjo, cfe-commits, jyknight, riccibruno, rsmith, nathanchance Tags: #clang Differential Revision: https://reviews.llvm.org/D71037
1 parent 53fc484 commit b4b904e

File tree

2 files changed

+121
-5
lines changed

2 files changed

+121
-5
lines changed

clang/lib/Parse/ParseStmt.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,42 @@ struct MisleadingIndentationChecker {
12141214
if (Kind == MSK_else && !ShouldSkip)
12151215
P.MisleadingIndentationElseLoc = SL;
12161216
}
1217+
1218+
/// Compute the column number will aligning tabs on TabStop (-ftabstop), this
1219+
/// gives the visual indentation of the SourceLocation.
1220+
static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
1221+
unsigned TabStop = SM.getDiagnostics().getDiagnosticOptions().TabStop;
1222+
1223+
unsigned ColNo = SM.getSpellingColumnNumber(Loc);
1224+
if (ColNo == 0 || TabStop == 1)
1225+
return ColNo;
1226+
1227+
std::pair<FileID, unsigned> FIDAndOffset = SM.getDecomposedLoc(Loc);
1228+
1229+
bool Invalid;
1230+
StringRef BufData = SM.getBufferData(FIDAndOffset.first, &Invalid);
1231+
if (Invalid)
1232+
return 0;
1233+
1234+
const char *EndPos = BufData.data() + FIDAndOffset.second;
1235+
// FileOffset are 0-based and Column numbers are 1-based
1236+
assert(FIDAndOffset.second + 1 >= ColNo &&
1237+
"Column number smaller than file offset?");
1238+
1239+
unsigned VisualColumn = 0; // Stored as 0-based column, here.
1240+
// Loop from beginning of line up to Loc's file position, counting columns,
1241+
// expanding tabs.
1242+
for (const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
1243+
++CurPos) {
1244+
if (*CurPos == '\t')
1245+
// Advance visual column to next tabstop.
1246+
VisualColumn += (TabStop - VisualColumn % TabStop);
1247+
else
1248+
VisualColumn++;
1249+
}
1250+
return VisualColumn + 1;
1251+
}
1252+
12171253
void Check() {
12181254
Token Tok = P.getCurToken();
12191255
if (P.getActions().getDiagnostics().isIgnored(
@@ -1230,9 +1266,9 @@ struct MisleadingIndentationChecker {
12301266
P.MisleadingIndentationElseLoc = SourceLocation();
12311267

12321268
SourceManager &SM = P.getPreprocessor().getSourceManager();
1233-
unsigned PrevColNum = SM.getSpellingColumnNumber(PrevLoc);
1234-
unsigned CurColNum = SM.getSpellingColumnNumber(Tok.getLocation());
1235-
unsigned StmtColNum = SM.getSpellingColumnNumber(StmtLoc);
1269+
unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
1270+
unsigned CurColNum = getVisualIndentation(SM, Tok.getLocation());
1271+
unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);
12361272

12371273
if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
12381274
((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||

clang/test/Parser/warn-misleading-indentation.cpp

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// RUN: %clang_cc1 -x c -fsyntax-only -verify %s
2-
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wmisleading-indentation -DWITH_WARN %s
3-
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -DWITH_WARN -DCXX17 %s
42
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -Wno-misleading-indentation -DCXX17 %s
3+
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wmisleading-indentation -DWITH_WARN -ftabstop 8 -DTAB_SIZE=8 %s
4+
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -DWITH_WARN -ftabstop 4 -DTAB_SIZE=4 -DCXX17 %s
5+
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall -Wno-unused -DWITH_WARN -ftabstop 1 -DTAB_SIZE=1 %s
6+
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -Wall -Wno-unused -Wmisleading-indentation -DCXX17 -DWITH_WARN -ftabstop 2 -DTAB_SIZE=2 %s
57

68
#ifndef WITH_WARN
79
// expected-no-diagnostics
@@ -225,3 +227,81 @@ void s(int num) {
225227
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
226228
#endif
227229
}
230+
int a4()
231+
{
232+
if (0)
233+
return 1;
234+
return 0;
235+
#if (TAB_SIZE == 1)
236+
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
237+
// expected-note@-5 {{here}}
238+
#endif
239+
}
240+
241+
int a5()
242+
{
243+
if (0)
244+
return 1;
245+
return 0;
246+
#if WITH_WARN
247+
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
248+
// expected-note@-5 {{here}}
249+
#endif
250+
}
251+
252+
int a6()
253+
{
254+
if (0)
255+
return 1;
256+
return 0;
257+
#if (TAB_SIZE == 8)
258+
// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}}
259+
// expected-note@-5 {{here}}
260+
#endif
261+
}
262+
263+
#define FOO \
264+
goto fail
265+
266+
int main(int argc, char* argv[]) {
267+
if (5 != 0)
268+
goto fail;
269+
else
270+
goto fail;
271+
272+
if (1) {
273+
if (1)
274+
goto fail;
275+
else if (1)
276+
goto fail;
277+
else if (1)
278+
goto fail;
279+
else
280+
goto fail;
281+
} else if (1) {
282+
if (1)
283+
goto fail;
284+
}
285+
286+
if (1) {
287+
if (1)
288+
goto fail;
289+
} else if (1)
290+
goto fail;
291+
292+
293+
if (1) goto fail; goto fail;
294+
295+
if (0)
296+
goto fail;
297+
298+
goto fail;
299+
300+
if (0)
301+
FOO;
302+
303+
goto fail;
304+
305+
fail:;
306+
}
307+

0 commit comments

Comments
 (0)