Skip to content

Commit 9ac29c3

Browse files
committed
Improve type checking of the builitn increment operators
1 parent dea098d commit 9ac29c3

File tree

4 files changed

+36
-13
lines changed

4 files changed

+36
-13
lines changed

src/parser/cxx/parser.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10733,6 +10733,7 @@ void Parser::completeFunctionDefinition(FunctionDefinitionAST* ast) {
1073310733
}
1073410734

1073510735
void Parser::check(ExpressionAST* ast) {
10736+
if (inTemplate_) return;
1073610737
TypeChecker check{unit};
1073710738
check.setScope(scope_);
1073810739
check.setReportErrors(config_.checkTypes);

src/parser/cxx/type_checker.cc

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) {
448448
}
449449

450450
if (!is_glvalue(ast->expression)) {
451+
error(ast->opLoc,
452+
std::format("cannot take the address of an rvalue of type '{}'",
453+
to_string(ast->expression->type)));
451454
break;
452455
}
453456

@@ -542,6 +545,8 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) {
542545

543546
case TokenKind::T_PLUS_PLUS: {
544547
if (!is_glvalue(ast->expression)) {
548+
error(ast->opLoc, std::format("cannot increment an rvalue of type '{}'",
549+
to_string(ast->expression->type)));
545550
break;
546551
}
547552

@@ -554,18 +559,23 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) {
554559
}
555560

556561
if (auto ptrTy = type_cast<PointerType>(ty)) {
557-
if (ptrTy && !control()->is_void(ptrTy->elementType())) {
562+
if (!control()->is_void(ptrTy->elementType())) {
558563
ast->type = ptrTy;
559564
ast->valueCategory = ValueCategory::kLValue;
565+
break;
560566
}
561567
}
562568

569+
error(ast->opLoc, std::format("cannot increment a value of type '{}'",
570+
to_string(ast->expression->type)));
563571
break;
564572
}
565573

566574
case TokenKind::T_MINUS_MINUS: {
567575
if (!is_glvalue(ast->expression)) {
568-
break;
576+
error(ast->opLoc, std::format("cannot decrement an rvalue of type '{}'",
577+
to_string(ast->expression->type)));
578+
break;
569579
}
570580

571581
auto ty = ast->expression->type;
@@ -580,9 +590,12 @@ void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) {
580590
if (ptrTy && !control()->is_void(ptrTy->elementType())) {
581591
ast->type = ptrTy;
582592
ast->valueCategory = ValueCategory::kLValue;
593+
break;
583594
}
584595
}
585596

597+
error(ast->opLoc, std::format("cannot decrement a value of type '{}'",
598+
to_string(ast->expression->type)));
586599
break;
587600
}
588601

tests/unit_tests/ast/template_lambda_01.cc

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,9 @@ struct S {
8383
// CHECK-NEXT: return-statement
8484
// CHECK-NEXT: expression: binary-expression
8585
// CHECK-NEXT: op: +
86-
// CHECK-NEXT: left-expression: implicit-cast-expression [prvalue T1]
87-
// CHECK-NEXT: cast-kind: lvalue-to-rvalue-conversion
88-
// CHECK-NEXT: expression: id-expression [lvalue T1]
89-
// CHECK-NEXT: unqualified-id: name-id
90-
// CHECK-NEXT: identifier: a
91-
// CHECK-NEXT: right-expression: implicit-cast-expression [prvalue T2]
92-
// CHECK-NEXT: cast-kind: lvalue-to-rvalue-conversion
93-
// CHECK-NEXT: expression: id-expression [lvalue T2]
94-
// CHECK-NEXT: unqualified-id: name-id
95-
// CHECK-NEXT: identifier: b
86+
// CHECK-NEXT: left-expression: id-expression [lvalue T1]
87+
// CHECK-NEXT: unqualified-id: name-id
88+
// CHECK-NEXT: identifier: a
89+
// CHECK-NEXT: right-expression: id-expression [lvalue T2]
90+
// CHECK-NEXT: unqualified-id: name-id
91+
// CHECK-NEXT: identifier: b

tests/unit_tests/sema/incr_01.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,18 @@ auto main() -> int {
3737
static_assert(__is_lvalue_reference(decltype(++pr)));
3838
static_assert(__is_lvalue_reference(decltype(--pr)));
3939

40+
// clang-format off
41+
42+
int a[10];
43+
44+
++(+a); // expected-error {{cannot increment an rvalue of type 'int*'}}
45+
46+
++a; // expected-error {{cannot increment a value of type 'int [10]'}}
47+
48+
--(+a); // expected-error {{cannot decrement an rvalue of type 'int*'}}
49+
50+
--a; // expected-error {{cannot decrement a value of type 'int [10]'}}
51+
52+
// clang-format on
4053
return 0;
41-
}
54+
}

0 commit comments

Comments
 (0)