Skip to content

Commit 56a899a

Browse files
committed
fix(cpp1): improve recognition of value-dependent expressions
1 parent 0ebac0d commit 56a899a

File tree

3 files changed

+125
-12
lines changed

3 files changed

+125
-12
lines changed

regression-tests/pure2-bugfix-for-dependent-types.cpp2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ f: <T, V: T::value_type> (x: T::value_type) -> T::value_type = {
1111
_ = :identity<T>::value_type = (); // First identifier.
1212
_ = :std::optional<T>::value_type = (); // Non-first identifier.
1313
_ = :std::array<i32, T::value>::value_type = ();
14+
_ = :std::array<i32, T::value + T::value>::value_type = ();
1415

1516
// Emitted `template`.
1617
ptr: type == * T; // Needed, pending #502.

regression-tests/test-results/pure2-bugfix-for-dependent-types.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include "cpp2util.h"
88

99

10-
#line 47 "pure2-bugfix-for-dependent-types.cpp2"
10+
#line 48 "pure2-bugfix-for-dependent-types.cpp2"
1111
template<typename T> class t;
1212

1313

@@ -19,14 +19,14 @@ template<typename T> using identity = T;
1919
template<typename T, T::value_type V> [[nodiscard]] auto f(cpp2::in<typename T::value_type> x) -> T::value_type;
2020

2121

22-
#line 47 "pure2-bugfix-for-dependent-types.cpp2"
22+
#line 48 "pure2-bugfix-for-dependent-types.cpp2"
2323
template<typename T> class t {
2424
struct u_x_as_base { T::value_type x; };
2525

26-
#line 48 "pure2-bugfix-for-dependent-types.cpp2"
26+
#line 49 "pure2-bugfix-for-dependent-types.cpp2"
2727
public: class u: public u_x_as_base, public T::type {
2828

29-
#line 51 "pure2-bugfix-for-dependent-types.cpp2"
29+
#line 52 "pure2-bugfix-for-dependent-types.cpp2"
3030
};
3131
public: T::value_type x {0};
3232
};
@@ -49,6 +49,7 @@ template<typename T, T::value_type V> [[nodiscard]] auto f(cpp2::in<typename T::
4949
(void) typename identity<T>::value_type{};// First identifier.
5050
(void) typename std::optional<T>::value_type{};// Non-first identifier.
5151
(void) typename std::array<cpp2::i32,T::value>::value_type{};
52+
(void) typename std::array<cpp2::i32,T::value + T::value>::value_type{};
5253

5354
// Emitted `template`.
5455
using ptr = T*; // Needed, pending #502.
@@ -82,7 +83,7 @@ template<typename T, T::value_type V> [[nodiscard]] auto f(cpp2::in<typename T::
8283
}
8384
}
8485

85-
#line 55 "pure2-bugfix-for-dependent-types.cpp2"
86+
#line 56 "pure2-bugfix-for-dependent-types.cpp2"
8687
auto main() -> int{
8788
using zero = std::integral_constant<cpp2::i32,0>;
8889
(void) f<zero,0>(0);

source/cppfront.cpp

Lines changed: 118 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,121 @@ class cppfront
18191819
return false;
18201820
}
18211821

1822+
struct is_dependent_expression_visitor {
1823+
cppfront* self;
1824+
1825+
auto operator()(expression_node const& expr) const
1826+
-> bool
1827+
{
1828+
return (*this)(*expr.expr);
1829+
}
1830+
1831+
template<String Name, typename Term>
1832+
auto operator()(binary_expression_node<Name, Term> const& expr) const
1833+
-> bool
1834+
{
1835+
return (*this)(*expr.expr) || std::any_of(expr.terms.begin(), expr.terms.end(), *this);
1836+
}
1837+
1838+
template<class BinaryExpressionTerm>
1839+
auto operator()(BinaryExpressionTerm const& term) const
1840+
-> bool
1841+
requires requires { term.op; term.expr; }
1842+
{
1843+
return (*this)(*term.expr);
1844+
}
1845+
1846+
auto operator()(is_as_expression_node const& expr) const
1847+
-> bool
1848+
{
1849+
return (*this)(*expr.expr) || std::any_of(expr.ops.begin(), expr.ops.end(), *this);
1850+
}
1851+
1852+
auto operator()(is_as_expression_node::term const& expr) const
1853+
-> bool
1854+
{
1855+
if (expr.expr) {
1856+
return (*this)(*expr.expr);
1857+
}
1858+
return self->is_dependent(*expr.type);
1859+
}
1860+
1861+
auto operator()(prefix_expression_node const& expr) const
1862+
-> bool
1863+
{
1864+
return (*this)(*expr.expr);
1865+
}
1866+
1867+
auto operator()(postfix_expression_node const& expr) const
1868+
-> bool
1869+
{
1870+
return (*this)(*expr.expr) || std::any_of(expr.ops.begin(), expr.ops.end(), *this);
1871+
}
1872+
1873+
auto operator()(postfix_expression_node::term const& expr) const
1874+
-> bool
1875+
{
1876+
if (expr.id_expr) {
1877+
return (*this)(*expr.id_expr);
1878+
}
1879+
return (*this)(*expr.expr_list);
1880+
}
1881+
1882+
auto operator()(primary_expression_node const& expr) const
1883+
-> bool
1884+
{
1885+
return std::visit([&]<typename T>(T const& expr) {
1886+
if constexpr (std::is_same_v<T, std::monostate>
1887+
|| std::is_same_v<T, token const*>
1888+
|| std::is_same_v<T, std::unique_ptr<literal_node>>) {
1889+
return false;
1890+
} else {
1891+
return (*this)(*expr);
1892+
}
1893+
}, expr.expr);
1894+
}
1895+
1896+
auto operator()(expression_list_node const& expr) const
1897+
-> bool
1898+
{
1899+
return std::any_of(expr.expressions.begin(), expr.expressions.end(), *this);
1900+
}
1901+
1902+
auto operator()(expression_list_node::term const& term) const
1903+
-> bool
1904+
{
1905+
return (*this)(*term.expr);
1906+
}
1907+
1908+
auto operator()(id_expression_node const& expr) const
1909+
-> bool
1910+
{
1911+
return std::visit([&]<typename T>(T const& expr) {
1912+
if constexpr (std::is_same_v<T, std::monostate>) {
1913+
return false;
1914+
} else {
1915+
return self->is_dependent(*expr);
1916+
}
1917+
}, expr.id);
1918+
}
1919+
1920+
auto operator()(declaration_node const& n) const
1921+
-> bool
1922+
{
1923+
auto& type_id = std::get<declaration_node::an_object>(n.type);
1924+
if (type_id->is_wildcard()) {
1925+
return false; // (*this)(*term.initializer);
1926+
}
1927+
return self->is_dependent(*type_id);
1928+
}
1929+
1930+
auto operator()(inspect_expression_node const& expr) const
1931+
-> bool
1932+
{
1933+
return self->is_deducible(*expr.result_type);
1934+
}
1935+
};
1936+
18221937
auto is_dependent(
18231938
const unqualified_id_node& n,
18241939
bool /*is_qualified*/ = false,
@@ -1835,13 +1950,9 @@ class cppfront
18351950
assert(n.identifier);
18361951
// and any of its template arguments is either
18371952
return std::any_of(n.template_args.begin(), n.template_args.end(), [&](unqualified_id_node::term const& arg) {
1838-
if (auto expr = get_if<unqualified_id_node::expression>(&arg.arg);
1839-
expr && (*expr)->is_id_expression()) {
1840-
// a dependent _id-expression_
1841-
auto& pid = (*expr)->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr->expr;
1842-
if (auto id = get_if<primary_expression_node::id_expression>(&pid)) {
1843-
return is_dependent(**id);
1844-
}
1953+
if (auto expr = get_if<unqualified_id_node::expression>(&arg.arg)) {
1954+
// a dependent _expression_
1955+
return is_dependent_expression_visitor{this}(**expr);
18451956
}
18461957
else if (auto type_id = get_if<unqualified_id_node::type_id>(&arg.arg)) {
18471958
// or a dependent _type-id_.

0 commit comments

Comments
 (0)