@@ -4348,14 +4348,68 @@ void Tokenizer::rebuildTokenDataAfterTemplateSimplification()
43484348void Tokenizer::updateTokenDataAfterTemplateSimplification ()
43494349{
43504350 // update the supporting token information incrementally: the information of the
4351- // unchanged tokens - variable ids, symbols, valuetypes - stays valid
4351+ // unchanged tokens - variable ids, symbols, AST, valuetypes - stays valid
43524352 setVarId (/* incremental*/ true );
43534353 createLinks2 (); // adds the "<>" links of the new tokens
43544354 Token::assignProgressValues (list.front ());
43554355 list.front ()->assignIndexes ();
4356- list.clearAst ();
4357- list.createAst ();
4356+
4357+ // The token regions whose AST and valuetypes must be recreated: the new tokens and
4358+ // the function bodies around the changed call sites.
4359+ bool rebuildAll = false ;
4360+ // the regions (first and last token, inclusive) whose AST and valuetypes must be recreated
4361+ std::vector<std::pair<Token*, Token*>> regions = mTemplateSimplifier ->newTokenRanges ();
4362+ for (const Token* siteTok : mTemplateSimplifier ->dirtyCallSites ()) {
4363+ const Scope* scope = siteTok->scope ();
4364+ if (!scope)
4365+ continue ; // a new token - covered by the new token ranges
4366+ // the outermost executable scope is the function body around the call
4367+ const Scope* functionScope = nullptr ;
4368+ for (const Scope* s = scope; s; s = s->nestedIn ) {
4369+ if (s->isExecutable ())
4370+ functionScope = s;
4371+ }
4372+ if (!functionScope || !functionScope->bodyStart || !functionScope->bodyEnd ||
4373+ functionScope->bodyStart ->astParent ()) {
4374+ // no function body around the call (global initializer, lambda body that is
4375+ // part of an expression, ..) - recreate everything
4376+ rebuildAll = true ;
4377+ break ;
4378+ }
4379+ regions.emplace_back (const_cast <Token*>(functionScope->bodyStart ), const_cast <Token*>(functionScope->bodyEnd ));
4380+ }
4381+
4382+ if (!rebuildAll && !regions.empty ()) {
4383+ // merge the overlapping regions - Token::index() is up to date
4384+ std::sort (regions.begin (), regions.end (), [](const std::pair<Token*, Token*>& lhs, const std::pair<Token*, Token*>& rhs) {
4385+ return lhs.first ->index () < rhs.first ->index ();
4386+ });
4387+ std::vector<std::pair<Token*, Token*>> merged;
4388+ for (const auto & region : regions) {
4389+ if (!merged.empty () && region.first ->index () <= merged.back ().second ->index ()) {
4390+ if (region.second ->index () > merged.back ().second ->index ())
4391+ merged.back ().second = region.second ;
4392+ } else
4393+ merged.push_back (region);
4394+ }
4395+ regions = std::move (merged);
4396+ }
4397+
4398+ if (rebuildAll) {
4399+ list.clearAst ();
4400+ list.createAst ();
4401+ } else {
4402+ for (const auto & region : regions) {
4403+ for (Token* tok = region.first ; tok; tok = tok->next ()) {
4404+ tok->clearAst ();
4405+ if (tok == region.second )
4406+ break ;
4407+ }
4408+ list.createAst (region.first , region.second ->next ());
4409+ }
4410+ }
43584411 list.validateAst (mSettings .debugnormal );
4412+
43594413 for (const Token* nameTok : mTemplateSimplifier ->convertedSpecializations ()) {
43604414 // the specialization became a normal function: its "template < >" tokens are gone
43614415 if (nameTok->function ())
@@ -4369,7 +4423,6 @@ void Tokenizer::updateTokenDataAfterTemplateSimplification()
43694423 tok->tokType (Token::eName);
43704424 }
43714425 mSymbolDatabase ->addSymbolsForNewTokenRanges (mTemplateSimplifier ->newTokenRanges ());
4372- mTemplateSimplifier ->clearTokenChanges ();
43734426 // safety net: every token needs a scope. A token that was added by a simplification
43744427 // that is not covered by the new token ranges gets the scope of the preceding token.
43754428 const Scope* lastScope = nullptr ;
@@ -4381,8 +4434,19 @@ void Tokenizer::updateTokenDataAfterTemplateSimplification()
43814434 } else if (lastScope)
43824435 tok->scope (lastScope);
43834436 }
4384- mSymbolDatabase ->setValueTypeInTokenList (false );
4385- mSymbolDatabase ->setValueTypeInTokenList (true );
4437+
4438+ // recreate the valuetypes of the changed regions
4439+ if (rebuildAll) {
4440+ mSymbolDatabase ->setValueTypeInTokenList (false );
4441+ mSymbolDatabase ->setValueTypeInTokenList (true );
4442+ } else {
4443+ mSymbolDatabase ->updateFunctionAndVariablePointers ();
4444+ for (const auto & region : regions) {
4445+ mSymbolDatabase ->setValueTypeInTokenList (false , region.first , region.second ->next ());
4446+ mSymbolDatabase ->setValueTypeInTokenList (true , region.first , region.second ->next ());
4447+ }
4448+ }
4449+ mTemplateSimplifier ->clearTokenChanges ();
43864450 mSymbolDatabase ->validate ();
43874451}
43884452// ---------------------------------------------------------------------------
0 commit comments