summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Hoad <mydeveloperday@gmail.com>2019-09-18 18:57:09 +0000
committerPaul Hoad <mydeveloperday@gmail.com>2019-09-18 18:57:09 +0000
commitda7c99cf283cf1773550f372cb50d3320db77e92 (patch)
tree203d31b64f527701e7795691286a166207272229
parent5e9c2181fcc9614b760e7ce1eceddd06d611b48d (diff)
downloadclang-da7c99cf283cf1773550f372cb50d3320db77e92.tar.gz
[clang-format][PR41964] Fix crash with SIGFPE when TabWidth is set to 0 and line starts with tab
Summary: clang-format 8.0 crashes with SIGFPE (floating point exception) when formatting following file: app.cpp: void a() { //line starts with '\t' } $ clang-format -style='{TabWidth: 0}' app.cpp Reviewers: owenpan, klimek, russellmcc, timwoj Reviewed By: klimek Subscribers: cfe-commits Tags: #clang-tools-extra, #clang Differential Revision: https://reviews.llvm.org/D67670 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@372246 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Format/Encoding.h3
-rw-r--r--lib/Format/FormatTokenLexer.cpp3
-rw-r--r--lib/Format/WhitespaceManager.cpp37
-rw-r--r--unittests/Format/FormatTest.cpp73
4 files changed, 99 insertions, 17 deletions
diff --git a/lib/Format/Encoding.h b/lib/Format/Encoding.h
index fe3d5f0198..a0d664121b 100644
--- a/lib/Format/Encoding.h
+++ b/lib/Format/Encoding.h
@@ -67,7 +67,8 @@ inline unsigned columnWidthWithTabs(StringRef Text, unsigned StartColumn,
if (TabPos == StringRef::npos)
return TotalWidth + columnWidth(Tail, Encoding);
TotalWidth += columnWidth(Tail.substr(0, TabPos), Encoding);
- TotalWidth += TabWidth - (TotalWidth + StartColumn) % TabWidth;
+ if (TabWidth)
+ TotalWidth += TabWidth - (TotalWidth + StartColumn) % TabWidth;
Tail = Tail.substr(TabPos + 1);
}
}
diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index 009b884975..e59a059fd6 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/lib/Format/FormatTokenLexer.cpp
@@ -657,7 +657,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
++Column;
break;
case '\t':
- Column += Style.TabWidth - Column % Style.TabWidth;
+ Column +=
+ Style.TabWidth - (Style.TabWidth ? Column % Style.TabWidth : 0);
break;
case '\\':
if (i + 1 == e || (Text[i + 1] != '\r' && Text[i + 1] != '\n'))
diff --git a/lib/Format/WhitespaceManager.cpp b/lib/Format/WhitespaceManager.cpp
index 33c0d53402..5a44500d35 100644
--- a/lib/Format/WhitespaceManager.cpp
+++ b/lib/Format/WhitespaceManager.cpp
@@ -815,19 +815,24 @@ void WhitespaceManager::appendIndentText(std::string &Text,
Text.append(Spaces, ' ');
break;
case FormatStyle::UT_Always: {
- unsigned FirstTabWidth =
- Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
- // Insert only spaces when we want to end up before the next tab.
- if (Spaces < FirstTabWidth || Spaces == 1) {
+ if (Style.TabWidth) {
+ unsigned FirstTabWidth =
+ Style.TabWidth - WhitespaceStartColumn % Style.TabWidth;
+
+ // Insert only spaces when we want to end up before the next tab.
+ if (Spaces < FirstTabWidth || Spaces == 1) {
+ Text.append(Spaces, ' ');
+ break;
+ }
+ // Align to the next tab.
+ Spaces -= FirstTabWidth;
+ Text.append("\t");
+
+ Text.append(Spaces / Style.TabWidth, '\t');
+ Text.append(Spaces % Style.TabWidth, ' ');
+ } else if (Spaces == 1) {
Text.append(Spaces, ' ');
- break;
}
- // Align to the next tab.
- Spaces -= FirstTabWidth;
- Text.append("\t");
-
- Text.append(Spaces / Style.TabWidth, '\t');
- Text.append(Spaces % Style.TabWidth, ' ');
break;
}
case FormatStyle::UT_ForIndentation:
@@ -837,14 +842,16 @@ void WhitespaceManager::appendIndentText(std::string &Text,
// the first one.
if (Indentation > Spaces)
Indentation = Spaces;
- unsigned Tabs = Indentation / Style.TabWidth;
- Text.append(Tabs, '\t');
- Spaces -= Tabs * Style.TabWidth;
+ if (Style.TabWidth) {
+ unsigned Tabs = Indentation / Style.TabWidth;
+ Text.append(Tabs, '\t');
+ Spaces -= Tabs * Style.TabWidth;
+ }
}
Text.append(Spaces, ' ');
break;
case FormatStyle::UT_ForContinuationAndIndentation:
- if (WhitespaceStartColumn == 0) {
+ if (WhitespaceStartColumn == 0 && Style.TabWidth) {
unsigned Tabs = Spaces / Style.TabWidth;
Text.append(Tabs, '\t');
Spaces -= Tabs * Style.TabWidth;
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index b1fcd39a49..dc20faf70c 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -9877,6 +9877,79 @@ TEST_F(FormatTest, ConfigurableUseOfTab) {
Tab);
}
+TEST_F(FormatTest, ZeroTabWidth) {
+ FormatStyle Tab = getLLVMStyleWithColumns(42);
+ Tab.IndentWidth = 8;
+ Tab.UseTab = FormatStyle::UT_Never;
+ Tab.TabWidth = 0;
+ EXPECT_EQ("void a(){\n"
+ " // line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t// line starts with '\t'\n"
+ "};",
+ Tab));
+
+ EXPECT_EQ("void a(){\n"
+ " // line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t\t// line starts with '\t'\n"
+ "};",
+ Tab));
+
+ Tab.UseTab = FormatStyle::UT_ForIndentation;
+ EXPECT_EQ("void a(){\n"
+ " // line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t// line starts with '\t'\n"
+ "};",
+ Tab));
+
+ EXPECT_EQ("void a(){\n"
+ " // line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t\t// line starts with '\t'\n"
+ "};",
+ Tab));
+
+ Tab.UseTab = FormatStyle::UT_ForContinuationAndIndentation;
+ EXPECT_EQ("void a(){\n"
+ " // line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t// line starts with '\t'\n"
+ "};",
+ Tab));
+
+ EXPECT_EQ("void a(){\n"
+ " // line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t\t// line starts with '\t'\n"
+ "};",
+ Tab));
+
+ Tab.UseTab = FormatStyle::UT_Always;
+ EXPECT_EQ("void a(){\n"
+ "// line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t// line starts with '\t'\n"
+ "};",
+ Tab));
+
+ EXPECT_EQ("void a(){\n"
+ "// line starts with '\t'\n"
+ "};",
+ format("void a(){\n"
+ "\t\t// line starts with '\t'\n"
+ "};",
+ Tab));
+}
+
TEST_F(FormatTest, CalculatesOriginalColumn) {
EXPECT_EQ("\"qqqqqqqqqqqqqqqqqqqqqqqqqq\\\n"
"q\"; /* some\n"