Skip to content

Commit 611d33d

Browse files
committed
Add APis to compute the qualification combined type
Signed-off-by: GitHub <[email protected]>
1 parent 91888b2 commit 611d33d

File tree

2 files changed

+141
-4
lines changed

2 files changed

+141
-4
lines changed

src/parser/cxx/type_checker.cc

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,14 @@ struct TypeChecker::Visitor {
109109
ExpressionAST*& other)
110110
-> const Type*;
111111

112+
[[nodiscard]] auto get_qualification_combined_type(const Type* left,
113+
const Type* right)
114+
-> const Type*;
115+
116+
[[nodiscard]] auto get_qualification_combined_type(
117+
const Type* left, const Type* right, bool& didChangeTypeOrQualifiers)
118+
-> const Type*;
119+
112120
[[nodiscard]] auto composite_pointer_type(ExpressionAST*& expr,
113121
ExpressionAST*& other)
114122
-> const Type*;
@@ -1736,6 +1744,98 @@ auto TypeChecker::Visitor::usual_arithmetic_conversion(ExpressionAST*& expr,
17361744
return control()->getIntType();
17371745
}
17381746

1747+
auto TypeChecker::Visitor::get_qualification_combined_type(const Type* left,
1748+
const Type* right)
1749+
-> const Type* {
1750+
bool didChangeTypeOrQualifiers = false;
1751+
1752+
auto type =
1753+
get_qualification_combined_type(left, right, didChangeTypeOrQualifiers);
1754+
1755+
return type;
1756+
}
1757+
1758+
auto TypeChecker::Visitor::get_qualification_combined_type(
1759+
const Type* left, const Type* right, bool& didChangeTypeOrQualifiers)
1760+
-> const Type* {
1761+
auto check_inputs = [&] {
1762+
if (control()->is_pointer(left) && control()->is_pointer(right)) {
1763+
return true;
1764+
}
1765+
1766+
if (control()->is_array(left) && control()->is_array(right)) {
1767+
return true;
1768+
}
1769+
1770+
return false;
1771+
};
1772+
1773+
auto cv1 = strip_cv(left);
1774+
auto cv2 = strip_cv(right);
1775+
1776+
if (!check_inputs()) {
1777+
const auto cv3 = merge_cv(cv1, cv2);
1778+
1779+
if (control()->is_same(left, right)) {
1780+
return control()->add_cv(left, cv3);
1781+
}
1782+
1783+
if (control()->is_base_of(left, right)) {
1784+
return control()->add_cv(left, cv1);
1785+
}
1786+
1787+
if (control()->is_base_of(right, left)) {
1788+
return control()->add_cv(right, cv2);
1789+
}
1790+
1791+
return nullptr;
1792+
}
1793+
1794+
auto leftElementType = control()->get_element_type(left);
1795+
if (control()->is_array(leftElementType)) {
1796+
cv1 = merge_cv(cv1, control()->get_cv_qualifiers(leftElementType));
1797+
}
1798+
1799+
auto rightElementType = control()->get_element_type(right);
1800+
if (control()->is_array(rightElementType)) {
1801+
cv2 = merge_cv(cv2, control()->get_cv_qualifiers(rightElementType));
1802+
}
1803+
1804+
auto elementType = get_qualification_combined_type(
1805+
leftElementType, rightElementType, didChangeTypeOrQualifiers);
1806+
1807+
if (!elementType) {
1808+
return nullptr;
1809+
}
1810+
1811+
auto cv3 = merge_cv(cv1, cv2);
1812+
1813+
if (didChangeTypeOrQualifiers) cv3 = cv3 | CvQualifiers::kConst;
1814+
1815+
if (cv1 != cv3 || cv2 != cv3) didChangeTypeOrQualifiers = true;
1816+
1817+
elementType = control()->add_cv(elementType, cv3);
1818+
1819+
if (control()->is_array(left) && control()->is_array(right)) {
1820+
auto leftArrayType = type_cast<BoundedArrayType>(left);
1821+
auto rightArrayType = type_cast<BoundedArrayType>(right);
1822+
1823+
if (leftArrayType && rightArrayType) {
1824+
if (leftArrayType->size() != rightArrayType->size()) return nullptr;
1825+
return control()->getBoundedArrayType(elementType, leftArrayType->size());
1826+
}
1827+
1828+
if (leftArrayType || rightArrayType) {
1829+
// one of arrays is unbounded
1830+
didChangeTypeOrQualifiers = true;
1831+
}
1832+
1833+
return control()->getUnboundedArrayType(elementType);
1834+
}
1835+
1836+
return control()->getPointerType(elementType);
1837+
}
1838+
17391839
auto TypeChecker::Visitor::composite_pointer_type(ExpressionAST*& expr,
17401840
ExpressionAST*& other)
17411841
-> const Type* {
@@ -1767,9 +1867,11 @@ auto TypeChecker::Visitor::composite_pointer_type(ExpressionAST*& expr,
17671867
return control()->getPointerType(control()->add_cv(t2, cv1));
17681868
}
17691869

1770-
// TODO: check for noexcept function pointers
1870+
if (auto type = get_qualification_combined_type(expr->type, other->type)) {
1871+
return type;
1872+
}
17711873

1772-
// TODO: check for reference related
1874+
// TODO: check for noexcept function pointers
17731875
}
17741876

17751877
return nullptr;

tests/unit_tests/sema/conditional_expr_01.cc

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// RUN: %cxx -verify -fcheck %s
22

3+
struct Base {};
4+
struct Derived : Base {};
5+
36
void returns_void();
47
int returns_int();
58
int& returns_int_ref();
@@ -44,8 +47,40 @@ void test_conditional(bool x) {
4447
static_assert(__is_same(unsigned, decltype(x ? 0 : 1u)));
4548
static_assert(__is_same(long, decltype(x ? 0 : 1l)));
4649

50+
const char cs[] = "";
4751
char s[10];
48-
char* cp;
52+
char* p;
53+
const char* cp = p;
54+
const char* const cpc = p;
55+
56+
static_assert(__is_same(char*, decltype(x ? s : p)));
57+
58+
static_assert(__is_same(const char*, decltype(true ? p : cp)));
59+
60+
static_assert(__is_same(const char*, decltype(true ? p : "")));
61+
static_assert(__is_same(const char*, decltype(true ? "" : cp)));
62+
63+
static_assert(__is_same(const char*, decltype(x ? cs : cp)));
64+
static_assert(__is_same(const char*, decltype(x ? cs : p)));
65+
static_assert(__is_same(const char*, decltype(x ? cs : cpc)));
66+
67+
Base* b;
68+
Derived* d;
69+
70+
static_assert(__is_same(Base*, decltype(true ? b : d)));
71+
72+
char (*a10)[10];
73+
char (*a100)[100];
74+
char (*a)[];
75+
const char (*ca)[];
76+
77+
// clang-format off
78+
// expected-error@1 {{left operand to ? is 'char (*)[10]', but right operand is of type 'char (*)[100]'}}
79+
x ? a10 : a100;
80+
// clang-format on
4981

50-
static_assert(__is_same(char*, decltype(x ? s : cp)));
82+
static_assert(__is_same(char (*&)[10], decltype(x ? a10 : a10)));
83+
static_assert(__is_same(const char (*)[], decltype(x ? a10 : a)));
84+
static_assert(__is_same(char (*&)[], decltype(x ? a : a)));
85+
static_assert(__is_same(const char (*)[], decltype(x ? a : ca)));
5186
}

0 commit comments

Comments
 (0)