@@ -4763,6 +4763,26 @@ static const std::unordered_set<std::string> notstart_cpp = { NOTSTART_C,
47634763 " delete" , " friend" , " new" , " throw" , " using" , " virtual" , " explicit" , " const_cast" , " dynamic_cast" , " reinterpret_cast" , " static_cast" , " template"
47644764};
47654765
4766+ // Returns the end of the lambda that starts at tok in a constructor initializer list, or nullptr
4767+ static const Token* findInitListLambdaEnd (const Token* tok)
4768+ {
4769+ if (!Token::simpleMatch (tok, " [" ) || Token::Match (tok->previous (), " %name%|)|]|>" ))
4770+ return nullptr ; // array subscript or array size of a new expression
4771+ // array size of a new expression with pointer or reference type: new T*[n]{...}, new (p) T*[n]{...}
4772+ for (const Token* prev = tok->previous (); Token::Match (prev, " *|&|&&|::|%name%|>|)" ); prev = prev->previous ()) {
4773+ if (prev->str () == " new" )
4774+ return nullptr ;
4775+ if (prev->str () == " )" )
4776+ prev = prev->link ();
4777+ else if (prev->str () == " >" ) {
4778+ prev = prev->findOpeningBracket ();
4779+ if (!prev)
4780+ break ;
4781+ }
4782+ }
4783+ return findLambdaEndScope (tok);
4784+ }
4785+
47664786void Tokenizer::setVarIdPass1 ()
47674787{
47684788 const bool cpp = isCPP ();
@@ -4778,6 +4798,7 @@ void Tokenizer::setVarIdPass1()
47784798 std::stack<const Token *> functionDeclEndStack;
47794799 const Token *functionDeclEndToken = nullptr ;
47804800 bool initlist = false ;
4801+ std::stack<const Token *> initlistLambdaEnds; // ends of lambdas in constructor initializer lists
47814802 bool inlineFunction = false ;
47824803 for (Token *tok = list.front (); tok; tok = tok->next ()) {
47834804 if (tok->isOp ())
@@ -4813,6 +4834,13 @@ void Tokenizer::setVarIdPass1()
48134834 variableMap.enterScope ();
48144835 }
48154836 }
4837+ } else if (const Token* lambdaEnd = initlist ? findInitListLambdaEnd (tok) : nullptr ) {
4838+ // lambda in initializer list: parse it like a lambda in executable code, the
4839+ // extra scope holds its parameters and is left at the end of the lambda
4840+ initlistLambdaEnds.push (lambdaEnd);
4841+ scopeStack.emplace (/* isExecutable=*/ true , /* isStructInit=*/ false , /* isEnum=*/ false , variableMap.getVarId ());
4842+ variableMap.enterScope ();
4843+ initlist = false ;
48164844 } else if (!initlist && tok->str ()==" (" ) {
48174845 const Token * newFunctionDeclEnd = nullptr ;
48184846 if (!scopeStack.top ().isExecutable )
@@ -4903,6 +4931,15 @@ void Tokenizer::setVarIdPass1()
49034931 }
49044932 }
49054933 }
4934+
4935+ if (!initlistLambdaEnds.empty () && initlistLambdaEnds.top () == tok) {
4936+ // end of lambda in initializer list
4937+ initlistLambdaEnds.pop ();
4938+ if (scopeStack.size () > 1 )
4939+ scopeStack.pop ();
4940+ variableMap.leaveScope ();
4941+ initlist = true ;
4942+ }
49064943 }
49074944
49084945 if ((!scopeStack.top ().isStructInit &&
0 commit comments