1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2021 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <tinyxml2.h>
20 
21 #include "checkfunctions.h"
22 #include "library.h"
23 #include "settings.h"
24 #include "standards.h"
25 #include "testsuite.h"
26 #include "tokenize.h"
27 
28 
29 class TestFunctions : public TestFixture {
30 public:
TestFunctions()31     TestFunctions() : TestFixture("TestFunctions") {}
32 
33 private:
34     Settings settings;
35 
run()36     void run() OVERRIDE {
37         settings.severity.enable(Severity::style);
38         settings.severity.enable(Severity::warning);
39         settings.severity.enable(Severity::performance);
40         settings.severity.enable(Severity::portability);
41         settings.certainty.enable(Certainty::inconclusive);
42         settings.libraries.emplace_back("posix");
43         settings.standards.c = Standards::C11;
44         settings.standards.cpp = Standards::CPP11;
45         LOAD_LIB_2(settings.library, "std.cfg");
46         LOAD_LIB_2(settings.library, "posix.cfg");
47 
48         // Prohibited functions
49         TEST_CASE(prohibitedFunctions_posix);
50         TEST_CASE(prohibitedFunctions_index);
51         TEST_CASE(prohibitedFunctions_qt_index); // FP when using the Qt function 'index'?
52         TEST_CASE(prohibitedFunctions_rindex);
53         TEST_CASE(prohibitedFunctions_var); // no false positives for variables
54         TEST_CASE(prohibitedFunctions_gets); // dangerous function
55         TEST_CASE(prohibitedFunctions_alloca);
56         TEST_CASE(prohibitedFunctions_declaredFunction); // declared function ticket #3121
57         TEST_CASE(prohibitedFunctions_std_gets); // test std::gets
58         TEST_CASE(prohibitedFunctions_multiple); // multiple use of obsolete functions
59         TEST_CASE(prohibitedFunctions_c_declaration); // c declared function
60         TEST_CASE(prohibitedFunctions_functionWithBody); // function with body
61         TEST_CASE(prohibitedFunctions_crypt); // Non-reentrant function
62         TEST_CASE(prohibitedFunctions_namespaceHandling);
63 
64         // Invalid function usage
65         TEST_CASE(invalidFunctionUsage1);
66         TEST_CASE(invalidFunctionUsageStrings);
67 
68         // Math function usage
69         TEST_CASE(mathfunctionCall_fmod);
70         TEST_CASE(mathfunctionCall_sqrt);
71         TEST_CASE(mathfunctionCall_log);
72         TEST_CASE(mathfunctionCall_acos);
73         TEST_CASE(mathfunctionCall_asin);
74         TEST_CASE(mathfunctionCall_pow);
75         TEST_CASE(mathfunctionCall_atan2);
76         TEST_CASE(mathfunctionCall_precision);
77 
78         // Ignored return value
79         TEST_CASE(checkIgnoredReturnValue);
80         TEST_CASE(checkIgnoredErrorCode);
81 
82         // memset..
83         TEST_CASE(memsetZeroBytes);
84         TEST_CASE(memsetInvalid2ndParam);
85 
86         // missing "return"
87         TEST_CASE(checkMissingReturn);
88 
89         // std::move for locar variable
90         TEST_CASE(returnLocalStdMove1);
91         TEST_CASE(returnLocalStdMove2);
92         TEST_CASE(returnLocalStdMove3);
93         TEST_CASE(returnLocalStdMove4);
94 
95         TEST_CASE(returnLocalStdMove5);
96     }
97 
check(const char code[],const char filename[]="test.cpp",const Settings * settings_=nullptr)98     void check(const char code[], const char filename[]="test.cpp", const Settings* settings_=nullptr) {
99         // Clear the error buffer..
100         errout.str("");
101 
102         if (!settings_)
103             settings_ = &settings;
104 
105         // Tokenize..
106         Tokenizer tokenizer(settings_, this);
107         std::istringstream istr(code);
108         tokenizer.tokenize(istr, filename);
109 
110         CheckFunctions checkFunctions(&tokenizer, settings_, this);
111         checkFunctions.runChecks(&tokenizer, settings_, this);
112     }
113 
prohibitedFunctions_posix()114     void prohibitedFunctions_posix() {
115         check("void f()\n"
116               "{\n"
117               "    bsd_signal(SIGABRT, SIG_IGN);\n"
118               "}");
119         ASSERT_EQUALS("[test.cpp:3]: (style) Obsolescent function 'bsd_signal' called. It is recommended to use 'sigaction' instead.\n", errout.str());
120 
121         check("int f()\n"
122               "{\n"
123               "    int bsd_signal(0);\n"
124               "    return bsd_signal;\n"
125               "}");
126         ASSERT_EQUALS("", errout.str());
127 
128         check("void f()\n"
129               "{\n"
130               "    struct hostent *hp;\n"
131               "    if(!hp = gethostbyname(\"127.0.0.1\")) {\n"
132               "        exit(1);\n"
133               "    }\n"
134               "}");
135         ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'gethostbyname' called. It is recommended to use 'getaddrinfo' instead.\n", errout.str());
136 
137         check("void f()\n"
138               "{\n"
139               "    long addr;\n"
140               "    addr = inet_addr(\"127.0.0.1\");\n"
141               "    if(!hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET)) {\n"
142               "        exit(1);\n"
143               "    }\n"
144               "}");
145         ASSERT_EQUALS("[test.cpp:5]: (style) Obsolescent function 'gethostbyaddr' called. It is recommended to use 'getnameinfo' instead.\n", errout.str());
146 
147         check("void f()\n"
148               "{\n"
149               "    usleep( 1000 );\n"
150               "}");
151         ASSERT_EQUALS("[test.cpp:3]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.\n", errout.str());
152     }
153 
prohibitedFunctions_index()154     void prohibitedFunctions_index() {
155         check("namespace n1 {\n"
156               "    int index(){ return 1; };\n"
157               "}\n"
158               "int main()\n"
159               "{\n"
160               "    n1::index();\n"
161               "    return 0;\n"
162               "}");
163         ASSERT_EQUALS("", errout.str());
164 
165         check("std::size_t f()\n"
166               "{\n"
167               "    std::size_t index(0);\n"
168               "    index++;\n"
169               "    return index;\n"
170               "}");
171         ASSERT_EQUALS("", errout.str());
172 
173         check("int f()\n"
174               "{\n"
175               "    return this->index();\n"
176               "}");
177         ASSERT_EQUALS("", errout.str());
178 
179         check("void f()\n"
180               "{\n"
181               "    int index( 0 );\n"
182               "}");
183         ASSERT_EQUALS("", errout.str());
184 
185         check("const char f()\n"
186               "{\n"
187               "    const char var[6] = \"index\";\n"
188               "    const char i = index(var, 0);\n"
189               "    return i;\n"
190               "}");
191         ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead.\n",
192                       errout.str());
193     }
194 
prohibitedFunctions_qt_index()195     void prohibitedFunctions_qt_index() {
196         check("void TDataModel::forceRowRefresh(int row) {\n"
197               "    emit dataChanged(index(row, 0), index(row, columnCount() - 1));\n"
198               "}");
199         ASSERT_EQUALS("[test.cpp:2]: (style) Obsolescent function 'index' called. It is recommended to use 'strchr' instead.\n", errout.str());
200     }
201 
prohibitedFunctions_rindex()202     void prohibitedFunctions_rindex() {
203         check("void f()\n"
204               "{\n"
205               "    int rindex( 0 );\n"
206               "}");
207         ASSERT_EQUALS("", errout.str());
208 
209         check("void f()\n"
210               "{\n"
211               "    const char var[7] = \"rindex\";\n"
212               "    print(rindex(var, 0));\n"
213               "}");
214         ASSERT_EQUALS("[test.cpp:4]: (style) Obsolescent function 'rindex' called. It is recommended to use 'strrchr' instead.\n", errout.str());
215     }
216 
217 
prohibitedFunctions_var()218     void prohibitedFunctions_var() {
219         check("class Fred {\n"
220               "public:\n"
221               "    Fred() : index(0) { }\n"
222               "    int index;\n"
223               "};");
224         ASSERT_EQUALS("", errout.str());
225     }
226 
prohibitedFunctions_gets()227     void prohibitedFunctions_gets() {
228         check("void f()\n"
229               "{\n"
230               "    char *x = gets(a);\n"
231               "}");
232         ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str());
233 
234         check("void f()\n"
235               "{\n"
236               "    foo(x, gets(a));\n"
237               "}");
238         ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str());
239     }
240 
prohibitedFunctions_alloca()241     void prohibitedFunctions_alloca() {
242         check("void f()\n"
243               "{\n"
244               "    char *x = alloca(10);\n"
245               "}", "test.cpp");  // #4382 - there are no VLAs in C++
246         ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'alloca' called.\n", errout.str());
247 
248         check("void f()\n"
249               "{\n"
250               "    char *x = alloca(10);\n"
251               "}", "test.c");
252         ASSERT_EQUALS("[test.c:3]: (warning) Obsolete function 'alloca' called. In C99 and later it is recommended to use a variable length array instead.\n", errout.str());
253 
254         settings.standards.c = Standards::C89;
255         settings.standards.cpp = Standards::CPP03;
256         check("void f()\n"
257               "{\n"
258               "    char *x = alloca(10);\n"
259               "}", "test.cpp");  // #4382 - there are no VLAs in C++
260         ASSERT_EQUALS("", errout.str());
261 
262         check("void f()\n"
263               "{\n"
264               "    char *x = alloca(10);\n"
265               "}", "test.c"); // #7558 - no alternative to alloca in C89
266         ASSERT_EQUALS("", errout.str());
267 
268         check("void f()\n"
269               "{\n"
270               "    char *x = alloca(10);\n"
271               "}", "test.c");
272         ASSERT_EQUALS("", errout.str());
273         settings.standards.c = Standards::C11;
274         settings.standards.cpp = Standards::CPP11;
275     }
276 
277     // ticket #3121
prohibitedFunctions_declaredFunction()278     void prohibitedFunctions_declaredFunction() {
279         check("int ftime ( int a )\n"
280               "{\n"
281               "    return a;\n"
282               "}\n"
283               "int main ()\n"
284               "{\n"
285               "    int b ; b = ftime ( 1 ) ;\n"
286               "    return 0 ;\n"
287               "}");
288         ASSERT_EQUALS("", errout.str());
289     }
290 
291     // test std::gets
prohibitedFunctions_std_gets()292     void prohibitedFunctions_std_gets() {
293         check("void f(char * str)\n"
294               "{\n"
295               "    char *x = std::gets(str);\n"
296               "    char *y = gets(str);\n"
297               "}");
298         ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n"
299                       "[test.cpp:4]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str());
300     }
301 
302     // multiple use
prohibitedFunctions_multiple()303     void prohibitedFunctions_multiple() {
304         check("void f(char * str)\n"
305               "{\n"
306               "    char *x = std::gets(str);\n"
307               "    usleep( 1000 );\n"
308               "}");
309         ASSERT_EQUALS("[test.cpp:3]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n"
310                       "[test.cpp:4]: (style) Obsolescent function 'usleep' called. It is recommended to use 'nanosleep' or 'setitimer' instead.\n", errout.str());
311     }
312 
prohibitedFunctions_c_declaration()313     void prohibitedFunctions_c_declaration() {
314         check("char * gets ( char * c ) ;\n"
315               "int main ()\n"
316               "{\n"
317               "    char s [ 10 ] ;\n"
318               "    gets ( s ) ;\n"
319               "    return 0;\n"
320               "}");
321         ASSERT_EQUALS("[test.cpp:5]: (warning) Obsolete function 'gets' called. It is recommended to use 'fgets' or 'gets_s' instead.\n", errout.str());
322 
323         check("int getcontext(ucontext_t *ucp);\n"
324               "void f (ucontext_t *ucp)\n"
325               "{\n"
326               "    getcontext ( ucp ) ;\n"
327               "}");
328         ASSERT_EQUALS("[test.cpp:4]: (portability) Obsolescent function 'getcontext' called. Applications are recommended to be rewritten to use POSIX threads.\n", errout.str());
329     }
330 
prohibitedFunctions_functionWithBody()331     void prohibitedFunctions_functionWithBody() {
332         check("char * gets ( char * c ) { return c; }\n"
333               "int main ()\n"
334               "{\n"
335               "    char s [ 10 ] ;\n"
336               "    gets ( s ) ;\n"
337               "    return 0;\n"
338               "}");
339         ASSERT_EQUALS("", errout.str());
340     }
341 
prohibitedFunctions_crypt()342     void prohibitedFunctions_crypt() {
343         check("void f(char *pwd)\n"
344               "{\n"
345               "    char *cpwd;"
346               "    crypt(pwd, cpwd);\n"
347               "}");
348         ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function crypt() is not used.\n"
349                       "[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str());
350 
351         check("void f()\n"
352               "{\n"
353               "    char *pwd = getpass(\"Password:\");"
354               "    char *cpwd;"
355               "    crypt(pwd, cpwd);\n"
356               "}");
357         ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function crypt() is not used.\n"
358                       "[test.cpp:3]: (portability) Non reentrant function 'crypt' called. For threadsafe applications it is recommended to use the reentrant replacement function 'crypt_r'.\n", errout.str());
359 
360         check("int f()\n"
361               "{\n"
362               "    int crypt = 0;"
363               "    return crypt;\n"
364               "}");
365         ASSERT_EQUALS("", errout.str());
366     }
367 
prohibitedFunctions_namespaceHandling()368     void prohibitedFunctions_namespaceHandling() {
369         check("void f()\n"
370               "{\n"
371               "    time_t t = 0;"
372               "    std::localtime(&t);\n"
373               "}");
374         ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str());
375 
376         // Passed as function argument
377         check("void f()\n"
378               "{\n"
379               "    printf(\"Magic guess: %d\", getpwent());\n"
380               "}");
381         ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str());
382 
383         // Pass return value
384         check("void f()\n"
385               "{\n"
386               "    time_t t = 0;"
387               "    struct tm *foo = localtime(&t);\n"
388               "}");
389         ASSERT_EQUALS("[test.cpp:3]: (portability) Non reentrant function 'localtime' called. For threadsafe applications it is recommended to use the reentrant replacement function 'localtime_r'.\n", errout.str());
390 
391         // Access via global namespace
392         check("void f()\n"
393               "{\n"
394               "    ::getpwent();\n"
395               "}");
396         ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function getpwent() is not used.\n"
397                       "[test.cpp:3]: (portability) Non reentrant function 'getpwent' called. For threadsafe applications it is recommended to use the reentrant replacement function 'getpwent_r'.\n", errout.str());
398 
399         // Be quiet on function definitions
400         check("int getpwent()\n"
401               "{\n"
402               "    return 123;\n"
403               "}");
404         ASSERT_EQUALS("", errout.str());
405 
406         // Be quiet on other namespaces
407         check("void f()\n"
408               "{\n"
409               "    foobar::getpwent();\n"
410               "}");
411         ASSERT_EQUALS("", errout.str());
412 
413         // Be quiet on class member functions
414         check("void f()\n"
415               "{\n"
416               "    foobar.getpwent();\n"
417               "}");
418         ASSERT_EQUALS("", errout.str());
419     }
420 
invalidFunctionUsage1()421     void invalidFunctionUsage1() {
422         check("void f() { memset(a,b,sizeof(a)!=12); }");
423         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
424 
425         check("void f() { memset(a,b,sizeof(a)!=0); }");
426         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
427 
428         check("void f() { memset(a,b,!c); }");
429         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
430 
431         // Ticket #6990
432         check("void f(bool c) { memset(a,b,c); }");
433         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
434         check("void f() { memset(a,b,true); }");
435         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
436 
437         // Ticket #6588 (c mode)
438         check("void record(char* buf, int n) {\n"
439               "  memset(buf, 0, n < 255);\n"           /* KO */
440               "  memset(buf, 0, n < 255 ? n : 255);\n" /* OK */
441               "}", "test.c");
442         ASSERT_EQUALS("[test.c:2]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
443 
444         // Ticket #6588 (c++ mode)
445         check("void record(char* buf, int n) {\n"
446               "  memset(buf, 0, n < 255);\n"           /* KO */
447               "  memset(buf, 0, n < 255 ? n : 255);\n" /* OK */
448               "}");
449         ASSERT_EQUALS("[test.cpp:2]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
450 
451         check("int boolArgZeroIsInvalidButOneIsValid(int a, int param) {\n"
452               "  return div(a, param > 0);\n"
453               "}");
454         ASSERT_EQUALS("[test.cpp:2]: (error) Invalid div() argument nr 2. The value is 0 or 1 (boolean) but the valid values are ':-1,1:'.\n", errout.str());
455 
456         check("void boolArgZeroIsValidButOneIsInvalid(int param) {\n"
457               "  strtol(a, b, param > 0);\n"
458               "}");
459         ASSERT_EQUALS("[test.cpp:2]: (error) Invalid strtol() argument nr 3. The value is 0 or 1 (boolean) but the valid values are '0,2:36'.\n", errout.str());
460 
461         check("void f() { strtol(a,b,1); }");
462         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strtol() argument nr 3. The value is 1 but the valid values are '0,2:36'.\n", errout.str());
463 
464         check("void f() { strtol(a,b,10); }");
465         ASSERT_EQUALS("", errout.str());
466     }
467 
invalidFunctionUsageStrings()468     void invalidFunctionUsageStrings() {
469         check("size_t f() { char x = 'x'; return strlen(&x); }");
470         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str());
471 
472         check("size_t f() { return strlen(&x); }");
473         ASSERT_EQUALS("", errout.str());
474 
475         check("size_t f(char x) { return strlen(&x); }");
476         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str());
477 
478         check("size_t f() { char x = '\\0'; return strlen(&x); }");
479         ASSERT_EQUALS("", errout.str());
480 
481         check("size_t f() {\n"
482               "  char x;\n"
483               "  if (y)\n"
484               "    x = '\\0';\n"
485               "  else\n"
486               "    x = 'a';\n"
487               "  return strlen(&x);\n"
488               "}");
489         ASSERT_EQUALS("[test.cpp:7]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str());
490 
491         check("int f() { char x = '\\0'; return strcmp(\"Hello world\", &x); }");
492         ASSERT_EQUALS("", errout.str());
493 
494         check("int f() { char x = 'x'; return strcmp(\"Hello world\", &x); }");
495         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strcmp() argument nr 2. A nul-terminated string is required.\n", errout.str());
496 
497         check("size_t f(char x) { char * y = &x; return strlen(y); }");
498         TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str());
499 
500         check("size_t f(char x) { char * y = &x; char *z = y; return strlen(z); }");
501         TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str());
502 
503         check("size_t f() { char x = 'x'; char * y = &x; char *z = y; return strlen(z); }");
504         TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str());
505 
506         check("size_t f() { char x = '\\0'; char * y = &x; char *z = y; return strlen(z); }");
507         ASSERT_EQUALS("", errout.str());
508 
509         check("size_t f() { char x[] = \"Hello world\"; return strlen(x); }");
510         ASSERT_EQUALS("", errout.str());
511 
512         check("size_t f(char x[]) { return strlen(x); }");
513         ASSERT_EQUALS("", errout.str());
514 
515         check("int f(char x, char y) { return strcmp(&x, &y); }");
516         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strcmp() argument nr 1. A nul-terminated string is required.\n"
517                       "[test.cpp:1]: (error) Invalid strcmp() argument nr 2. A nul-terminated string is required.\n", errout.str());
518 
519         check("size_t f() { char x[] = \"Hello world\"; return strlen(&x[0]); }");
520         ASSERT_EQUALS("", errout.str());
521 
522         check("size_t f() { char* x = \"Hello world\"; return strlen(&x[0]); }");
523         ASSERT_EQUALS("", errout.str());
524 
525         check("struct S {\n"
526               "  char x;\n"
527               "};\n"
528               "size_t f() {\n"
529               "  S s1 = {0};\n"
530               "  S s2;\n;"
531               "  s2.x = 'x';\n"
532               "  size_t l1 = strlen(&s1.x);\n"
533               "  size_t l2 = strlen(&s2.x);\n"
534               "  return l1 + l2;\n"
535               "}");
536         TODO_ASSERT_EQUALS("[test.cpp:9]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str());
537 
538         check("const char x = 'x'; size_t f() { return strlen(&x); }");
539         TODO_ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", "", errout.str());
540 
541         check("const char x = 'x'; size_t f() { char y = x; return strlen(&y); }");
542         ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strlen() argument nr 1. A nul-terminated string is required.\n", errout.str());
543 
544         check("const char x = '\\0'; size_t f() { return strlen(&x); }");
545         ASSERT_EQUALS("", errout.str());
546 
547         check("const char x = '\\0'; size_t f() { char y = x; return strlen(&y); }");
548         ASSERT_EQUALS("", errout.str());
549 
550         check("size_t f() {\n"
551               "  char * a = \"Hello world\";\n"
552               "  char ** b = &a;\n"
553               "  return strlen(&b[0][0]);\n"
554               "}");
555         ASSERT_EQUALS("", errout.str());
556 
557         check("size_t f() {\n"
558               "  char ca[] = \"asdf\";\n"
559               "  return strlen((char*) &ca);\n"
560               "}");
561         ASSERT_EQUALS("", errout.str());
562 
563         // #5225
564         check("int main(void)\n"
565               "{\n"
566               "  char str[80] = \"hello worl\";\n"
567               "  char d = 'd';\n"
568               "  strcat(str, &d);\n"
569               "  puts(str);\n"
570               "  return 0;\n"
571               "}");
572         ASSERT_EQUALS("[test.cpp:5]: (error) Invalid strcat() argument nr 2. A nul-terminated string is required.\n", errout.str());
573     }
574 
mathfunctionCall_sqrt()575     void mathfunctionCall_sqrt() {
576         // sqrt, sqrtf, sqrtl
577         check("void foo()\n"
578               "{\n"
579               "    std::cout <<  sqrt(-1) << std::endl;\n"
580               "    std::cout <<  sqrtf(-1) << std::endl;\n"
581               "    std::cout <<  sqrtl(-1) << std::endl;\n"
582               "}");
583         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid sqrt() argument nr 1. The value is -1 but the valid values are '0.0:'.\n"
584                       "[test.cpp:4]: (error) Invalid sqrtf() argument nr 1. The value is -1 but the valid values are '0.0:'.\n"
585                       "[test.cpp:5]: (error) Invalid sqrtl() argument nr 1. The value is -1 but the valid values are '0.0:'.\n", errout.str());
586 
587         // implementation-defined behaviour for "finite values of x<0" only:
588         check("void foo()\n"
589               "{\n"
590               "    std::cout <<  sqrt(-0.) << std::endl;\n"
591               "    std::cout <<  sqrtf(-0.) << std::endl;\n"
592               "    std::cout <<  sqrtl(-0.) << std::endl;\n"
593               "}");
594         ASSERT_EQUALS("", errout.str());
595 
596         check("void foo()\n"
597               "{\n"
598               "    std::cout <<  sqrt(1) << std::endl;\n"
599               "    std::cout <<  sqrtf(1) << std::endl;\n"
600               "    std::cout <<  sqrtl(1) << std::endl;\n"
601               "}");
602         ASSERT_EQUALS("", errout.str());
603     }
604 
mathfunctionCall_log()605     void mathfunctionCall_log() {
606         // log,log10,logf,logl,log10f,log10l,log2,log2f,log2l,log1p,log1pf,log1pl
607         check("void foo()\n"
608               "{\n"
609               "    std::cout <<  log(-2) << std::endl;\n"
610               "    std::cout <<  logf(-2) << std::endl;\n"
611               "    std::cout <<  logl(-2) << std::endl;\n"
612               "    std::cout <<  log10(-2) << std::endl;\n"
613               "    std::cout <<  log10f(-2) << std::endl;\n"
614               "    std::cout <<  log10l(-2) << std::endl;\n"
615               "    std::cout <<  log2(-2) << std::endl;\n"
616               "    std::cout <<  log2f(-2) << std::endl;\n"
617               "    std::cout <<  log2l(-2) << std::endl;\n"
618               "    std::cout <<  log1p(-3) << std::endl;\n"
619               "    std::cout <<  log1pf(-3) << std::endl;\n"
620               "    std::cout <<  log1pl(-3) << std::endl;\n"
621               "}");
622         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n"
623                       "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -2 but the valid values are '1.4013e-45:'.\n"
624                       "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n"
625                       "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n"
626                       "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -2 but the valid values are '1.4013e-45:'.\n"
627                       "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n"
628                       "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n"
629                       "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -2 but the valid values are '1.4013e-45:'.\n"
630                       "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -2 but the valid values are '4.94066e-324:'.\n"
631                       "[test.cpp:3]: (warning) Passing value -2 to log() leads to implementation-defined result.\n"
632                       "[test.cpp:4]: (warning) Passing value -2 to logf() leads to implementation-defined result.\n"
633                       "[test.cpp:5]: (warning) Passing value -2 to logl() leads to implementation-defined result.\n"
634                       "[test.cpp:6]: (warning) Passing value -2 to log10() leads to implementation-defined result.\n"
635                       "[test.cpp:7]: (warning) Passing value -2 to log10f() leads to implementation-defined result.\n"
636                       "[test.cpp:8]: (warning) Passing value -2 to log10l() leads to implementation-defined result.\n"
637                       "[test.cpp:9]: (warning) Passing value -2 to log2() leads to implementation-defined result.\n"
638                       "[test.cpp:10]: (warning) Passing value -2 to log2f() leads to implementation-defined result.\n"
639                       "[test.cpp:11]: (warning) Passing value -2 to log2l() leads to implementation-defined result.\n"
640                       "[test.cpp:12]: (warning) Passing value -3 to log1p() leads to implementation-defined result.\n"
641                       "[test.cpp:13]: (warning) Passing value -3 to log1pf() leads to implementation-defined result.\n"
642                       "[test.cpp:14]: (warning) Passing value -3 to log1pl() leads to implementation-defined result.\n", errout.str());
643 
644         check("void foo()\n"
645               "{\n"
646               "    std::cout <<  log(-1) << std::endl;\n"
647               "    std::cout <<  logf(-1) << std::endl;\n"
648               "    std::cout <<  logl(-1) << std::endl;\n"
649               "    std::cout <<  log10(-1) << std::endl;\n"
650               "    std::cout <<  log10f(-1) << std::endl;\n"
651               "    std::cout <<  log10l(-1) << std::endl;\n"
652               "    std::cout <<  log2(-1) << std::endl;\n"
653               "    std::cout <<  log2f(-1) << std::endl;\n"
654               "    std::cout <<  log2l(-1) << std::endl;\n"
655               "    std::cout <<  log1p(-2) << std::endl;\n"
656               "    std::cout <<  log1pf(-2) << std::endl;\n"
657               "    std::cout <<  log1pl(-2) << std::endl;\n"
658               "}");
659         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
660                       "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n"
661                       "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
662                       "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
663                       "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n"
664                       "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
665                       "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
666                       "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n"
667                       "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
668                       "[test.cpp:3]: (warning) Passing value -1 to log() leads to implementation-defined result.\n"
669                       "[test.cpp:4]: (warning) Passing value -1 to logf() leads to implementation-defined result.\n"
670                       "[test.cpp:5]: (warning) Passing value -1 to logl() leads to implementation-defined result.\n"
671                       "[test.cpp:6]: (warning) Passing value -1 to log10() leads to implementation-defined result.\n"
672                       "[test.cpp:7]: (warning) Passing value -1 to log10f() leads to implementation-defined result.\n"
673                       "[test.cpp:8]: (warning) Passing value -1 to log10l() leads to implementation-defined result.\n"
674                       "[test.cpp:9]: (warning) Passing value -1 to log2() leads to implementation-defined result.\n"
675                       "[test.cpp:10]: (warning) Passing value -1 to log2f() leads to implementation-defined result.\n"
676                       "[test.cpp:11]: (warning) Passing value -1 to log2l() leads to implementation-defined result.\n"
677                       "[test.cpp:12]: (warning) Passing value -2 to log1p() leads to implementation-defined result.\n"
678                       "[test.cpp:13]: (warning) Passing value -2 to log1pf() leads to implementation-defined result.\n"
679                       "[test.cpp:14]: (warning) Passing value -2 to log1pl() leads to implementation-defined result.\n", errout.str());
680 
681         check("void foo()\n"
682               "{\n"
683               "    std::cout <<  log(-1.0) << std::endl;\n"
684               "    std::cout <<  logf(-1.0) << std::endl;\n"
685               "    std::cout <<  logl(-1.0) << std::endl;\n"
686               "    std::cout <<  log10(-1.0) << std::endl;\n"
687               "    std::cout <<  log10f(-1.0) << std::endl;\n"
688               "    std::cout <<  log10l(-1.0) << std::endl;\n"
689               "    std::cout <<  log2(-1.0) << std::endl;\n"
690               "    std::cout <<  log2f(-1.0) << std::endl;\n"
691               "    std::cout <<  log2l(-1.0) << std::endl;\n"
692               "    std::cout <<  log1p(-2.0) << std::endl;\n"
693               "    std::cout <<  log1pf(-2.0) << std::endl;\n"
694               "    std::cout <<  log1pl(-2.0) << std::endl;\n"
695               "}");
696         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
697                       "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n"
698                       "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
699                       "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
700                       "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n"
701                       "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
702                       "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
703                       "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -1 but the valid values are '1.4013e-45:'.\n"
704                       "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -1 but the valid values are '4.94066e-324:'.\n"
705                       "[test.cpp:3]: (warning) Passing value -1.0 to log() leads to implementation-defined result.\n"
706                       "[test.cpp:4]: (warning) Passing value -1.0 to logf() leads to implementation-defined result.\n"
707                       "[test.cpp:5]: (warning) Passing value -1.0 to logl() leads to implementation-defined result.\n"
708                       "[test.cpp:6]: (warning) Passing value -1.0 to log10() leads to implementation-defined result.\n"
709                       "[test.cpp:7]: (warning) Passing value -1.0 to log10f() leads to implementation-defined result.\n"
710                       "[test.cpp:8]: (warning) Passing value -1.0 to log10l() leads to implementation-defined result.\n"
711                       "[test.cpp:9]: (warning) Passing value -1.0 to log2() leads to implementation-defined result.\n"
712                       "[test.cpp:10]: (warning) Passing value -1.0 to log2f() leads to implementation-defined result.\n"
713                       "[test.cpp:11]: (warning) Passing value -1.0 to log2l() leads to implementation-defined result.\n"
714                       "[test.cpp:12]: (warning) Passing value -2.0 to log1p() leads to implementation-defined result.\n"
715                       "[test.cpp:13]: (warning) Passing value -2.0 to log1pf() leads to implementation-defined result.\n"
716                       "[test.cpp:14]: (warning) Passing value -2.0 to log1pl() leads to implementation-defined result.\n", errout.str());
717 
718         check("void foo()\n"
719               "{\n"
720               "    std::cout <<  log(-0.1) << std::endl;\n"
721               "    std::cout <<  logf(-0.1) << std::endl;\n"
722               "    std::cout <<  logl(-0.1) << std::endl;\n"
723               "    std::cout <<  log10(-0.1) << std::endl;\n"
724               "    std::cout <<  log10f(-0.1) << std::endl;\n"
725               "    std::cout <<  log10l(-0.1) << std::endl;\n"
726               "    std::cout <<  log2(-0.1) << std::endl;\n"
727               "    std::cout <<  log2f(-0.1) << std::endl;\n"
728               "    std::cout <<  log2l(-0.1) << std::endl;\n"
729               "    std::cout <<  log1p(-1.1) << std::endl;\n"
730               "    std::cout <<  log1pf(-1.1) << std::endl;\n"
731               "    std::cout <<  log1pl(-1.1) << std::endl;\n"
732               "}");
733         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n"
734                       "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is -0.1 but the valid values are '1.4013e-45:'.\n"
735                       "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n"
736                       "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n"
737                       "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is -0.1 but the valid values are '1.4013e-45:'.\n"
738                       "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n"
739                       "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n"
740                       "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is -0.1 but the valid values are '1.4013e-45:'.\n"
741                       "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is -0.1 but the valid values are '4.94066e-324:'.\n"
742                       "[test.cpp:3]: (warning) Passing value -0.1 to log() leads to implementation-defined result.\n"
743                       "[test.cpp:4]: (warning) Passing value -0.1 to logf() leads to implementation-defined result.\n"
744                       "[test.cpp:5]: (warning) Passing value -0.1 to logl() leads to implementation-defined result.\n"
745                       "[test.cpp:6]: (warning) Passing value -0.1 to log10() leads to implementation-defined result.\n"
746                       "[test.cpp:7]: (warning) Passing value -0.1 to log10f() leads to implementation-defined result.\n"
747                       "[test.cpp:8]: (warning) Passing value -0.1 to log10l() leads to implementation-defined result.\n"
748                       "[test.cpp:9]: (warning) Passing value -0.1 to log2() leads to implementation-defined result.\n"
749                       "[test.cpp:10]: (warning) Passing value -0.1 to log2f() leads to implementation-defined result.\n"
750                       "[test.cpp:11]: (warning) Passing value -0.1 to log2l() leads to implementation-defined result.\n"
751                       "[test.cpp:12]: (warning) Passing value -1.1 to log1p() leads to implementation-defined result.\n"
752                       "[test.cpp:13]: (warning) Passing value -1.1 to log1pf() leads to implementation-defined result.\n"
753                       "[test.cpp:14]: (warning) Passing value -1.1 to log1pl() leads to implementation-defined result.\n", errout.str());
754 
755         check("void foo()\n"
756               "{\n"
757               "    std::cout <<  log(0) << std::endl;\n"
758               "    std::cout <<  logf(0.) << std::endl;\n"
759               "    std::cout <<  logl(0.0) << std::endl;\n"
760               "    std::cout <<  log10(0.0) << std::endl;\n"
761               "    std::cout <<  log10f(0) << std::endl;\n"
762               "    std::cout <<  log10l(0.) << std::endl;\n"
763               "    std::cout <<  log2(0.) << std::endl;\n"
764               "    std::cout <<  log2f(0.0) << std::endl;\n"
765               "    std::cout <<  log2l(0) << std::endl;\n"
766               "    std::cout <<  log1p(-1.) << std::endl;\n"
767               "    std::cout <<  log1pf(-1.0) << std::endl;\n"
768               "    std::cout <<  log1pl(-1) << std::endl;\n"
769               "}");
770         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid log() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n"
771                       "[test.cpp:4]: (error) Invalid logf() argument nr 1. The value is 0 but the valid values are '1.4013e-45:'.\n"
772                       "[test.cpp:5]: (error) Invalid logl() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n"
773                       "[test.cpp:6]: (error) Invalid log10() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n"
774                       "[test.cpp:7]: (error) Invalid log10f() argument nr 1. The value is 0 but the valid values are '1.4013e-45:'.\n"
775                       "[test.cpp:8]: (error) Invalid log10l() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n"
776                       "[test.cpp:9]: (error) Invalid log2() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n"
777                       "[test.cpp:10]: (error) Invalid log2f() argument nr 1. The value is 0 but the valid values are '1.4013e-45:'.\n"
778                       "[test.cpp:11]: (error) Invalid log2l() argument nr 1. The value is 0 but the valid values are '4.94066e-324:'.\n"
779                       "[test.cpp:3]: (warning) Passing value 0 to log() leads to implementation-defined result.\n"
780                       "[test.cpp:4]: (warning) Passing value 0. to logf() leads to implementation-defined result.\n"
781                       "[test.cpp:5]: (warning) Passing value 0.0 to logl() leads to implementation-defined result.\n"
782                       "[test.cpp:6]: (warning) Passing value 0.0 to log10() leads to implementation-defined result.\n"
783                       "[test.cpp:7]: (warning) Passing value 0 to log10f() leads to implementation-defined result.\n"
784                       "[test.cpp:8]: (warning) Passing value 0. to log10l() leads to implementation-defined result.\n"
785                       "[test.cpp:9]: (warning) Passing value 0. to log2() leads to implementation-defined result.\n"
786                       "[test.cpp:10]: (warning) Passing value 0.0 to log2f() leads to implementation-defined result.\n"
787                       "[test.cpp:11]: (warning) Passing value 0 to log2l() leads to implementation-defined result.\n"
788                       "[test.cpp:12]: (warning) Passing value -1. to log1p() leads to implementation-defined result.\n"
789                       "[test.cpp:13]: (warning) Passing value -1.0 to log1pf() leads to implementation-defined result.\n"
790                       "[test.cpp:14]: (warning) Passing value -1 to log1pl() leads to implementation-defined result.\n", errout.str());
791 
792         check("void foo()\n"
793               "{\n"
794               "    std::cout <<  log(1E-3)         << std::endl;\n"
795               "    std::cout <<  logf(1E-3)        << std::endl;\n"
796               "    std::cout <<  logl(1E-3)        << std::endl;\n"
797               "    std::cout <<  log10(1E-3)       << std::endl;\n"
798               "    std::cout <<  log10f(1E-3)      << std::endl;\n"
799               "    std::cout <<  log10l(1E-3)      << std::endl;\n"
800               "    std::cout <<  log2(1E-3)        << std::endl;\n"
801               "    std::cout <<  log2f(1E-3)       << std::endl;\n"
802               "    std::cout <<  log2l(1E-3)       << std::endl;\n"
803               "    std::cout <<  log1p(-1+1E-3)    << std::endl;\n"
804               "    std::cout <<  log1pf(-1+1E-3)   << std::endl;\n"
805               "    std::cout <<  log1pl(-1+1E-3)   << std::endl;\n"
806               "    std::cout <<  log(1.0E-3)       << std::endl;\n"
807               "    std::cout <<  logf(1.0E-3)      << std::endl;\n"
808               "    std::cout <<  logl(1.0E-3)      << std::endl;\n"
809               "    std::cout <<  log10(1.0E-3)     << std::endl;\n"
810               "    std::cout <<  log10f(1.0E-3)    << std::endl;\n"
811               "    std::cout <<  log10l(1.0E-3)    << std::endl;\n"
812               "    std::cout <<  log2(1.0E-3)      << std::endl;\n"
813               "    std::cout <<  log2f(1.0E-3)     << std::endl;\n"
814               "    std::cout <<  log2l(1.0E-3)     << std::endl;\n"
815               "    std::cout <<  log1p(-1+1.0E-3)  << std::endl;\n"
816               "    std::cout <<  log1pf(-1+1.0E-3) << std::endl;\n"
817               "    std::cout <<  log1pl(-1+1.0E-3) << std::endl;\n"
818               "    std::cout <<  log(1.0E+3)       << std::endl;\n"
819               "    std::cout <<  logf(1.0E+3)      << std::endl;\n"
820               "    std::cout <<  logl(1.0E+3)      << std::endl;\n"
821               "    std::cout <<  log10(1.0E+3)     << std::endl;\n"
822               "    std::cout <<  log10f(1.0E+3)    << std::endl;\n"
823               "    std::cout <<  log10l(1.0E+3)    << std::endl;\n"
824               "    std::cout <<  log2(1.0E+3)      << std::endl;\n"
825               "    std::cout <<  log2f(1.0E+3)     << std::endl;\n"
826               "    std::cout <<  log2l(1.0E+3)     << std::endl;\n"
827               "    std::cout <<  log1p(1.0E+3)     << std::endl;\n"
828               "    std::cout <<  log1pf(1.0E+3)    << std::endl;\n"
829               "    std::cout <<  log1pl(1.0E+3)    << std::endl;\n"
830               "    std::cout <<  log(2.0)          << std::endl;\n"
831               "    std::cout <<  logf(2.0)         << std::endl;\n"
832               "    std::cout <<  logf(2.0f)        << std::endl;\n"
833               "    std::cout <<  log10(2.0)        << std::endl;\n"
834               "    std::cout <<  log10f(2.0)       << std::endl;\n"
835               "    std::cout <<  log10f(2.0f)      << std::endl;\n"
836               "    std::cout <<  log2(2.0)         << std::endl;\n"
837               "    std::cout <<  log2f(2.0)        << std::endl;\n"
838               "    std::cout <<  log2f(2.0f)       << std::endl;\n"
839               "    std::cout <<  log1p(2.0)        << std::endl;\n"
840               "    std::cout <<  log1pf(2.0)       << std::endl;\n"
841               "    std::cout <<  log1pf(2.0f)      << std::endl;\n"
842               "}");
843         ASSERT_EQUALS("", errout.str());
844 
845         check("void foo()\n"
846               "{\n"
847               "    std::string *log(0);\n"
848               "}");
849         ASSERT_EQUALS("", errout.str());
850 
851         // #3473 - no warning if "log" is a variable
852         check("Fred::Fred() : log(0) { }");
853         ASSERT_EQUALS("", errout.str());
854 
855         // #5748
856         check("void f() { foo.log(0); }");
857         ASSERT_EQUALS("", errout.str());
858     }
859 
mathfunctionCall_acos()860     void mathfunctionCall_acos() {
861         // acos, acosf, acosl
862         check("void foo()\n"
863               "{\n"
864               " return acos(-1)     \n"
865               "    + acos(0.1)      \n"
866               "    + acos(0.0001)   \n"
867               "    + acos(0.01)     \n"
868               "    + acos(1.0E-1)   \n"
869               "    + acos(-1.0E-1)  \n"
870               "    + acos(+1.0E-1)  \n"
871               "    + acos(0.1E-1)   \n"
872               "    + acos(+0.1E-1)  \n"
873               "    + acos(-0.1E-1)  \n"
874               "    + acosf(-1)      \n"
875               "    + acosf(0.1)     \n"
876               "    + acosf(0.0001)  \n"
877               "    + acosf(0.01)    \n"
878               "    + acosf(1.0E-1)  \n"
879               "    + acosf(-1.0E-1) \n"
880               "    + acosf(+1.0E-1) \n"
881               "    + acosf(0.1E-1)  \n"
882               "    + acosf(+0.1E-1) \n"
883               "    + acosf(-0.1E-1) \n"
884               "    + acosl(-1)      \n"
885               "    + acosl(0.1)     \n"
886               "    + acosl(0.0001)  \n"
887               "    + acosl(0.01)    \n"
888               "    + acosl(1.0E-1)  \n"
889               "    + acosl(-1.0E-1) \n"
890               "    + acosl(+1.0E-1) \n"
891               "    + acosl(0.1E-1)  \n"
892               "    + acosl(+0.1E-1) \n"
893               "    + acosl(-0.1E-1);\n"
894               "}");
895         ASSERT_EQUALS("", errout.str());
896 
897         check("void foo()\n"
898               "{\n"
899               "    std::cout <<  acos(1.1) << std::endl;\n"
900               "    std::cout <<  acosf(1.1) << std::endl;\n"
901               "    std::cout <<  acosl(1.1) << std::endl;\n"
902               "}");
903         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
904                       "[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
905                       "[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
906 
907         check("void foo()\n"
908               "{\n"
909               "    std::cout <<  acos(-1.1) << std::endl;\n"
910               "    std::cout <<  acosf(-1.1) << std::endl;\n"
911               "    std::cout <<  acosl(-1.1) << std::endl;\n"
912               "}");
913         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid acos() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
914                       "[test.cpp:4]: (error) Invalid acosf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
915                       "[test.cpp:5]: (error) Invalid acosl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
916     }
917 
mathfunctionCall_asin()918     void mathfunctionCall_asin() {
919         // asin, asinf, asinl
920         check("void foo()\n"
921               "{\n"
922               " return asin(1)      \n"
923               "    + asin(-1)       \n"
924               "    + asin(0.1)      \n"
925               "    + asin(0.0001)   \n"
926               "    + asin(0.01)     \n"
927               "    + asin(1.0E-1)   \n"
928               "    + asin(-1.0E-1)  \n"
929               "    + asin(+1.0E-1)  \n"
930               "    + asin(0.1E-1)   \n"
931               "    + asin(+0.1E-1)  \n"
932               "    + asin(-0.1E-1)  \n"
933               "    + asinf(1)       \n"
934               "    + asinf(-1)      \n"
935               "    + asinf(0.1)     \n"
936               "    + asinf(0.0001)  \n"
937               "    + asinf(0.01)    \n"
938               "    + asinf(1.0E-1)  \n"
939               "    + asinf(-1.0E-1) \n"
940               "    + asinf(+1.0E-1) \n"
941               "    + asinf(0.1E-1)  \n"
942               "    + asinf(+0.1E-1) \n"
943               "    + asinf(-0.1E-1) \n"
944               "    + asinl(1)       \n"
945               "    + asinl(-1)      \n"
946               "    + asinl(0.1)     \n"
947               "    + asinl(0.0001)  \n"
948               "    + asinl(0.01)    \n"
949               "    + asinl(1.0E-1)  \n"
950               "    + asinl(-1.0E-1) \n"
951               "    + asinl(+1.0E-1) \n"
952               "    + asinl(0.1E-1)  \n"
953               "    + asinl(+0.1E-1) \n"
954               "    + asinl(-0.1E-1);\n"
955               "}");
956         ASSERT_EQUALS("", errout.str());
957 
958         check("void foo()\n"
959               "{\n"
960               "    std::cout <<  asin(1.1) << std::endl;\n"
961               "    std::cout <<  asinf(1.1) << std::endl;\n"
962               "    std::cout <<  asinl(1.1) << std::endl;\n"
963               "}");
964         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
965                       "[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n"
966                       "[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is 1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
967 
968         check("void foo()\n"
969               "{\n"
970               "    std::cout <<  asin(-1.1) << std::endl;\n"
971               "    std::cout <<  asinf(-1.1) << std::endl;\n"
972               "    std::cout <<  asinl(-1.1) << std::endl;\n"
973               "}");
974         ASSERT_EQUALS("[test.cpp:3]: (error) Invalid asin() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
975                       "[test.cpp:4]: (error) Invalid asinf() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n"
976                       "[test.cpp:5]: (error) Invalid asinl() argument nr 1. The value is -1.1 but the valid values are '-1.0:1.0'.\n", errout.str());
977     }
978 
mathfunctionCall_pow()979     void mathfunctionCall_pow() {
980         // pow, powf, powl
981         check("void foo()\n"
982               "{\n"
983               "    std::cout <<  pow(0,-10) << std::endl;\n"
984               "    std::cout <<  powf(0,-10) << std::endl;\n"
985               "    std::cout <<  powl(0,-10) << std::endl;\n"
986               "}");
987         ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 0 and -10 to pow() leads to implementation-defined result.\n"
988                       "[test.cpp:4]: (warning) Passing values 0 and -10 to powf() leads to implementation-defined result.\n"
989                       "[test.cpp:5]: (warning) Passing values 0 and -10 to powl() leads to implementation-defined result.\n", errout.str());
990 
991         check("void foo()\n"
992               "{\n"
993               "    std::cout <<  pow(0,10) << std::endl;\n"
994               "    std::cout <<  powf(0,10) << std::endl;\n"
995               "    std::cout <<  powl(0,10) << std::endl;\n"
996               "}");
997         ASSERT_EQUALS("", errout.str());
998     }
999 
mathfunctionCall_atan2()1000     void mathfunctionCall_atan2() {
1001         // atan2
1002         check("void foo()\n"
1003               "{\n"
1004               "    std::cout <<  atan2(1,1)         ;\n"
1005               "    std::cout <<  atan2(-1,-1)       ;\n"
1006               "    std::cout <<  atan2(0.1,1)       ;\n"
1007               "    std::cout <<  atan2(0.0001,100)  ;\n"
1008               "    std::cout <<  atan2(0.0,1e-1)    ;\n"
1009               "    std::cout <<  atan2(1.0E-1,-3)   ;\n"
1010               "    std::cout <<  atan2(-1.0E-1,+2)  ;\n"
1011               "    std::cout <<  atan2(+1.0E-1,0)   ;\n"
1012               "    std::cout <<  atan2(0.1E-1,3)    ;\n"
1013               "    std::cout <<  atan2(+0.1E-1,1)   ;\n"
1014               "    std::cout <<  atan2(-0.1E-1,8)   ;\n"
1015               "    std::cout <<  atan2f(1,1)        ;\n"
1016               "    std::cout <<  atan2f(-1,-1)      ;\n"
1017               "    std::cout <<  atan2f(0.1,1)      ;\n"
1018               "    std::cout <<  atan2f(0.0001,100) ;\n"
1019               "    std::cout <<  atan2f(0.0,1e-1)   ;\n"
1020               "    std::cout <<  atan2f(1.0E-1,-3)  ;\n"
1021               "    std::cout <<  atan2f(-1.0E-1,+2) ;\n"
1022               "    std::cout <<  atan2f(+1.0E-1,0)  ;\n"
1023               "    std::cout <<  atan2f(0.1E-1,3)   ;\n"
1024               "    std::cout <<  atan2f(+0.1E-1,1)  ;\n"
1025               "    std::cout <<  atan2f(-0.1E-1,8)  ;\n"
1026               "    std::cout <<  atan2l(1,1)        ;\n"
1027               "    std::cout <<  atan2l(-1,-1)      ;\n"
1028               "    std::cout <<  atan2l(0.1,1)      ;\n"
1029               "    std::cout <<  atan2l(0.0001,100) ;\n"
1030               "    std::cout <<  atan2l(0.0,1e-1)   ;\n"
1031               "    std::cout <<  atan2l(1.0E-1,-3)  ;\n"
1032               "    std::cout <<  atan2l(-1.0E-1,+2) ;\n"
1033               "    std::cout <<  atan2l(+1.0E-1,0)  ;\n"
1034               "    std::cout <<  atan2l(0.1E-1,3)   ;\n"
1035               "    std::cout <<  atan2l(+0.1E-1,1)  ;\n"
1036               "    std::cout <<  atan2l(-0.1E-1,8)  ;\n"
1037               "}");
1038         ASSERT_EQUALS("", errout.str());
1039 
1040         check("void foo()\n"
1041               "{\n"
1042               "    std::cout <<  atan2(0,0) << std::endl;\n"
1043               "    std::cout <<  atan2f(0,0) << std::endl;\n"
1044               "    std::cout <<  atan2l(0,0) << std::endl;\n"
1045               "}");
1046         ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 0 and 0 to atan2() leads to implementation-defined result.\n"
1047                       "[test.cpp:4]: (warning) Passing values 0 and 0 to atan2f() leads to implementation-defined result.\n"
1048                       "[test.cpp:5]: (warning) Passing values 0 and 0 to atan2l() leads to implementation-defined result.\n", errout.str());
1049     }
1050 
mathfunctionCall_fmod()1051     void mathfunctionCall_fmod() {
1052         // fmod, fmodl, fmodf
1053         check("void foo()\n"
1054               "{\n"
1055               "    std::cout <<  fmod(1.0,0) << std::endl;\n"
1056               "    std::cout <<  fmodf(1.0,0) << std::endl;\n"
1057               "    std::cout <<  fmodl(1.0,0) << std::endl;\n"
1058               "}");
1059         ASSERT_EQUALS("[test.cpp:3]: (warning) Passing values 1.0 and 0 to fmod() leads to implementation-defined result.\n"
1060                       "[test.cpp:4]: (warning) Passing values 1.0 and 0 to fmodf() leads to implementation-defined result.\n"
1061                       "[test.cpp:5]: (warning) Passing values 1.0 and 0 to fmodl() leads to implementation-defined result.\n", errout.str());
1062 
1063         check("void foo()\n"
1064               "{\n"
1065               "    std::cout <<  fmod(1.0,1) << std::endl;\n"
1066               "    std::cout <<  fmodf(1.0,1) << std::endl;\n"
1067               "    std::cout <<  fmodl(1.0,1) << std::endl;\n"
1068               "}");
1069         ASSERT_EQUALS("", errout.str());
1070     }
1071 
mathfunctionCall_precision()1072     void mathfunctionCall_precision() {
1073         check("void foo() {\n"
1074               "    print(exp(x) - 1);\n"
1075               "    print(log(1 + x));\n"
1076               "    print(1 - erf(x));\n"
1077               "}");
1078         ASSERT_EQUALS("[test.cpp:2]: (style) Expression 'exp(x) - 1' can be replaced by 'expm1(x)' to avoid loss of precision.\n"
1079                       "[test.cpp:3]: (style) Expression 'log(1 + x)' can be replaced by 'log1p(x)' to avoid loss of precision.\n"
1080                       "[test.cpp:4]: (style) Expression '1 - erf(x)' can be replaced by 'erfc(x)' to avoid loss of precision.\n", errout.str());
1081 
1082         check("void foo() {\n"
1083               "    print(exp(x) - 1.0);\n"
1084               "    print(log(1.0 + x));\n"
1085               "    print(1.0 - erf(x));\n"
1086               "}");
1087         ASSERT_EQUALS("[test.cpp:2]: (style) Expression 'exp(x) - 1' can be replaced by 'expm1(x)' to avoid loss of precision.\n"
1088                       "[test.cpp:3]: (style) Expression 'log(1 + x)' can be replaced by 'log1p(x)' to avoid loss of precision.\n"
1089                       "[test.cpp:4]: (style) Expression '1 - erf(x)' can be replaced by 'erfc(x)' to avoid loss of precision.\n", errout.str());
1090 
1091         check("void foo() {\n"
1092               "    print(exp(3 + x*f(a)) - 1);\n"
1093               "    print(log(x*4 + 1));\n"
1094               "    print(1 - erf(34*x + f(x) - c));\n"
1095               "}");
1096         ASSERT_EQUALS("[test.cpp:2]: (style) Expression 'exp(x) - 1' can be replaced by 'expm1(x)' to avoid loss of precision.\n"
1097                       "[test.cpp:3]: (style) Expression 'log(1 + x)' can be replaced by 'log1p(x)' to avoid loss of precision.\n"
1098                       "[test.cpp:4]: (style) Expression '1 - erf(x)' can be replaced by 'erfc(x)' to avoid loss of precision.\n", errout.str());
1099 
1100         check("void foo() {\n"
1101               "    print(2*exp(x) - 1);\n"
1102               "    print(1 - erf(x)/2.0);\n"
1103               "}");
1104         ASSERT_EQUALS("", errout.str());
1105     }
1106 
checkIgnoredReturnValue()1107     void checkIgnoredReturnValue() {
1108         Settings settings2;
1109         settings2.severity.enable(Severity::warning);
1110         const char xmldata[] = "<?xml version=\"1.0\"?>\n"
1111                                "<def version=\"2\">\n"
1112                                "  <function name=\"mystrcmp,foo::mystrcmp\">\n"
1113                                "    <use-retval/>\n"
1114                                "    <arg nr=\"1\"/>\n"
1115                                "    <arg nr=\"2\"/>\n"
1116                                "  </function>\n"
1117                                "</def>";
1118         tinyxml2::XMLDocument doc;
1119         doc.Parse(xmldata, sizeof(xmldata));
1120         settings2.library.load(doc);
1121 
1122         check("void foo() {\n"
1123               "  mystrcmp(a, b);\n"
1124               "}", "test.cpp", &settings2);
1125         ASSERT_EQUALS("[test.cpp:2]: (warning) Return value of function mystrcmp() is not used.\n", errout.str());
1126 
1127         check("void foo() {\n"
1128               "  foo::mystrcmp(a, b);\n"
1129               "}", "test.cpp", &settings2);
1130         ASSERT_EQUALS("[test.cpp:2]: (warning) Return value of function foo::mystrcmp() is not used.\n", errout.str());
1131 
1132         check("void f() {\n"
1133               "  foo x;\n"
1134               "  x.mystrcmp(a, b);\n"
1135               "}", "test.cpp", &settings2);
1136         ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function x.mystrcmp() is not used.\n", errout.str());
1137 
1138         check("bool mystrcmp(char* a, char* b);\n" // cppcheck sees a custom strcmp definition, but it returns a value. Assume it is the one specified in the library.
1139               "void foo() {\n"
1140               "    mystrcmp(a, b);\n"
1141               "}", "test.cpp", &settings2);
1142         ASSERT_EQUALS("[test.cpp:3]: (warning) Return value of function mystrcmp() is not used.\n", errout.str());
1143 
1144         check("void mystrcmp(char* a, char* b);\n" // cppcheck sees a custom strcmp definition which returns void!
1145               "void foo() {\n"
1146               "    mystrcmp(a, b);\n"
1147               "}", "test.cpp", &settings2);
1148         ASSERT_EQUALS("", errout.str());
1149 
1150         check("void foo() {\n"
1151               "    class mystrcmp { mystrcmp() {} };\n" // strcmp is a constructor definition here
1152               "}", "test.cpp", &settings2);
1153         ASSERT_EQUALS("", errout.str());
1154 
1155         check("void foo() {\n"
1156               "    return mystrcmp(a, b);\n"
1157               "}", "test.cpp", &settings2);
1158         ASSERT_EQUALS("", errout.str());
1159 
1160         check("void foo() {\n"
1161               "    return foo::mystrcmp(a, b);\n"
1162               "}", "test.cpp", &settings2);
1163         ASSERT_EQUALS("", errout.str());
1164 
1165         check("void foo() {\n"
1166               "    if(mystrcmp(a, b));\n"
1167               "}", "test.cpp", &settings2);
1168         ASSERT_EQUALS("", errout.str());
1169 
1170         check("void foo() {\n"
1171               "    bool b = mystrcmp(a, b);\n"
1172               "}", "test.cpp", &settings2);
1173         ASSERT_EQUALS("", errout.str());
1174 
1175         // #6194
1176         check("void foo() {\n"
1177               "    MyStrCmp mystrcmp(x, y);\n"
1178               "}", "test.cpp", &settings2);
1179         ASSERT_EQUALS("", errout.str());
1180 
1181         // #6197
1182         check("void foo() {\n"
1183               "    abc::def.mystrcmp(a,b);\n"
1184               "}", "test.cpp", &settings2);
1185         ASSERT_EQUALS("", errout.str());
1186 
1187         // #6233
1188         check("int main() {\n"
1189               "    auto lambda = [](double value) {\n"
1190               "        double rounded = floor(value + 0.5);\n"
1191               "        printf(\"Rounded value = %f\\n\", rounded);\n"
1192               "    };\n"
1193               "    lambda(13.3);\n"
1194               "    return 0;\n"
1195               "}");
1196         ASSERT_EQUALS("", errout.str());
1197 
1198         // #6669
1199         check("void foo(size_t size) {\n"
1200               "   void * res{malloc(size)};\n"
1201               "}");
1202         ASSERT_EQUALS("", errout.str());
1203 
1204         // #7447
1205         check("void foo() {\n"
1206               "   int x{mystrcmp(a,b)};\n"
1207               "}", "test.cpp", &settings2);
1208         ASSERT_EQUALS("", errout.str());
1209 
1210         // #7905
1211         check("void foo() {\n"
1212               "   int x({mystrcmp(a,b)});\n"
1213               "}", "test.cpp", &settings2);
1214         ASSERT_EQUALS("", errout.str());
1215 
1216         check("void foo() {\n" // don't crash
1217               "  DEBUG(123)(mystrcmp(a,b))(fd);\n"
1218               "}", "test.c", &settings2);
1219         check("struct teststruct {\n"
1220               "    int testfunc1() __attribute__ ((warn_unused_result)) { return 1; }\n"
1221               "    [[nodiscard]] int testfunc2() { return 1; }\n"
1222               "    void foo() { testfunc1(); testfunc2(); }\n"
1223               "};\n"
1224               "int main() {\n"
1225               "    teststruct TestStruct1;\n"
1226               "    TestStruct1.testfunc1();\n"
1227               "    TestStruct1.testfunc2();\n"
1228               "    return 0;\n"
1229               "}", "test.cpp", &settings2);
1230         ASSERT_EQUALS("[test.cpp:4]: (warning) Return value of function testfunc1() is not used.\n"
1231                       "[test.cpp:4]: (warning) Return value of function testfunc2() is not used.\n"
1232                       "[test.cpp:8]: (warning) Return value of function TestStruct1.testfunc1() is not used.\n"
1233                       "[test.cpp:9]: (warning) Return value of function TestStruct1.testfunc2() is not used.\n", errout.str());
1234 
1235         // #9006
1236         check("template <typename... a> uint8_t b(std::tuple<uint8_t> d) {\n"
1237               "  std::tuple<a...> c{std::move(d)};\n"
1238               "  return std::get<0>(c);\n"
1239               "}");
1240         ASSERT_EQUALS("", errout.str());
1241 
1242         check("struct A { int x; };\n"
1243               "template <class... Ts>\n"
1244               "A f(int x, Ts... xs) {\n"
1245               "    return {std::move(x), static_cast<int>(xs)...};\n"
1246               "}\n"
1247               "A g() { return f(1); }");
1248         ASSERT_EQUALS("", errout.str());
1249 
1250         // #8412 - unused operator result
1251         check("void foo() {\n"
1252               "  !mystrcmp(a, b);\n"
1253               "}", "test.cpp", &settings2);
1254         ASSERT_EQUALS("[test.cpp:2]: (warning) Return value of function mystrcmp() is not used.\n", errout.str());
1255 
1256     }
1257 
checkIgnoredErrorCode()1258     void checkIgnoredErrorCode() {
1259         Settings settings2;
1260         settings2.addEnabled("style");
1261         const char xmldata[] = "<?xml version=\"1.0\"?>\n"
1262                                "<def version=\"2\">\n"
1263                                "  <function name=\"mystrcmp\">\n"
1264                                "    <use-retval type=\"error-code\"/>\n"
1265                                "    <arg nr=\"1\"/>\n"
1266                                "    <arg nr=\"2\"/>\n"
1267                                "  </function>\n"
1268                                "</def>";
1269         tinyxml2::XMLDocument doc;
1270         doc.Parse(xmldata, sizeof(xmldata));
1271         settings2.library.load(doc);
1272 
1273         check("void foo() {\n"
1274               "  mystrcmp(a, b);\n"
1275               "}", "test.cpp", &settings2);
1276         ASSERT_EQUALS("[test.cpp:2]: (style) Error code from the return value of function mystrcmp() is not used.\n", errout.str());
1277     }
1278 
memsetZeroBytes()1279     void memsetZeroBytes() {
1280         check("void f() {\n"
1281               "    memset(p, 10, 0x0);\n"
1282               "}");
1283         ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0 bytes.\n", errout.str());
1284 
1285         check("void f() {\n"
1286               "    memset(p, sizeof(p), 0);\n"
1287               "}");
1288         ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0 bytes.\n", errout.str());
1289 
1290         check("void f() {\n"
1291               "    memset(p, sizeof(p), i);\n"
1292               "}");
1293         ASSERT_EQUALS("", errout.str());
1294 
1295         // #6269 false positives in case of overloaded standard library functions
1296         check("class c {\n"
1297               "  void memset( int i );\n"
1298               "  void f( void )   {\n"
1299               "     memset( 0 );\n"
1300               "  }\n"
1301               "};");
1302         ASSERT_EQUALS("", errout.str());
1303 
1304         // #7285
1305         check("void f() {\n"
1306               "    memset(&tm, sizeof(tm), 0);\n"
1307               "}");
1308         ASSERT_EQUALS("[test.cpp:2]: (warning) memset() called to fill 0 bytes.\n", errout.str());
1309 
1310     }
1311 
memsetInvalid2ndParam()1312     void memsetInvalid2ndParam() {
1313         check("void f() {\n"
1314               "    int* is = new int[10];\n"
1315               "    memset(is, 1.0f, 40);\n"
1316               "    int* is2 = new int[10];\n"
1317               "    memset(is2, 0.1f, 40);\n"
1318               "}");
1319         ASSERT_EQUALS("[test.cpp:3]: (portability) The 2nd memset() argument '1.0f' is a float, its representation is implementation defined.\n"
1320                       "[test.cpp:5]: (portability) The 2nd memset() argument '0.1f' is a float, its representation is implementation defined.\n", errout.str());
1321 
1322         check("void f() {\n"
1323               "    int* is = new int[10];\n"
1324               "    float g = computeG();\n"
1325               "    memset(is, g, 40);\n"
1326               "}");
1327         ASSERT_EQUALS("[test.cpp:4]: (portability) The 2nd memset() argument 'g' is a float, its representation is implementation defined.\n", errout.str());
1328 
1329         check("void f() {\n"
1330               "    int* is = new int[10];\n"
1331               "    memset(is, 0.0f, 40);\n"
1332               "}");
1333         ASSERT_EQUALS("", errout.str());
1334 
1335         check("void f() {\n" // FP
1336               "    float x = 2.3f;\n"
1337               "    memset(a, (x?64:0), 40);\n"
1338               "}");
1339         ASSERT_EQUALS("", errout.str());
1340 
1341         check("void f() {\n"
1342               "    short ss[] = {1, 2};\n"
1343               "    memset(ss, 256, 4);\n"
1344               "    short ss2[2];\n"
1345               "    memset(ss2, -129, 4);\n"
1346               "}");
1347         ASSERT_EQUALS("[test.cpp:3]: (warning) The 2nd memset() argument '256' doesn't fit into an 'unsigned char'.\n"
1348                       "[test.cpp:5]: (warning) The 2nd memset() argument '-129' doesn't fit into an 'unsigned char'.\n", errout.str());
1349 
1350         check("void f() {\n"
1351               "    int is[10];\n"
1352               "    memset(is, 0xEE, 40);\n"
1353               "    unsigned char* cs = malloc(256);\n"
1354               "    memset(cs, -1, 256);\n"
1355               "    short* ss[30];\n"
1356               "    memset(ss, -128, 60);\n"
1357               "    char cs2[30];\n"
1358               "    memset(cs2, 255, 30);\n"
1359               "    char cs3[30];\n"
1360               "    memset(cs3, 0, 30);\n"
1361               "}");
1362         ASSERT_EQUALS("", errout.str());
1363 
1364         check("void f() {\n"
1365               "    int is[10];\n"
1366               "    const int i = g();\n"
1367               "    memset(is, 1.0f + i, 40);\n"
1368               "}");
1369         ASSERT_EQUALS("[test.cpp:4]: (portability) The 2nd memset() argument '1.0f+i' is a float, its representation is implementation defined.\n", errout.str());
1370     }
1371 
checkMissingReturn()1372     void checkMissingReturn() {
1373         check("int f() {}");
1374         ASSERT_EQUALS("[test.cpp:1]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
1375 
1376         {
1377             const char code[] = "int main(void) {}";
1378             Settings s;
1379 
1380             s.standards.c = Standards::C89;
1381             check(code, "test.c", &s); // c code (c89)
1382             ASSERT_EQUALS("[test.c:1]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
1383 
1384             s.standards.c = Standards::C99;
1385             check(code, "test.c", &s); // c code (c99)
1386             ASSERT_EQUALS("", errout.str());
1387 
1388             check(code, "test.cpp", &s); // c++ code
1389             ASSERT_EQUALS("", errout.str());
1390         }
1391 
1392         check("F(A,B) { x=1; }");
1393         ASSERT_EQUALS("", errout.str());
1394 
1395         check("auto foo4() -> void {}");
1396         ASSERT_EQUALS("", errout.str());
1397 
1398         check("void STDCALL foo() {}");
1399         ASSERT_EQUALS("", errout.str());
1400 
1401         check("void operator=(int y) { x=y; }");
1402         ASSERT_EQUALS("", errout.str());
1403 
1404         check("int f() {\n"
1405               "back:\n"
1406               "    return 0;\n"
1407               "ng:\n"
1408               "    x=y;\n"
1409               "    goto back;\n"
1410               "}\n");
1411         ASSERT_EQUALS("", errout.str());
1412 
1413         // unreachable code..
1414         check("int foo(int x) {\n"
1415               "  return 1;\n"
1416               "  (void)x;\n"
1417               "}");
1418         ASSERT_EQUALS("", errout.str());
1419 
1420         check("int foo(int x) {\n"
1421               "  if (x) goto out;\n"
1422               "  return 1;\n"
1423               "out:\n"
1424               "}");
1425         ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
1426 
1427         // switch
1428         check("int f() {\n"
1429               "    switch (x) {\n"
1430               "        case 1: break;\n" // <- error
1431               "        case 2: return 1;\n"
1432               "    }\n"
1433               "}");
1434         ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
1435 
1436         check("int f() {\n"
1437               "    switch (x) {\n"
1438               "        case 1: return 2; break;\n"
1439               "        default: return 1;\n"
1440               "    }\n"
1441               "}");
1442         ASSERT_EQUALS("", errout.str());
1443 
1444         // if/else
1445         check("int f(int x) {\n"
1446               "    if (x) {\n"
1447               "        return 1;\n"
1448               "    }\n" // <- error (missing else)
1449               "}");
1450         ASSERT_EQUALS("[test.cpp:4]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
1451 
1452         check("int f(int x) {\n"
1453               "    if (x) {\n"
1454               "        ;\n" // <- error
1455               "    } else {\n"
1456               "        return 1;\n"
1457               "    }\n"
1458               "}");
1459         ASSERT_EQUALS("[test.cpp:3]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
1460 
1461         check("int f() {\n"
1462               "    if (!0) {\n"
1463               "        return 1;\n"
1464               "    }\n"
1465               "}");
1466         ASSERT_EQUALS("", errout.str());
1467 
1468         check("int f() {\n"
1469               "    if (!0) {}\n"
1470               "}");
1471         ASSERT_EQUALS("[test.cpp:2]: (error) Found a exit path from function with non-void return type that has missing return statement\n", errout.str());
1472 
1473         // loop
1474         check("int f(int x) {\n"
1475               "    while (1) {\n"
1476               "        dostuff();\n"
1477               "    }\n"
1478               "}");
1479         ASSERT_EQUALS("", errout.str());
1480 
1481         // return {..}
1482         check("std::pair<int, int> typeDecl(int tok) {\n"
1483               "    if (!tok)\n"
1484               "        return {};\n"
1485               "    else\n"
1486               "        return {1, 2};\n"
1487               "}");
1488         ASSERT_EQUALS("", errout.str());
1489 
1490         // noreturn function
1491         check("int f(int x) { exit(0); }");
1492         ASSERT_EQUALS("", errout.str());
1493 
1494         check("int f(int x) { assert(0); }");
1495         ASSERT_EQUALS("", errout.str());
1496 
1497         check("int f(int x) { if (x) return 1; else return bar({1}, {}); }");
1498         ASSERT_EQUALS("", errout.str());
1499     }
1500 
1501     // NRVO check
returnLocalStdMove1()1502     void returnLocalStdMove1() {
1503         check("struct A{}; A f() { A var; return std::move(var); }");
1504         ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization."
1505                       " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str());
1506     }
1507 
1508     // RVO, C++03 ctor style
returnLocalStdMove2()1509     void returnLocalStdMove2() {
1510         check("struct A{}; A f() { return std::move( A() ); }");
1511         ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization."
1512                       " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str());
1513     }
1514 
1515     // RVO, new ctor style
returnLocalStdMove3()1516     void returnLocalStdMove3() {
1517         check("struct A{}; A f() { return std::move(A{}); }");
1518         ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization."
1519                       " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str());
1520     }
1521 
1522     // Function argument
returnLocalStdMove4()1523     void returnLocalStdMove4() {
1524         check("struct A{}; A f(A a) { return std::move(A{}); }");
1525         ASSERT_EQUALS("[test.cpp:1]: (performance) Using std::move for returning object by-value from function will affect copy elision optimization."
1526                       " More: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-return-move-local\n", errout.str());
1527     }
1528 
returnLocalStdMove5()1529     void returnLocalStdMove5() {
1530         check("struct A{} a; A f1() { return std::move(a); }\n"
1531               "A f2() { volatile A var; return std::move(var); }");
1532         ASSERT_EQUALS("", errout.str());
1533     }
1534 };
1535 
1536 REGISTER_TEST(TestFunctions)
1537