thakis created this revision.
thakis added reviewers: klimek, sammccall.

Fixes PR39247.

While here, also make C++20 `namespace A::inline B::inline C` nested
inline namespaced definitions work.

Before:

  #define DEPRECATE_WOOF [[deprecated("meow")]]
  
  namespace DEPRECATE_WOOF woof {
  void f() {}
  } // namespace DEPRECATE_WOOFwoof
  
  namespace [[deprecated("meow")]] woof {
    void f() {}
  } // namespace [[deprecated("meow")]]woof
  
  namespace woof::inline bark {
    void f() {}
  } // namespace woof::inlinebark

Now:

  #define DEPRECATE_WOOF [[deprecated("meow")]]
  
  namespace DEPRECATE_WOOF woof {
  void f() {}
  } // namespace woof
  
  namespace [[deprecated("meow")]] woof {
  void f() {}
  } // namespace woof
  
  namespace woof::inline bark {
  void f() {}
  } // namespace woof::inline bark

(In addition to the fixed namespace end comments, also note the correct
indent of the namespace contents.)


https://reviews.llvm.org/D65125

Files:
  clang/lib/Format/NamespaceEndCommentsFixer.cpp
  clang/lib/Format/UnwrappedLineParser.cpp
  clang/unittests/Format/FormatTest.cpp
  clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp

Index: clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
===================================================================
--- clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
+++ clang/unittests/Format/NamespaceEndCommentsFixerTest.cpp
@@ -77,6 +77,44 @@
                                     "int i;\n"
                                     "int j;\n"
                                     "}"));
+
+  EXPECT_EQ("namespace [[deprecated(\"foo\")]] A::B {\n"
+            "int i;\n"
+            "int j;\n"
+            "}// namespace A::B",
+            fixNamespaceEndComments("namespace [[deprecated(\"foo\")]] A::B {\n"
+                                    "int i;\n"
+                                    "int j;\n"
+                                    "}"));
+
+  EXPECT_EQ("namespace [[deprecated(\"foo\")]] A::inline B::inline C {\n"
+            "int i;\n"
+            "int j;\n"
+            "}// namespace A::inline B::inline C",
+            fixNamespaceEndComments(
+                "namespace [[deprecated(\"foo\")]] A::inline B::inline C {\n"
+                "int i;\n"
+                "int j;\n"
+                "}"));
+
+  EXPECT_EQ("namespace DEPRECATED A::B {\n"
+            "int i;\n"
+            "int j;\n"
+            "}// namespace A::B",
+            fixNamespaceEndComments("namespace DEPRECATED A::B {\n"
+                                    "int i;\n"
+                                    "int j;\n"
+                                    "}"));
+
+  EXPECT_EQ("inline namespace [[deprecated]] A {\n"
+            "int i;\n"
+            "int j;\n"
+            "}// namespace A",
+            fixNamespaceEndComments("inline namespace [[deprecated]] A {\n"
+                                    "int i;\n"
+                                    "int j;\n"
+                                    "}"));
+
   EXPECT_EQ("namespace ::A {\n"
             "int i;\n"
             "int j;\n"
@@ -410,7 +448,8 @@
                                     /*Ranges=*/{1, tooling::Range(16, 3)}));
 }
 
-TEST_F(NamespaceEndCommentsFixerTest, DoesNotAddCommentAfterRBraceInPPDirective) {
+TEST_F(NamespaceEndCommentsFixerTest,
+       DoesNotAddCommentAfterRBraceInPPDirective) {
   EXPECT_EQ("#define SAD \\\n"
             "namespace A { \\\n"
             "int i; \\\n"
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -1767,6 +1767,21 @@
                "void f() { f(); }\n"
                "}",
                LLVMWithNoNamespaceFix);
+  verifyFormat("namespace N::inline D {\n"
+               "class A {};\n"
+               "void f() { f(); }\n"
+               "}",
+               LLVMWithNoNamespaceFix);
+  verifyFormat("namespace N::inline D::E {\n"
+               "class A {};\n"
+               "void f() { f(); }\n"
+               "}",
+               LLVMWithNoNamespaceFix);
+  verifyFormat("namespace [[deprecated(\"foo[bar\")]] some_namespace {\n"
+               "class A {};\n"
+               "void f() { f(); }\n"
+               "}",
+               LLVMWithNoNamespaceFix);
   verifyFormat("/* something */ namespace some_namespace {\n"
                "class A {};\n"
                "void f() { f(); }\n"
Index: clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -1872,8 +1872,13 @@
   if (InitialToken.is(TT_NamespaceMacro)) {
     parseParens();
   } else {
-    while (FormatTok->isOneOf(tok::identifier, tok::coloncolon))
-      nextToken();
+    while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
+                              tok::l_square)) {
+      if (FormatTok->is(tok::l_square))
+        parseSquare();
+      else
+        nextToken();
+    }
   }
   if (FormatTok->Tok.is(tok::l_brace)) {
     if (ShouldBreakBeforeBrace(Style, InitialToken))
Index: clang/lib/Format/NamespaceEndCommentsFixer.cpp
===================================================================
--- clang/lib/Format/NamespaceEndCommentsFixer.cpp
+++ clang/lib/Format/NamespaceEndCommentsFixer.cpp
@@ -36,7 +36,7 @@
   const FormatToken *Tok = NamespaceTok->getNextNonComment();
   if (NamespaceTok->is(TT_NamespaceMacro)) {
     // Collects all the non-comment tokens between opening parenthesis
-    // and closing parenthesis or comma
+    // and closing parenthesis or comma.
     assert(Tok && Tok->is(tok::l_paren) && "expected an opening parenthesis");
     Tok = Tok->getNextNonComment();
     while (Tok && !Tok->isOneOf(tok::r_paren, tok::comma)) {
@@ -44,9 +44,21 @@
       Tok = Tok->getNextNonComment();
     }
   } else {
-    // Collects all the non-comment tokens between 'namespace' and '{'.
+    // For `namespace [[foo]] A::B::inline C {` or
+    // `namespace MACRO1 MACRO2 A::B::inline C {`, returns "A::B::inline C".
+    // Peek for the first '::' (or '{') and then return all tokens from one
+    // token before that up until the '{'.
+    const FormatToken *FirstNSTok = Tok;
+    while (Tok && !Tok->is(tok::l_brace) && !Tok->is(tok::coloncolon)) {
+      FirstNSTok = Tok;
+      Tok = Tok->getNextNonComment();
+    }
+
+    Tok = FirstNSTok;
     while (Tok && !Tok->is(tok::l_brace)) {
       name += Tok->TokenText;
+      if (Tok->is(tok::kw_inline))
+        name += " ";
       Tok = Tok->getNextNonComment();
     }
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to