aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2013-01-05 22:56:06 +0000
committerManuel Klimek <klimek@google.com>2013-01-05 22:56:06 +0000
commit52d0fd8961ef4d03e042ac9eb1b30610518e3016 (patch)
tree66f1f3dd31828000ce6c155da69c284c020ced81
parentef2cfb110d776dd9fc34c4154a1e6d5f774df25f (diff)
downloadllvm-52d0fd8961ef4d03e042ac9eb1b30610518e3016.zip
llvm-52d0fd8961ef4d03e042ac9eb1b30610518e3016.tar.gz
llvm-52d0fd8961ef4d03e042ac9eb1b30610518e3016.tar.bz2
Fixes parsing of hash tokens in the middle of a line.
To parse # correctly, we need to know whether it is the first token in a line - we can deduct this either from the whitespace or seeing that the token is the first in the file - we already calculate this information. This patch moves the identification of the first token into the getNextToken method and stores it inside the FormatToken, so the UnwrappedLineParser can stay independent of the SourceManager. llvm-svn: 171640
-rw-r--r--clang/lib/Format/Format.cpp12
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp4
-rw-r--r--clang/lib/Format/UnwrappedLineParser.h6
-rw-r--r--clang/unittests/Format/FormatTest.cpp4
4 files changed, 19 insertions, 7 deletions
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index effe0bc..4d401a5 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -483,8 +483,7 @@ private:
unsigned Newlines =
std::min(Token.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
- unsigned Offset = SourceMgr.getFileOffset(Token.WhiteSpaceStart);
- if (Newlines == 0 && Offset != 0)
+ if (Newlines == 0 && !Token.IsFirst)
Newlines = 1;
unsigned Indent = Line.Level * 2;
if ((Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
@@ -685,9 +684,10 @@ public:
next();
if (Index >= Tokens.size())
return;
- // It is the responsibility of the UnwrappedLineParser to make sure
- // this sequence is not produced inside an unwrapped line.
- assert(Tokens[Index].Tok.getIdentifierInfo() != NULL);
+ // Hashes in the middle of a line can lead to any strange token
+ // sequence.
+ if (Tokens[Index].Tok.getIdentifierInfo() == NULL)
+ return;
switch (Tokens[Index].Tok.getIdentifierInfo()->getPPKeywordID()) {
case tok::pp_include:
case tok::pp_import:
@@ -1033,6 +1033,8 @@ public:
Lex.LexFromRawLexer(FormatTok.Tok);
StringRef Text = tokenText(FormatTok.Tok);
FormatTok.WhiteSpaceStart = FormatTok.Tok.getLocation();
+ if (SourceMgr.getFileOffset(FormatTok.WhiteSpaceStart) == 0)
+ FormatTok.IsFirst = true;
// Consume and record whitespace until we find a significant token.
while (FormatTok.Tok.is(tok::unknown)) {
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 2f3a603..72b4750 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -470,7 +470,9 @@ void UnwrappedLineParser::nextToken() {
void UnwrappedLineParser::readToken() {
FormatTok = Tokens->getNextToken();
- while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash)) {
+ while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash) &&
+ ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
+ FormatTok.IsFirst)) {
// FIXME: This is incorrect - the correct way is to create a
// data structure that will construct the parts around the preprocessor
// directive as a structured \c UnwrappedLine.
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index a8e5b73..287143d 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -31,7 +31,8 @@ namespace format {
/// whitespace characters preceeding it.
struct FormatToken {
FormatToken()
- : NewlinesBefore(0), HasUnescapedNewline(false), WhiteSpaceLength(0) {
+ : NewlinesBefore(0), HasUnescapedNewline(false), WhiteSpaceLength(0),
+ IsFirst(false) {
}
/// \brief The \c Token.
@@ -56,6 +57,9 @@ struct FormatToken {
/// \brief The length in characters of the whitespace immediately preceeding
/// the \c Token.
unsigned WhiteSpaceLength;
+
+ /// \brief Indicates that this is the first token.
+ bool IsFirst;
};
/// \brief An unwrapped line is a sequence of \c Token, that we would like to
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 2165056..8d95538 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -470,6 +470,10 @@ TEST_F(FormatTest, IndentPreprocessorDirectivesAtZero) {
EXPECT_EQ("{\n {\n#define A\n }\n}", format("{{\n#define A\n}}"));
}
+TEST_F(FormatTest, FormatHashIfNotAtStartOfLine) {
+ verifyFormat("{\n {\n a #c;\n }\n}");
+}
+
// FIXME: write test for unbalanced braces in macros...
// FIXME: test # inside a normal statement (like {#define A b})