@@ -632,10 +632,106 @@ bool TemplateSimplifier::removeTemplate(Token *tok)
632632 return false ;
633633}
634634
635+ // / TODO: This is copy pasted from Tokenizer. We should reuse this code.
636+ namespace {
637+ struct ScopeInfo2 {
638+ ScopeInfo2 (const std::string &name_, const Token *bodyEnd_) : name(name_), bodyEnd(bodyEnd_) {}
639+ const std::string name;
640+ const Token * const bodyEnd;
641+ std::set<std::string> usingNamespaces;
642+ };
643+ }
644+ static std::string getScopeName (const std::list<ScopeInfo2> &scopeInfo)
645+ {
646+ std::string ret;
647+ for (const ScopeInfo2 &i : scopeInfo) {
648+ if (!i.name .empty ())
649+ ret += (ret.empty () ? " " : " :: " ) + i.name ;
650+ }
651+ return ret;
652+ }
653+
654+ static void setScopeInfo (Token *tok, std::list<ScopeInfo2> *scopeInfo, bool all = false )
655+ {
656+ while (tok->str () == " }" && !scopeInfo->empty () && tok == scopeInfo->back ().bodyEnd )
657+ scopeInfo->pop_back ();
658+ if (!Token::Match (tok, " namespace|class|struct|union %name% {|:|::" )) {
659+ // check for using namespace
660+ if (Token::Match (tok, " using namespace %name% ;|::" )) {
661+ const Token * tok1 = tok->tokAt (2 );
662+ std::string nameSpace;
663+ while (tok1 && tok1->str () != " ;" ) {
664+ if (!nameSpace.empty ())
665+ nameSpace += " " ;
666+ nameSpace += tok1->str ();
667+ tok1 = tok1->next ();
668+ }
669+ scopeInfo->back ().usingNamespaces .insert (nameSpace);
670+ }
671+ // check for member function
672+ else if (tok->str () == " {" ) {
673+ bool added = false ;
674+ Token *tok1 = tok;
675+ while (Token::Match (tok1->previous (), " const|volatile|final|override|&|&&|noexcept" ))
676+ tok1 = tok1->previous ();
677+ if (tok1 && tok1->previous () && tok1->strAt (-1 ) == " )" ) {
678+ tok1 = tok1->linkAt (-1 );
679+ if (Token::Match (tok1->previous (), " throw|noexcept" )) {
680+ tok1 = tok1->previous ();
681+ while (Token::Match (tok1->previous (), " const|volatile|final|override|&|&&|noexcept" ))
682+ tok1 = tok1->previous ();
683+ if (tok1->strAt (-1 ) != " )" )
684+ return ;
685+ } else if (Token::Match (tok->tokAt (-2 ), " :|, %name%" )) {
686+ tok1 = tok1->tokAt (-2 );
687+ if (tok1->strAt (-1 ) != " )" )
688+ return ;
689+ }
690+ if (tok1->strAt (-1 ) == " >" )
691+ tok1 = tok1->previous ()->findOpeningBracket ();
692+ if (tok1 && Token::Match (tok1->tokAt (-3 ), " %name% :: %name%" )) {
693+ tok1 = tok1->tokAt (-2 );
694+ std::string scope = tok1->strAt (-1 );
695+ while (Token::Match (tok1->tokAt (-2 ), " :: %name%" )) {
696+ scope = tok1->strAt (-3 ) + " :: " + scope;
697+ tok1 = tok1->tokAt (-2 );
698+ }
699+ scopeInfo->emplace_back (scope, tok->link ());
700+ added = true ;
701+ }
702+ }
703+
704+ if (all && !added)
705+ scopeInfo->emplace_back (" " , tok->link ());
706+ }
707+ return ;
708+ }
709+
710+ tok = tok->next ();
711+ std::string classname = tok->str ();
712+ while (Token::Match (tok, " %name% :: %name%" )) {
713+ tok = tok->tokAt (2 );
714+ classname += " :: " + tok->str ();
715+ }
716+ tok = tok->next ();
717+ if (tok && tok->str () == " :" ) {
718+ while (tok && !Token::Match (tok, " ;|{" ))
719+ tok = tok->next ();
720+ }
721+ if (tok && tok->str () == " {" ) {
722+ scopeInfo->emplace_back (classname,tok->link ());
723+ }
724+ }
725+
635726bool TemplateSimplifier::getTemplateDeclarations ()
636727{
637728 bool codeWithTemplates = false ;
729+ std::list<ScopeInfo2> scopeInfo;
638730 for (Token *tok = mTokenList .front (); tok; tok = tok->next ()) {
731+ if (Token::Match (tok, " {|}|namespace|class|struct|union" )) {
732+ setScopeInfo (tok, &scopeInfo);
733+ continue ;
734+ }
639735 if (!Token::simpleMatch (tok, " template <" ))
640736 continue ;
641737 // ignore template template parameter
@@ -660,7 +756,7 @@ bool TemplateSimplifier::getTemplateDeclarations()
660756 else if (Token::Match (tok2, " {|=|;" )) {
661757 const int namepos = getTemplateNamePosition (parmEnd);
662758 if (namepos > 0 ) {
663- TokenAndName decl (tok, tok-> scopeInfo ()-> name , parmEnd->tokAt (namepos), parmEnd);
759+ TokenAndName decl (tok, getScopeName (scopeInfo) , parmEnd->tokAt (namepos), parmEnd);
664760 if (decl.isForwardDeclaration ()) {
665761 // Declaration => add to mTemplateForwardDeclarations
666762 mTemplateForwardDeclarations .emplace_back (decl);
@@ -697,9 +793,18 @@ void TemplateSimplifier::getTemplateInstantiations()
697793 functionNameMap.insert (std::make_pair (decl.name , &decl));
698794 }
699795
796+ std::list<ScopeInfo2> scopeList;
700797 const Token *skip = nullptr ;
701798
799+ scopeList.emplace_back (" " , nullptr );
800+
702801 for (Token *tok = mTokenList .front (); tok; tok = tok->next ()) {
802+ if (Token::Match (tok, " {|}|namespace|class|struct|union" ) ||
803+ Token::Match (tok, " using namespace %name% ;|::" )) {
804+ setScopeInfo (tok, &scopeList);
805+ continue ;
806+ }
807+
703808 // template definition.. skip it
704809 if (Token::simpleMatch (tok, " template <" )) {
705810 tok = tok->next ()->findClosingBracket ();
@@ -750,7 +855,7 @@ void TemplateSimplifier::getTemplateInstantiations()
750855 } else if (Token::Match (tok->previous (), " (|{|}|;|=|>|<<|:|.|*|&|return|<|, %name% ::|<|(" ) ||
751856 Token::Match (tok->previous (), " %type% %name% ::|<" ) ||
752857 Token::Match (tok->tokAt (-2 ), " [,:] private|protected|public %name% ::|<" )) {
753- std::string scopeName = tok-> scopeInfo ()-> name ;
858+ std::string scopeName = getScopeName (scopeList) ;
754859 std::string qualification;
755860 Token * qualificationTok = tok;
756861 while (Token::Match (tok, " %name% :: %name%" )) {
@@ -846,7 +951,7 @@ void TemplateSimplifier::getTemplateInstantiations()
846951 for (; tok2 && tok2 != tok; tok2 = tok2->previous ()) {
847952 if (Token::Match (tok2, " ,|< %name% <" ) &&
848953 (tok2->strAt (3 ) == " >" || templateParameters (tok2->tokAt (2 )))) {
849- addInstantiation (tok2->next (), tok-> scopeInfo ()-> name );
954+ addInstantiation (tok2->next (), getScopeName (scopeList) );
850955 } else if (Token::Match (tok2->next (), " class|struct" ))
851956 tok2->deleteNext ();
852957 }
@@ -865,7 +970,7 @@ void TemplateSimplifier::getTemplateInstantiations()
865970 } else {
866971 // full name doesn't match so try with using namespaces if available
867972 bool found = false ;
868- for (const auto & nameSpace : tok-> scopeInfo ()-> usingNamespaces ) {
973+ for (const auto & nameSpace : scopeList. back (). usingNamespaces ) {
869974 std::string fullNameSpace = scopeName + (scopeName.empty ()?" " :" :: " ) +
870975 nameSpace + (qualification.empty ()?" " :" :: " ) + qualification;
871976 std::string newFullName = fullNameSpace + " :: " + tok->str ();
@@ -892,7 +997,7 @@ void TemplateSimplifier::getTemplateInstantiations()
892997 if (!qualification.empty ())
893998 addInstantiation (tok, qualification);
894999 else
895- addInstantiation (tok, tok-> scopeInfo ()-> name );
1000+ addInstantiation (tok, getScopeName (scopeList) );
8961001 break ;
8971002 }
8981003 const std::string::size_type pos = scopeName.rfind (" :: " );
@@ -1433,6 +1538,7 @@ void TemplateSimplifier::expandTemplate(
14331538 const std::string &newName,
14341539 bool copy)
14351540{
1541+ std::list<ScopeInfo2> scopeInfo;
14361542 bool inTemplateDefinition = false ;
14371543 const Token *startOfTemplateDeclaration = nullptr ;
14381544 const Token *endOfTemplateDefinition = nullptr ;
@@ -1647,6 +1753,10 @@ void TemplateSimplifier::expandTemplate(
16471753 }
16481754
16491755 for (Token *tok3 = mTokenList .front (); tok3; tok3 = tok3 ? tok3->next () : nullptr ) {
1756+ if (Token::Match (tok3, " {|}|namespace|class|struct|union" )) {
1757+ setScopeInfo (tok3, &scopeInfo);
1758+ continue ;
1759+ }
16501760 if (inTemplateDefinition) {
16511761 if (!endOfTemplateDefinition) {
16521762 if (isVariable) {
@@ -2826,8 +2936,13 @@ void TemplateSimplifier::replaceTemplateUsage(
28262936 const std::list<std::string> &typeStringsUsedInTemplateInstantiation,
28272937 const std::string &newName)
28282938{
2939+ std::list<ScopeInfo2> scopeInfo;
28292940 std::list< std::pair<Token *, Token *> > removeTokens;
28302941 for (Token *nameTok = mTokenList .front (); nameTok; nameTok = nameTok->next ()) {
2942+ if (Token::Match (nameTok, " {|}|namespace|class|struct|union" )) {
2943+ setScopeInfo (nameTok, &scopeInfo);
2944+ continue ;
2945+ }
28312946 if (!Token::Match (nameTok, " %name% <" ) ||
28322947 Token::Match (nameTok, " template|const_cast|dynamic_cast|reinterpret_cast|static_cast" ))
28332948 continue ;
@@ -3255,10 +3370,6 @@ void TemplateSimplifier::simplifyTemplates(
32553370 unsigned int passCount = 0 ;
32563371 const unsigned int passCountMax = 10 ;
32573372 for (; passCount < passCountMax; ++passCount) {
3258- // Recalculate scopes from scratch every pass, in case a scope is missing or incorrect
3259- for (auto tok = mTokenizer ->list .front (); tok; tok = tok->next ()) tok->scopeInfo (nullptr );
3260- mTokenizer ->calculateScopes ();
3261-
32623373 if (passCount) {
32633374 // it may take more than one pass to simplify type aliases
32643375 bool usingChanged = false ;
0 commit comments