@@ -372,6 +372,13 @@ private List<TopLevelItem> parseTopLevelItem(List<CppLexerToken> leadingComments
372372 if (checkKeyword ("class" ) || checkKeyword ("struct" )) {
373373 // Partial specialization: "template<typename T> struct Foo<T*> { ... }"
374374 // After parsing the class/struct, check for a specialization arg list.
375+ // BUT: "struct TypeName funcName(...)" is a function with elaborated return type
376+ if (pos + 2 < tokens .size ()
377+ && tokens .get (pos + 1 ).type () == CppLexerTokenType .IDENTIFIER
378+ && tokens .get (pos + 2 ).type () == CppLexerTokenType .IDENTIFIER
379+ && !tokens .get (pos + 1 ).isKeyword ("class" ) && !tokens .get (pos + 1 ).isKeyword ("struct" )) {
380+ return parseFunctionOrVariable (leadingComments , templateParams , true );
381+ }
375382 return List .of (parseTypeDef (leadingComments , templateParams ));
376383 }
377384 if (checkKeyword ("enum" )) {
@@ -899,6 +906,12 @@ private List<TopLevelItem> parseClassMember(List<CppLexerToken> leadingComments,
899906 raw .append (";" );
900907 return List .of (new PreprocessorLine (raw .toString (), tokens .get (anonStart ).line (), tokens .get (anonStart ).col (), leadingComments ));
901908 }
909+ // "struct/class Name funcName(" -- elaborated return type, not a definition
910+ if (pos + 2 < tokens .size ()
911+ && tokens .get (pos + 1 ).type () == CppLexerTokenType .IDENTIFIER
912+ && tokens .get (pos + 2 ).type () == CppLexerTokenType .IDENTIFIER ) {
913+ return parseFunctionOrVariable (leadingComments , templateParams , false );
914+ }
902915 return List .of (parseTypeDef (leadingComments , templateParams ));
903916 }
904917 if (checkKeyword ("enum" )) {
@@ -955,11 +968,11 @@ private List<TopLevelItem> parseClassMember(List<CppLexerToken> leadingComments,
955968 matchKeyword ("explicit" ); // plain explicit
956969 }
957970 boolean isConstexprCtor = false ;
958- if (checkKeyword ("constexpr" ) && pos + 1 < tokens .size ()
971+ if (( checkKeyword ("constexpr" ) || checkKeyword ( "consteval" ) ) && pos + 1 < tokens .size ()
959972 && tokens .get (pos + 1 ).type () == CppLexerTokenType .IDENTIFIER
960973 && tokens .get (pos + 1 ).text ().equals (enclosingClassName )
961974 && pos + 2 < tokens .size () && tokens .get (pos + 2 ).isPunct ("(" )) {
962- advance (); // consume constexpr
975+ advance (); // consume constexpr/consteval
963976 isConstexprCtor = true ;
964977 }
965978 // Constructor: match enclosingClassName OR just its base name (for specializations like Grid<T,N,false>)
@@ -1000,18 +1013,6 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
10001013 // order-flexible: also accept override before const, just in case
10011014 if (!isConst ) isConst = matchKeyword ("const" );
10021015
1003- List <FunctionDecl .ConstructorInit > initList = new ArrayList <>();
1004- if (!isDestructor && matchPunct (":" )) {
1005- FunctionDecl .ConstructorInit ci1 = parseConstructorInitEntry ();
1006- if (matchPunct ("..." )) ci1 = new FunctionDecl .ConstructorInit (ci1 .memberName () + "..." , ci1 .args ());
1007- initList .add (ci1 );
1008- while (matchPunct ("," )) {
1009- FunctionDecl .ConstructorInit ci = parseConstructorInitEntry ();
1010- if (matchPunct ("..." )) ci = new FunctionDecl .ConstructorInit (ci .memberName () + "..." , ci .args ());
1011- initList .add (ci );
1012- }
1013- }
1014-
10151016 // Consume trailing qualifiers: noexcept, noexcept(expr), override, final, requires
10161017 while (true ) {
10171018 if (checkKeyword ("noexcept" )) {
@@ -1027,6 +1028,18 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
10271028 else { while (!isAtEnd () && !checkPunct ("{" ) && !checkPunct (";" ) && !checkOp ("=" )) { if (checkOp ("<" )) { advance (); int d =1 ; while (!isAtEnd ()&&d >0 ){if (checkOp ("<" ))d ++;else if (checkOp (">" ))d --;advance ();} } else advance (); } }
10281029 } else break ;
10291030 }
1031+ List <FunctionDecl .ConstructorInit > initList = new ArrayList <>();
1032+ if (!isDestructor && matchPunct (":" )) {
1033+ FunctionDecl .ConstructorInit ci1 = parseConstructorInitEntry ();
1034+ if (matchPunct ("..." )) ci1 = new FunctionDecl .ConstructorInit (ci1 .memberName () + "..." , ci1 .args ());
1035+ initList .add (ci1 );
1036+ while (matchPunct ("," )) {
1037+ FunctionDecl .ConstructorInit ci = parseConstructorInitEntry ();
1038+ if (matchPunct ("..." )) ci = new FunctionDecl .ConstructorInit (ci .memberName () + "..." , ci .args ());
1039+ initList .add (ci );
1040+ }
1041+
1042+ }
10301043
10311044 // Pure-virtual specifier ("= 0"), e.g. "virtual ~A() = 0;" -- a
10321045 // real, valid C++ idiom for ensuring polymorphic deletion through
@@ -1515,6 +1528,10 @@ private boolean looksLikeParamList() {
15151528 expectPunct ("(" );
15161529 if (checkPunct (")" )) return true ;
15171530 if (!(check (CppLexerTokenType .IDENTIFIER ) || check (CppLexerTokenType .KEYWORD ))) return false ;
1531+ // Skip explicit object param keyword: "this"
1532+ if (checkKeyword ("this" )) advance ();
1533+ if (checkPunct (")" )) return true ;
1534+ if (!(check (CppLexerTokenType .IDENTIFIER ) || check (CppLexerTokenType .KEYWORD ))) return false ;
15181535 try {
15191536 parseTypeRef ();
15201537 } catch (ParseException e ) {
@@ -1664,8 +1681,9 @@ private TypeRef parseTypeRef(boolean leadingConst) {
16641681 }
16651682
16661683 private TypeRef parseTypeRefAfterConst (boolean isConst ) {
1667- // typename X::Y -- dependent type name , consume and continue
1684+ // typename/struct/class/enum X -- type elaboration or dependent type, consume prefix
16681685 if (checkKeyword ("typename" )) advance ();
1686+ else if (checkKeyword ("struct" ) || checkKeyword ("class" ) || checkKeyword ("enum" )) advance ();
16691687
16701688 // decltype(expr) -- C++11 computed type
16711689 if (checkKeyword ("decltype" )) {
@@ -3020,9 +3038,13 @@ private Capture parseCapture() {
30203038 boolean byRef = matchOp ("&" );
30213039 // "this" is a keyword capture: [this] or [&this]
30223040 if (checkKeyword ("this" )) { advance (); return new Capture ("this" , byRef ); }
3041+ // C++20 pack init-capture: "[...vals = expr]" -- "..." precedes the name
3042+ boolean packPrefix = checkPunct ("..." );
3043+ if (packPrefix ) advance ();
30233044 String name = expectIdentifier ().text ();
30243045 // Pack expansion in capture: "[args...]"
30253046 if (checkPunct ("..." )) { advance (); name = name + "..." ; }
3047+ if (packPrefix ) name = "..." + name ;
30263048 // Init-capture: "z = z * 2" or "w = x + y" -- encode into name string
30273049 if (checkOp ("=" )) {
30283050 advance ();
0 commit comments