]> granicus.if.org Git - clang/commitdiff
Fixes various bugs around the keywords class, struct and union.
authorManuel Klimek <klimek@google.com>
Tue, 15 Jan 2013 13:38:33 +0000 (13:38 +0000)
committerManuel Klimek <klimek@google.com>
Tue, 15 Jan 2013 13:38:33 +0000 (13:38 +0000)
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

lib/Format/UnwrappedLineParser.cpp
lib/Format/UnwrappedLineParser.h
unittests/Format/FormatTest.cpp

index b3671b30409204b5c88e54f2a6c38531954ca06f..fe522ac9d8f8d8f41754c8a3980f6f1fbdc3ab5b 100644 (file)
@@ -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() {
index 487e7019f7a9741f1d14ebd033cbb9a0dd4a7c47..08faff15af1d77e7c62848eeb2115b1d267d4ba1 100644 (file)
@@ -146,7 +146,7 @@ private:
   void parseNamespace();
   void parseAccessSpecifier();
   void parseEnum();
-  void parseStructClassOrBracedList();
+  void parseRecord();
   void parseObjCProtocolList();
   void parseObjCUntilAtEnd();
   void parseObjCInterfaceOrImplementation();
index f8a81b5982053b6f22824ecfdaedabc90a3137d8..e9fa666f907efbee4d1b957705db01759678c88c 100644 (file)
@@ -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: