@@ -176,6 +176,17 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp,
176
176
return ret;
177
177
}
178
178
179
+ bool isFunctionCall (const Token* tok)
180
+ {
181
+ if (Token::Match (tok, " %name% (" ))
182
+ return true ;
183
+ if (Token::Match (tok, " %name% <" ) && Token::simpleMatch (tok->next ()->link (), " > (" ))
184
+ return true ;
185
+ if (Token::Match (tok, " %name% ::" ))
186
+ return isFunctionCall (tok->tokAt (2 ));
187
+ return false ;
188
+ }
189
+
179
190
static bool hasToken (const Token * startTok, const Token * stopTok, const Token * tok)
180
191
{
181
192
for (const Token * tok2 = startTok; tok2 != stopTok; tok2 = tok2->next ()) {
@@ -227,8 +238,10 @@ bool precedes(const Token * tok1, const Token * tok2)
227
238
return tok1->index () < tok2->index ();
228
239
}
229
240
230
- static bool isAliased (const Token * startTok, const Token * endTok, nonneg int varid)
241
+ bool isAliased (const Token *startTok, const Token *endTok, nonneg int varid)
231
242
{
243
+ if (!precedes (startTok, endTok))
244
+ return false ;
232
245
for (const Token *tok = startTok; tok != endTok; tok = tok->next ()) {
233
246
if (Token::Match (tok, " = & %varid% ;" , varid))
234
247
return true ;
@@ -248,6 +261,18 @@ static bool isAliased(const Token * startTok, const Token * endTok, nonneg int v
248
261
return false ;
249
262
}
250
263
264
+ bool isAliased (const Variable *var)
265
+ {
266
+ if (!var)
267
+ return false ;
268
+ if (!var->scope ())
269
+ return false ;
270
+ const Token *start = var->declEndToken ();
271
+ if (!start)
272
+ return false ;
273
+ return isAliased (start, var->scope ()->bodyEnd , var->declarationId ());
274
+ }
275
+
251
276
static bool exprDependsOnThis (const Token *expr, nonneg int depth)
252
277
{
253
278
if (!expr)
@@ -814,6 +839,19 @@ bool isVariableChangedByFunctionCall(const Token *tok, nonneg int varid, const S
814
839
isVariableChangedByFunctionCall (tok->astOperand2 (), varid, settings, inconclusive);
815
840
}
816
841
842
+ static bool isScopeBracket (const Token *tok)
843
+ {
844
+ if (!Token::Match (tok, " {|}" ))
845
+ return false ;
846
+ if (!tok->scope ())
847
+ return false ;
848
+ if (tok->str () == " {" )
849
+ return tok->scope ()->bodyStart == tok;
850
+ if (tok->str () == " }" )
851
+ return tok->scope ()->bodyEnd == tok;
852
+ return false ;
853
+ }
854
+
817
855
bool isVariableChangedByFunctionCall (const Token *tok, const Settings *settings, bool *inconclusive)
818
856
{
819
857
if (!tok)
@@ -832,7 +870,7 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
832
870
parent = parent->astParent ();
833
871
834
872
// passing variable to subfunction?
835
- if (Token::Match (parent, " [(,]" ))
873
+ if (Token::Match (parent, " [(,{ ]" ))
836
874
;
837
875
else if (Token::simpleMatch (parent, " :" )) {
838
876
while (Token::Match (parent, " [?:]" ))
@@ -847,24 +885,24 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
847
885
848
886
// goto start of function call and get argnr
849
887
int argnr = 0 ;
850
- while (tok && !Token::Match (tok, " [;{}] " )) {
888
+ while (tok && !Token::simpleMatch (tok, " ; " ) && ! isScopeBracket (tok )) {
851
889
if (tok->str () == " ," )
852
890
++argnr;
853
891
else if (tok->str () == " )" )
854
892
tok = tok->link ();
855
- else if (Token::Match (tok->previous (), " %name% (" ))
893
+ else if (Token::Match (tok->previous (), " %name% (|{ " ))
856
894
break ;
857
- else if (Token::simpleMatch (tok->previous (), " > (" ) && tok->previous ()->link ())
895
+ else if (Token::Match (tok->previous (), " > (|{ " ) && tok->previous ()->link ())
858
896
break ;
859
897
tok = tok->previous ();
860
898
}
861
- if (!tok || tok-> str () != " ( " )
899
+ if (!Token::Match ( tok, " {|( " ) )
862
900
return false ;
863
- const bool possiblyPassedByReference = (tok->next () == tok1 || Token::Match (tok1->previous (), " , %name% [,)]" ));
901
+ const bool possiblyPassedByReference = (tok->next () == tok1 || Token::Match (tok1->previous (), " , %name% [,)} ]" ));
864
902
tok = tok->previous ();
865
903
if (tok && tok->link () && tok->str () == " >" )
866
904
tok = tok->link ()->previous ();
867
- if (!Token::Match (tok, " %name% [(<]" ))
905
+ if (!Token::Match (tok, " %name% [({ <]" ))
868
906
return false ; // not a function => variable not changed
869
907
870
908
// Constructor call
@@ -932,6 +970,8 @@ bool isVariableChangedByFunctionCall(const Token *tok, const Settings *settings,
932
970
933
971
bool isVariableChanged (const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp)
934
972
{
973
+ if (!precedes (start, end))
974
+ return false ;
935
975
for (const Token *tok = start; tok != end; tok = tok->next ()) {
936
976
if (tok->varId () != varid) {
937
977
if (globalvar && Token::Match (tok, " %name% (" ))
@@ -941,20 +981,32 @@ bool isVariableChanged(const Token *start, const Token *end, const nonneg int va
941
981
}
942
982
943
983
const Token *tok2 = tok;
944
- while (Token::simpleMatch (tok2->astParent (), " *" ))
984
+ while (Token::simpleMatch (tok2->astParent (), " *" ) || (Token::simpleMatch (tok2->astParent (), " ." ) && !Token::simpleMatch (tok2->astParent ()->astParent (), " (" )) ||
985
+ (Token::simpleMatch (tok2->astParent (), " [" ) && tok2 == tok2->astParent ()->astOperand1 ()))
945
986
tok2 = tok2->astParent ();
946
987
947
988
if (Token::Match (tok2->astParent (), " ++|--" ))
948
989
return true ;
949
990
950
- if (tok2->astParent () && tok2->astParent ()->isAssignmentOp () && tok2 == tok2->astParent ()->astOperand1 ())
951
- return true ;
991
+ if (tok2->astParent () && tok2->astParent ()->isAssignmentOp ()) {
992
+ if (tok2 == tok2->astParent ()->astOperand1 ())
993
+ return true ;
994
+ // Check if assigning to a non-const lvalue
995
+ const Variable * var = getLHSVariable (tok2->astParent ());
996
+ if (var && var->isReference () && !var->isConst () && var->nameToken () && var->nameToken ()->next () == tok2->astParent ()) {
997
+ if (!var->isLocal () || isVariableChanged (var, settings, cpp))
998
+ return true ;
999
+ }
1000
+ }
952
1001
953
1002
if (isLikelyStreamRead (cpp, tok->previous ()))
954
1003
return true ;
955
1004
1005
+ if (isLikelyStream (cpp, tok2))
1006
+ return true ;
1007
+
956
1008
// Member function call
957
- if (Token::Match (tok , " %name% . %name% ( " ) ) {
1009
+ if (tok-> variable () && Token::Match (tok2-> astParent () , " . %name%" ) && isFunctionCall (tok2-> astParent ()-> next ()) && tok2-> astParent ()-> astOperand1 () == tok2 ) {
958
1010
const Variable * var = tok->variable ();
959
1011
bool isConst = var && var->isConst ();
960
1012
if (!isConst && var) {
@@ -966,25 +1018,42 @@ bool isVariableChanged(const Token *start, const Token *end, const nonneg int va
966
1018
const Function * fun = ftok->function ();
967
1019
if (!isConst && (!fun || !fun->isConst ()))
968
1020
return true ;
1021
+ else
1022
+ continue ;
969
1023
}
970
1024
971
- const Token *ftok = tok ;
972
- while (ftok && (!Token::Match (ftok, " [({[ ]" ) || ftok->isCast ()))
1025
+ const Token *ftok = tok2 ;
1026
+ while (ftok && (!Token::Match (ftok, " [({]" ) || ftok->isCast ()))
973
1027
ftok = ftok->astParent ();
974
1028
975
- if (ftok && Token::Match (ftok->link (), " ) !!{" )) {
1029
+ if (ftok && Token::Match (ftok->link (), " )|} !!{" )) {
1030
+ const Token * ptok = tok2;
1031
+ while (Token::Match (ptok->astParent (), " .|::|[" ))
1032
+ ptok = ptok->astParent ();
976
1033
bool inconclusive = false ;
977
- bool isChanged = isVariableChangedByFunctionCall (tok , settings, &inconclusive);
1034
+ bool isChanged = isVariableChangedByFunctionCall (ptok , settings, &inconclusive);
978
1035
isChanged |= inconclusive;
979
1036
if (isChanged)
980
1037
return true ;
981
1038
}
982
1039
983
- const Token *parent = tok ->astParent ();
1040
+ const Token *parent = tok2 ->astParent ();
984
1041
while (Token::Match (parent, " .|::" ))
985
1042
parent = parent->astParent ();
986
1043
if (parent && parent->tokType () == Token::eIncDecOp)
987
1044
return true ;
1045
+
1046
+ if (Token::simpleMatch (tok2->astParent (), " :" ) && tok2->astParent ()->astParent () && Token::simpleMatch (tok2->astParent ()->astParent ()->previous (), " for (" )) {
1047
+ const Token * varTok = tok2->astParent ()->previous ();
1048
+ if (!varTok)
1049
+ continue ;
1050
+ const Variable * loopVar = varTok->variable ();
1051
+ if (!loopVar)
1052
+ continue ;
1053
+ if (!loopVar->isConst () && loopVar->isReference () && isVariableChanged (loopVar, settings, cpp))
1054
+ return true ;
1055
+ continue ;
1056
+ }
988
1057
}
989
1058
return false ;
990
1059
}
@@ -1072,6 +1141,23 @@ const Token *findLambdaEndToken(const Token *first)
1072
1141
return nullptr ;
1073
1142
}
1074
1143
1144
+ bool isLikelyStream (bool cpp, const Token *stream)
1145
+ {
1146
+ if (!cpp)
1147
+ return false ;
1148
+
1149
+ if (!stream)
1150
+ return false ;
1151
+
1152
+ if (!Token::Match (stream->astParent (), " &|<<|>>" ) || !stream->astParent ()->isBinaryOp ())
1153
+ return false ;
1154
+
1155
+ if (stream->astParent ()->astOperand1 () != stream)
1156
+ return false ;
1157
+
1158
+ return !astIsIntegral (stream, false );
1159
+ }
1160
+
1075
1161
bool isLikelyStreamRead (bool cpp, const Token *op)
1076
1162
{
1077
1163
if (!cpp)
0 commit comments