Repository: cython/cython

Issue:
[BUG] Compiler crashes when one enum class references another
### Describe the bug

I have two enum classes where one of them references members of the other. The Cython compiler crashes when parsing the second enum class definition at the point of the reference to the first, specifically when attempting to access a member.

### Code to reproduce the behavior:

```cython
# distutils: language = c++                                                                                                                                                                               
 
from libcpp cimport bool as cbool
from libc.stdint cimport int8_t  # Could also use something simpler like int, which I tried.
 
cdef enum class Color(int8_t):
    RED = 1
    GREEN = 2


cdef enum class Color2(int8_t):
    RED = (<int8_t> Color.RED)
    GREEN = (<int8_t> Color.GREEN)
```

This results in:
```
(test_cython_3) vyasr-dt% cythonize -i example2.pyx
Compiling /home/vyasr/local/testing/cython_cdef_enum/example2.pyx because it changed.
[1/1] Cythonizing ...

Error compiling Cython file:
------------------------------------------------------------
...
    RED = 1
    GREEN = 2


cdef enum class Color2(int8_t):
    RED = (<int8_t> Color.RED)
                         ^
------------------------------------------------------------

example2.pyx:13:25: Compiler crash in AnalyseDeclarationsTransform

File 'ModuleNode.py', line 203, in analyse_declarations: ModuleNode(example2.pyx:1:0,
    full_module_name = 'example2')
File 'Nodes.py', line 393, in analyse_declarations: StatListNode(example2.pyx:3:0)
File 'Nodes.py', line 1728, in analyse_declarations: CEnumDefNode(example2.pyx:12:5,
    name = 'Color2',
    scoped = True,
    visibility = 'private')
File 'Nodes.py', line 1766, in analyse_enum_declarations: CEnumDefItemNode(example2.pyx:13:4,
    name = 'RED')
File 'ExprNodes.py', line 628, in analyse_const_expression: TypecastNode(example2.pyx:13:11,
    result_is_used = True,
    use_managed_ref = True)
File 'ExprNodes.py', line 10936, in analyse_types: TypecastNode(example2.pyx:13:11,
    result_is_used = True,
    use_managed_ref = True)
File 'ExprNodes.py', line 7323, in analyse_types: AttributeNode(example2.pyx:13:25,
    attribute = 'RED',
    is_attribute = 1,
    needs_none_check = True,
    result_is_used = True,
    use_managed_ref = True)

Compiler crash traceback from this point on:
  File "/home/vyasr/miniconda3/envs/test_cython_3/lib/python3.10/site-packages/Cython/Compiler/ExprNodes.py", line 7323, in analyse_types
    self.initialized_check = env.directives['initializedcheck']
AttributeError: 'CppScopedEnumScope' object has no attribute 'directives'
Traceback (most recent call last):
  File "/home/vyasr/miniconda3/envs/test_cython_3/bin/cythonize", line 11, in <module>
    sys.exit(main())
  File "/home/vyasr/miniconda3/envs/test_cython_3/lib/python3.10/site-packages/Cython/Build/Cythonize.py", line 243, in main
    _cython_compile_files(all_paths, options)
  File "/home/vyasr/miniconda3/envs/test_cython_3/lib/python3.10/site-packages/Cython/Build/Cythonize.py", line 70, in _cython_compile_files
    ext_modules = cythonize(
  File "/home/vyasr/miniconda3/envs/test_cython_3/lib/python3.10/site-packages/Cython/Build/Dependencies.py", line 1134, in cythonize
    cythonize_one(*args)
  File "/home/vyasr/miniconda3/envs/test_cython_3/lib/python3.10/site-packages/Cython/Build/Dependencies.py", line 1301, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: /home/vyasr/local/testing/cython_cdef_enum/example2.pyx

```

### Expected behaviour

This should compile successfully.

### OS

Linux

### Python version

3.10.2

### Cython version

3.0.0

### Additional context

This particular example is of course a contrived MWE. The practical use case I had in mind is wrapping a `cdef extern` `cdef enum class` corresponding to a C++ enum into a `cpdef enum class` that may be used by Python and Cython consumers of a Cython module. I have made sure that the two enums have the same underlying integral types, and I've included the appropriate casts. The equivalent C++ code (which compiles fine) would be something like:

```
enum class Color : int {
    RED,
    GREEN
};

enum class Color2 : int {
    RED = static_cast<int>(Color::RED),
    GREEN = static_cast<int>(Color::GREEN)
};

int main() {
    auto x = Color2::RED;
}
```


Discussion:
> The practical use case I had in mind is wrapping a cdef extern cdef enum class corresponding to a C++ enum into a cpdef enum class that may be used by Python and Cython consumers of a Cython module

You can just do this directly by declaring it as `cpdef` in the extern block:

https://github.com/cython/cython/blob/6ad6ca0e9e7d030354b7fe7d7b56c3f6e6a4bc23/tests/run/cpdef_enums.pyx#L61-L65

The linked example is for a regular enum rather than an enum class but I don't think that should make a difference.

With that said, it's still a real bug, even if I don't think your use-case is necessary
Yup that is the workaround I went with.

Resolving patch:
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -1712,6 +1712,7 @@ def analyse_declarations(self, env):
         if self.scoped and self.items is not None:
             scope = CppScopedEnumScope(self.name, env)
             scope.type = self.entry.type
+            scope.directives = env.directives
         else:
             scope = env
 


Test patch:
diff --git a/tests/compile/cppenum.pyx b/tests/compile/cppenum.pyx
--- a/tests/compile/cppenum.pyx
+++ b/tests/compile/cppenum.pyx
@@ -29,3 +29,14 @@ cdef void eggs():
     c1 = Cheese.x
 
 eggs()
+
+
+# enum interdependency
+cdef enum class Color(int):
+    RED = 1
+    GREEN = 2
+
+
+cdef enum class Color2(int):
+    RED = (<int> Color.RED)
+    GREEN = (<int> Color.GREEN)