
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
117 lines
2.9 KiB
Plaintext
117 lines
2.9 KiB
Plaintext
== Why is this an issue?
|
|
|
|
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
|
|
|
|
[source,cpp]
|
|
----
|
|
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
|
|
|
|
[source,cpp]
|
|
----
|
|
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
|
|
|
|
* 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[]
|