Skip to content

Commit 018fde1

Browse files
committed
Fix increments and assignments to enums
Fixes #599 Signed-off-by: Roberto Raggi <[email protected]>
1 parent d0c26fb commit 018fde1

File tree

2 files changed

+66
-21
lines changed

2 files changed

+66
-21
lines changed

src/parser/cxx/type_checker.cc

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ struct TypeChecker::Visitor {
5050
return check.unit_->control();
5151
}
5252

53+
[[nodiscard]] auto is_parsing_c() const {
54+
return check.unit_->language() == LanguageKind::kC;
55+
}
56+
57+
[[nodiscard]] auto is_parsing_cxx() const {
58+
return check.unit_->language() == LanguageKind::kCXX;
59+
}
60+
5361
void error(SourceLocation loc, std::string message) {
5462
if (!check.reportErrors_) return;
5563
check.unit_->error(loc, std::move(message));
@@ -498,7 +506,16 @@ void TypeChecker::Visitor::operator()(PostIncrExpressionAST* ast) {
498506
}
499507

500508
auto incr_arithmetic = [&]() {
501-
if (!control()->is_arithmetic(ast->baseExpression->type)) return false;
509+
if (control()->is_const(ast->baseExpression->type)) return false;
510+
511+
if (is_parsing_cxx() &&
512+
!control()->is_arithmetic(ast->baseExpression->type))
513+
return false;
514+
515+
if (is_parsing_c() &&
516+
!control()->is_arithmetic_or_unscoped_enum(ast->baseExpression->type))
517+
return false;
518+
502519
auto ty = control()->remove_cv(ast->baseExpression->type);
503520
if (type_cast<BoolType>(ty)) return false;
504521

@@ -798,20 +815,23 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) {
798815
break;
799816
}
800817

801-
auto ty = ast->expression->type;
818+
if (!control()->is_const(ast->expression->type)) {
819+
const auto ty = ast->expression->type;
802820

803-
if (control()->is_arithmetic(ty) && !control()->is_const(ty)) {
804-
ast->type = ty;
805-
ast->valueCategory = ValueCategory::kLValue;
806-
break;
807-
}
808-
809-
if (auto ptrTy = type_cast<PointerType>(ty)) {
810-
if (!control()->is_void(ptrTy->elementType())) {
811-
ast->type = ptrTy;
821+
if (is_parsing_cxx() ? control()->is_arithmetic(ty)
822+
: control()->is_arithmetic_or_unscoped_enum(ty)) {
823+
ast->type = ty;
812824
ast->valueCategory = ValueCategory::kLValue;
813825
break;
814826
}
827+
828+
if (auto ptrTy = type_cast<PointerType>(ty)) {
829+
if (!control()->is_void(ptrTy->elementType())) {
830+
ast->type = ptrTy;
831+
ast->valueCategory = ValueCategory::kLValue;
832+
break;
833+
}
834+
}
815835
}
816836

817837
error(ast->opLoc, std::format("cannot increment a value of type '{}'",
@@ -826,20 +846,23 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) {
826846
break;
827847
}
828848

829-
auto ty = ast->expression->type;
830-
831-
if (control()->is_arithmetic(ty) && !control()->is_const(ty)) {
832-
ast->type = ty;
833-
ast->valueCategory = ValueCategory::kLValue;
834-
break;
835-
}
849+
if (!control()->is_const(ast->expression->type)) {
850+
auto ty = ast->expression->type;
836851

837-
if (auto ptrTy = type_cast<PointerType>(ty)) {
838-
if (ptrTy && !control()->is_void(ptrTy->elementType())) {
839-
ast->type = ptrTy;
852+
if (is_parsing_cxx() ? control()->is_arithmetic(ty)
853+
: control()->is_arithmetic_or_unscoped_enum(ty)) {
854+
ast->type = ty;
840855
ast->valueCategory = ValueCategory::kLValue;
841856
break;
842857
}
858+
859+
if (auto ptrTy = type_cast<PointerType>(ty)) {
860+
if (ptrTy && !control()->is_void(ptrTy->elementType())) {
861+
ast->type = ptrTy;
862+
ast->valueCategory = ValueCategory::kLValue;
863+
break;
864+
}
865+
}
843866
}
844867

845868
error(ast->opLoc, std::format("cannot decrement a value of type '{}'",

tests/unit_tests/sema/incr_c_01.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %cxx -verify -fcheck -xc %s
2+
3+
enum E { a, b, c };
4+
5+
int main() {
6+
enum E e = a;
7+
++e;
8+
--e;
9+
e++;
10+
e--;
11+
12+
const E ce = a;
13+
// expected-error@1 {{cannot increment a value of type 'const E'}}
14+
++ce;
15+
// expected-error@1 {{cannot decrement a value of type 'const E'}}
16+
--ce;
17+
// expected-error@1 {{cannot increment a value of type 'const E'}}
18+
ce++;
19+
// expected-error@1 {{cannot decrement a value of type 'const E'}}
20+
ce--;
21+
return 0;
22+
}

0 commit comments

Comments
 (0)