117 lines
2.9 KiB
Plaintext
Raw Permalink Normal View History

== Why is this an issue?
2021-04-28 16:49:39 +02:00
Having a ``++switch++`` and its cases wholly encompassed by a control structure such as a ``++try++``, ``++@try++``, ``++catch++``, ``++@catch++``, or a loop is perfectly acceptable. (``++try++`` and ``++catch++`` are used hereafter to refer to both variants.) It is also acceptable to have a ``++goto++`` and its target label wholly encompassed in a control structure.
What is not acceptable is using a ``++goto++`` or ``++case++`` to suddenly jump into the body of a ``++try++``, ``++catch++``, Objective-C ``++@finally++``, or loop structure. Tangling labels or ``++switch++`` blocks with other control structures results in code that is difficult, if not impossible to understand. More importantly, when it compiles (some of these constructs won't compile under ISO-conformant compilers), it can lead to unexpected results. Therefore this usage should be strictly avoided.
This {cpp} code sample, which is also applicable to Objective-C if ``++try++`` and ``++catch++`` are converted to ``++@try++`` and ``++@catch++``, demonstrates jumping into a ``++switch++`` and into a ``++try++`` and ``++catch++`` :
=== Noncompliant code example
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,cpp]
2021-04-28 16:49:39 +02:00
----
void f ( int32_t i )
{
if ( 10 == i )
{
goto Label_10; // Noncompliant; goto transfers control into try block
}
if ( 11 == i )
{
goto Label_11; // Noncompliant; goto transfers control into catch block
}
switch ( i )
{
case 1:
try
{
Label_10:
case 2: // Noncompliant; switch transfers control into try block
// Action
break;
}
catch ( ... )
{
Label_11:
case 3: // Noncompliant; switch transfers control into catch block
// Action
break;
}
break;
default:
{
// Default Action
break;
}
}
}
----
=== Compliant solution
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,cpp]
2021-04-28 16:49:39 +02:00
----
void f ( int32_t i )
{
switch ( i )
{
case 1:
case 2:
// Action
break;
case 3:
// Action
break;
case 10:
default:
{
// Default Action
break;
}
}
try
{
if ( 2 == i || 10 == i)
{
// Action
}
}
catch ( ... )
{
if (3 == i || 11 == i)
{
// Action
}
}
}
----
== Resources
2021-04-28 16:49:39 +02:00
* MISRA {cpp}:2008, 15-0-3 - Control shall not be transferred into a try or catch block using goto or switch statement
* https://wiki.sei.cmu.edu/confluence/x/zdYxBQ[CERT, MSC20-C.] - Do not use a switch statement to transfer control into a complex block
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
\[Remove this use of "goto" to jump to the "xxx" label, which is located in a "[try|catch]" |
Extract this case from the "[try|catch|loop]" block because its switch is outside the block].
endif::env-github,rspecator-view[]