@@ -889,21 +889,12 @@ class ovl_iterator {
return (TREE_CODE (ovl) == USING_DECL
|| (TREE_CODE (ovl) == OVERLOAD && OVL_USING_P (ovl)));
}
- /* Whether this using is in the module purview. */
- bool purview_p () const
- {
- return OVL_PURVIEW_P (get_using ());
- }
- /* Whether this using is being exported. */
- bool exporting_p () const
- {
- return OVL_EXPORT_P (get_using ());
- }
-
bool hidden_p () const
{
return TREE_CODE (ovl) == OVERLOAD && OVL_HIDDEN_P (ovl);
}
+ bool purview_p () const;
+ bool exporting_p () const;
public:
tree remove_node (tree head)
@@ -702,12 +702,13 @@ poplevel (int keep, int reverse, int functionbody)
/* There are cases where D itself is a TREE_LIST. See in
push_local_binding where the list of decls returned by
getdecls is built. */
- decl = TREE_CODE (d) == TREE_LIST ? TREE_VALUE (d) : d;
+ tree udecl = TREE_CODE (d) == TREE_LIST ? TREE_VALUE (d) : d;
+ decl = strip_using_decl (udecl);
tree type = TREE_TYPE (decl);
if (VAR_P (decl)
- && (! TREE_USED (decl) || !DECL_READ_P (decl))
- && ! DECL_IN_SYSTEM_HEADER (decl)
+ && (!TREE_USED (decl) || !DECL_READ_P (decl))
+ && !DECL_IN_SYSTEM_HEADER (udecl)
/* For structured bindings, consider only real variables, not
subobjects. */
&& (DECL_DECOMPOSITION_P (decl) ? DECL_DECOMP_IS_BASE (decl)
@@ -720,9 +721,13 @@ poplevel (int keep, int reverse, int functionbody)
|| lookup_attribute ("warn_unused",
TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
{
- if (! TREE_USED (decl))
+ if (!TREE_USED (decl))
{
- if (!DECL_NAME (decl) && DECL_DECOMPOSITION_P (decl))
+ if (TREE_CODE (udecl) == USING_DECL)
+ warning_at (DECL_SOURCE_LOCATION (udecl),
+ OPT_Wunused_variable,
+ "unused using-declaration %qD", udecl);
+ else if (!DECL_NAME (decl) && DECL_DECOMPOSITION_P (decl))
warning_at (DECL_SOURCE_LOCATION (decl),
OPT_Wunused_variable,
"unused structured binding declaration");
@@ -16495,7 +16500,6 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
/* First try ordinary name lookup, ignoring hidden class name
injected via friend declaration. */
decl = lookup_name (name, LOOK_want::TYPE);
- decl = strip_using_decl (decl);
/* If that fails, the name will be placed in the smallest
non-class, non-function-prototype scope according to 3.3.1/5.
We may already have a hidden name declared as friend in this
@@ -13122,6 +13122,7 @@ bool
depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
{
auto data = static_cast <add_binding_data *> (data_);
+ decl = strip_using_decl (decl);
if (!(TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl)))
{
@@ -13156,18 +13157,14 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
/* Ignore NTTP objects. */
return false;
- bool unscoped_enum_const_p = false;
if (!(flags & WMB_Using) && CP_DECL_CONTEXT (decl) != data->ns)
{
- /* A using that lost its wrapper or an unscoped enum
- constant. */
- /* FIXME: Ensure that unscoped enums are differentiated from
- 'using enum' declarations when PR c++/114683 is fixed. */
- unscoped_enum_const_p = (TREE_CODE (decl) == CONST_DECL);
+ /* An unscoped enum constant implicitly brought into the containing
+ namespace. We treat this like a using-decl. */
+ gcc_checking_assert (TREE_CODE (decl) == CONST_DECL);
+
flags = WMB_Flags (flags | WMB_Using);
- if (DECL_MODULE_EXPORT_P (TREE_CODE (decl) == CONST_DECL
- ? TYPE_NAME (TREE_TYPE (decl))
- : STRIP_TEMPLATE (decl)))
+ if (DECL_MODULE_EXPORT_P (TYPE_NAME (TREE_TYPE (decl))))
flags = WMB_Flags (flags | WMB_Export);
}
@@ -13225,8 +13222,7 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
if (flags & WMB_Using)
{
decl = ovl_make (decl, NULL_TREE);
- if (!unscoped_enum_const_p)
- OVL_USING_P (decl) = true;
+ OVL_USING_P (decl) = true;
OVL_PURVIEW_P (decl) = true;
if (flags & WMB_Export)
OVL_EXPORT_P (decl) = true;
@@ -13250,12 +13246,8 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
data->met_namespace = true;
if (data->hash->add_namespace_entities (decl, data->partitions))
{
- /* It contains an exported thing, so it is exported.
-
- FIXME we have to set DECL_MODULE_PURVIEW_P instead of asserting
- that it is already set because of the c++/114683 issue with
- exported using-declarations; see do_nonmember_using_decl. */
- DECL_MODULE_PURVIEW_P (decl) = true;
+ /* It contains an exported thing, so it is exported. */
+ gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl));
DECL_MODULE_EXPORT_P (decl) = true;
}
@@ -14964,7 +14956,6 @@ enum ct_bind_flags
cbf_export = 0x1, /* An exported decl. */
cbf_hidden = 0x2, /* A hidden (friend) decl. */
cbf_using = 0x4, /* A using decl. */
- cbf_wrapped = 0x8, /* ... that is wrapped. */
};
/* DEP belongs to a different cluster, seed it to prevent
@@ -15127,13 +15118,9 @@ module_state::write_cluster (elf_out *to, depset *scc[], unsigned size,
if (!(TREE_CODE (bound) == CONST_DECL
&& UNSCOPED_ENUM_P (TREE_TYPE (bound))
&& decl == TYPE_NAME (TREE_TYPE (bound))))
- {
- /* An unscope enumerator in its enumeration's
- scope is not a using. */
- flags |= cbf_using;
- if (OVL_USING_P (ovl))
- flags |= cbf_wrapped;
- }
+ /* An unscoped enumerator in its enumeration's
+ scope is not a using. */
+ flags |= cbf_using;
if (OVL_EXPORT_P (ovl))
flags |= cbf_export;
}
@@ -15300,13 +15287,54 @@ module_state::read_cluster (unsigned snum)
/* Stat hack. */
if (type || !DECL_IMPLICIT_TYPEDEF_P (decl))
sec.set_overrun ();
- type = decl;
+
+ if (flags & cbf_using)
+ {
+ type = build_lang_decl_loc (UNKNOWN_LOCATION,
+ USING_DECL,
+ DECL_NAME (decl),
+ NULL_TREE);
+ USING_DECL_DECLS (type) = decl;
+ USING_DECL_SCOPE (type) = CP_DECL_CONTEXT (decl);
+ DECL_CONTEXT (type) = ns;
+
+ DECL_MODULE_PURVIEW_P (type) = true;
+ if (flags & cbf_export)
+ DECL_MODULE_EXPORT_P (type) = true;
+ }
+ else
+ type = decl;
}
else
{
- if (decls
- || (flags & (cbf_hidden | cbf_wrapped))
- || DECL_FUNCTION_TEMPLATE_P (decl))
+ if ((flags & cbf_using) &&
+ !DECL_DECLARES_FUNCTION_P (decl))
+ {
+ /* We should only see a single non-function using-decl
+ for a binding; more than that would clash. */
+ if (decls)
+ sec.set_overrun ();
+
+ /* FIXME: Propagate the location of the using-decl
+ for use in diagnostics. */
+ decls = build_lang_decl_loc (UNKNOWN_LOCATION,
+ USING_DECL,
+ DECL_NAME (decl),
+ NULL_TREE);
+ USING_DECL_DECLS (decls) = decl;
+ /* We don't currently record the actual scope of the
+ using-declaration, but this approximation should
+ generally be good enough. */
+ USING_DECL_SCOPE (decls) = CP_DECL_CONTEXT (decl);
+ DECL_CONTEXT (decls) = ns;
+
+ DECL_MODULE_PURVIEW_P (decls) = true;
+ if (flags & cbf_export)
+ DECL_MODULE_EXPORT_P (decls) = true;
+ }
+ else if (decls
+ || (flags & (cbf_hidden | cbf_using))
+ || DECL_FUNCTION_TEMPLATE_P (decl))
{
decls = ovl_make (decl, decls);
if (flags & cbf_using)
@@ -281,10 +281,11 @@ get_fixed_binding_slot (tree *slot, tree name, unsigned ix, int create)
/* Propagate global & module entities to the global and
partition slots. */
- if (tree type = MAYBE_STAT_TYPE (orig))
+ if (tree type = strip_using_decl (MAYBE_STAT_TYPE (orig)))
init_global_partition (cluster, type);
- for (ovl_iterator iter (MAYBE_STAT_DECL (orig)); iter; ++iter)
+ for (ovl_iterator iter (strip_using_decl (MAYBE_STAT_DECL (orig)));
+ iter; ++iter)
{
tree decl = *iter;
@@ -767,6 +768,9 @@ name_lookup::process_binding (tree new_val, tree new_type)
&& (want & LOOK_want::TYPE_NAMESPACE) == LOOK_want::NAMESPACE)
new_type = NULL_TREE;
+ new_val = strip_using_decl (new_val);
+ new_type = strip_using_decl (new_type);
+
/* Do we really see a value? */
if (new_val)
switch (TREE_CODE (new_val))
@@ -827,17 +831,6 @@ name_lookup::process_module_binding (tree new_val, tree new_type,
marker |= 2;
}
- /* add_binding_entity wraps decls brought in by 'using' in an OVERLOAD even
- for non-functions; strip it now.
- ??? Why isn't it represented with a USING_DECL? Or do we want to use
- OVERLOAD for using more widely to address 114683? */
- if (new_val && TREE_CODE (new_val) == OVERLOAD
- && !DECL_DECLARES_FUNCTION_P (OVL_FUNCTION (new_val)))
- {
- gcc_checking_assert (OVL_USING_P (new_val) && !OVL_CHAIN (new_val));
- new_val = OVL_FUNCTION (new_val);
- }
-
if (new_type || new_val)
marker |= process_binding (new_val, new_type);
@@ -2998,6 +2991,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
if (old == error_mark_node)
old = NULL_TREE;
+ old = strip_using_decl (old);
if (DECL_IMPLICIT_TYPEDEF_P (decl))
{
@@ -3102,11 +3096,7 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot,
}
else if (TREE_CODE (old) == VAR_DECL)
{
- /* There can be two block-scope declarations of the same
- variable, so long as they are `extern' declarations. */
- if (!DECL_EXTERNAL (old) || !DECL_EXTERNAL (decl))
- goto conflict;
- else if (tree match = duplicate_decls (decl, old))
+ if (tree match = duplicate_decls (decl, old))
{
gcc_checking_assert (!hide_value && !hiding);
return match;
@@ -4205,6 +4195,28 @@ lookup_class_binding (tree klass, tree name)
return found;
}
+/* Whether this using is declared in the module purview. */
+
+bool
+ovl_iterator::purview_p () const
+{
+ gcc_checking_assert (using_p ());
+ if (TREE_CODE (ovl) == USING_DECL)
+ return DECL_MODULE_PURVIEW_P (ovl);
+ return OVL_PURVIEW_P (ovl);
+}
+
+/* Whether this using is exported from this module. */
+
+bool
+ovl_iterator::exporting_p () const
+{
+ gcc_checking_assert (using_p ());
+ if (TREE_CODE (ovl) == USING_DECL)
+ return DECL_MODULE_EXPORT_P (ovl);
+ return OVL_EXPORT_P (ovl);
+}
+
/* Given a namespace-level binding BINDING, walk it, calling CALLBACK
for all decls of the current module. When partitions are involved,
decls might be mentioned more than once. Return the accumulation of
@@ -4215,8 +4227,6 @@ walk_module_binding (tree binding, bitmap partitions,
bool (*callback) (tree decl, WMB_Flags, void *data),
void *data)
{
- // FIXME: We don't quite deal with using decls naming stat hack
- // type.
tree current = binding;
unsigned count = 0;
@@ -4229,6 +4239,14 @@ walk_module_binding (tree binding, bitmap partitions,
WMB_Flags flags = WMB_None;
if (STAT_TYPE_HIDDEN_P (current))
flags = WMB_Flags (flags | WMB_Hidden);
+ if (TREE_CODE (type) == USING_DECL)
+ {
+ flags = WMB_Flags (flags | WMB_Using);
+ if (DECL_MODULE_PURVIEW_P (type))
+ flags = WMB_Flags (flags | WMB_Purview);
+ if (DECL_MODULE_EXPORT_P (type))
+ flags = WMB_Flags (flags | WMB_Export);
+ }
count += callback (type, flags, data);
decl_hidden = STAT_DECL_HIDDEN_P (current);
}
@@ -4300,7 +4318,14 @@ walk_module_binding (tree binding, bitmap partitions,
flags = WMB_Flags (flags | WMB_Dups);
if (STAT_TYPE_HIDDEN_P (bind))
flags = WMB_Flags (flags | WMB_Hidden);
-
+ if (TREE_CODE (btype) == USING_DECL)
+ {
+ flags = WMB_Flags (flags | WMB_Using);
+ if (DECL_MODULE_PURVIEW_P (btype))
+ flags = WMB_Flags (flags | WMB_Purview);
+ if (DECL_MODULE_EXPORT_P (btype))
+ flags = WMB_Flags (flags | WMB_Export);
+ }
count += callback (btype, flags, data);
}
bool part_hidden = STAT_DECL_HIDDEN_P (bind);
@@ -5201,7 +5226,7 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
/* Shift the old and new bindings around so we're comparing class and
enumeration names to each other. */
- if (value && DECL_IMPLICIT_TYPEDEF_P (value))
+ if (value && DECL_IMPLICIT_TYPEDEF_P (strip_using_decl (value)))
{
type = value;
value = NULL_TREE;
@@ -5306,61 +5331,70 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p,
else if (value
/* Ignore anticipated builtins. */
&& !anticipated_builtin_p (value)
- && (fn_scope_p || !decls_match (lookup.value, value)))
+ && (fn_scope_p
+ || !decls_match (lookup.value, strip_using_decl (value))))
{
diagnose_name_conflict (lookup.value, value);
failed = true;
}
else if (insert_p)
{
- /* FIXME: Handle exporting declarations from a different scope
- without also marking those declarations as exported.
- This will require not just binding directly to the underlying
- value; see c++/114683 and c++/114685. We allow the extra exports
- for now as this doesn't (currently) cause ICEs
- later down the line, but this should be revisited. */
- if (revealing_p)
+ /* A using-decl does not necessarily have the same purview-ness or
+ exporting as the declaration it reveals, so build a USING_DECL
+ that we can attach this information to. This also gives us a
+ location for the using-decl that we can use in diagnostics.
+
+ But this is unnecessary if we're just redeclaring the same decl;
+ in that case we can just mark it purview or exported directly.
+ Except for using-decls of enumerators, which are currently
+ handled specially in modules code and so need to be wrapped. */
+ if (value != lookup.value || TREE_CODE (value) == CONST_DECL)
{
- if (module_exporting_p ()
- && check_can_export_using_decl (lookup.value)
- && !DECL_MODULE_EXPORT_P (lookup.value))
- {
- /* We're redeclaring the same value, but this time as
- newly exported: make sure to mark it as such. */
- if (TREE_CODE (lookup.value) == TEMPLATE_DECL)
- DECL_MODULE_EXPORT_P (DECL_TEMPLATE_RESULT (lookup.value)) = true;
- DECL_MODULE_EXPORT_P (lookup.value) = true;
- }
- /* We're also revealing this declaration with a using-decl,
- so mark it as purview to ensure it's emitted. */
- tree inner = STRIP_TEMPLATE (lookup.value);
- retrofit_lang_decl (inner);
- DECL_MODULE_PURVIEW_P (inner) = true;
+ value = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
+ USING_DECL_DECLS (value) = lookup.value;
+ USING_DECL_SCOPE (value) = CP_DECL_CONTEXT (lookup.value);
+ DECL_CONTEXT (value) = current_scope ();
+ DECL_MODULE_PURVIEW_P (value) = module_purview_p ();
+ }
+ else
+ set_instantiating_module (value);
+
+ if (revealing_p
+ && module_exporting_p ()
+ && check_can_export_using_decl (lookup.value))
+ {
+ if (TREE_CODE (value) == TEMPLATE_DECL)
+ DECL_MODULE_EXPORT_P (DECL_TEMPLATE_RESULT (value)) = true;
+ DECL_MODULE_EXPORT_P (value) = true;
}
- value = lookup.value;
}
-
+
/* Now the type binding. */
if (lookup.type)
{
- if (type && !decls_match (lookup.type, type))
+ if (type && !decls_match (lookup.type, strip_using_decl (type)))
{
diagnose_name_conflict (lookup.type, type);
failed = true;
}
else if (insert_p)
{
- if (revealing_p)
+ /* As with revealing value bindings. */
+ if (type != lookup.type)
{
- /* As with revealing value bindings. */
- if (module_exporting_p ()
- && check_can_export_using_decl (lookup.type)
- && lookup.type == type)
- DECL_MODULE_EXPORT_P (lookup.type) = true;
- retrofit_lang_decl (lookup.type);
- DECL_MODULE_PURVIEW_P (lookup.type) = true;
+ type = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
+ USING_DECL_DECLS (type) = lookup.type;
+ USING_DECL_SCOPE (type) = CP_DECL_CONTEXT (lookup.type);
+ DECL_CONTEXT (type) = current_scope ();
+ DECL_MODULE_PURVIEW_P (type) = module_purview_p ();
}
- type = lookup.type;
+ else
+ set_instantiating_module (type);
+
+ if (revealing_p
+ && module_exporting_p ()
+ && check_can_export_using_decl (lookup.type))
+ DECL_MODULE_EXPORT_P (type) = true;
}
}
@@ -6217,7 +6251,7 @@ get_namespace_binding (tree ns, tree name)
if (TREE_CODE (ret) == BINDING_VECTOR)
ret = BINDING_VECTOR_CLUSTER (ret, 0).slots[0];
if (ret)
- ret = MAYBE_STAT_DECL (ret);
+ ret = strip_using_decl (MAYBE_STAT_DECL (ret));
}
return ret;
@@ -8000,7 +8034,7 @@ lookup_name (tree name, LOOK_where where, LOOK_want want)
if (binding)
{
- val = binding;
+ val = strip_using_decl (binding);
break;
}
}
@@ -8073,7 +8107,7 @@ lookup_elaborated_type (tree name, TAG_how how)
typedef struct C {} C;
correctly. */
- if (tree type = iter->type)
+ if (tree type = strip_using_decl (iter->type))
{
if (qualify_lookup (type, LOOK_want::TYPE)
&& (how != TAG_how::CURRENT_ONLY
@@ -8089,7 +8123,8 @@ lookup_elaborated_type (tree name, TAG_how how)
}
else
{
- if (qualify_lookup (iter->value, LOOK_want::TYPE)
+ tree value = strip_using_decl (iter->value);
+ if (qualify_lookup (value, LOOK_want::TYPE)
&& (how != TAG_how::CURRENT_ONLY
|| !INHERITED_VALUE_BINDING_P (iter)))
{
@@ -8097,7 +8132,7 @@ lookup_elaborated_type (tree name, TAG_how how)
/* It is no longer a hidden binding. */
HIDDEN_TYPE_BINDING_P (iter) = false;
- return iter->value;
+ return value;
}
}
}
@@ -8121,7 +8156,7 @@ lookup_elaborated_type (tree name, TAG_how how)
if (bind)
{
/* If this is the kind of thing we're looking for, we're done. */
- if (tree type = MAYBE_STAT_TYPE (bind))
+ if (tree type = strip_using_decl (MAYBE_STAT_TYPE (bind)))
{
if (how != TAG_how::HIDDEN_FRIEND)
/* No longer hidden. */
@@ -8129,7 +8164,7 @@ lookup_elaborated_type (tree name, TAG_how how)
return type;
}
- else if (tree decl = MAYBE_STAT_DECL (bind))
+ else if (tree decl = strip_using_decl (MAYBE_STAT_DECL (bind)))
{
if (qualify_lookup (decl, LOOK_want::TYPE))
{
@@ -8210,10 +8245,10 @@ lookup_elaborated_type (tree name, TAG_how how)
}
if (type && qualify_lookup (type, LOOK_want::TYPE))
- return type;
+ return strip_using_decl (type);
if (bind && qualify_lookup (bind, LOOK_want::TYPE))
- return bind;
+ return strip_using_decl (bind);
}
if (!module_purview_p ())
@@ -19506,8 +19506,6 @@ cp_parser_template_name (cp_parser* parser,
/*ambiguous_decls=*/NULL,
token->location);
- decl = strip_using_decl (decl);
-
/* 13.3 [temp.names] A < is interpreted as the delimiter of a
template-argument-list if it follows a name that is not a
conversion-function-id and
@@ -21140,8 +21138,6 @@ cp_parser_nonclass_name (cp_parser* parser)
/* Look up the type-name. */
type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
- type_decl = strip_using_decl (type_decl);
-
if (TREE_CODE (type_decl) != TYPE_DECL
&& (objc_is_id (identifier) || objc_is_class_name (identifier)))
{
@@ -26916,8 +26912,6 @@ cp_parser_class_name (cp_parser *parser,
decl = TYPE_NAME (decl);
}
- decl = strip_using_decl (decl);
-
/* Check to see that it is really the name of a class. */
if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
&& identifier_p (TREE_OPERAND (decl, 0))
@@ -51,7 +51,7 @@ struct I2 : H
struct J
{
- struct type {};
+ struct type {}; // { dg-message "previous" }
};
struct K : J
@@ -62,8 +62,8 @@ struct K : J
struct L : J
{
- using J::type; // { dg-message "previous" }
- struct type {}; // { dg-error "conflicts" }
+ using J::type;
+ struct type {}; // { dg-error "redefinition" }
};
struct M
@@ -1,21 +1,23 @@
// PR c++/20420
+// FIXME: These error messages aren't great, rather than multiple definition
+// we should talk about conflicting declarations with the using-decl.
class B
{
protected:
- enum E { E1, E2, E3 };
- struct S { int i; E e; };
+ enum E { E1, E2, E3 }; // { dg-message "previous" }
+ struct S { int i; E e; }; // { dg-message "previous" }
};
class D : private B
{
public:
- using B::E; // { dg-message "previous" }
- using B::S; // { dg-message "previous" }
+ using B::E;
+ using B::S;
private:
- enum E {}; // { dg-error "conflicts" }
- struct S {}; // { dg-error "conflicts" }
+ enum E {}; // { dg-error "multiple definition" }
+ struct S {}; // { dg-error "redefinition" }
};
template<typename T>
@@ -30,11 +32,11 @@ template<typename T>
class DT : private BT<T>
{
public:
- using BT<T>::E; // { dg-message "previous" }
+ using BT<T>::E; // { dg-message "previous" "PR c++/115806" { xfail *-*-* } }
using BT<T>::S; // { dg-message "previous" }
private:
- enum E {}; // { dg-error "conflicts" }
+ enum E {}; // { dg-error "conflicts" "PR c++/115806" { xfail *-*-* } }
struct S {}; // { dg-error "conflicts" }
};
@@ -50,5 +52,5 @@ void
f ()
{
using N::i;
- using N::i; // { dg-error "redeclaration" }
+ using N::i; // { dg-bogus "conflicts" "See P1787 (CWG36)" { xfail *-*-* } }
}
new file mode 100644
@@ -0,0 +1,7 @@
+// { dg-do compile }
+
+struct S {}; // { dg-message "previous" }
+void foo() {
+ using ::S;
+ struct S {}; // { dg-error "redefinition" }
+}
@@ -7,7 +7,9 @@ int main()
std::basic_string<char> s;
// The inline namespace should not be exported, only the 'using' in std.
- std::__cxx11::basic_string<char> s2; // { dg-error "has not been declared" "" { xfail *-*-* } }
+ std::__cxx11::basic_string<char> s2; // { dg-error "has not been declared" }
// The non-exported using should also not be visible.
- foo::basic_string<char> s3; // { dg-error "has not been declared" "" { xfail *-*-* } }
+ foo::basic_string<char> s3; // { dg-error "has not been declared" }
}
+
+// { dg-prune-output "expected primary-expression" }
new file mode 100644
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi M }
+
+module;
+
+namespace foo {
+ struct S {} S;
+}
+
+export module M;
+
+namespace bar {
+ export using foo::S;
+ export using X = struct foo::S;
+}
new file mode 100644
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+namespace foo {}
+
+int main() {
+ struct bar::S a = bar::S;
+ bar::X b = bar::S;
+
+ struct foo::S c; // { dg-error "does not name a type" }
+ auto d = foo::S; // { dg-error "not a member" }
+}
new file mode 100644
@@ -0,0 +1,15 @@
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi M }
+
+module;
+namespace A {
+ enum E1 { Exposed_1, Hidden_1 };
+ enum E2 { Exposed_2, Hidden_2 };
+}
+export module M;
+namespace A {
+ export using E1::Exposed_1;
+}
+namespace B {
+ export using A::E2::Exposed_2;
+}
new file mode 100644
@@ -0,0 +1,17 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+
+int main() {
+ // These have been exported by using-decls and should be OK
+ auto a = A::Exposed_1;
+ auto b = B::Exposed_2;
+
+ // But we shouldn't have exposed the type names
+ A::E1 c; // { dg-error "not a member" }
+ B::E2 d; // { dg-error "not a member" }
+
+ // We also shouldn't have exposed any other enumerators
+ auto e = A::Hidden_1; // { dg-error "not a member" }
+ auto f = B::Hidden_2; // { dg-error "not a member" }
+}
new file mode 100644
@@ -0,0 +1,13 @@
+// PR c++/114683
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi M:a }
+
+module;
+namespace foo {
+ enum class a { x, y, z };
+}
+export module M:a;
+namespace bar {
+ export using enum foo::a;
+}
new file mode 100644
@@ -0,0 +1,7 @@
+// PR c++/114683
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi M }
+
+export module M;
+export import :a;
new file mode 100644
@@ -0,0 +1,11 @@
+// PR c++/114683
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+int main() {
+ auto y = bar::y;
+
+ // This should not be made visible.
+ auto z = foo::a::z; // { dg-error "not been declared" }
+}
@@ -4,11 +4,18 @@
namespace N
{
- int i; // { dg-warning "unused variable" }
+ int i;
}
void
f ()
{
- using N::i;
+ using N::i; // { dg-warning "unused using" }
+}
+
+void
+g ()
+{
+ using N::i; // { dg-bogus "set but not used" }
+ i = 10;
}