@@ -606,9 +606,13 @@ def _parse_template_decl(self) -> TemplateDecl:
606606 lex .return_token (ptok )
607607 param = self ._parse_template_type_parameter (tok , None )
608608 else :
609- param = self ._parse_parameter (ptok , TemplateNonTypeParam , ">" )
609+ param , _ = self ._parse_parameter (
610+ ptok , TemplateNonTypeParam , False , ">"
611+ )
610612 else :
611- param = self ._parse_parameter (tok , TemplateNonTypeParam , ">" )
613+ param , _ = self ._parse_parameter (
614+ tok , TemplateNonTypeParam , concept_ok = False , end = ">"
615+ )
612616
613617 params .append (param )
614618
@@ -1644,23 +1648,43 @@ def _parse_pqname(
16441648 #
16451649
16461650 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 ]]:
16491657 """
16501658 Parses a single parameter (excluding vararg parameters). Also used
16511659 to parse template non-type parameters
1660+
1661+ Returns parameter type, abbreviated template type
16521662 """
16531663
16541664 param_name = None
16551665 default = None
16561666 param_pack = False
1667+ parsed_type : typing .Optional [Type ]
1668+ at_type : typing .Optional [Type ] = None
16571669
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 ()
16621672
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 ()])
16641688
16651689 dtype = self ._parse_cv_ptr (parsed_type )
16661690
@@ -1688,32 +1712,50 @@ def _parse_parameter(
16881712 if self .lex .token_if ("=" ):
16891713 default = self ._create_value (self ._consume_value_until ([], "," , end ))
16901714
1715+ # abbreviated template pack
1716+ if at_type and self .lex .token_if ("ELLIPSIS" ):
1717+ param_pack = True
1718+
16911719 param = cls (type = dtype , name = param_name , default = default , param_pack = param_pack )
16921720 self .debug_print ("parameter: %s" , param )
1693- return param
1721+ return param , at_type
16941722
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 ]]:
16961726 """
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
16981730 """
16991731
17001732 # starting at a (
17011733
17021734 # special case: zero parameters
17031735 if self .lex .token_if (")" ):
1704- return [], False
1736+ return [], False , []
17051737
17061738 params : typing .List [Parameter ] = []
17071739 vararg = False
1740+ at_params : typing .List [TemplateParam ] = []
17081741
17091742 while True :
17101743 if self .lex .token_if ("ELLIPSIS" ):
17111744 vararg = True
17121745 self ._next_token_must_be (")" )
17131746 break
17141747
1715- param = self ._parse_parameter (None , Parameter )
1748+ param , at_type = self ._parse_parameter (None , Parameter , concept_ok )
17161749 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+
17171759 tok = self ._next_token_must_be ("," , ")" )
17181760 if tok .value == ")" :
17191761 break
@@ -1728,7 +1770,7 @@ def _parse_parameters(self) -> typing.Tuple[typing.List[Parameter], bool]:
17281770 ):
17291771 params = []
17301772
1731- return params , vararg
1773+ return params , vararg , at_params
17321774
17331775 _auto_return_typename = PQName ([AutoSpecifier ()])
17341776
@@ -1875,7 +1917,16 @@ def _parse_function(
18751917 state .location = location
18761918 is_class_block = isinstance (state , ClassBlockState )
18771919
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 )
18791930
18801931 # A method outside of a class has multiple name segments
18811932 multiple_name_segments = len (pqname .segments ) > 1
@@ -2048,7 +2099,7 @@ def _parse_cv_ptr_or_fn(
20482099 toks = self ._consume_balanced_tokens (gtok )
20492100 self .lex .return_tokens (toks [1 :- 1 ])
20502101
2051- fn_params , vararg = self ._parse_parameters ()
2102+ fn_params , vararg , _ = self ._parse_parameters (False )
20522103
20532104 assert not isinstance (dtype , FunctionType )
20542105 dtype = dtype_fn = FunctionType (dtype , fn_params , vararg )
@@ -2076,7 +2127,7 @@ def _parse_cv_ptr_or_fn(
20762127 assert not isinstance (dtype , FunctionType )
20772128 dtype = self ._parse_array_type (aptok , dtype )
20782129 elif aptok .type == "(" :
2079- fn_params , vararg = self ._parse_parameters ()
2130+ fn_params , vararg , _ = self ._parse_parameters (False )
20802131 # the type we already have is the return type of the function pointer
20812132
20822133 assert not isinstance (dtype , FunctionType )
0 commit comments