xref: /llvm-project/clang-tools-extra/docs/clang-tidy/checks/bugprone/empty-catch.rst (revision 047273fc9c84aa8b4197111b0de068b853ccfe27)
1.. title:: clang-tidy - bugprone-empty-catch
2
3bugprone-empty-catch
4====================
5
6Detects and suggests addressing issues with empty catch statements.
7
8.. code-block:: c++
9
10  try {
11    // Some code that can throw an exception
12  } catch(const std::exception&) {
13  }
14
15Having empty catch statements in a codebase can be a serious problem that
16developers should be aware of. Catch statements are used to handle exceptions
17that are thrown during program execution. When an exception is thrown, the
18program jumps to the nearest catch statement that matches the type of the
19exception.
20
21Empty catch statements, also known as "swallowing" exceptions, catch the
22exception but do nothing with it. This means that the exception is not handled
23properly, and the program continues to run as if nothing happened. This can
24lead to several issues, such as:
25
26* *Hidden Bugs*: If an exception is caught and ignored, it can lead to hidden
27  bugs that are difficult to diagnose and fix. The root cause of the problem
28  may not be apparent, and the program may continue to behave in unexpected
29  ways.
30
31* *Security Issues*: Ignoring exceptions can lead to security issues, such as
32  buffer overflows or null pointer dereferences. Hackers can exploit these
33  vulnerabilities to gain access to sensitive data or execute malicious code.
34
35* *Poor Code Quality*: Empty catch statements can indicate poor code quality
36  and a lack of attention to detail. This can make the codebase difficult to
37  maintain and update, leading to longer development cycles and increased
38  costs.
39
40* *Unreliable Code*: Code that ignores exceptions is often unreliable and can
41  lead to unpredictable behavior. This can cause frustration for users and
42  erode trust in the software.
43
44To avoid these issues, developers should always handle exceptions properly.
45This means either fixing the underlying issue that caused the exception or
46propagating the exception up the call stack to a higher-level handler.
47If an exception is not important, it should still be logged or reported in
48some way so that it can be tracked and addressed later.
49
50If the exception is something that can be handled locally, then it should be
51handled within the catch block. This could involve logging the exception or
52taking other appropriate action to ensure that the exception is not ignored.
53
54Here is an example:
55
56.. code-block:: c++
57
58  try {
59    // Some code that can throw an exception
60  } catch (const std::exception& ex) {
61    // Properly handle the exception, e.g.:
62    std::cerr << "Exception caught: " << ex.what() << std::endl;
63  }
64
65If the exception cannot be handled locally and needs to be propagated up the
66call stack, it should be re-thrown or new exception should be thrown.
67
68Here is an example:
69
70.. code-block:: c++
71
72  try {
73    // Some code that can throw an exception
74  } catch (const std::exception& ex) {
75    // Re-throw the exception
76    throw;
77  }
78
79In some cases, catching the exception at this level may not be necessary, and
80it may be appropriate to let the exception propagate up the call stack.
81This can be done simply by not using ``try/catch`` block.
82
83Here is an example:
84
85.. code-block:: c++
86
87  void function() {
88    // Some code that can throw an exception
89  }
90
91  void callerFunction() {
92    try {
93      function();
94    } catch (const std::exception& ex) {
95      // Handling exception on higher level
96      std::cerr << "Exception caught: " << ex.what() << std::endl;
97    }
98  }
99
100Other potential solution to avoid empty catch statements is to modify the code
101to avoid throwing the exception in the first place. This can be achieved by
102using a different API, checking for error conditions beforehand, or handling
103errors in a different way that does not involve exceptions. By eliminating the
104need for try-catch blocks, the code becomes simpler and less error-prone.
105
106Here is an example:
107
108.. code-block:: c++
109
110  // Old code:
111  try {
112    mapContainer["Key"].callFunction();
113  } catch(const std::out_of_range&) {
114  }
115
116  // New code
117  if (auto it = mapContainer.find("Key"); it != mapContainer.end()) {
118    it->second.callFunction();
119  }
120
121In conclusion, empty catch statements are a bad practice that can lead to hidden
122bugs, security issues, poor code quality, and unreliable code. By handling
123exceptions properly, developers can ensure that their code is robust, secure,
124and maintainable.
125
126Options
127-------
128
129.. option:: IgnoreCatchWithKeywords
130
131  This option can be used to ignore specific catch statements containing
132  certain keywords. If a ``catch`` statement body contains (case-insensitive)
133  any of the keywords listed in this semicolon-separated option, then the
134  catch will be ignored, and no warning will be raised.
135  Default value: `@TODO;@FIXME`.
136
137.. option:: AllowEmptyCatchForExceptions
138
139  This option can be used to ignore empty catch statements for specific
140  exception types. By default, the check will raise a warning if an empty
141  catch statement is detected, regardless of the type of exception being
142  caught. However, in certain situations, such as when a developer wants to
143  intentionally ignore certain exceptions or handle them in a different way,
144  it may be desirable to allow empty catch statements for specific exception
145  types.
146  To configure this option, a semicolon-separated list of exception type names
147  should be provided. If an exception type name in the list is caught in an
148  empty catch statement, no warning will be raised.
149  Default value: empty string.
150