From: Manuel Klimek Date: Tue, 15 Jan 2013 13:38:33 +0000 (+0000) Subject: Fixes various bugs around the keywords class, struct and union. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47ea7f64108163491ed74dc746c8d94e10764704;p=clang Fixes various bugs around the keywords class, struct and union. This switches to parsing record definitions only if we can clearly identify them. We're specifically allowing common patterns for visibility control through macros and attributes, but we cannot currently fix all instances. This fixes all known bugs we have though. Before: static class A f() { return g(); } int x; After: static class A f() { return g(); } int x; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172530 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index b3671b3040..fe522ac9d8 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -320,8 +320,10 @@ void UnwrappedLineParser::parseStructuralElement() { 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(); @@ -569,30 +571,29 @@ void UnwrappedLineParser::parseEnum() { } 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() { diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index 487e7019f7..08faff15af 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/lib/Format/UnwrappedLineParser.h @@ -146,7 +146,7 @@ private: void parseNamespace(); void parseAccessSpecifier(); void parseEnum(); - void parseStructClassOrBracedList(); + void parseRecord(); void parseObjCProtocolList(); void parseObjCUntilAtEnd(); void parseObjCInterfaceOrImplementation(); diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index f8a81b5982..e9fa666f90 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -1290,8 +1290,37 @@ TEST_F(FormatTest, PullTrivialFunctionDefinitionsIntoSingleLine) { "}"); } -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 void f() {}\nint n;"); + verifyFormat("template void f() {}\nint n;"); + verifyFormat("template void f() {}\nint n;"); + + // Actual definitions... + verifyFormat("struct {} n;"); + verifyFormat("template