Skip to content

Commit ad0f4ef

Browse files
committed
c++: Support exporting using-decls in same namespace as target
Currently a using-declaration bringing a name into its own namespace is a no-op, except for functions. This prevents people from being able to redeclare a name brought in from the GMF as exported, however, which this patch fixes. Apart from marking declarations as exported they are also now marked as effectively being in the module purview (due to the using-decl) so that they are properly processed, as 'add_binding_entity' assumes that declarations not in the module purview cannot possibly be exported. gcc/cp/ChangeLog: * name-lookup.cc (walk_module_binding): Remove completed FIXME. (do_nonmember_using_decl): Mark redeclared entities as exported when needed. Check for re-exporting internal linkage types. gcc/testsuite/ChangeLog: * g++.dg/modules/using-12.C: New test. * g++.dg/modules/using-13.h: New test. * g++.dg/modules/using-13_a.C: New test. * g++.dg/modules/using-13_b.C: New test. Signed-off-by: Nathaniel Shead <[email protected]>
1 parent d646db0 commit ad0f4ef

File tree

5 files changed

+166
-8
lines changed

5 files changed

+166
-8
lines changed

gcc/cp/name-lookup.cc

+42-8
Original file line numberDiff line numberDiff line change
@@ -4189,7 +4189,7 @@ walk_module_binding (tree binding, bitmap partitions,
41894189
void *data)
41904190
{
41914191
// FIXME: We don't quite deal with using decls naming stat hack
4192-
// type. Also using decls exporting something from the same scope.
4192+
// type.
41934193
tree current = binding;
41944194
unsigned count = 0;
41954195

@@ -5238,13 +5238,36 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
52385238
}
52395239
else if (insert_p)
52405240
{
5241-
value = lookup.value;
5242-
if (revealing_p && module_exporting_p ())
5243-
check_can_export_using_decl (value);
5241+
if (revealing_p
5242+
&& module_exporting_p ()
5243+
&& check_can_export_using_decl (lookup.value)
5244+
&& lookup.value == value
5245+
&& !DECL_MODULE_EXPORT_P (value))
5246+
{
5247+
/* We're redeclaring the same value, but this time as
5248+
newly exported: make sure to mark it as such. */
5249+
if (TREE_CODE (value) == TEMPLATE_DECL)
5250+
{
5251+
DECL_MODULE_EXPORT_P (value) = true;
5252+
5253+
tree result = DECL_TEMPLATE_RESULT (value);
5254+
retrofit_lang_decl (result);
5255+
DECL_MODULE_PURVIEW_P (result) = true;
5256+
DECL_MODULE_EXPORT_P (result) = true;
5257+
}
5258+
else
5259+
{
5260+
retrofit_lang_decl (value);
5261+
DECL_MODULE_PURVIEW_P (value) = true;
5262+
DECL_MODULE_EXPORT_P (value) = true;
5263+
}
5264+
}
5265+
else
5266+
value = lookup.value;
52445267
}
52455268

52465269
/* Now the type binding. */
5247-
if (lookup.type && lookup.type != type)
5270+
if (lookup.type)
52485271
{
52495272
if (type && !decls_match (lookup.type, type))
52505273
{
@@ -5253,9 +5276,20 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
52535276
}
52545277
else if (insert_p)
52555278
{
5256-
type = lookup.type;
5257-
if (revealing_p && module_exporting_p ())
5258-
check_can_export_using_decl (type);
5279+
if (revealing_p
5280+
&& module_exporting_p ()
5281+
&& check_can_export_using_decl (lookup.type)
5282+
&& lookup.type == type
5283+
&& !DECL_MODULE_EXPORT_P (type))
5284+
{
5285+
/* We're redeclaring the same type, but this time as
5286+
newly exported: make sure to mark it as such. */
5287+
retrofit_lang_decl (type);
5288+
DECL_MODULE_PURVIEW_P (type) = true;
5289+
DECL_MODULE_EXPORT_P (type) = true;
5290+
}
5291+
else
5292+
type = lookup.type;
52595293
}
52605294
}
52615295

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// { dg-additional-options "-fmodules-ts" }
2+
// { dg-module-cmi !bad }
3+
4+
// Like using-10.C, but test exporting names within the same namespace.
5+
6+
export module bad;
7+
8+
// internal linkage
9+
namespace s {
10+
namespace {
11+
struct a1 {}; // { dg-message "declared here with internal linkage" }
12+
13+
template <typename T>
14+
struct b1; // { dg-message "declared here with internal linkage" }
15+
16+
int x1; // { dg-message "declared here with internal linkage" }
17+
18+
template <typename T>
19+
T y1; // { dg-message "declared here with internal linkage" }
20+
21+
void f1(); // { dg-message "declared here with internal linkage" }
22+
23+
template <typename T>
24+
void g1(); // { dg-message "declared here with internal linkage" }
25+
26+
export using s::a1; // { dg-error "does not have external linkage" }
27+
export using s::b1; // { dg-error "does not have external linkage" }
28+
export using s::x1; // { dg-error "does not have external linkage" }
29+
export using s::y1; // { dg-error "does not have external linkage" }
30+
export using s::f1; // { dg-error "does not have external linkage" }
31+
export using s::g1; // { dg-error "does not have external linkage" }
32+
}
33+
}
34+
35+
// module linkage
36+
namespace m {
37+
struct a2 {}; // { dg-message "declared here with module linkage" }
38+
39+
template <typename T>
40+
struct b2; // { dg-message "declared here with module linkage" }
41+
42+
int x2; // { dg-message "declared here with module linkage" }
43+
44+
template <typename T>
45+
T y2; // { dg-message "declared here with module linkage" }
46+
47+
void f2(); // { dg-message "declared here with module linkage" }
48+
49+
template <typename T>
50+
void g2(); // { dg-message "declared here with module linkage" }
51+
52+
export using m::a2; // { dg-error "does not have external linkage" }
53+
export using m::b2; // { dg-error "does not have external linkage" }
54+
export using m::x2; // { dg-error "does not have external linkage" }
55+
export using m::y2; // { dg-error "does not have external linkage" }
56+
export using m::f2; // { dg-error "does not have external linkage" }
57+
export using m::g2; // { dg-error "does not have external linkage" }
58+
}
59+
60+
namespace t {
61+
using a = int; // { dg-message "declared here with no linkage" }
62+
63+
template <typename T>
64+
using b = int; // { dg-message "declared here with no linkage" }
65+
66+
typedef int c; // { dg-message "declared here with no linkage" }
67+
68+
export using t::a; // { dg-error "does not have external linkage" }
69+
export using t::b; // { dg-error "does not have external linkage" }
70+
export using t::c; // { dg-error "does not have external linkage" }
71+
}
72+
73+
// { dg-prune-output "not writing module" }
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Like using-11.h, but additional kinds of declarations.
2+
3+
struct A {};
4+
5+
template <typename> struct B {};
6+
template <> struct B<int> { using foo = int; };
7+
template <typename T> struct B<T*> { using bar = T; };
8+
9+
using C = int;
10+
11+
inline int D = 0;
12+
13+
#if __cpp_concepts >= 201907L
14+
template <typename>
15+
concept E = true;
16+
#endif
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// { dg-additional-options "-fmodules-ts" }
2+
// { dg-module-cmi M }
3+
4+
module;
5+
#include "using-13.h"
6+
7+
export module M;
8+
export using ::A;
9+
export using ::B;
10+
export using ::C;
11+
export using ::D;
12+
13+
#if __cpp_concepts >= 201907L
14+
export using ::E;
15+
#endif
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// { dg-additional-options "-fmodules-ts" }
2+
3+
import M;
4+
5+
int main() {
6+
A a;
7+
8+
// Check all specialisations are correctly exported
9+
B<void> b;
10+
B<int>::foo b1;
11+
B<int*>::bar b2;
12+
13+
C c;
14+
15+
auto d = D;
16+
17+
#if __cpp_concepts >= 201907L
18+
auto e = E<void>;
19+
#endif
20+
}

0 commit comments

Comments
 (0)