diff options
author | Manuel Klimek <klimek@google.com> | 2014-03-18 11:22:45 +0000 |
---|---|---|
committer | Manuel Klimek <klimek@google.com> | 2014-03-18 11:22:45 +0000 |
commit | 819788da83bf49096761f39826cd846204ca81bf (patch) | |
tree | 8009c7ccf78e959dad3b63d66397300cf9a7e21d /clang/lib/Format/ContinuationIndenter.cpp | |
parent | f88f317d35814d99bc4e605ef9a8d9e66d7e2b99 (diff) | |
download | bcm5719-llvm-819788da83bf49096761f39826cd846204ca81bf.tar.gz bcm5719-llvm-819788da83bf49096761f39826cd846204ca81bf.zip |
Fix crasher bug.
Due to not resetting the fake rparen data on the token when iterating
over annotated lines, we would pop the last element of the paren stack.
This patch fixes the underlying root cause, and makes the code more
robust against similar problems in the future:
- reset the first token when iterating on the same annotated lines due
to preprocessor branches
- never pop the last element from the paren stack, so we do not crash,
but rather incorrectly format
- add assert()s so we can figure out if our assumptions are violated
llvm-svn: 204140
Diffstat (limited to 'clang/lib/Format/ContinuationIndenter.cpp')
-rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 380532a47cc..cb4e4f53b2f 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -217,8 +217,8 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, unsigned ExtraSpaces) { const FormatToken &Current = *State.NextToken; - if (State.Stack.size() == 0 || - (Current.Type == TT_ImplicitStringLiteral && + assert(!State.Stack.empty()); + if ((Current.Type == TT_ImplicitStringLiteral && (Current.Previous->Tok.getIdentifierInfo() == NULL || Current.Previous->Tok.getIdentifierInfo()->getPPKeywordID() == tok::pp_not_keyword))) { @@ -628,8 +628,14 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, // SomeFunction(a, [] { // f(); // break // }); - for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) + for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) { + assert(State.Stack.size() > 1); + if (State.Stack.size() == 1) { + // Do not pop the last element. + break; + } State.Stack.pop_back(); + } bool IsObjCBlock = Previous && (Previous->is(tok::caret) || @@ -709,6 +715,11 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, // as they will have been removed early (see above). for (unsigned i = 0, e = Current.FakeRParens; i != e; ++i) { unsigned VariablePos = State.Stack.back().VariablePos; + assert(State.Stack.size() > 1); + if (State.Stack.size() == 1) { + // Do not pop the last element. + break; + } State.Stack.pop_back(); State.Stack.back().VariablePos = VariablePos; } |