https://github.com/kwk updated https://github.com/llvm/llvm-project/pull/148277

>From e5f1b218ae17c2c9767ddff7fe3d2fbb2962e4fb Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkle...@redhat.com>
Date: Fri, 11 Jul 2025 18:39:16 +0000
Subject: [PATCH 1/7] [doc] Add documentation for clang-change-namespace

This adds rst documentation for the `clang-change-namespace` program.

I ran the examples locally to ensure they work.

See #35519
---
 .../docs/clang-change-namespace.rst           | 158 ++++++++++++++++++
 clang-tools-extra/docs/index.rst              |   1 +
 2 files changed, 159 insertions(+)
 create mode 100644 clang-tools-extra/docs/clang-change-namespace.rst

diff --git a/clang-tools-extra/docs/clang-change-namespace.rst 
b/clang-tools-extra/docs/clang-change-namespace.rst
new file mode 100644
index 0000000000000..23c3dcc8b7412
--- /dev/null
+++ b/clang-tools-extra/docs/clang-change-namespace.rst
@@ -0,0 +1,158 @@
+======================
+Clang-Change-Namespace
+======================
+
+.. contents::
+
+.. toctree::
+  :maxdepth: 1
+
+:program:`clang-change-namespace` can be used to change the surrounding
+namespaces of class/function definitions.
+
+Classes/functions in the moved namespace will have new namespaces while
+references to symbols (e.g. types, functions) which are not defined in the
+changed namespace will be correctly qualified by prepending namespace 
specifiers
+before them. This will try to add shortest namespace specifiers possible.
+
+When a symbol reference needs to be fully-qualified, this adds a `::` prefix to
+the namespace specifiers unless the new namespace is the global namespace. For
+classes, only classes that are declared/defined in the given namespace in
+specified files will be moved: forward declarations will remain in the old
+namespace. The will be demonstrated in the next example.
+
+Example usage
+-------------
+
+For example, consider this `test.cc` example here with the forward declared
+class `FWD` and the defined class `A`, both in the namespace `a`.
+
+.. code-block:: c++
+  :linenos:
+
+  namespace a {
+  class FWD;
+  class A {
+    FWD *fwd;
+  };
+  } // namespace a
+
+And now let's change the namespace `a` to `x`.
+
+.. code-block:: console
+  clang-change-namespace \
+    --old_namespace "a" \
+    --new_namespace "x" \
+    --file_pattern "test.cc" \
+    --i \
+    test.cc
+
+Note that in the code below there's still the forward decalred class `FWD` that
+stayed in the namespace `a`. It wasn't moved to the new namespace because it
+wasn't defined/declared here in `a` but only forward declared.
+
+.. code-block:: c++
+  :linenos:
+
+  namespace a {
+  class FWD;
+  } // namespace a
+  namespace x {
+
+  class A {
+    a::FWD *fwd;
+  };
+  } // namespace x
+
+
+Another example
+---------------
+
+Consider this `test.cc` file:
+
+.. code-block:: c++
+  :linenos:
+
+  namespace na {
+  class X {};
+  namespace nb {
+  class Y {
+    X x;
+  };
+  } // namespace nb
+  } // namespace na
+
+To move the definition of class `Y` from namespace `na::nb` to `x::y`, run:
+
+.. code-block:: console
+
+  clang-change-namespace \
+    --old_namespace "na::nb" \
+    --new_namespace "x::y" \
+    --file_pattern "test.cc" \
+    --i \
+    test.cc
+
+This will overwrite `test.cc` to look like this:
+
+.. code-block:: c++
+  :linenos:
+
+  namespace na {
+  class X {};
+
+  } // namespace na
+  namespace x {
+  namespace y {
+  class Y {
+    na::X x;
+  };
+  } // namespace y
+  } // namespace x
+
+Note, that we've successfully moved the class `Y` from namespace `na::nb` to
+namespace `x::y`.
+
+:program:`clang-change-namespace` Command Line Options
+======================================================
+
+.. option:: --allowed_file=<string>     
+
+  A file containing regexes of symbol names that are not expected to be updated
+  when changing namespaces around them.
+
+.. option:: --dump_result               
+
+  Dump new file contents in YAML, if specified.
+
+.. option:: --extra-arg=<string>        
+
+  Additional argument to append to the compiler command line
+
+.. option:: --extra-arg-before=<string> 
+
+  Additional argument to prepend to the compiler command line
+
+.. option:: --file_pattern=<string>     
+
+  Only rename namespaces in files that match the given pattern.
+
+.. option:: -i                          
+ 
+  Inplace edit <file>s, if specified.
+
+.. option:: --new_namespace=<string>    
+ 
+  New namespace.
+
+.. option:: --old_namespace=<string>    
+ 
+  Old namespace.
+
+.. option:: -p <string>                 
+ 
+  Build path
+
+.. option:: --style=<string>            
+ 
+  The style name used for reformatting.
diff --git a/clang-tools-extra/docs/index.rst b/clang-tools-extra/docs/index.rst
index 9f7324fcf7419..3f3a99d1b70c6 100644
--- a/clang-tools-extra/docs/index.rst
+++ b/clang-tools-extra/docs/index.rst
@@ -17,6 +17,7 @@ Contents
 
    clang-tidy/index
    clang-include-fixer
+   clang-change-namespace
    modularize
    pp-trace
    clangd <https://clangd.llvm.org/>

>From 255552b76b1c62d098bf8da22633678bacd00892 Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkle...@redhat.com>
Date: Fri, 11 Jul 2025 21:34:07 +0000
Subject: [PATCH 2/7] Fixup

---
 clang-tools-extra/docs/clang-change-namespace.rst | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/clang-tools-extra/docs/clang-change-namespace.rst 
b/clang-tools-extra/docs/clang-change-namespace.rst
index 23c3dcc8b7412..0e83165c48cfc 100644
--- a/clang-tools-extra/docs/clang-change-namespace.rst
+++ b/clang-tools-extra/docs/clang-change-namespace.rst
@@ -28,7 +28,6 @@ For example, consider this `test.cc` example here with the 
forward declared
 class `FWD` and the defined class `A`, both in the namespace `a`.
 
 .. code-block:: c++
-  :linenos:
 
   namespace a {
   class FWD;
@@ -40,6 +39,7 @@ class `FWD` and the defined class `A`, both in the namespace 
`a`.
 And now let's change the namespace `a` to `x`.
 
 .. code-block:: console
+
   clang-change-namespace \
     --old_namespace "a" \
     --new_namespace "x" \
@@ -52,7 +52,6 @@ stayed in the namespace `a`. It wasn't moved to the new 
namespace because it
 wasn't defined/declared here in `a` but only forward declared.
 
 .. code-block:: c++
-  :linenos:
 
   namespace a {
   class FWD;
@@ -71,7 +70,6 @@ Another example
 Consider this `test.cc` file:
 
 .. code-block:: c++
-  :linenos:
 
   namespace na {
   class X {};
@@ -96,7 +94,6 @@ To move the definition of class `Y` from namespace `na::nb` 
to `x::y`, run:
 This will overwrite `test.cc` to look like this:
 
 .. code-block:: c++
-  :linenos:
 
   namespace na {
   class X {};

>From 73a64b462271b09617fa570d6352abb7ebf2689d Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkle...@redhat.com>
Date: Mon, 18 Aug 2025 10:39:25 +0000
Subject: [PATCH 3/7] Add caveats section

Document the problem when content already exists in new namespace.
---
 .../docs/clang-change-namespace.rst           | 54 +++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/clang-tools-extra/docs/clang-change-namespace.rst 
b/clang-tools-extra/docs/clang-change-namespace.rst
index 0e83165c48cfc..c6419cc8849ff 100644
--- a/clang-tools-extra/docs/clang-change-namespace.rst
+++ b/clang-tools-extra/docs/clang-change-namespace.rst
@@ -110,6 +110,60 @@ This will overwrite `test.cc` to look like this:
 Note, that we've successfully moved the class `Y` from namespace `na::nb` to
 namespace `x::y`.
 
+Caveats
+=======
+
+Content already exists in new namespace
+---------------------------------------
+
+Consider this `test.cc` example that defines two `class A` one inside the
+namespace `a` and one in namespace `b`:
+
+.. code-block:: c++
+
+  namespace a {
+  class A {
+      int classAFromWithinNamespace_a;
+  };
+  } // namespace a
+
+  namespace b {
+  class A {
+      int classAFromWithinNamespace_b;
+  };
+  } //namespace b
+
+Let's move everything from the namespace `a` to the global namespace
+(`--new_namespace ""` means global namespace):
+
+.. code-block:: console
+
+  clang-change-namespace \
+    --old_namespace "a" \
+    --new_namespace "b" \
+    --file_pattern test.cc \
+    test.cc
+
+As expected we now have to definitions of `class A` inside the namespace `b`:
+
+.. code-block:: c++
+
+  namespace b {
+  class A {
+    int classAFromWithinNamespace_a;
+  };
+  } // namespace b
+
+  namespace b {
+  class A {
+      int classAFromWithinNamespace_b;
+  };
+  } //namespace b
+
+The re-factoring looks correct but the code will not compile due to the name
+duplication. It is not up to the tool to ensure compilability in that sense.
+But one has to be aware of that.
+
 :program:`clang-change-namespace` Command Line Options
 ======================================================
 

>From 5ca20a39227caae7e7d61a605b38b06b743515a2 Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkle...@redhat.com>
Date: Mon, 18 Aug 2025 10:47:17 +0000
Subject: [PATCH 4/7] Document --file_pattern parameter to be regular
 expression

---
 clang-tools-extra/docs/clang-change-namespace.rst | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/docs/clang-change-namespace.rst 
b/clang-tools-extra/docs/clang-change-namespace.rst
index c6419cc8849ff..64be182383812 100644
--- a/clang-tools-extra/docs/clang-change-namespace.rst
+++ b/clang-tools-extra/docs/clang-change-namespace.rst
@@ -184,11 +184,12 @@ But one has to be aware of that.
 
   Additional argument to prepend to the compiler command line
 
-.. option:: --file_pattern=<string>     
+.. option:: --file_pattern=<string>
 
-  Only rename namespaces in files that match the given pattern.
+  Only rename namespaces in files that match the given regular expression
+  pattern.
 
-.. option:: -i                          
+.. option:: -i     
  
   Inplace edit <file>s, if specified.
 

>From c08050c857f55879b093316989278112b9646aa4 Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkle...@redhat.com>
Date: Mon, 18 Aug 2025 10:49:20 +0000
Subject: [PATCH 5/7] Document --new_namespace global namespace

---
 clang-tools-extra/docs/clang-change-namespace.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/clang-change-namespace.rst 
b/clang-tools-extra/docs/clang-change-namespace.rst
index 64be182383812..faf92e42b0ba2 100644
--- a/clang-tools-extra/docs/clang-change-namespace.rst
+++ b/clang-tools-extra/docs/clang-change-namespace.rst
@@ -195,7 +195,7 @@ But one has to be aware of that.
 
 .. option:: --new_namespace=<string>    
  
-  New namespace.
+  New namespace. Use `""` when you target the global namespace.
 
 .. option:: --old_namespace=<string>    
  

>From 0b5560c7a32510d864a843f405ce1ae82d146aae Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkle...@redhat.com>
Date: Mon, 18 Aug 2025 10:49:33 +0000
Subject: [PATCH 6/7] Trim trailing whitespaces

---
 .../docs/clang-change-namespace.rst           | 28 +++++++++----------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/clang-tools-extra/docs/clang-change-namespace.rst 
b/clang-tools-extra/docs/clang-change-namespace.rst
index faf92e42b0ba2..d2b7b5032d2f0 100644
--- a/clang-tools-extra/docs/clang-change-namespace.rst
+++ b/clang-tools-extra/docs/clang-change-namespace.rst
@@ -167,20 +167,20 @@ But one has to be aware of that.
 :program:`clang-change-namespace` Command Line Options
 ======================================================
 
-.. option:: --allowed_file=<string>     
+.. option:: --allowed_file=<string>
 
   A file containing regexes of symbol names that are not expected to be updated
   when changing namespaces around them.
 
-.. option:: --dump_result               
+.. option:: --dump_result
 
   Dump new file contents in YAML, if specified.
 
-.. option:: --extra-arg=<string>        
+.. option:: --extra-arg=<string>
 
   Additional argument to append to the compiler command line
 
-.. option:: --extra-arg-before=<string> 
+.. option:: --extra-arg-before=<string>
 
   Additional argument to prepend to the compiler command line
 
@@ -189,22 +189,22 @@ But one has to be aware of that.
   Only rename namespaces in files that match the given regular expression
   pattern.
 
-.. option:: -i     
- 
+.. option:: -i
+
   Inplace edit <file>s, if specified.
 
-.. option:: --new_namespace=<string>    
- 
+.. option:: --new_namespace=<string>
+
   New namespace. Use `""` when you target the global namespace.
 
-.. option:: --old_namespace=<string>    
- 
+.. option:: --old_namespace=<string>
+
   Old namespace.
 
-.. option:: -p <string>                 
- 
+.. option:: -p <string>
+
   Build path
 
-.. option:: --style=<string>            
- 
+.. option:: --style=<string>
+
   The style name used for reformatting.

>From ea8c545b6c645941edb5f73146f89383d6eff503 Mon Sep 17 00:00:00 2001
From: Konrad Kleine <kkle...@redhat.com>
Date: Mon, 18 Aug 2025 11:06:26 +0000
Subject: [PATCH 7/7] Add caveat sub-section on inlining namespaces

---
 .../docs/clang-change-namespace.rst           | 63 +++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/clang-tools-extra/docs/clang-change-namespace.rst 
b/clang-tools-extra/docs/clang-change-namespace.rst
index d2b7b5032d2f0..1b6a845b987f9 100644
--- a/clang-tools-extra/docs/clang-change-namespace.rst
+++ b/clang-tools-extra/docs/clang-change-namespace.rst
@@ -164,6 +164,69 @@ The re-factoring looks correct but the code will not 
compile due to the name
 duplication. It is not up to the tool to ensure compilability in that sense.
 But one has to be aware of that.
 
+Inline namespace doesn't work
+-----------------------------
+
+Consider this usage of two versions of implementations for a `greet` function:
+
+.. code-block:: c++
+  #include <cstdio>
+
+  namespace Greeter {
+  inline namespace Version1 {
+    const char* greet() { return "Hello from version 1!"; }
+  } // namespace Version1
+  namespace Version2 {
+    const char* greet() { return "Hello from version 2!"; }
+  } // namespace Version2
+  } // namespace Greeter
+
+  int main(int argc, char* argv[]) {
+    printf("%s\n", Greeter::greet());
+    return 0;
+  }
+
+Note, that currently `Greeter::greet()` will result in a call to
+`Greeter::Version1::greet()` because that's the inlined namespace.
+
+Let's say you want to move one and make `Version2` the default now and remove
+the `inline` from the `Version1`. First let's try to turn `namespace Version2`
+into `inline namespace Version2`:
+
+.. code-block:: console
+
+  clang-change-namespace \
+    --old_namespace "Greeter::Version2" \
+    --new_namespace "inline Version2" \
+    --file_pattern main.cc main.cc
+
+But this will put the `inline` keyword in the wrong place resulting in:
+
+.. code-block:: c++
+
+  #include <cstdio>
+
+  namespace Greeter {
+  inline namespace Version1 {
+          const char* greet() { return "Hello from version 1!"; }
+  } // namespace Version1
+
+  } // namespace Greeter
+  namespace inline Greeter {
+  namespace Version2 {
+  const char *greet() { return "Hello from version 2!"; }
+  } // namespace Version2
+  } // namespace inline Greeter
+
+  int main(int argc, char* argv[]) {
+          printf("%s\n", Greeter::greet());
+          return 0;
+  }
+
+Apparently one cannot use `:program:`clang-change-namespace` to inline a
+namespace.
+
+
 :program:`clang-change-namespace` Command Line Options
 ======================================================
 

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to