Move non-template requires to the function
- Methods can have a requires() that refer to the class template without an explicit function template - This is a breaking change, but since the values aren't parsed yet I can't imagine anyone is using it
This commit is contained in:
parent
f1708bf9b8
commit
85f93ec09e
@ -1907,12 +1907,10 @@ class CxxParser:
|
|||||||
else:
|
else:
|
||||||
rtok = self.lex.token_if("requires")
|
rtok = self.lex.token_if("requires")
|
||||||
if rtok:
|
if rtok:
|
||||||
fn_template = fn.template
|
# requires on a function must always be accompanied by a template
|
||||||
if fn_template is None:
|
if fn.template is None:
|
||||||
raise self._parse_error(rtok)
|
raise self._parse_error(rtok)
|
||||||
elif isinstance(fn_template, list):
|
fn.raw_requires = self._parse_requires(rtok)
|
||||||
fn_template = fn_template[0]
|
|
||||||
fn_template.raw_requires_post = self._parse_requires(rtok)
|
|
||||||
|
|
||||||
if self.lex.token_if("ARROW"):
|
if self.lex.token_if("ARROW"):
|
||||||
self._parse_trailing_return_type(fn)
|
self._parse_trailing_return_type(fn)
|
||||||
@ -1978,12 +1976,7 @@ class CxxParser:
|
|||||||
toks = self._consume_balanced_tokens(otok)[1:-1]
|
toks = self._consume_balanced_tokens(otok)[1:-1]
|
||||||
method.noexcept = self._create_value(toks)
|
method.noexcept = self._create_value(toks)
|
||||||
elif tok_value == "requires":
|
elif tok_value == "requires":
|
||||||
method_template = method.template
|
method.raw_requires = self._parse_requires(tok)
|
||||||
if method_template is None:
|
|
||||||
raise self._parse_error(tok)
|
|
||||||
elif isinstance(method_template, list):
|
|
||||||
method_template = method_template[0]
|
|
||||||
method_template.raw_requires_post = self._parse_requires(tok)
|
|
||||||
else:
|
else:
|
||||||
self.lex.return_token(tok)
|
self.lex.return_token(tok)
|
||||||
break
|
break
|
||||||
|
@ -526,9 +526,6 @@ class TemplateDecl:
|
|||||||
#: template <typename T> requires ...
|
#: template <typename T> requires ...
|
||||||
raw_requires_pre: typing.Optional[Value] = None
|
raw_requires_pre: typing.Optional[Value] = None
|
||||||
|
|
||||||
#: template <typename T> int main() requires ...
|
|
||||||
raw_requires_post: typing.Optional[Value] = None
|
|
||||||
|
|
||||||
|
|
||||||
#: If no template, this is None. This is a TemplateDecl if this there is a single
|
#: If no template, this is None. This is a TemplateDecl if this there is a single
|
||||||
#: declaration:
|
#: declaration:
|
||||||
@ -730,6 +727,13 @@ class Function:
|
|||||||
#: is the string "conversion" and the full Type is found in return_type
|
#: is the string "conversion" and the full Type is found in return_type
|
||||||
operator: typing.Optional[str] = None
|
operator: typing.Optional[str] = None
|
||||||
|
|
||||||
|
#: A requires constraint following the function declaration. If you need the
|
||||||
|
#: prior, look at TemplateDecl.raw_requires_pre. At the moment this is just
|
||||||
|
#: a raw value, if we interpret it in the future this will change.
|
||||||
|
#:
|
||||||
|
#: template <typename T> int main() requires ...
|
||||||
|
raw_requires: typing.Optional[Value] = None
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Method(Function):
|
class Method(Function):
|
||||||
|
@ -6,6 +6,7 @@ from cxxheaderparser.types import (
|
|||||||
Concept,
|
Concept,
|
||||||
Function,
|
Function,
|
||||||
FundamentalSpecifier,
|
FundamentalSpecifier,
|
||||||
|
Method,
|
||||||
MoveReference,
|
MoveReference,
|
||||||
NameSpecifier,
|
NameSpecifier,
|
||||||
PQName,
|
PQName,
|
||||||
@ -495,15 +496,15 @@ def test_requires_last_elem() -> None:
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
template=TemplateDecl(
|
template=TemplateDecl(
|
||||||
params=[TemplateTypeParam(typekey="typename", name="T")],
|
params=[TemplateTypeParam(typekey="typename", name="T")]
|
||||||
raw_requires_post=Value(
|
),
|
||||||
tokens=[
|
raw_requires=Value(
|
||||||
Token(value="Eq"),
|
tokens=[
|
||||||
Token(value="<"),
|
Token(value="Eq"),
|
||||||
Token(value="T"),
|
Token(value="<"),
|
||||||
Token(value=">"),
|
Token(value="T"),
|
||||||
]
|
Token(value=">"),
|
||||||
),
|
]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -752,14 +753,14 @@ def test_requires_both() -> None:
|
|||||||
Token(value=">"),
|
Token(value=">"),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
raw_requires_post=Value(
|
),
|
||||||
tokens=[
|
raw_requires=Value(
|
||||||
Token(value="Subtractable"),
|
tokens=[
|
||||||
Token(value="<"),
|
Token(value="Subtractable"),
|
||||||
Token(value="T"),
|
Token(value="<"),
|
||||||
Token(value=">"),
|
Token(value="T"),
|
||||||
]
|
Token(value=">"),
|
||||||
),
|
]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -791,21 +792,87 @@ def test_requires_paren() -> None:
|
|||||||
)
|
)
|
||||||
],
|
],
|
||||||
template=TemplateDecl(
|
template=TemplateDecl(
|
||||||
params=[TemplateTypeParam(typekey="class", name="T")],
|
params=[TemplateTypeParam(typekey="class", name="T")]
|
||||||
raw_requires_post=Value(
|
),
|
||||||
tokens=[
|
raw_requires=Value(
|
||||||
Token(value="("),
|
tokens=[
|
||||||
Token(value="is_purrable"),
|
Token(value="("),
|
||||||
Token(value="<"),
|
Token(value="is_purrable"),
|
||||||
Token(value="T"),
|
Token(value="<"),
|
||||||
Token(value=">"),
|
Token(value="T"),
|
||||||
Token(value="("),
|
Token(value=">"),
|
||||||
Token(value=")"),
|
Token(value="("),
|
||||||
Token(value=")"),
|
Token(value=")"),
|
||||||
]
|
Token(value=")"),
|
||||||
),
|
]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_non_template_requires() -> None:
|
||||||
|
content = """
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct Payload
|
||||||
|
{
|
||||||
|
constexpr Payload(T v)
|
||||||
|
requires(std::is_pod_v<T>)
|
||||||
|
: Value(v)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
data = parse_string(content, cleandoc=True)
|
||||||
|
|
||||||
|
assert data == ParsedData(
|
||||||
|
namespace=NamespaceScope(
|
||||||
|
classes=[
|
||||||
|
ClassScope(
|
||||||
|
class_decl=ClassDecl(
|
||||||
|
typename=PQName(
|
||||||
|
segments=[NameSpecifier(name="Payload")], classkey="struct"
|
||||||
|
),
|
||||||
|
template=TemplateDecl(
|
||||||
|
params=[TemplateTypeParam(typekey="class", name="T")]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
methods=[
|
||||||
|
Method(
|
||||||
|
return_type=None,
|
||||||
|
name=PQName(segments=[NameSpecifier(name="Payload")]),
|
||||||
|
parameters=[
|
||||||
|
Parameter(
|
||||||
|
type=Type(
|
||||||
|
typename=PQName(
|
||||||
|
segments=[NameSpecifier(name="T")]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
name="v",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
constexpr=True,
|
||||||
|
has_body=True,
|
||||||
|
raw_requires=Value(
|
||||||
|
tokens=[
|
||||||
|
Token(value="("),
|
||||||
|
Token(value="std"),
|
||||||
|
Token(value="::"),
|
||||||
|
Token(value="is_pod_v"),
|
||||||
|
Token(value="<"),
|
||||||
|
Token(value="T"),
|
||||||
|
Token(value=">"),
|
||||||
|
Token(value=")"),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
access="public",
|
||||||
|
constructor=True,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user