Skip to content

Commit f6fd00b

Browse files
committed
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171640 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c37b4d6 commit f6fd00b

File tree

4 files changed

+19
-7
lines changed

4 files changed

+19
-7
lines changed

lib/Format/Format.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,7 @@ class UnwrappedLineFormatter {
483483

484484
unsigned Newlines =
485485
std::min(Token.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
486-
unsigned Offset = SourceMgr.getFileOffset(Token.WhiteSpaceStart);
487-
if (Newlines == 0 && Offset != 0)
486+
if (Newlines == 0 && !Token.IsFirst)
488487
Newlines = 1;
489488
unsigned Indent = Line.Level * 2;
490489
if ((Token.Tok.is(tok::kw_public) || Token.Tok.is(tok::kw_protected) ||
@@ -685,9 +684,10 @@ class TokenAnnotator {
685684
next();
686685
if (Index >= Tokens.size())
687686
return;
688-
// It is the responsibility of the UnwrappedLineParser to make sure
689-
// this sequence is not produced inside an unwrapped line.
690-
assert(Tokens[Index].Tok.getIdentifierInfo() != NULL);
687+
// Hashes in the middle of a line can lead to any strange token
688+
// sequence.
689+
if (Tokens[Index].Tok.getIdentifierInfo() == NULL)
690+
return;
691691
switch (Tokens[Index].Tok.getIdentifierInfo()->getPPKeywordID()) {
692692
case tok::pp_include:
693693
case tok::pp_import:
@@ -1033,6 +1033,8 @@ class LexerBasedFormatTokenSource : public FormatTokenSource {
10331033
Lex.LexFromRawLexer(FormatTok.Tok);
10341034
StringRef Text = tokenText(FormatTok.Tok);
10351035
FormatTok.WhiteSpaceStart = FormatTok.Tok.getLocation();
1036+
if (SourceMgr.getFileOffset(FormatTok.WhiteSpaceStart) == 0)
1037+
FormatTok.IsFirst = true;
10361038

10371039
// Consume and record whitespace until we find a significant token.
10381040
while (FormatTok.Tok.is(tok::unknown)) {

lib/Format/UnwrappedLineParser.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,9 @@ void UnwrappedLineParser::nextToken() {
470470

471471
void UnwrappedLineParser::readToken() {
472472
FormatTok = Tokens->getNextToken();
473-
while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash)) {
473+
while (!Line.InPPDirective && FormatTok.Tok.is(tok::hash) &&
474+
((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
475+
FormatTok.IsFirst)) {
474476
// FIXME: This is incorrect - the correct way is to create a
475477
// data structure that will construct the parts around the preprocessor
476478
// directive as a structured \c UnwrappedLine.

lib/Format/UnwrappedLineParser.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ namespace format {
3131
/// whitespace characters preceeding it.
3232
struct FormatToken {
3333
FormatToken()
34-
: NewlinesBefore(0), HasUnescapedNewline(false), WhiteSpaceLength(0) {
34+
: NewlinesBefore(0), HasUnescapedNewline(false), WhiteSpaceLength(0),
35+
IsFirst(false) {
3536
}
3637

3738
/// \brief The \c Token.
@@ -56,6 +57,9 @@ struct FormatToken {
5657
/// \brief The length in characters of the whitespace immediately preceeding
5758
/// the \c Token.
5859
unsigned WhiteSpaceLength;
60+
61+
/// \brief Indicates that this is the first token.
62+
bool IsFirst;
5963
};
6064

6165
/// \brief An unwrapped line is a sequence of \c Token, that we would like to

unittests/Format/FormatTest.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ TEST_F(FormatTest, IndentPreprocessorDirectivesAtZero) {
470470
EXPECT_EQ("{\n {\n#define A\n }\n}", format("{{\n#define A\n}}"));
471471
}
472472

473+
TEST_F(FormatTest, FormatHashIfNotAtStartOfLine) {
474+
verifyFormat("{\n {\n a #c;\n }\n}");
475+
}
476+
473477
// FIXME: write test for unbalanced braces in macros...
474478
// FIXME: test # inside a normal statement (like {#define A b})
475479

0 commit comments

Comments
 (0)