@@ -105,7 +105,12 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *token, const std::string &
105105 throw InternalError (mToken , " explicit specialization of alias templates is not permitted" , InternalError::SYNTAX);
106106 }
107107
108- isClass (Token::Match (mParamEnd ->next (), " class|struct|union %name% <|{|:|;|::" ));
108+ isFriend (mParamEnd ->strAt (1 ) == " friend" );
109+ const Token *next = mParamEnd ->next ();
110+ if (isFriend ())
111+ next = next->next ();
112+
113+ isClass (Token::Match (next, " class|struct|union %name% <|{|:|;|::" ));
109114 if (mToken ->strAt (1 ) == " <" && !isSpecialization ()) {
110115 const Token *end = mToken ->next ()->findClosingBracket ();
111116 isVariadic (end && Token::findmatch (mToken ->tokAt (2 ), " typename|class . . ." , end));
@@ -119,22 +124,24 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *token, const std::string &
119124 throw InternalError (mToken , " unsupported syntax" , InternalError::SYNTAX);
120125 }
121126 isFunction (tok1->str () == " (" );
122- isVariable (!isClass () && !isAlias () && Token::Match (tok1, " =|;" ));
123- if (isVariable ())
124- isForwardDeclaration (tok1->str () == " ;" );
125- else if (!isAlias ()) {
126- if (isFunction ())
127- tok1 = tok1->link ()->next ();
128- while (tok1 && !Token::Match (tok1, " ;|{" )) {
129- if (tok1->str () == " <" )
130- tok1 = tok1->findClosingBracket ();
131- else if (Token::Match (tok1, " (|[" ) && tok1->link ())
132- tok1 = tok1->link ();
127+ isVariable (!isClass () && !isAlias () && !isFriend () && Token::Match (tok1, " =|;" ));
128+ if (!isFriend ()) {
129+ if (isVariable ())
130+ isForwardDeclaration (tok1->str () == " ;" );
131+ else if (!isAlias ()) {
132+ if (isFunction ())
133+ tok1 = tok1->link ()->next ();
134+ while (tok1 && !Token::Match (tok1, " ;|{" )) {
135+ if (tok1->str () == " <" )
136+ tok1 = tok1->findClosingBracket ();
137+ else if (Token::Match (tok1, " (|[" ) && tok1->link ())
138+ tok1 = tok1->link ();
139+ if (tok1)
140+ tok1 = tok1->next ();
141+ }
133142 if (tok1)
134- tok1 = tok1-> next ( );
143+ isForwardDeclaration ( tok1-> str () == " ; " );
135144 }
136- if (tok1)
137- isForwardDeclaration (tok1->str () == " ;" );
138145 }
139146 // check for member class or function and adjust scope
140147 if ((isFunction () || isClass ()) && mNameToken ->strAt (-1 ) == " ::" ) {
@@ -983,7 +990,7 @@ void TemplateSimplifier::useDefaultArgumentValues()
983990void TemplateSimplifier::useDefaultArgumentValues (TokenAndName &declaration)
984991{
985992 // Ticket #5762: Skip specialization tokens
986- if (declaration.isSpecialization () || declaration.isAlias ())
993+ if (declaration.isSpecialization () || declaration.isAlias () || declaration. isFriend () )
987994 return ;
988995
989996 // template parameters with default value has syntax such as:
@@ -1395,9 +1402,9 @@ bool TemplateSimplifier::getTemplateNamePositionTemplateVariable(const Token *to
13951402
13961403bool TemplateSimplifier::getTemplateNamePositionTemplateClass (const Token *tok, int &namepos)
13971404{
1398- if (Token::Match (tok, " > class|struct|union %type% :|<|;|{|::" )) {
1399- namepos = 2 ;
1400- tok = tok->tokAt (2 );
1405+ if (Token::Match (tok, " > friend| class|struct|union %type% :|<|;|{|::" )) {
1406+ namepos = tok-> strAt ( 1 ) == " friend " ? 3 : 2 ;
1407+ tok = tok->tokAt (namepos );
14011408 while (Token::Match (tok, " %type% :: %type%" ) ||
14021409 (Token::Match (tok, " %type% <" ) && Token::Match (tok->next ()->findClosingBracket (), " > :: %type%" ))) {
14031410 if (tok->strAt (1 ) == " ::" ) {
@@ -2026,7 +2033,11 @@ void TemplateSimplifier::expandTemplate(
20262033 }
20272034 }
20282035 } else {
2029- if (copy) {
2036+ // don't modify friend
2037+ if (Token::Match (tok3->tokAt (-3 ), " > friend class|struct|union" )) {
2038+ if (copy)
2039+ mTokenList .addtoken (tok3);
2040+ } else if (copy) {
20302041 // add namespace if necessary
20312042 if (!templateDeclaration.scope ().empty () &&
20322043 (isClass ? tok3->strAt (1 ) != " (" : true )) {
@@ -3154,7 +3165,7 @@ static bool specMatch(
31543165 const TemplateSimplifier::TokenAndName &decl)
31553166{
31563167 // make sure decl is really a declaration
3157- if (decl.isPartialSpecialization () || decl.isSpecialization () || decl.isAlias ())
3168+ if (decl.isPartialSpecialization () || decl.isSpecialization () || decl.isAlias () || decl. isFriend () )
31583169 return false ;
31593170
31603171 return spec.isSameFamily (decl);
@@ -3237,8 +3248,8 @@ void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
32373248 getTemplateParametersInDeclaration (forwardDecl.token ()->tokAt (2 ), params1);
32383249
32393250 for (auto & decl : mTemplateDeclarations ) {
3240- // skip partializations
3241- if (decl.isPartialSpecialization ())
3251+ // skip partializations, type aliases and friends
3252+ if (decl.isPartialSpecialization () || decl. isAlias () || decl. isFriend () )
32423253 continue ;
32433254
32443255 std::vector<const Token *> params2;
@@ -3321,6 +3332,8 @@ void TemplateSimplifier::printOut(const TokenAndName &tokenAndName, const std::s
33213332 std::cout << " isForwardDeclaration" ;
33223333 if (tokenAndName.isVariadic ())
33233334 std::cout << " isVariadic" ;
3335+ if (tokenAndName.isFriend ())
3336+ std::cout << " isFriend" ;
33243337 std::cout << std::endl;
33253338 if (tokenAndName.token () && !tokenAndName.paramEnd () && tokenAndName.token ()->strAt (1 ) == " <" ) {
33263339 const Token *end = tokenAndName.token ()->next ()->findClosingBracket ();
@@ -3544,13 +3557,13 @@ void TemplateSimplifier::simplifyTemplates(
35443557 std::set<std::string> expandedtemplates;
35453558
35463559 for (std::list<TokenAndName>::reverse_iterator iter1 = mTemplateDeclarations .rbegin (); iter1 != mTemplateDeclarations .rend (); ++iter1) {
3547- if (iter1->isAlias ())
3560+ if (iter1->isAlias () || iter1-> isFriend () )
35483561 continue ;
35493562
35503563 // get specializations..
35513564 std::list<const Token *> specializations;
35523565 for (std::list<TokenAndName>::const_iterator iter2 = mTemplateDeclarations .begin (); iter2 != mTemplateDeclarations .end (); ++iter2) {
3553- if (iter2->isAlias ())
3566+ if (iter2->isAlias () || iter2-> isFriend () )
35543567 continue ;
35553568
35563569 if (iter1->fullName () == iter2->fullName ())
0 commit comments