brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · 1eab83f Raw
315 lines · plain
1======================2Clang-Change-Namespace3======================4 5.. contents::6 7.. toctree::8  :maxdepth: 19 10:program:`clang-change-namespace` can be used to change the surrounding11namespaces of class/function definitions.12 13Classes/functions in the moved namespace will have new namespaces while14references to symbols (e.g. types, functions) which are not defined in the15changed namespace will be correctly qualified by prepending namespace specifiers16before them. This will try to add shortest namespace specifiers possible.17 18When a symbol reference needs to be fully-qualified, this adds a `::` prefix to19the namespace specifiers unless the new namespace is the global namespace. For20classes, only classes that are declared/defined in the given namespace in21specified files will be moved: forward declarations will remain in the old22namespace. The will be demonstrated in the next example.23 24Example usage25-------------26 27For example, consider this `test.cc` example here with the forward declared28class `FWD` and the defined class `A`, both in the namespace `a`.29 30.. code-block:: c++31 32  namespace a {33  class FWD;34  class A {35    FWD *fwd;36  };37  } // namespace a38 39And now let's change the namespace `a` to `x`.40 41.. code-block:: console42 43  clang-change-namespace \44    --old_namespace "a" \45    --new_namespace "x" \46    --file_pattern "test.cc" \47    --i \48    test.cc49 50Note that in the code below there's still the forward decalred class `FWD` that51stayed in the namespace `a`. It wasn't moved to the new namespace because it52wasn't defined/declared here in `a` but only forward declared.53 54.. code-block:: c++55 56  namespace a {57  class FWD;58  } // namespace a59  namespace x {60 61  class A {62    a::FWD *fwd;63  };64  } // namespace x65 66 67Another example68---------------69 70Consider this `test.cc` file:71 72.. code-block:: c++73 74  namespace na {75  class X {};76  namespace nb {77  class Y {78    X x;79  };80  } // namespace nb81  } // namespace na82 83To move the definition of class `Y` from namespace `na::nb` to `x::y`, run:84 85.. code-block:: console86 87  clang-change-namespace \88    --old_namespace "na::nb" \89    --new_namespace "x::y" \90    --file_pattern "test.cc" \91    --i \92    test.cc93 94This will overwrite `test.cc` to look like this:95 96.. code-block:: c++97 98  namespace na {99  class X {};100 101  } // namespace na102  namespace x {103  namespace y {104  class Y {105    na::X x;106  };107  } // namespace y108  } // namespace x109 110Note, that we've successfully moved the class `Y` from namespace `na::nb` to111namespace `x::y`.112 113Caveats114=======115 116Content already exists in new namespace117---------------------------------------118 119Consider this `test.cc` example that defines two `class A` one inside the120namespace `a` and one in namespace `b`:121 122.. code-block:: c++123 124  namespace a {125  class A {126      int classAFromWithinNamespace_a;127  };128  } // namespace a129 130  namespace b {131  class A {132      int classAFromWithinNamespace_b;133  };134  } //namespace b135 136Let's move everything from namespace `a` to namespace `b`:137 138.. code-block:: console139 140  clang-change-namespace \141    --old_namespace "a" \142    --new_namespace "b" \143    --file_pattern test.cc \144    test.cc145 146As expected we now have to definitions of `class A` inside the namespace `b`:147 148.. code-block:: c++149 150  namespace b {151  class A {152    int classAFromWithinNamespace_a;153  };154  } // namespace b155 156  namespace b {157  class A {158      int classAFromWithinNamespace_b;159  };160  } //namespace b161 162The re-factoring looks correct but the code will not compile due to the name163duplication. It is not up to the tool to ensure compilability in that sense.164But one has to be aware of that.165 166Inline namespace doesn't work167-----------------------------168 169Consider this usage of two versions of implementations for a `greet` function:170 171.. code-block:: c++172 173  #include <cstdio>174 175  namespace Greeter {176  inline namespace Version1 {177    const char* greet() { return "Hello from version 1!"; }178  } // namespace Version1179  namespace Version2 {180    const char* greet() { return "Hello from version 2!"; }181  } // namespace Version2182  } // namespace Greeter183 184  int main(int argc, char* argv[]) {185    printf("%s\n", Greeter::greet());186    return 0;187  }188 189Note, that currently `Greeter::greet()` will result in a call to190`Greeter::Version1::greet()` because that's the inlined namespace.191 192Let's say you want to move one and make `Version2` the default now and remove193the `inline` from the `Version1`. First let's try to turn `namespace Version2`194into `inline namespace Version2`:195 196.. code-block:: console197 198  clang-change-namespace \199    --old_namespace "Greeter::Version2" \200    --new_namespace "inline Version2" \201    --file_pattern main.cc main.cc202 203But this will put the `inline` keyword in the wrong place resulting in:204 205.. code-block:: c++206 207  #include <cstdio>208 209  namespace Greeter {210  inline namespace Version1 {211          const char* greet() { return "Hello from version 1!"; }212  } // namespace Version1213 214  } // namespace Greeter215  namespace inline Greeter {216  namespace Version2 {217  const char *greet() { return "Hello from version 2!"; }218  } // namespace Version2219  } // namespace inline Greeter220 221  int main(int argc, char* argv[]) {222          printf("%s\n", Greeter::greet());223          return 0;224  }225 226One cannot use `:program:`clang-change-namespace` to inline a namespace.227 228Symbol references not updated229-----------------------------230 231Consider this `test.cc` file:232 233.. code-block:: c++234 235  namespace old {236  struct foo {};237  }  // namespace old238 239  namespace b {240  old::foo g_foo;241  }  // namespace b242 243Notice that namespace `b` defines a global variable of type `old::foo`. If we244now change the name of the `old` namespace to `modern`, the reference will not245be updated:246 247.. code-block:: console248 249  clang-change-namespace \250    --old_namespace "old" \251    --new_namespace "modern" \252    --file_pattern test.cc \253    test.cc254 255.. code-block:: c++256 257  namespace modern {258  struct foo {};259  } // namespace modern260 261  namespace b {262  old::foo g_foo;263  }  // namespace b264 265`g_foo` is still of the no longer existing type `old::foo` while instead it266should use `modern::foo`.267 268Only symbol references in the moved namespace are updated, not outside of it.269 270 271:program:`clang-change-namespace` Command Line Options272======================================================273 274.. option:: --allowed_file=<string>275 276  A file containing regexes of symbol names that are not expected to be updated277  when changing namespaces around them.278 279.. option:: --dump_result280 281  Dump new file contents in YAML, if specified.282 283.. option:: --extra-arg=<string>284 285  Additional argument to append to the compiler command line286 287.. option:: --extra-arg-before=<string>288 289  Additional argument to prepend to the compiler command line290 291.. option:: --file_pattern=<string>292 293  Only rename namespaces in files that match the given regular expression294  pattern.295 296.. option:: -i297 298  Inplace edit <file>s, if specified.299 300.. option:: --new_namespace=<string>301 302  New namespace. Use `""` when you target the global namespace.303 304.. option:: --old_namespace=<string>305 306  Old namespace.307 308.. option:: -p <string>309 310  Build path311 312.. option:: --style=<string>313 314  The style name used for reformatting.315