Cppcheck
checkexceptionsafety.h
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2024 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 //---------------------------------------------------------------------------
20 #ifndef checkexceptionsafetyH
21 #define checkexceptionsafetyH
22 //---------------------------------------------------------------------------
23 
24 #include "check.h"
25 #include "config.h"
26 #include "tokenize.h"
27 
28 #include <string>
29 
30 class Settings;
31 class ErrorLogger;
32 class Token;
33 
34 
35 /// @addtogroup Checks
36 /// @{
37 
38 
39 /**
40  * @brief %Check exception safety (exceptions shouldn't cause leaks nor corrupt data)
41  *
42  * The problem with these checks is that Cppcheck can't determine what the valid
43  * values are for variables. But in some cases (dead pointers) it can be determined
44  * that certain variable values are corrupt.
45  */
46 
48 public:
49  /** This constructor is used when registering the CheckClass */
50  CheckExceptionSafety() : Check(myName()) {}
51 
52 private:
53  /** This constructor is used when running checks. */
54  CheckExceptionSafety(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
55  : Check(myName(), tokenizer, settings, errorLogger) {}
56 
57  void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override {
58  if (tokenizer.isC())
59  return;
60 
61  CheckExceptionSafety checkExceptionSafety(&tokenizer, &tokenizer.getSettings(), errorLogger);
62  checkExceptionSafety.destructors();
63  checkExceptionSafety.deallocThrow();
64  checkExceptionSafety.checkRethrowCopy();
65  checkExceptionSafety.checkCatchExceptionByValue();
66  checkExceptionSafety.nothrowThrows();
67  checkExceptionSafety.unhandledExceptionSpecification();
68  checkExceptionSafety.rethrowNoCurrentException();
69  }
70 
71  /** Don't throw exceptions in destructors */
72  void destructors();
73 
74  /** deallocating memory and then throw (dead pointer) */
75  void deallocThrow();
76 
77  /** Don't rethrow a copy of the caught exception; use a bare throw instead */
78  void checkRethrowCopy();
79 
80  /** @brief %Check for exceptions that are caught by value instead of by reference */
81  void checkCatchExceptionByValue();
82 
83  /** @brief %Check for functions that throw that shouldn't */
84  void nothrowThrows();
85 
86  /** @brief %Check for unhandled exception specification */
87  void unhandledExceptionSpecification();
88 
89  /** @brief %Check for rethrow not from catch scope */
90  void rethrowNoCurrentException();
91 
92  /** Don't throw exceptions in destructors */
93  void destructorsError(const Token * const tok, const std::string &className);
94  void deallocThrowError(const Token * const tok, const std::string &varname);
95  void rethrowCopyError(const Token * const tok, const std::string &varname);
96  void catchExceptionByValueError(const Token *tok);
97  void noexceptThrowError(const Token * const tok);
98  /** Missing exception specification */
99  void unhandledExceptionSpecificationError(const Token * const tok1, const Token * const tok2, const std::string & funcname);
100  /** Rethrow without currently handled exception */
101  void rethrowNoCurrentExceptionError(const Token *tok);
102 
103  /** Generate all possible errors (for --errorlist) */
104  void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override {
105  CheckExceptionSafety c(nullptr, settings, errorLogger);
106  c.destructorsError(nullptr, "Class");
107  c.deallocThrowError(nullptr, "p");
108  c.rethrowCopyError(nullptr, "varname");
109  c.catchExceptionByValueError(nullptr);
110  c.noexceptThrowError(nullptr);
111  c.unhandledExceptionSpecificationError(nullptr, nullptr, "funcname");
113  }
114 
115  /** Short description of class (for --doc) */
116  static std::string myName() {
117  return "Exception Safety";
118  }
119 
120  /** wiki formatted description of the class (for --doc) */
121  std::string classInfo() const override {
122  return "Checking exception safety\n"
123  "- Throwing exceptions in destructors\n"
124  "- Throwing exception during invalid state\n"
125  "- Throwing a copy of a caught exception instead of rethrowing the original exception\n"
126  "- Exception caught by value instead of by reference\n"
127  "- Throwing exception in noexcept, nothrow(), __attribute__((nothrow)) or __declspec(nothrow) function\n"
128  "- Unhandled exception specification when calling function foo()\n"
129  "- Rethrow without currently handled exception\n";
130  }
131 };
132 /// @}
133 //---------------------------------------------------------------------------
134 #endif // checkexceptionsafetyH
Check exception safety (exceptions shouldn't cause leaks nor corrupt data)
void unhandledExceptionSpecification()
Check for unhandled exception specification
void destructors()
Don't throw exceptions in destructors.
static std::string myName()
Short description of class (for –doc)
void nothrowThrows()
Check for functions that throw that shouldn't
void deallocThrowError(const Token *const tok, const std::string &varname)
void rethrowCopyError(const Token *const tok, const std::string &varname)
void noexceptThrowError(const Token *const tok)
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override
Generate all possible errors (for –errorlist)
void rethrowNoCurrentException()
Check for rethrow not from catch scope
void checkCatchExceptionByValue()
Check for exceptions that are caught by value instead of by reference
CheckExceptionSafety()
This constructor is used when registering the CheckClass.
void runChecks(const Tokenizer &tokenizer, ErrorLogger *errorLogger) override
run checks, the token list is not simplified
void catchExceptionByValueError(const Token *tok)
void deallocThrow()
deallocating memory and then throw (dead pointer)
std::string classInfo() const override
wiki formatted description of the class (for –doc)
void rethrowNoCurrentExceptionError(const Token *tok)
Rethrow without currently handled exception.
void checkRethrowCopy()
Don't rethrow a copy of the caught exception; use a bare throw instead.
void unhandledExceptionSpecificationError(const Token *const tok1, const Token *const tok2, const std::string &funcname)
Missing exception specification.
void destructorsError(const Token *const tok, const std::string &className)
Don't throw exceptions in destructors.
CheckExceptionSafety(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
This constructor is used when running checks.
Interface class that cppcheck uses to communicate with the checks.
Definition: check.h:59
This is an interface, which the class responsible of error logging should implement.
Definition: errorlogger.h:214
This is just a container for general settings so that we don't need to pass individual values to func...
Definition: settings.h:95
The token list that the TokenList generates is a linked-list of this class.
Definition: token.h:150
The main purpose is to tokenize the source code.
Definition: tokenize.h:46
const Settings & getSettings() const
Definition: tokenize.h:615
bool isC() const
Is the code C.
Definition: tokenize.h:64
#define CPPCHECKLIB
Definition: config.h:35