case tok::kw_struct: // fallthrough
case tok::kw_union: // fallthrough
case tok::kw_class:
- parseStructClassOrBracedList();
- return;
+ parseRecord();
+ // A record declaration or definition is always the start of a structural
+ // element.
+ break;
case tok::semi:
nextToken();
addUnwrappedLine();
} while (!eof());
}
-void UnwrappedLineParser::parseStructClassOrBracedList() {
+void UnwrappedLineParser::parseRecord() {
nextToken();
- do {
- switch (FormatTok.Tok.getKind()) {
- case tok::l_brace:
- // FIXME: Think about how to resolve the error handling here.
- parseBlock();
- parseStructuralElement();
- return;
- case tok::semi:
- nextToken();
- addUnwrappedLine();
- return;
- case tok::equal:
+ if (FormatTok.Tok.is(tok::identifier) ||
+ FormatTok.Tok.is(tok::kw___attribute) ||
+ FormatTok.Tok.is(tok::kw___declspec)) {
+ nextToken();
+ // We can have macros or attributes in between 'class' and the class name.
+ if (FormatTok.Tok.is(tok::l_paren)) {
+ parseParens();
+ }
+ if (FormatTok.Tok.is(tok::identifier))
nextToken();
- if (FormatTok.Tok.is(tok::l_brace)) {
- parseBracedList();
+
+ if (FormatTok.Tok.is(tok::colon)) {
+ while (FormatTok.Tok.isNot(tok::l_brace)) {
+ if (FormatTok.Tok.is(tok::semi))
+ return;
+ nextToken();
}
- break;
- default:
- nextToken();
- break;
}
- } while (!eof());
+ }
+ if (FormatTok.Tok.is(tok::l_brace))
+ parseBlock();
}
void UnwrappedLineParser::parseObjCProtocolList() {
void parseNamespace();
void parseAccessSpecifier();
void parseEnum();
- void parseStructClassOrBracedList();
+ void parseRecord();
void parseObjCProtocolList();
void parseObjCUntilAtEnd();
void parseObjCInterfaceOrImplementation();
"}");
}
-TEST_F(FormatTest, BracedInitListWithElaboratedTypeSpecifier) {
+TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {
+ // Elaborate type variable declarations.
verifyFormat("struct foo a = { bar };\nint n;");
+ verifyFormat("class foo a = { bar };\nint n;");
+ verifyFormat("union foo a = { bar };\nint n;");
+
+ // Elaborate types inside function definitions.
+ verifyFormat("struct foo f() {}\nint n;");
+ verifyFormat("class foo f() {}\nint n;");
+ verifyFormat("union foo f() {}\nint n;");
+
+ // Templates.
+ verifyFormat("template <class X> void f() {}\nint n;");
+ verifyFormat("template <struct X> void f() {}\nint n;");
+ verifyFormat("template <union X> void f() {}\nint n;");
+
+ // Actual definitions...
+ verifyFormat("struct {} n;");
+ verifyFormat("template <template <class T, class Y>, class Z > class X {} n;");
+ verifyFormat("union Z {\n int n;\n} x;");
+ verifyFormat("class MACRO Z {} n;");
+ verifyFormat("class MACRO(X) Z {} n;");
+ verifyFormat("class __attribute__(X) Z {} n;");
+ verifyFormat("class __declspec(X) Z {} n;");
+
+ // Elaborate types where incorrectly parsing the structural element would
+ // break the indent.
+ verifyFormat("if (true)\n"
+ " class X x;\n"
+ "else\n"
+ " f();\n");
}
// FIXME: This breaks the order of the unwrapped lines: