@@ -739,7 +739,9 @@ private String parseBaseClassEntry() {
739739 sb .append ('>' );
740740 name = sb .toString ();
741741 }
742- return isVirtualBase ? "virtual " + name : name ;
742+ boolean isPackExpansion = matchPunct ("..." ); // pack expansion in base class list: "Bases..."
743+ String suffix = isPackExpansion ? "..." : "" ;
744+ return isVirtualBase ? "virtual " + name + suffix : name + suffix ;
743745 }
744746
745747 /**
@@ -852,9 +854,13 @@ private FunctionDecl parseFunctionOrConstructorOrDestructor(List<CppLexerToken>
852854
853855 List <FunctionDecl .ConstructorInit > initList = new ArrayList <>();
854856 if (!isDestructor && matchPunct (":" )) {
855- initList .add (parseConstructorInitEntry ());
857+ FunctionDecl .ConstructorInit ci1 = parseConstructorInitEntry ();
858+ if (matchPunct ("..." )) ci1 = new FunctionDecl .ConstructorInit (ci1 .memberName () + "..." , ci1 .args ());
859+ initList .add (ci1 );
856860 while (matchPunct ("," )) {
857- initList .add (parseConstructorInitEntry ());
861+ FunctionDecl .ConstructorInit ci = parseConstructorInitEntry ();
862+ if (matchPunct ("..." )) ci = new FunctionDecl .ConstructorInit (ci .memberName () + "..." , ci .args ());
863+ initList .add (ci );
858864 }
859865 }
860866
@@ -969,6 +975,7 @@ private List<TopLevelItem> parseFunctionOrVariable(List<CppLexerToken> leadingCo
969975 matchKeyword ("volatile" ); // consume volatile qualifier
970976 boolean isConst = matchKeyword ("const" );
971977 boolean isConstexprFn = matchKeyword ("constexpr" ); if (isConstexprFn ) isConst = true ;
978+ if (!isVirtual ) isVirtual = matchKeyword ("virtual" ); // constexpr virtual
972979 if (!isStatic ) isStatic = matchKeyword ("static" );
973980 if (!isConst ) isConst = matchKeyword ("const" );
974981 matchKeyword ("volatile" ); // volatile may appear after const
@@ -1053,6 +1060,7 @@ && looksLikeParamList()) {
10531060 }
10541061 // Constructor initializer list: ": mem(val), mem2(val2)"
10551062 if (matchPunct (":" ) && !checkPunct (":" )) {
1063+ System .err .println ("[INITV] consuming init list, next=" + peek ().text ());
10561064 // consume initializer list entries until { or ;
10571065 int _d = 0 ;
10581066 while (!isAtEnd ()) {
@@ -1727,6 +1735,20 @@ private TypeRef parseTemplateArg() {
17271735 if (checkPunct ("(" )) {
17281736 return parseFunctionSignatureTail (maybeReturnType );
17291737 }
1738+ // NTTP arithmetic expression: "N-1", "N*2", "N+1" etc.
1739+ // After parsing the base type/value, consume arithmetic ops and operands
1740+ if (maybeReturnType instanceof NamedType nt && !nt .baseName ().equals ("void" )) {
1741+ StringBuilder expr = new StringBuilder (nt .baseName ());
1742+ while (!isAtEnd () && (checkOp ("+" ) || checkOp ("-" ) || checkOp ("*" ) || checkOp ("/" ) || checkOp ("%" ))) {
1743+ expr .append (advance ().text ());
1744+ if (!isAtEnd () && (check (CppLexerTokenType .INT_LITERAL ) || check (CppLexerTokenType .IDENTIFIER ))) {
1745+ expr .append (advance ().text ());
1746+ }
1747+ }
1748+ if (expr .length () > nt .baseName ().length ()) {
1749+ return new NamedType (expr .toString (), List .of (), 0 , false , false );
1750+ }
1751+ }
17301752 return maybeReturnType ;
17311753 }
17321754
@@ -2548,6 +2570,14 @@ private Expr parseInitializerElement() {
25482570 if (checkPunct ("{" )) {
25492571 return parseInitializerList (); // anonymous nested brace-init
25502572 }
2573+ // Designated initializer: ".field = expr" (C++20)
2574+ if (checkPunct ("." ) && pos + 1 < tokens .size ()
2575+ && tokens .get (pos + 1 ).type () == CppLexerTokenType .IDENTIFIER
2576+ && pos + 2 < tokens .size () && tokens .get (pos + 2 ).isOp ("=" )) {
2577+ advance (); // consume "."
2578+ advance (); // consume field name
2579+ advance (); // consume "="
2580+ }
25512581 Expr e = parseExpr ();
25522582 matchPunct ("..." ); // pack expansion in brace-init: "{args...}"
25532583 return e ;
@@ -2953,8 +2983,7 @@ private Statement parseStatement(List<CppLexerToken> leadingComments) {
29532983
29542984 private Statement parseIf (List <CppLexerToken > leadingComments ) {
29552985 CppLexerToken start = expectKeyword ("if" );
2956- matchKeyword ("constexpr" ); // C++17 if constexpr
2957- boolean isConstexpr = matchKeyword ("constexpr" );
2986+ boolean isConstexpr = matchKeyword ("constexpr" ); // C++17 if constexpr
29582987 expectPunct ("(" );
29592988 // C++17 if-init-statement: if (init; cond) -- collect init decls,
29602989 // wrap the IfStatement in a Block so the init vars are in scope.
0 commit comments