hash *chain; /* Original table. */
depset *current; /* Current depset being depended. */
unsigned section; /* When writing out, the section. */
- bool sneakoscope; /* Detecting dark magic (of a voldemort). */
bool reached_unreached; /* We reached an unreached entity. */
public:
hash (size_t size, hash *c = NULL)
: parent (size), chain (c), current (NULL), section (0),
- sneakoscope (false), reached_unreached (false)
+ reached_unreached (false)
{
worklist.create (size);
}
dep = dep_hash->find_dependency (decl);
else if (TREE_CODE (ctx) != FUNCTION_DECL
|| TREE_CODE (decl) == TEMPLATE_DECL
- || (dep_hash->sneakoscope && DECL_IMPLICIT_TYPEDEF_P (decl))
+ || DECL_IMPLICIT_TYPEDEF_P (decl)
|| (DECL_LANG_SPECIFIC (decl)
&& DECL_MODULE_IMPORT_P (decl)))
{
add_namespace_context (item, ns);
}
- // FIXME: Perhaps p1815 makes this redundant? Or at
- // least simplifies it. Voldemort types are only
- // ever emissable when containing (inline) function
- // definition is emitted?
- /* Turn the Sneakoscope on when depending the decl. */
- sneakoscope = true;
walker.decl_value (decl, current);
- sneakoscope = false;
if (current->has_defn ())
walker.write_definition (decl);
}
--- /dev/null
+// PR c++/104919
+// PR c++/106009
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi Enum13 }
+
+export module Enum13;
+
+export
+constexpr int f() {
+ enum E { e = 42 };
+ return e;
+}
+
+template<class T>
+constexpr int ft(T) {
+ enum E { e = 43 };
+ return e;
+}
+
+export
+constexpr int g() {
+ return ft(0);
+}
--- /dev/null
+// PR c++/104919
+// PR c++/106009
+// { dg-additional-options -fmodules-ts }
+
+import Enum13;
+
+static_assert(f() == 42);
+static_assert(g() == 43);
constexpr void duration_cast ()
{
- // the constexpr's body's clone merely duplicates the TYPE_DECL, it
- // doesn't create a kosher typedef
typedef int __to_rep;
}
// { dg-final { scan-lang-dump-times {merge key \(matched\) function_decl:'::duration_cast} 1 module } }
// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }
-// { dg-final { scan-lang-dump-times {merge key \(unique\) type_decl:'#null#'} 2 module } }
+// { dg-final { scan-lang-dump-times {merge key \(unique\) type_decl:'#null#'} 1 module } }
// { dg-final { scan-lang-dump-times {Cloned:-[0-9]* typedef integer_type:'::duration_cast::__to_rep'} 1 module } }
need this decl for TYPE_STUB_DECL. */
insert_decl_map (id, decl, t);
- if (!DECL_P (t))
+ if (!DECL_P (t) || t == decl)
return t;
/* Remap types, if necessary. */
TREE_CHAIN. If we remapped this variable to the return slot, it's
already declared somewhere else, so don't declare it here. */
- if (new_var == id->retvar)
+ if (new_var == old_var || new_var == id->retvar)
;
else if (!new_var)
{
id.src_cfun = DECL_STRUCT_FUNCTION (fn);
id.decl_map = &decl_map;
- id.copy_decl = copy_decl_no_change;
+ id.copy_decl = [] (tree decl, copy_body_data *id)
+ {
+ if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == CONST_DECL)
+ /* Don't make copies of local types or injected enumerators,
+ the C++ constexpr evaluator doesn't need them and they
+ confuse modules streaming. */
+ return decl;
+ return copy_decl_no_change (decl, id);
+ };
id.transform_call_graph_edges = CB_CGE_DUPLICATE;
id.transform_new_cfg = false;
id.transform_return_to_modify = false;