Skip to content

Commit 5692546

Browse files
committed
Merge branch 'main' into distr_utils_fix
2 parents 521f0ff + b20bbd4 commit 5692546

40 files changed

+1307
-530
lines changed

clang-tools-extra/clang-tidy/add_new_check.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,9 @@ def write_header(
8989
+ check_name_camel.upper()
9090
+ "_H"
9191
)
92-
f.write("//===--- ")
93-
f.write(os.path.basename(filename))
94-
f.write(" - clang-tidy ")
95-
f.write("-" * max(0, 42 - len(os.path.basename(filename))))
96-
f.write("*- C++ -*-===//")
9792
f.write(
9893
"""
94+
//===----------------------------------------------------------------------===//
9995
//
10096
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
10197
// See https://llvm.org/LICENSE.txt for license information.
@@ -145,13 +141,9 @@ def write_implementation(
145141
filename = os.path.join(module_path, check_name_camel) + ".cpp"
146142
print("Creating %s..." % filename)
147143
with io.open(filename, "w", encoding="utf8", newline="\n") as f:
148-
f.write("//===--- ")
149-
f.write(os.path.basename(filename))
150-
f.write(" - clang-tidy ")
151-
f.write("-" * max(0, 51 - len(os.path.basename(filename))))
152-
f.write("-===//")
153144
f.write(
154145
"""
146+
//===----------------------------------------------------------------------===//
155147
//
156148
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
157149
// See https://llvm.org/LICENSE.txt for license information.
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
======================
2+
Clang-Change-Namespace
3+
======================
4+
5+
.. contents::
6+
7+
.. toctree::
8+
:maxdepth: 1
9+
10+
:program:`clang-change-namespace` can be used to change the surrounding
11+
namespaces of class/function definitions.
12+
13+
Classes/functions in the moved namespace will have new namespaces while
14+
references to symbols (e.g. types, functions) which are not defined in the
15+
changed namespace will be correctly qualified by prepending namespace specifiers
16+
before them. This will try to add shortest namespace specifiers possible.
17+
18+
When a symbol reference needs to be fully-qualified, this adds a `::` prefix to
19+
the namespace specifiers unless the new namespace is the global namespace. For
20+
classes, only classes that are declared/defined in the given namespace in
21+
specified files will be moved: forward declarations will remain in the old
22+
namespace. The will be demonstrated in the next example.
23+
24+
Example usage
25+
-------------
26+
27+
For example, consider this `test.cc` example here with the forward declared
28+
class `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 a
38+
39+
And now let's change the namespace `a` to `x`.
40+
41+
.. code-block:: console
42+
43+
clang-change-namespace \
44+
--old_namespace "a" \
45+
--new_namespace "x" \
46+
--file_pattern "test.cc" \
47+
--i \
48+
test.cc
49+
50+
Note that in the code below there's still the forward decalred class `FWD` that
51+
stayed in the namespace `a`. It wasn't moved to the new namespace because it
52+
wasn't defined/declared here in `a` but only forward declared.
53+
54+
.. code-block:: c++
55+
56+
namespace a {
57+
class FWD;
58+
} // namespace a
59+
namespace x {
60+
61+
class A {
62+
a::FWD *fwd;
63+
};
64+
} // namespace x
65+
66+
67+
Another example
68+
---------------
69+
70+
Consider 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 nb
81+
} // namespace na
82+
83+
To move the definition of class `Y` from namespace `na::nb` to `x::y`, run:
84+
85+
.. code-block:: console
86+
87+
clang-change-namespace \
88+
--old_namespace "na::nb" \
89+
--new_namespace "x::y" \
90+
--file_pattern "test.cc" \
91+
--i \
92+
test.cc
93+
94+
This will overwrite `test.cc` to look like this:
95+
96+
.. code-block:: c++
97+
98+
namespace na {
99+
class X {};
100+
101+
} // namespace na
102+
namespace x {
103+
namespace y {
104+
class Y {
105+
na::X x;
106+
};
107+
} // namespace y
108+
} // namespace x
109+
110+
Note, that we've successfully moved the class `Y` from namespace `na::nb` to
111+
namespace `x::y`.
112+
113+
Caveats
114+
=======
115+
116+
Content already exists in new namespace
117+
---------------------------------------
118+
119+
Consider this `test.cc` example that defines two `class A` one inside the
120+
namespace `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 a
129+
130+
namespace b {
131+
class A {
132+
int classAFromWithinNamespace_b;
133+
};
134+
} //namespace b
135+
136+
Let's move everything from namespace `a` to namespace `b`:
137+
138+
.. code-block:: console
139+
140+
clang-change-namespace \
141+
--old_namespace "a" \
142+
--new_namespace "b" \
143+
--file_pattern test.cc \
144+
test.cc
145+
146+
As 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 b
155+
156+
namespace b {
157+
class A {
158+
int classAFromWithinNamespace_b;
159+
};
160+
} //namespace b
161+
162+
The re-factoring looks correct but the code will not compile due to the name
163+
duplication. It is not up to the tool to ensure compilability in that sense.
164+
But one has to be aware of that.
165+
166+
Inline namespace doesn't work
167+
-----------------------------
168+
169+
Consider 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 Version1
179+
namespace Version2 {
180+
const char* greet() { return "Hello from version 2!"; }
181+
} // namespace Version2
182+
} // namespace Greeter
183+
184+
int main(int argc, char* argv[]) {
185+
printf("%s\n", Greeter::greet());
186+
return 0;
187+
}
188+
189+
Note, that currently `Greeter::greet()` will result in a call to
190+
`Greeter::Version1::greet()` because that's the inlined namespace.
191+
192+
Let's say you want to move one and make `Version2` the default now and remove
193+
the `inline` from the `Version1`. First let's try to turn `namespace Version2`
194+
into `inline namespace Version2`:
195+
196+
.. code-block:: console
197+
198+
clang-change-namespace \
199+
--old_namespace "Greeter::Version2" \
200+
--new_namespace "inline Version2" \
201+
--file_pattern main.cc main.cc
202+
203+
But 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 Version1
213+
214+
} // namespace Greeter
215+
namespace inline Greeter {
216+
namespace Version2 {
217+
const char *greet() { return "Hello from version 2!"; }
218+
} // namespace Version2
219+
} // namespace inline Greeter
220+
221+
int main(int argc, char* argv[]) {
222+
printf("%s\n", Greeter::greet());
223+
return 0;
224+
}
225+
226+
One cannot use `:program:`clang-change-namespace` to inline a namespace.
227+
228+
Symbol references not updated
229+
-----------------------------
230+
231+
Consider this `test.cc` file:
232+
233+
.. code-block:: c++
234+
235+
namespace old {
236+
struct foo {};
237+
} // namespace old
238+
239+
namespace b {
240+
old::foo g_foo;
241+
} // namespace b
242+
243+
Notice that namespace `b` defines a global variable of type `old::foo`. If we
244+
now change the name of the `old` namespace to `modern`, the reference will not
245+
be updated:
246+
247+
.. code-block:: console
248+
249+
clang-change-namespace \
250+
--old_namespace "old" \
251+
--new_namespace "modern" \
252+
--file_pattern test.cc \
253+
test.cc
254+
255+
.. code-block:: c++
256+
257+
namespace modern {
258+
struct foo {};
259+
} // namespace modern
260+
261+
namespace b {
262+
old::foo g_foo;
263+
} // namespace b
264+
265+
`g_foo` is still of the no longer existing type `old::foo` while instead it
266+
should use `modern::foo`.
267+
268+
Only symbol references in the moved namespace are updated, not outside of it.
269+
270+
271+
:program:`clang-change-namespace` Command Line Options
272+
======================================================
273+
274+
.. option:: --allowed_file=<string>
275+
276+
A file containing regexes of symbol names that are not expected to be updated
277+
when changing namespaces around them.
278+
279+
.. option:: --dump_result
280+
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 line
286+
287+
.. option:: --extra-arg-before=<string>
288+
289+
Additional argument to prepend to the compiler command line
290+
291+
.. option:: --file_pattern=<string>
292+
293+
Only rename namespaces in files that match the given regular expression
294+
pattern.
295+
296+
.. option:: -i
297+
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 path
311+
312+
.. option:: --style=<string>
313+
314+
The style name used for reformatting.

clang-tools-extra/docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Contents
1717

1818
clang-tidy/index
1919
clang-include-fixer
20+
clang-change-namespace
2021
modularize
2122
pp-trace
2223
clangd <https://clangd.llvm.org/>

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,13 @@ def err_drv_reduced_module_output_overrided : Warning<
581581
"please consider use '-fmodule-output=' to specify the output file for reduced BMI explicitly">,
582582
InGroup<DiagGroup<"reduced-bmi-output-overrided">>;
583583

584+
def remark_found_cxx20_module_usage : Remark<
585+
"found C++20 module usage in file '%0'">,
586+
InGroup<ModulesDriver>;
587+
def remark_performing_driver_managed_module_build : Remark<
588+
"performing driver managed module build">,
589+
InGroup<ModulesDriver>;
590+
584591
def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
585592
"-fdelayed-template-parsing is deprecated after C++20">,
586593
InGroup<DiagGroup<"delayed-template-parsing-in-cxx20">>;

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ def ModuleConflict : DiagGroup<"module-conflict">;
635635
def ModuleFileExtension : DiagGroup<"module-file-extension">;
636636
def ModuleIncludeDirectiveTranslation : DiagGroup<"module-include-translation">;
637637
def ModuleMap : DiagGroup<"module-map">;
638+
def ModulesDriver : DiagGroup<"modules-driver">;
638639
def RoundTripCC1Args : DiagGroup<"round-trip-cc1-args">;
639640
def NewlineEOF : DiagGroup<"newline-eof">;
640641
def Nullability : DiagGroup<"nullability">;

0 commit comments

Comments
 (0)