summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2013-01-15 13:38:33 +0000
committerManuel Klimek <klimek@google.com>2013-01-15 13:38:33 +0000
commite01bab587cd283e2c1813e9a74bf50827309feaf (patch)
tree09ed6ded56bb45a11758ff4923308808383f59d3 /clang
parent9ab63f68fcff6027cf35ec01a952be3ac000fcb9 (diff)
downloadbcm5719-llvm-e01bab587cd283e2c1813e9a74bf50827309feaf.tar.gz
bcm5719-llvm-e01bab587cd283e2c1813e9a74bf50827309feaf.zip
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; llvm-svn: 172530
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp45
-rw-r--r--clang/lib/Format/UnwrappedLineParser.h2
-rw-r--r--clang/unittests/Format/FormatTest.cpp31
3 files changed, 54 insertions, 24 deletions
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index b3671b30409..fe522ac9d8f 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/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/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 487e7019f7a..08faff15af1 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/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/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index f8a81b59820..e9fa666f907 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/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 <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:
OpenPOWER on IntegriCloud