public:
AnnotatedLine(const UnwrappedLine &Line)
: First(Line.Tokens.front()), Level(Line.Level),
- InPPDirective(Line.InPPDirective) {
+ InPPDirective(Line.InPPDirective),
+ MustBeDeclaration(Line.MustBeDeclaration) {
assert(!Line.Tokens.empty());
AnnotatedToken *Current = &First;
for (std::list<FormatToken>::const_iterator I = ++Line.Tokens.begin(),
}
AnnotatedLine(const AnnotatedLine &Other)
: First(Other.First), Type(Other.Type), Level(Other.Level),
- InPPDirective(Other.InPPDirective) {
+ InPPDirective(Other.InPPDirective),
+ MustBeDeclaration(Other.MustBeDeclaration) {
Last = &First;
while (!Last->Children.empty()) {
Last->Children[0].Parent = Last;
LineType Type;
unsigned Level;
bool InPPDirective;
+ bool MustBeDeclaration;
};
static prec::Level getPrecedence(const AnnotatedToken &Tok) {
// It is very unlikely that we are going to find a pointer or reference type
// definition on the RHS of an assignment.
- if (IsRHS)
+ if (IsRHS || !Line.MustBeDeclaration)
return TT_BinaryOperator;
return TT_PointerOrReference;
namespace clang {
namespace format {
+class ScopedDeclarationState {
+public:
+ ScopedDeclarationState(UnwrappedLine &Line, std::vector<bool> &Stack,
+ bool MustBeDeclaration)
+ : Line(Line), Stack(Stack) {
+ Stack.push_back(MustBeDeclaration);
+ Line.MustBeDeclaration = MustBeDeclaration;
+ }
+ ~ScopedDeclarationState() {
+ Line.MustBeDeclaration = Stack.back();
+ Stack.pop_back();
+ }
+private:
+ UnwrappedLine &Line;
+ std::vector<bool> &Stack;
+};
+
class ScopedMacroState : public FormatTokenSource {
public:
ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource,
}
bool UnwrappedLineParser::parseFile() {
+ ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
+ /*MustBeDeclaration=*/ true);
bool Error = parseLevel(/*HasOpeningBrace=*/false);
// Make sure to format the remaining tokens.
flushComments(true);
addUnwrappedLine();
break;
case tok::l_brace:
- Error |= parseBlock();
+ // FIXME: Add parameter whether this can happen - if this happens, we must
+ // be in a non-declaration context.
+ Error |= parseBlock(/*MustBeDeclaration=*/ false);
addUnwrappedLine();
break;
case tok::r_brace:
return Error;
}
-bool UnwrappedLineParser::parseBlock(unsigned AddLevels) {
+bool UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels) {
assert(FormatTok.Tok.is(tok::l_brace) && "'{' expected");
nextToken();
addUnwrappedLine();
+ ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
+ MustBeDeclaration);
Line->Level += AddLevels;
parseLevel(/*HasOpeningBrace=*/true);
if (FormatTok.Tok.is(tok::string_literal)) {
nextToken();
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock(0);
+ parseBlock(/*MustBeDeclaration=*/ true, 0);
addUnwrappedLine();
return;
}
// structural element.
// FIXME: Figure out cases where this is not true, and add projections for
// them (the one we know is missing are lambdas).
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ false);
addUnwrappedLine();
return;
case tok::identifier:
{
nextToken();
ScopedLineState LineState(*this);
+ ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
+ /*MustBeDeclaration=*/ false);
Line->Level += 1;
- parseLevel(/*HasOpeningBrace=*/true);
+ parseLevel(/*HasOpeningBrace=*/ true);
Line->Level -= 1;
}
break;
parseParens();
bool NeedsUnwrappedLine = false;
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ false);
NeedsUnwrappedLine = true;
} else {
addUnwrappedLine();
if (FormatTok.Tok.is(tok::kw_else)) {
nextToken();
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ false);
addUnwrappedLine();
} else if (FormatTok.Tok.is(tok::kw_if)) {
parseIfThenElse();
if (FormatTok.Tok.is(tok::identifier))
nextToken();
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock(0);
+ parseBlock(/*MustBeDeclaration=*/ true, 0);
addUnwrappedLine();
}
// FIXME: Add error handling.
if (FormatTok.Tok.is(tok::l_paren))
parseParens();
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ false);
addUnwrappedLine();
} else {
addUnwrappedLine();
assert(FormatTok.Tok.is(tok::kw_do) && "'do' expected");
nextToken();
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ false);
} else {
addUnwrappedLine();
++Line->Level;
if (Line->Level > 0)
--Line->Level;
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ false);
if (FormatTok.Tok.is(tok::kw_break))
parseStructuralElement(); // "break;" after "}" goes on the same line.
}
if (FormatTok.Tok.is(tok::l_paren))
parseParens();
if (FormatTok.Tok.is(tok::l_brace)) {
- parseBlock(Style.IndentCaseLabels ? 2 : 1);
+ parseBlock(/*MustBeDeclaration=*/ false, Style.IndentCaseLabels ? 2 : 1);
addUnwrappedLine();
} else {
addUnwrappedLine();
}
}
if (FormatTok.Tok.is(tok::l_brace))
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ true);
// We fall through to parsing a structural element afterwards, so
// class A {} n, m;
// will end up in one unwrapped line.
// If instance variables are present, keep the '{' on the first line too.
if (FormatTok.Tok.is(tok::l_brace))
- parseBlock();
+ parseBlock(/*MustBeDeclaration=*/ true);
// With instance variables, this puts '}' on its own line. Without instance
// variables, this ends the @interface line.
/// \c UnwrappedLineFormatter. The key property is that changing the formatting
/// within an unwrapped line does not affect any other unwrapped lines.
struct UnwrappedLine {
- UnwrappedLine() : Level(0), InPPDirective(false) {
+ UnwrappedLine() : Level(0), InPPDirective(false), MustBeDeclaration(false) {
}
// FIXME: Don't use std::list here.
/// \brief Whether this \c UnwrappedLine is part of a preprocessor directive.
bool InPPDirective;
+
+ bool MustBeDeclaration;
};
class UnwrappedLineConsumer {
private:
bool parseFile();
bool parseLevel(bool HasOpeningBrace);
- bool parseBlock(unsigned AddLevels = 1);
+ bool parseBlock(bool MustBeDeclaration, unsigned AddLevels = 1);
void parsePPDirective();
void parsePPDefine();
void parsePPUnknown();
// \c &PreprocessorDirectives.
std::vector<UnwrappedLine> *CurrentLines;
+ // We store for each line whether it must be a declaration depending on
+ // whether we are in a compound statement or not.
+ std::vector<bool> DeclarationScopeStack;
+
clang::DiagnosticsEngine &Diag;
const FormatStyle &Style;
FormatTokenSource *Tokens;