@@ -497,6 +497,9 @@ bool TemplateSimplifier::getTemplateDeclarations()
497497 tok2 = tok2->link ();
498498 else if (tok2->str () == " )" )
499499 break ;
500+ // skip decltype(...)
501+ else if (Token::Match (tok2, " decltype (" ))
502+ tok2 = tok2->linkAt (1 );
500503 // Declaration => add to mTemplateForwardDeclarations
501504 else if (tok2->str () == " ;" ) {
502505 const int namepos = getTemplateNamePosition (parmEnd, true );
@@ -891,17 +894,24 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateFunction(const Token *to
891894 while (tok && tok->next ()) {
892895 if (Token::Match (tok->next (), " ;|{" ))
893896 return false ;
894- else if (Token::Match (tok->next (), " %type% <" )) {
897+ // skip decltype(...)
898+ else if (Token::Match (tok, " decltype (" )) {
899+ const Token * end = tok->linkAt (1 );
900+ while (tok && tok != end) {
901+ tok = tok->next ();
902+ namepos++;
903+ }
904+ } else if (Token::Match (tok->next (), " %type% <" )) {
895905 const Token *closing = tok->tokAt (2 )->findClosingBracket ();
896906 if (closing) {
897- if (closing->strAt (1 ) == " (" && mTokenizer -> isFunctionHead (closing->tokAt ( 2 ), " ;|{|:" ))
907+ if (closing->strAt (1 ) == " (" && Tokenizer:: isFunctionHead (closing->next ( ), " ;|{|:" , true ))
898908 return true ;
899909 while (tok && tok->next () && tok->next () != closing) {
900910 tok = tok->next ();
901911 namepos++;
902912 }
903913 }
904- } else if (Token::Match (tok->next (), " %type% (" ) && mTokenizer -> isFunctionHead (tok->tokAt (2 ), " ;|{|:" )) {
914+ } else if (Token::Match (tok->next (), " %type% (" ) && Tokenizer:: isFunctionHead (tok->tokAt (2 ), " ;|{|:" , true )) {
905915 return true ;
906916 }
907917 tok = tok->next ();
@@ -984,15 +994,19 @@ void TemplateSimplifier::expandTemplate(
984994 const Token *endOfTemplateDefinition = nullptr ;
985995 const Token * const templateDeclarationNameToken = templateDeclarationToken->tokAt (getTemplateNamePosition (templateDeclarationToken));
986996 const bool isClass = Token::Match (templateDeclarationToken->next (), " class|struct|union %name% <|{|:" );
987- const bool isFunction = templateDeclarationNameToken->strAt (1 ) == " (" ;
997+ const bool isFunction = templateDeclarationNameToken->strAt (1 ) == " (" ||
998+ (templateDeclarationNameToken->strAt (1 ) == " <" && templateDeclarationNameToken->next ()->findClosingBracket ()->strAt (1 ) == " (" );
999+ const bool isSpecialization = Token::Match (templateDeclaration.token , " template < >" );
9881000
9891001 // add forward declarations
9901002 if (copy && isClass) {
9911003 templateDeclaration.token ->insertToken (templateDeclarationToken->strAt (1 ), " " , true );
9921004 templateDeclaration.token ->insertToken (newName, " " , true );
9931005 templateDeclaration.token ->insertToken (" ;" , " " , true );
994- } else if (copy && isFunction ) {
1006+ } else if (isFunction && ( copy || (!copy && isSpecialization)) ) {
9951007 Token * dst = templateDeclaration.token ;
1008+ bool isStatic = false ;
1009+ std::string scope;
9961010 Token * start;
9971011 Token * end;
9981012 auto it = mTemplateForwardDeclarationsMap .find (dst);
@@ -1003,8 +1017,21 @@ void TemplateSimplifier::expandTemplate(
10031017 start = temp1->next ();
10041018 end = temp2->linkAt (1 )->next ();
10051019 } else {
1020+ auto it2 = mTemplateUserSpecializationMap .find (dst);
1021+ if (it2 != mTemplateUserSpecializationMap .end ()) {
1022+ dst = it2->second ;
1023+ isStatic = dst->next ()->findClosingBracket ()->strAt (1 ) == " static" ;
1024+ const Token * temp = templateDeclarationNameToken;
1025+ while (Token::Match (temp->tokAt (-2 ), " %name% ::" )) {
1026+ scope.insert (0 , temp->strAt (-2 ) + " :: " );
1027+ temp = temp->tokAt (-2 );
1028+ }
1029+ }
10061030 start = templateDeclarationToken->next ();
1007- end = templateDeclarationNameToken->linkAt (1 )->next ();
1031+ if (templateDeclarationNameToken->strAt (1 ) == " (" )
1032+ end = templateDeclarationNameToken->linkAt (1 )->next ();
1033+ else
1034+ end = templateDeclarationNameToken->next ()->findClosingBracket ()->linkAt (1 )->next ();
10081035 }
10091036 unsigned int typeindentlevel = 0 ;
10101037 while (!(typeindentlevel == 0 && Token::Match (end, " ;|{|:" ))) {
@@ -1015,6 +1042,9 @@ void TemplateSimplifier::expandTemplate(
10151042 end = end->next ();
10161043 }
10171044
1045+ if (isStatic)
1046+ dst->insertToken (" static" , " " , true );
1047+
10181048 std::map<const Token *, Token *> links;
10191049 while (start && start != end) {
10201050 unsigned int itype = 0 ;
@@ -1041,7 +1071,11 @@ void TemplateSimplifier::expandTemplate(
10411071 dst->previous ()->isLong (typetok->isLong ());
10421072 }
10431073 } else {
1044- if (start->str () == templateDeclarationNameToken->str ()) {
1074+ if (isSpecialization && !copy && !scope.empty () && Token::Match (start, (scope + templateDeclarationNameToken->str ()).c_str ())) {
1075+ // skip scope
1076+ while (start->strAt (1 ) != templateDeclarationNameToken->str ())
1077+ start = start->next ();
1078+ } else if (start->str () == templateDeclarationNameToken->str ()) {
10451079 dst->insertToken (newName, " " , true );
10461080 if (start->strAt (1 ) == " <" )
10471081 start = start->next ()->findClosingBracket ();
@@ -1133,6 +1167,8 @@ void TemplateSimplifier::expandTemplate(
11331167 // Start of template..
11341168 if (tok3 == templateDeclarationToken) {
11351169 tok3 = tok3->next ();
1170+ if (tok3->str () == " static" )
1171+ tok3 = tok3->next ();
11361172 }
11371173
11381174 // member function implemented outside class definition
@@ -1907,23 +1943,12 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
19071943 return false ;
19081944
19091945 // already simplified
1910- if (!Token::Match (startToken , " %name% <" ))
1946+ if (!Token::Match (tok2 , " %name% <" ))
19111947 return false ;
19121948
1913- if (templateDeclaration.scope .empty ()) {
1914- if (startToken->str () != templateDeclaration.name )
1915- return false ;
1916- } else {
1917- std::string name = templateDeclaration.scope + " :: " + startToken->str ();
1918- if (name != templateDeclaration.name )
1919- return false ;
1920- }
1921-
1922- if (!matchSpecialization (tok->tokAt (namepos), startToken, specializations))
1949+ if (!matchSpecialization (tok->tokAt (namepos), tok2, specializations))
19231950 return false ;
19241951
1925- tok2 = startToken;
1926-
19271952 // New type..
19281953 mTypesUsedInTemplateInstantiation .clear ();
19291954 std::list<std::string> typeStringsUsedInTemplateInstantiation;
@@ -2051,6 +2076,61 @@ void TemplateSimplifier::replaceTemplateUsage(
20512076 }
20522077}
20532078
2079+ static std::string getPathName (const TemplateSimplifier::TokenAndName & decl)
2080+ {
2081+ std::string name = decl.scope ;
2082+ if (!name.empty ())
2083+ name += " :: " ;
2084+ if (decl.nameToken ->strAt (-1 ) == " ::" ) {
2085+ const Token * start = decl.nameToken ;
2086+
2087+ while (Token::Match (start->tokAt (-2 ), " %name% ::" ))
2088+ start = start->tokAt (-2 );
2089+
2090+ while (start != decl.nameToken ) {
2091+ name += (start->str () + " " );
2092+ start = start->next ();
2093+ }
2094+ }
2095+ name += decl.name ;
2096+ return name;
2097+ }
2098+
2099+ void TemplateSimplifier::getUserDefinedSpecializations ()
2100+ {
2101+ // try to locate a matching declaration for each user defined specialization
2102+ for (auto & spec : mTemplateDeclarations ) {
2103+ if (Token::Match (spec.token , " template < >" )) {
2104+ std::string specName = getPathName (spec);
2105+
2106+ bool found = false ;
2107+ for (auto & decl : mTemplateDeclarations ) {
2108+ if (Token::Match (decl.token , " template < >" ))
2109+ continue ;
2110+ std::string declName = getPathName (decl);
2111+
2112+ // make sure the scopes and names match
2113+ if (specName == declName) {
2114+ // @todo make sure function parameters also match
2115+ mTemplateUserSpecializationMap [spec.token ] = decl.token ;
2116+ }
2117+ }
2118+
2119+ if (!found) {
2120+ for (auto & decl : mTemplateForwardDeclarations ) {
2121+ std::string declName = getPathName (decl);
2122+
2123+ // make sure the scopes and names match
2124+ if (specName == declName) {
2125+ // @todo make sure function parameters also match
2126+ mTemplateUserSpecializationMap [spec.token ] = decl.token ;
2127+ }
2128+ }
2129+ }
2130+ }
2131+ }
2132+ }
2133+
20542134void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues ()
20552135{
20562136 // try to locate a matching declaration for each forward declaration
@@ -2066,26 +2146,8 @@ void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
20662146
20672147 // make sure the number of arguments match
20682148 if (params1.size () == params2.size ()) {
2069- std::string declName = decl.scope ;
2070- if (!declName.empty ())
2071- declName += " :: " ;
2072- if (decl.nameToken ->strAt (-1 ) == " ::" ) {
2073- const Token * start = decl.nameToken ;
2074-
2075- while (Token::Match (start->tokAt (-2 ), " %name% ::" ))
2076- start = start->tokAt (-2 );
2077-
2078- while (start != decl.nameToken ) {
2079- declName += (start->str () + " " );
2080- start = start->next ();
2081- }
2082- }
2083- declName += decl.name ;
2084-
2085- std::string forwardDeclName = forwardDecl.scope ;
2086- if (!forwardDeclName.empty ())
2087- forwardDeclName += " :: " ;
2088- forwardDeclName += forwardDecl.name ;
2149+ std::string declName = getPathName (decl);
2150+ std::string forwardDeclName = getPathName (forwardDecl);
20892151
20902152 // make sure the scopes and names match
20912153 if (forwardDeclName == declName) {
@@ -2124,6 +2186,7 @@ void TemplateSimplifier::simplifyTemplates(
21242186 mTemplateDeclarations .clear ();
21252187 mTemplateForwardDeclarations .clear ();
21262188 mTemplateForwardDeclarationsMap .clear ();
2189+ mTemplateUserSpecializationMap .clear ();
21272190 mTemplateInstantiations .clear ();
21282191 mInstantiatedTemplates .clear ();
21292192 mExplicitInstantiationsToDelete .clear ();
@@ -2157,6 +2220,9 @@ void TemplateSimplifier::simplifyTemplates(
21572220 // Copy default argument values from forward declaration to declaration
21582221 fixForwardDeclaredDefaultArgumentValues ();
21592222
2223+ // Locate user defined specializations.
2224+ getUserDefinedSpecializations ();
2225+
21602226 // Locate possible instantiations of templates..
21612227 getTemplateInstantiations ();
21622228
0 commit comments