If the approach is not right, I'll try to rework the fix with your feedback.

Problem:
========
FormatStyle Spaces = getLLVMStyle();
verifyFormat("Deleted &operator=(const Deleted &)& = default;");

Spaces.SpacesInParentheses= true;
verifyFormat("Deleted( const Deleted & )& = default;", Spaces); // Fail 
"Deleted(const Deleted &)& = default;"

Spaces.SpacesInCStyleCastParentheses = true;
Spaces.SpacesInParentheses= false;
verifyFormat("Deleted(const Deleted &)& = default;", Spaces); // Fail "Deleted( 
const Deleted & )& = default;"

Solution:
=======
The cast seemed too eager: There does not seem to be a reason for a binary 
operator to follow a C-cast.

The type of the function reference qualification seems to make sense as 
TT_PointerOrReference:
 -Extend in the case of to handle the '&&' case "Deleted(const Deleted &)&& = 
default;"
 -Extend to handle the case without '=' for '*', '&' and '&&' case 
"Deleted(const Deleted &)&;"

Ensure no spaces between parenthesis and  the reference qualification:
"Deleted &operator=(const Deleted &)&;" can be detected with 
TT_OverloadedOperatorLParen
"SomeType MemberFunction(const Deleted &)&;" can be detected with 
TT_FunctionDeclarationName
But "Deleted(const Deleted &)&;" cannot be detected with existing mechanisms:
  - Introduce TT_FunctionLParen to recognize Function parentheses.

TT_FunctionLParen assume that an 'identifier(' necessarily represent a function 
declaration or function call including constructors.
It could also happen for functional C-cast, but it seem safe to assume they 
should be treated as function.
This changeset is already quite big for me, so I did not try to ensure 
TT_FunctionDeclarationName is always followed by TT_FunctionLParen.
As TT_FunctionDeclarationName,  TT_FunctionLParen is currently a best effort 
guess. It could be added in a separate changeset with a new set of tests.

Tests:
=====
The set of unit tests is not quite minimal, it needs:
- To cover LLVM, Google, SpacesInCStyleCastParentheses, SpacesInParentheses.
- Both ref-qualifications : '&' and '&&'
- Operator, function, and constructor.

Additional test:
Verify clang-format output is unchanged for the 3 modified files FormatToken.h, 
TokenAnnotator.cpp, FormatTest.cpp

http://reviews.llvm.org/D7813

Files:
  lib/Format/FormatToken.h
  lib/Format/TokenAnnotator.cpp
  unittests/Format/FormatTest.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/Format/FormatToken.h
===================================================================
--- lib/Format/FormatToken.h
+++ lib/Format/FormatToken.h
@@ -43,6 +43,7 @@
   TT_DictLiteral,
   TT_FunctionDeclarationName,
   TT_FunctionLBrace,
+  TT_FunctionLParen,
   TT_FunctionTypeLParen,
   TT_ImplicitStringLiteral,
   TT_InheritanceColon,
Index: lib/Format/TokenAnnotator.cpp
===================================================================
--- lib/Format/TokenAnnotator.cpp
+++ lib/Format/TokenAnnotator.cpp
@@ -460,6 +460,8 @@
         return false;
       break;
     case tok::l_paren:
+      if (Tok->Previous && Tok->Previous->is(tok::identifier))
+        Tok->Type = TT_FunctionLParen;
       if (!parseParens())
         return false;
       if (Line.MustBeDeclaration && Contexts.size() == 1 &&
@@ -766,8 +768,8 @@
               break;
           }
           if (Previous->isOneOf(TT_BinaryOperator, TT_UnaryOperator) &&
-              Previous->isOneOf(tok::star, tok::amp) && Previous->Previous &&
-              Previous->Previous->isNot(tok::equal))
+              Previous->isOneOf(tok::star, tok::amp, tok::ampamp) &&
+              Previous->Previous && Previous->Previous->isNot(tok::equal))
             Previous->Type = TT_PointerOrReference;
         }
       }
@@ -802,6 +804,9 @@
     } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) {
       // This should be the condition or increment in a for-loop.
       Contexts.back().IsExpression = true;
+      if (Current.is(tok::semi) && Line.MustBeDeclaration && Current.Previous &&
+          Current.Previous->isOneOf(tok::star, tok::amp, tok::ampamp))
+        Current.Previous->Type = TT_PointerOrReference;
     }
   }
 
@@ -972,8 +977,7 @@
     bool IsSizeOfOrAlignOf =
         LeftOfParens && LeftOfParens->isOneOf(tok::kw_sizeof, tok::kw_alignof);
     if (ParensAreType && !ParensCouldEndDecl && !IsSizeOfOrAlignOf &&
-        ((Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression) ||
-         (Tok.Next && Tok.Next->isBinaryOperator())))
+        (Contexts.size() > 1 && Contexts[Contexts.size() - 2].IsExpression))
       IsCast = true;
     else if (Tok.Next && Tok.Next->isNot(tok::string_literal) &&
              (Tok.Next->Tok.isLiteral() ||
@@ -1663,9 +1667,12 @@
   if (Left.is(tok::l_square) && Right.is(tok::amp))
     return false;
   if (Right.is(TT_PointerOrReference))
-    return Left.Tok.isLiteral() ||
-           (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
-            Style.PointerAlignment != FormatStyle::PAS_Left);
+    return !(Left.is(tok::r_paren) && Left.MatchingParen &&
+             Left.MatchingParen->isOneOf(TT_OverloadedOperatorLParen,
+                                         TT_FunctionLParen)) &&
+           (Left.Tok.isLiteral() ||
+            (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) &&
+             Style.PointerAlignment != FormatStyle::PAS_Left));
   if (Right.is(TT_FunctionTypeLParen) && Left.isNot(tok::l_paren) &&
       (!Left.is(TT_PointerOrReference) ||
        Style.PointerAlignment != FormatStyle::PAS_Right))
Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -5164,17 +5164,52 @@
 
   verifyFormat("using A::operator+;");
 
-  verifyFormat("Deleted &operator=(const Deleted &)& = default;");
-  verifyFormat("Deleted &operator=(const Deleted &)&& = delete;");
-  verifyGoogleFormat("Deleted& operator=(const Deleted&)& = default;");
-  verifyGoogleFormat("Deleted& operator=(const Deleted&)&& = delete;");
-
   verifyFormat("string // break\n"
                "operator()() & {}");
   verifyFormat("string // break\n"
                "operator()() && {}");
 }
 
+TEST_F(FormatTest, UnderstandsFunctionRefQualification) {
+  verifyFormat("Deleted(const Deleted &)& = default;");
+  verifyFormat("Deleted(const Deleted &)&& = delete;");
+  verifyFormat("Deleted &operator=(const Deleted &)& = default;");
+  verifyFormat("Deleted &operator=(const Deleted &)&& = delete;");
+  verifyFormat("SomeType MemberFunction(const Deleted &)& = delete;");
+  verifyFormat("SomeType MemberFunction(const Deleted &)&& = delete;");
+  verifyFormat("Deleted(const Deleted &)&;");
+  verifyFormat("Deleted(const Deleted &)&&;");
+  verifyFormat("Deleted &operator=(const Deleted &)&;");
+  verifyFormat("Deleted &operator=(const Deleted &)&&;");
+  verifyFormat("SomeType MemberFunction(const Deleted &)&;");
+  verifyFormat("SomeType MemberFunction(const Deleted &)&&;");
+
+  verifyGoogleFormat("Deleted(const Deleted&)& = default;");
+  verifyGoogleFormat("Deleted& operator=(const Deleted&)& = default;");
+  verifyGoogleFormat("SomeType MemberFunction(const Deleted&)& = delete;");
+  verifyGoogleFormat("Deleted(const Deleted&)&;");
+  verifyGoogleFormat("Deleted& operator=(const Deleted&)&;");
+  verifyGoogleFormat("SomeType MemberFunction(const Deleted&)&;");
+
+  FormatStyle Spaces = getLLVMStyle();
+  Spaces.SpacesInCStyleCastParentheses = true;
+  verifyFormat("Deleted(const Deleted &)& = default;", Spaces);
+  verifyFormat("Deleted &operator=(const Deleted &)& = default;", Spaces);
+  verifyFormat("SomeType MemberFunction(const Deleted &)& = delete;", Spaces);
+  verifyFormat("Deleted(const Deleted &)&;", Spaces);
+  verifyFormat("Deleted &operator=(const Deleted &)&;", Spaces);
+  verifyFormat("SomeType MemberFunction(const Deleted &)&;", Spaces);
+
+  Spaces.SpacesInCStyleCastParentheses = false;
+  Spaces.SpacesInParentheses = true;
+  verifyFormat("Deleted( const Deleted & )& = default;", Spaces);
+  verifyFormat("Deleted &operator=( const Deleted & )& = default;", Spaces);
+  verifyFormat("SomeType MemberFunction( const Deleted & )& = delete;", Spaces);
+  verifyFormat("Deleted( const Deleted & )&;", Spaces);
+  verifyFormat("Deleted &operator=( const Deleted & )&;", Spaces);
+  verifyFormat("SomeType MemberFunction( const Deleted & )&;", Spaces);
+}
+
 TEST_F(FormatTest, UnderstandsNewAndDelete) {
   verifyFormat("void f() {\n"
                "  A *a = new A;\n"
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to