Skip to content

Commit 4e1783c

Browse files
committed
fix(parser): allow restricted explicit pointer casting
Signed-off-by: vibhatsu <maulikbarot2915@gmail.com>
1 parent 90bd377 commit 4e1783c

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

src/parser/parser.y

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,7 +2084,7 @@ static void check_array_bounds(const TypePtr &array_type,
20842084
} else if (!are_types_equal(lhs_type, rhs_type)) {
20852085
parser_add_error(op_loc.begin.line,
20862086
op_loc.begin.column,
2087-
op_name + ": incompatible types for assignment");
2087+
op_name + ": incompatible types for assignment ('" + lhs_type->debug_name() + "' and '" + rhs_type->debug_name() + "')");
20882088
return nullptr;
20892089
}
20902090
}
@@ -2111,7 +2111,53 @@ static void check_array_bounds(const TypePtr &array_type,
21112111
}
21122112

21132113
if (is_pointer_type(from_type) && is_pointer_type(to_type)) {
2114-
return true;
2114+
auto from_ptr = std::static_pointer_cast<PointerType>(from_type);
2115+
auto to_ptr = std::static_pointer_cast<PointerType>(to_type);
2116+
2117+
TypePtr from_pointee = strip_typedefs(from_ptr->pointee.type);
2118+
TypePtr to_pointee = strip_typedefs(to_ptr->pointee.type);
2119+
2120+
if (are_types_equal(from_pointee, to_pointee)) {
2121+
return true;
2122+
}
2123+
2124+
// Allow void* conversions (void* can point to anything)
2125+
if (is_void_type(from_pointee) || is_void_type(to_pointee)) {
2126+
// TODO: add warning for void* casts
2127+
return true;
2128+
}
2129+
2130+
// Allow casting between related class types (base/derived)
2131+
if (is_class_type(from_pointee) && is_class_type(to_pointee)) {
2132+
auto from_class = std::static_pointer_cast<ClassType>(from_pointee);
2133+
auto to_class = std::static_pointer_cast<ClassType>(to_pointee);
2134+
2135+
ClassTypePtr current = from_class;
2136+
while (current && current->base.base_type) {
2137+
if (is_class_type(current->base.base_type)) {
2138+
ClassTypePtr base = std::static_pointer_cast<ClassType>(current->base.base_type);
2139+
if (are_types_equal(base, to_class)) {
2140+
return true; // Upcasting (derived to base)
2141+
}
2142+
current = base;
2143+
} else {
2144+
break;
2145+
}
2146+
}
2147+
current = to_class;
2148+
while (current && current->base.base_type) {
2149+
if (is_class_type(current->base.base_type)) {
2150+
ClassTypePtr base = std::static_pointer_cast<ClassType>(current->base.base_type);
2151+
if (are_types_equal(base, from_class)) {
2152+
return true; // Downcasting (base to derived) - allowed in explicit cast
2153+
}
2154+
current = base;
2155+
} else {
2156+
break;
2157+
}
2158+
}
2159+
}
2160+
return false;
21152161
}
21162162

21172163
// Special case: allow casting literal 0 to pointer type (NULL pointer idiom)

0 commit comments

Comments
 (0)