diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 48bc6a0a..900d8a6b 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -6599,6 +6599,16 @@ void Parser::parse_enumerator_list(List*& yyast, *it = make_list_node(pool_, enumerator); it = &(*it)->next; + std::optional lastValue; + ASTInterpreter interp{unit}; + + if (enumerator->expression) { + lastValue = enumerator->symbol->value(); + } else { + lastValue = std::intmax_t{0}; + enumerator->symbol->setValue(*lastValue); + } + SourceLocation commaLoc; while (match(TokenKind::T_COMMA, commaLoc)) { @@ -6610,6 +6620,27 @@ void Parser::parse_enumerator_list(List*& yyast, EnumeratorAST* enumerator = nullptr; parse_enumerator(enumerator, type); + if (!enumerator->expression) { + if (lastValue.has_value()) { + if (control_->is_unsigned(type)) { + if (auto v = interp.toUInt(lastValue.value())) { + lastValue = v.value() + 1; + } else { + lastValue = std::nullopt; + } + } else { + if (auto v = interp.toInt(lastValue.value())) { + lastValue = v.value() + 1; + } else { + lastValue = std::nullopt; + } + } + } + enumerator->symbol->setValue(*lastValue); + } else { + lastValue = enumerator->symbol->value(); + } + *it = make_list_node(pool_, enumerator); it = &(*it)->next; } diff --git a/tests/unit_tests/sema/enum_c_01.c b/tests/unit_tests/sema/enum_c_01.c index cb999ae1..afae4cd3 100644 --- a/tests/unit_tests/sema/enum_c_01.c +++ b/tests/unit_tests/sema/enum_c_01.c @@ -2,10 +2,16 @@ enum X { A, - B, - C, + B = 1, + C = B, + D, }; +static_assert(A == 0); +static_assert(B == 1); +static_assert(C == 1); +static_assert(D == 2); + enum X x; // CHECK:namespace @@ -13,4 +19,5 @@ enum X x; // CHECK-NEXT:enumerator X A // CHECK-NEXT:enumerator X B // CHECK-NEXT:enumerator X C +// CHECK-NEXT:enumerator X D // CHECK-NEXT:variable X x \ No newline at end of file