Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -63,6 +63,8 @@ InGroup, DefaultIgnore; def note_previous_statement : Note< "previous statement is here">; +def note_misleading_indentation_tab_space_mix : Note< + "there is a mix of tabs spaces; the tab size (-ftabstop=X) is set to %0">; def ext_thread_before : Extension<"'__thread' before '%0'">; def ext_keyword_as_ident : ExtWarn< Index: clang/lib/Parse/ParseStmt.cpp =================================================================== --- clang/lib/Parse/ParseStmt.cpp +++ clang/lib/Parse/ParseStmt.cpp @@ -1217,11 +1217,12 @@ /// Compute the column number will aligning tabs on TabStop (-ftabstop), this /// gives the visual indentation of the SourceLocation. - static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) { + static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc, + bool& HasTab, bool& HasSpace) { unsigned TabStop = SM.getDiagnostics().getDiagnosticOptions().TabStop; unsigned ColNo = SM.getSpellingColumnNumber(Loc); - if (ColNo == 0 || TabStop == 1) + if (ColNo == 0) return ColNo; std::pair FIDAndOffset = SM.getDecomposedLoc(Loc); @@ -1241,6 +1242,8 @@ // expanding tabs. for (const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos; ++CurPos) { + HasTab |= *CurPos == '\t'; + HasSpace |= *CurPos == ' '; if (*CurPos == '\t') // Advance visual column to next tabstop. VisualColumn += (TabStop - VisualColumn % TabStop); @@ -1266,9 +1269,12 @@ P.MisleadingIndentationElseLoc = SourceLocation(); SourceManager &SM = P.getPreprocessor().getSourceManager(); - unsigned PrevColNum = getVisualIndentation(SM, PrevLoc); - unsigned CurColNum = getVisualIndentation(SM, Tok.getLocation()); - unsigned StmtColNum = getVisualIndentation(SM, StmtLoc); + bool HasTab = false; + bool HasSpace = false; + unsigned PrevColNum = getVisualIndentation(SM, PrevLoc, HasTab, HasSpace); + unsigned CurColNum = + getVisualIndentation(SM, Tok.getLocation(), HasTab, HasSpace); + unsigned StmtColNum = getVisualIndentation(SM, StmtLoc, HasTab, HasSpace); if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 && ((PrevColNum > StmtColNum && PrevColNum == CurColNum) || @@ -1278,6 +1284,10 @@ (Tok.isNot(tok::identifier) || P.getPreprocessor().LookAhead(0).isNot(tok::colon))) { P.Diag(Tok.getLocation(), diag::warn_misleading_indentation) << Kind; + if (HasTab && HasSpace) + P.Diag(Tok.getLocation(), + diag::note_misleading_indentation_tab_space_mix) + << SM.getDiagnostics().getDiagnosticOptions().TabStop; P.Diag(StmtLoc, diag::note_previous_statement); } } Index: clang/test/Parser/warn-misleading-indentation.cpp =================================================================== --- clang/test/Parser/warn-misleading-indentation.cpp +++ clang/test/Parser/warn-misleading-indentation.cpp @@ -234,7 +234,8 @@ return 0; #if (TAB_SIZE == 1) // expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}} -// expected-note@-5 {{here}} +// expected-note@-3 {{there is a mix of tabs spaces; the tab size (-ftabstop=X) is set to 1}} +// expected-note@-6 {{here}} #endif } @@ -256,7 +257,20 @@ return 0; #if (TAB_SIZE == 8) // expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}} -// expected-note@-5 {{here}} +// expected-note@-3 {{there is a mix of tabs spaces; the tab size (-ftabstop=X) is set to 8}} +// expected-note@-6 {{here}} +#endif +} + +int a7() +{ + if (0) + return 1; + return 0; +#if (TAB_SIZE == 4) +// expected-warning@-2 {{misleading indentation; statement is not part of the previous 'if'}} +// expected-note@-3 {{there is a mix of tabs spaces; the tab size (-ftabstop=X) is set to 4}} +// expected-note@-6 {{here}} #endif }