@@ -606,9 +606,13 @@ def _parse_template_decl(self) -> TemplateDecl:
606
606
lex .return_token (ptok )
607
607
param = self ._parse_template_type_parameter (tok , None )
608
608
else :
609
- param = self ._parse_parameter (ptok , TemplateNonTypeParam , ">" )
609
+ param , _ = self ._parse_parameter (
610
+ ptok , TemplateNonTypeParam , False , ">"
611
+ )
610
612
else :
611
- param = self ._parse_parameter (tok , TemplateNonTypeParam , ">" )
613
+ param , _ = self ._parse_parameter (
614
+ tok , TemplateNonTypeParam , concept_ok = False , end = ">"
615
+ )
612
616
613
617
params .append (param )
614
618
@@ -1644,23 +1648,43 @@ def _parse_pqname(
1644
1648
#
1645
1649
1646
1650
def _parse_parameter (
1647
- self , tok : typing .Optional [LexToken ], cls : typing .Type [PT ], end : str = ")"
1648
- ) -> PT :
1651
+ self ,
1652
+ tok : typing .Optional [LexToken ],
1653
+ cls : typing .Type [PT ],
1654
+ concept_ok : bool ,
1655
+ end : str = ")" ,
1656
+ ) -> typing .Tuple [PT , typing .Optional [Type ]]:
1649
1657
"""
1650
1658
Parses a single parameter (excluding vararg parameters). Also used
1651
1659
to parse template non-type parameters
1660
+
1661
+ Returns parameter type, abbreviated template type
1652
1662
"""
1653
1663
1654
1664
param_name = None
1655
1665
default = None
1656
1666
param_pack = False
1667
+ parsed_type : typing .Optional [Type ]
1668
+ at_type : typing .Optional [Type ] = None
1657
1669
1658
- # required typename + decorators
1659
- parsed_type , mods = self ._parse_type (tok )
1660
- if parsed_type is None :
1661
- raise self ._parse_error (None )
1670
+ if not tok :
1671
+ tok = self .lex .token ()
1662
1672
1663
- mods .validate (var_ok = False , meth_ok = False , msg = "parsing parameter" )
1673
+ # placeholder type, skip typename
1674
+ if tok .type == "auto" :
1675
+ at_type = parsed_type = Type (PQName ([AutoSpecifier ()]))
1676
+ else :
1677
+ # required typename + decorators
1678
+ parsed_type , mods = self ._parse_type (tok )
1679
+ if parsed_type is None :
1680
+ raise self ._parse_error (None )
1681
+
1682
+ mods .validate (var_ok = False , meth_ok = False , msg = "parsing parameter" )
1683
+
1684
+ # Could be a concept
1685
+ if concept_ok and self .lex .token_if ("auto" ):
1686
+ at_type = Type (parsed_type .typename )
1687
+ parsed_type .typename = PQName ([AutoSpecifier ()])
1664
1688
1665
1689
dtype = self ._parse_cv_ptr (parsed_type )
1666
1690
@@ -1688,32 +1712,50 @@ def _parse_parameter(
1688
1712
if self .lex .token_if ("=" ):
1689
1713
default = self ._create_value (self ._consume_value_until ([], "," , end ))
1690
1714
1715
+ # abbreviated template pack
1716
+ if at_type and self .lex .token_if ("ELLIPSIS" ):
1717
+ param_pack = True
1718
+
1691
1719
param = cls (type = dtype , name = param_name , default = default , param_pack = param_pack )
1692
1720
self .debug_print ("parameter: %s" , param )
1693
- return param
1721
+ return param , at_type
1694
1722
1695
- def _parse_parameters (self ) -> typing .Tuple [typing .List [Parameter ], bool ]:
1723
+ def _parse_parameters (
1724
+ self , concept_ok : bool
1725
+ ) -> typing .Tuple [typing .List [Parameter ], bool , typing .List [TemplateParam ]]:
1696
1726
"""
1697
- Consumes function parameters and returns them, and vararg if found
1727
+ Consumes function parameters and returns them, and vararg if found, and
1728
+ promotes abbreviated template parameters to actual template parameters
1729
+ if concept_ok is True
1698
1730
"""
1699
1731
1700
1732
# starting at a (
1701
1733
1702
1734
# special case: zero parameters
1703
1735
if self .lex .token_if (")" ):
1704
- return [], False
1736
+ return [], False , []
1705
1737
1706
1738
params : typing .List [Parameter ] = []
1707
1739
vararg = False
1740
+ at_params : typing .List [TemplateParam ] = []
1708
1741
1709
1742
while True :
1710
1743
if self .lex .token_if ("ELLIPSIS" ):
1711
1744
vararg = True
1712
1745
self ._next_token_must_be (")" )
1713
1746
break
1714
1747
1715
- param = self ._parse_parameter (None , Parameter )
1748
+ param , at_type = self ._parse_parameter (None , Parameter , concept_ok )
1716
1749
params .append (param )
1750
+ if at_type :
1751
+ at_params .append (
1752
+ TemplateNonTypeParam (
1753
+ type = at_type ,
1754
+ param_idx = len (params ) - 1 ,
1755
+ param_pack = param .param_pack ,
1756
+ )
1757
+ )
1758
+
1717
1759
tok = self ._next_token_must_be ("," , ")" )
1718
1760
if tok .value == ")" :
1719
1761
break
@@ -1728,7 +1770,7 @@ def _parse_parameters(self) -> typing.Tuple[typing.List[Parameter], bool]:
1728
1770
):
1729
1771
params = []
1730
1772
1731
- return params , vararg
1773
+ return params , vararg , at_params
1732
1774
1733
1775
_auto_return_typename = PQName ([AutoSpecifier ()])
1734
1776
@@ -1875,7 +1917,16 @@ def _parse_function(
1875
1917
state .location = location
1876
1918
is_class_block = isinstance (state , ClassBlockState )
1877
1919
1878
- params , vararg = self ._parse_parameters ()
1920
+ params , vararg , at_params = self ._parse_parameters (True )
1921
+
1922
+ # Promote abbreviated template parameters
1923
+ if at_params :
1924
+ if template is None :
1925
+ template = TemplateDecl (at_params )
1926
+ elif isinstance (template , TemplateDecl ):
1927
+ template .params .extend (at_params )
1928
+ else :
1929
+ template [- 1 ].params .extend (at_params )
1879
1930
1880
1931
# A method outside of a class has multiple name segments
1881
1932
multiple_name_segments = len (pqname .segments ) > 1
@@ -2048,7 +2099,7 @@ def _parse_cv_ptr_or_fn(
2048
2099
toks = self ._consume_balanced_tokens (gtok )
2049
2100
self .lex .return_tokens (toks [1 :- 1 ])
2050
2101
2051
- fn_params , vararg = self ._parse_parameters ()
2102
+ fn_params , vararg , _ = self ._parse_parameters (False )
2052
2103
2053
2104
assert not isinstance (dtype , FunctionType )
2054
2105
dtype = dtype_fn = FunctionType (dtype , fn_params , vararg )
@@ -2076,7 +2127,7 @@ def _parse_cv_ptr_or_fn(
2076
2127
assert not isinstance (dtype , FunctionType )
2077
2128
dtype = self ._parse_array_type (aptok , dtype )
2078
2129
elif aptok .type == "(" :
2079
- fn_params , vararg = self ._parse_parameters ()
2130
+ fn_params , vararg , _ = self ._parse_parameters (False )
2080
2131
# the type we already have is the return type of the function pointer
2081
2132
2082
2133
assert not isinstance (dtype , FunctionType )
0 commit comments