tamas.petz updated this revision to Diff 247561.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75364/new/

https://reviews.llvm.org/D75364

Files:
  clang/lib/Format/TokenAnnotator.cpp
  clang/unittests/Format/FormatTest.cpp

Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -7356,6 +7356,10 @@
   verifyFormat("void f(const MyFinal &final);");
   verifyIndependentOfContext("bool a = f() && override.f();");
   verifyIndependentOfContext("bool a = f() && final.f();");
+  verifyFormat("int f(M(x) *p1 = nullptr, M(x) *p2, volatile M(x) *p3);");
+  verifyFormat("M(x) *foo();");
+  verifyFormat("const M(x) *foo(M(x) *a = nullptr);");
+  verifyFormat("const M(x) *foo::bar(M(x) *a = nullptr);");
 
   verifyIndependentOfContext("InvalidRegions[*R] = 0;");
 
@@ -7396,6 +7400,10 @@
   verifyGoogleFormat("void f(Bar* a = nullptr, Bar* b);");
   verifyGoogleFormat("template <typename T>\n"
                      "void f(int i = 0, SomeType** temps = NULL);");
+  verifyGoogleFormat("int f(M(x)* p1 = nullptr, const M(x)* p2);");
+  verifyGoogleFormat("M(x)* foo();");
+  verifyGoogleFormat("const M(x)* foo(M(x)* a = nullptr);");
+  verifyGoogleFormat("const M(x)* foo::bar(M(x)* a = nullptr);");
 
   FormatStyle Left = getLLVMStyle();
   Left.PointerAlignment = FormatStyle::PAS_Left;
@@ -7410,6 +7418,11 @@
   verifyFormat("auto x(A&&, B&&, C&&) -> D;", Left);
   verifyFormat("auto x = [](A&&, B&&, C&&) -> D {};", Left);
   verifyFormat("template <class T> X(T&&, T&&, T&&) -> X<T>;", Left);
+  verifyFormat("int f(M(x)* p1 = nullptr, const M(x)* p2, volatile M(x)* p3);",
+               Left);
+  verifyFormat("M(x)* foo();", Left);
+  verifyFormat("const M(x)* foo(M(x)* a = nullptr);", Left);
+  verifyFormat("const M(x)* foo::bar(M(x)* a = nullptr);", Left);
 
   verifyIndependentOfContext("a = *(x + y);");
   verifyIndependentOfContext("a = &(x + y);");
@@ -7537,6 +7550,11 @@
   verifyFormat("A = new SomeType *[Length]();", PointerMiddle);
   verifyFormat("A = new SomeType *[Length];", PointerMiddle);
   verifyFormat("T ** t = new T *;", PointerMiddle);
+  verifyFormat("int f(M(x) * p1 = nullptr, const M(x) * p2 = nullptr);",
+               PointerMiddle);
+  verifyFormat("M(x) * foo();", PointerMiddle);
+  verifyFormat("const M(x) * foo(M(x) * a = nullptr);", PointerMiddle);
+  verifyFormat("const M(x) * foo::bar(M(x) * a = nullptr);", PointerMiddle);
 
   // Member function reference qualifiers aren't binary operators.
   verifyFormat("string // break\n"
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -160,6 +160,14 @@
     return false;
   }
 
+  /// Parses CPP qualified function names.
+  bool parse_function_qname(FormatToken *Tok) const {
+    while (Tok && Tok->isOneOf(tok::coloncolon, tok::identifier)) {
+      Tok = Tok->Next;
+    }
+    return Tok && Tok->is(tok::l_paren);
+  }
+
   bool parseParens(bool LookForDecls = false) {
     if (!CurrentToken)
       return false;
@@ -250,6 +258,7 @@
     bool HasMultipleParametersOnALine = false;
     bool MightBeObjCForRangeLoop =
         Left->Previous && Left->Previous->is(tok::kw_for);
+    bool HasStarToken = false;
     FormatToken *PossibleObjCForInToken = nullptr;
     while (CurrentToken) {
       // LookForDecls is set when "if (" has been seen. Check for
@@ -299,6 +308,55 @@
           }
         }
 
+        // Detect cases where macros are used in function parameter lists,
+        // for example:
+        //   void f(volatile ElfW(Addr)* addr = nullptr);
+        if (HasStarToken) {
+          for (FormatToken *Tok = Left; Tok != CurrentToken; Tok = Tok->Next) {
+            // Search for ') *' patterns.
+            if (Tok->is(tok::star) && Tok->Previous->is(tok::r_paren)) {
+              // Extend search to left looking for 'X(...) *' patterns.
+              FormatToken *LparenTok = Tok->Previous->MatchingParen;
+              if (LparenTok && LparenTok->is(tok::l_paren) &&
+                  LparenTok->Previous) {
+                FormatToken *MacroTok = LparenTok->Previous;
+                // Decide if 'X' is following "l_paren" of this function,
+                // a keyword or a comma.
+                if (MacroTok->is(tok::identifier) && MacroTok->Previous &&
+                    (MacroTok->Previous == Left ||
+                     MacroTok->Previous->isOneOf(tok::comma, tok::kw_const,
+                                                 tok::kw_volatile))) {
+                  Tok->Type = TT_PointerOrReference;
+                  LparenTok->Previous->Type = TT_TypenameMacro;
+                }
+              }
+            }
+          }
+        }
+
+        // Detect cases where macros are used in function return types,
+        // for example:
+        //   const ElfW(Addr)* f();
+        if (CurrentToken->Next && CurrentToken->Next->is(tok::star)) {
+          if (parse_function_qname(CurrentToken->Next->Next)) {
+            bool Found = true;
+            FormatToken *const Prev = CurrentToken->MatchingParen->Previous;
+            if (Prev && Prev->is(tok::identifier)) {
+              for (FormatToken *Tok = Prev; Tok; Tok = Tok->Previous) {
+                if (!Tok->is(TT_Unknown)) {
+                  Found = false;
+                  break;
+                } else if (Prev->is(tok::semi))
+                  break;
+              }
+            }
+            if (Found) {
+              CurrentToken->Next->Type = TT_PointerOrReference;
+              Prev->Type = TT_TypenameMacro;
+            }
+          }
+        }
+
         if (StartsObjCMethodExpr) {
           CurrentToken->Type = TT_ObjCMethodExpr;
           if (Contexts.back().FirstObjCSelectorName) {
@@ -355,6 +413,9 @@
       if (CurrentToken->is(tok::comma))
         Contexts.back().CanBeExpression = true;
 
+      if (CurrentToken->is(tok::star))
+        HasStarToken = true;
+
       FormatToken *Tok = CurrentToken;
       if (!consumeToken())
         return false;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to