aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jasper <djasper@google.com>2013-01-04 18:52:56 +0000
committerDaniel Jasper <djasper@google.com>2013-01-04 18:52:56 +0000
commit1f42f11870325d1869eb7d51b98ebf5e6d7bcc26 (patch)
treeb62e5945f375315060a6d60ebb3074883a2a3a68
parent463b383bcd0269ab56dfa13a3b86fb382c97b515 (diff)
Let the formatter ignore UnwrappedLines containing errors.
This prevents code like: namespace { class Foo { Foo( }; } // comment from causing segfaults (see llvm.org/PR14774). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171495 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Format/Format.cpp52
-rw-r--r--unittests/Format/FormatTest.cpp7
2 files changed, 42 insertions, 17 deletions
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index 54a2771eb9..69020c6575 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -120,7 +120,7 @@ public:
// Check whether the UnwrappedLine can be put onto a single line. If so,
// this is bound to be the optimal solution (by definition) and we don't
- // need to analyze the entire solution space.
+ // need to analyze the entire solution space.
unsigned Columns = State.Column;
bool FitsOnALine = true;
for (unsigned i = 1, n = Line.Tokens.size(); i != n; ++i) {
@@ -535,14 +535,16 @@ public:
return true;
}
if (Tokens[Index].Tok.is(tok::r_paren) ||
- Tokens[Index].Tok.is(tok::r_square))
+ Tokens[Index].Tok.is(tok::r_square) ||
+ Tokens[Index].Tok.is(tok::r_brace))
return false;
if (Tokens[Index].Tok.is(tok::pipepipe) ||
Tokens[Index].Tok.is(tok::ampamp) ||
Tokens[Index].Tok.is(tok::question) ||
Tokens[Index].Tok.is(tok::colon))
return false;
- consumeToken();
+ if (!consumeToken())
+ return false;
}
return false;
}
@@ -553,9 +555,11 @@ public:
next();
return true;
}
- if (Tokens[Index].Tok.is(tok::r_square))
+ if (Tokens[Index].Tok.is(tok::r_square) ||
+ Tokens[Index].Tok.is(tok::r_brace))
+ return false;
+ if (!consumeToken())
return false;
- consumeToken();
}
return false;
}
@@ -566,9 +570,11 @@ public:
next();
return true;
}
- if (Tokens[Index].Tok.is(tok::r_paren))
+ if (Tokens[Index].Tok.is(tok::r_paren) ||
+ Tokens[Index].Tok.is(tok::r_brace))
+ return false;
+ if (!consumeToken())
return false;
- consumeToken();
}
return false;
}
@@ -580,7 +586,8 @@ public:
next();
return true;
}
- consumeToken();
+ if (!consumeToken())
+ return false;
}
return false;
}
@@ -598,19 +605,21 @@ public:
return false;
}
- void consumeToken() {
+ bool consumeToken() {
unsigned CurrentIndex = Index;
next();
switch (Tokens[CurrentIndex].Tok.getKind()) {
case tok::l_paren:
- parseParens();
+ if (!parseParens())
+ return false;
if (Index < Tokens.size() && Tokens[Index].Tok.is(tok::colon)) {
Annotations[Index].Type = TokenAnnotation::TT_CtorInitializerColon;
next();
}
break;
case tok::l_square:
- parseSquare();
+ if (!parseSquare())
+ return false;
break;
case tok::less:
if (parseAngle())
@@ -620,6 +629,9 @@ public:
Index = CurrentIndex + 1;
}
break;
+ case tok::r_paren:
+ case tok::r_square:
+ return false;
case tok::greater:
Annotations[CurrentIndex].Type = TokenAnnotation::TT_BinaryOperator;
break;
@@ -647,6 +659,7 @@ public:
default:
break;
}
+ return true;
}
void parseIncludeDirective() {
@@ -678,14 +691,16 @@ public:
}
}
- void parseLine() {
+ bool parseLine() {
if (Tokens[Index].Tok.is(tok::hash)) {
parsePreprocessorDirective();
- return;
+ return true;
}
while (Index < Tokens.size()) {
- consumeToken();
+ if (!consumeToken())
+ return false;
}
+ return true;
}
void next() {
@@ -698,14 +713,15 @@ public:
unsigned Index;
};
- void annotate() {
+ bool annotate() {
Annotations.clear();
for (int i = 0, e = Line.Tokens.size(); i != e; ++i) {
Annotations.push_back(TokenAnnotation());
}
AnnotatingParser Parser(Line.Tokens, Annotations);
- Parser.parseLine();
+ if (!Parser.parseLine())
+ return false;
determineTokenTypes();
bool IsObjCMethodDecl =
@@ -806,6 +822,7 @@ public:
if (Annotation.MustBreakBefore)
Annotation.CanBreakBefore = true;
}
+ return true;
}
const std::vector<TokenAnnotation> &getAnnotations() {
@@ -1092,7 +1109,8 @@ private:
continue;
TokenAnnotator Annotator(TheLine, Style, SourceMgr);
- Annotator.annotate();
+ if (!Annotator.annotate())
+ return;
UnwrappedLineFormatter Formatter(Style, SourceMgr, TheLine,
Annotator.getAnnotations(), Replaces,
StructuralError);
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index e713280d91..8eadb545f7 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -859,6 +859,13 @@ TEST_F(FormatTest, IncorrectCodeDoNoWhile) {
"};");
}
+TEST_F(FormatTest, DoesNotTouchUnwrappedLinesWithErrors) {
+ verifyFormat("namespace {\n"
+ "class Foo {\n"
+ " Foo ( };\n"
+ "} // comment");
+}
+
TEST_F(FormatTest, IncorrectCodeErrorDetection) {
EXPECT_EQ("{\n{\n}\n", format("{\n{\n}\n"));
EXPECT_EQ("{\n {\n}\n", format("{\n {\n}\n"));