Переглянути джерело

cppparser: fix infinite recursion stack overflow with enum classes

rdb 7 роки тому
батько
коміт
6175e79c57
1 змінених файлів з 18 додано та 6 видалено
  1. 18 6
      dtool/src/cppparser/cppEnumType.cxx

+ 18 - 6
dtool/src/cppparser/cppEnumType.cxx

@@ -224,12 +224,24 @@ substitute_decl(CPPDeclaration::SubstDecl &subst,
   bool any_changed = false;
 
   for (size_t i = 0; i < _elements.size(); ++i) {
-    CPPInstance *elem_rep =
-      _elements[i]->substitute_decl(subst, current_scope, global_scope)
-      ->as_instance();
-
-    if (elem_rep != _elements[i]) {
-      rep->_elements[i] = elem_rep;
+    // We don't just do substitute_decl on the instance, which could lead to
+    // an infinite recursion.
+    CPPInstance *element = _elements[i];
+    CPPExpression *value = element->_initializer->
+      substitute_decl(subst, current_scope, global_scope)->as_expression();
+
+    if (is_scoped()) {
+      // For a strong enum, we consider the elements to be of this type.
+      if (value != element->_initializer) {
+        rep->_elements[i] = new CPPInstance(rep, element->_ident);
+        rep->_elements[i]->_initializer = value;
+        any_changed = true;
+      }
+    } else if (value != element->_initializer ||
+               rep->get_underlying_type() != get_underlying_type()) {
+      // In an unscoped enum, the elements are integers.
+      rep->_elements[i] = new CPPInstance(rep->get_underlying_type(), element->_ident);
+      rep->_elements[i]->_initializer = value;
       any_changed = true;
     }
   }