Appendix A

Enforcing the C++ Core Guidelines

You can check to see if you are breaking the rules of the C++ Core Guidelines.

Let’s start with a program that breaks type safety, bounds safety, and lifetime safety.

1   // gslCheck.cpp
2   
3   #include <iostream>
4  
5   void f(int* p, int count) {
6   }
7  
8   void f2(int* p) {
9       int x = *p;
10  }
11  
12  int main() {
13  
14      // Break of type safety
15     // use of a c-cast
16     double d = 2;
17     auto p = (long*)&d;
18     auto q = (long long*)&d;
19  
20    // Break of bounds safety
21    // array-to-pointer decay
22    int myArray[100];
23    f(myArray, 100);

24  
25    // Break of lifetime safety
26    // a is not valid
27    int* a = new int;
28    delete a;
29    f2(a);
30  
31  }

The comments in the source code document the issues. Let me check the program with Visual Studio and clang-tidy.

Visual Studio

These are the steps to detect the issues with the program gslCheck.cpp.

  1. Enable code analysis on build.

    You have to enable the checkbox. Per default, type-safety, bounds-safety, and lifetime-safety rules are not part of the Microsoft Native Recommended Rules. See Figure A.1.

    Images

    Figure A.1 Enable code analysis

  2. Configure the active rules.

    As you can see in Figure A.2, I create rule set CheckProfiles, which consists of the rules C++ Core Guidelines Bounds Rules, C++ Core Guidelines Type Rules, and C++ Core Guidelines Lifetime Rules.

    Images

    Figure A.2 Configure the applied rules

  3. Run code analysis.

    Applying the set of rules on the code example is quite promising. See Figure A.3.

    Images

    Figure A.3 Automatic managing of a device

    All issues are found. For each issue such as the first one, I get the line number (17) and the rule of the affected profile (Type.4).

  4. Suppress warnings.

    Sometimes you want to suppress specific warnings. You can achieve this with attributes. My next example, gslCheckSuppress.cpp, applies an array-to-pointer decay twice. Only the second call should give a warning.

// gslCheckSuppress.cpp; C++20 with MSVC
 
#include <iostream>
 
void f(int* p, int count) {
}
 
int main() {
 
   int myArray[100];
 
   // Break of bounds safety
   [[gsl::suppress(bounds.3)]] { // suppress warning
         f(myArray, 100);
   }
 
   f(myArray, 100);             // warning 
 
}

The attribute gsl::suppress(bounds.3) behaves as expected. It’s only valid in its scope. The second violation of bounds safety is displayed. See Figure A.4.

Images

Figure A.4 Suppress warnings

clang-tidy

clang-tidy is a clang-based C++ “linter” tool. Its purpose is to provide an extensible framework for diagnosing and fixing typical programming errors, like style violations, interface misuse, or bugs that can be deduced via static analysis. clang-tidy is modular and provides a convenient interface for writing new checks—Extra Clang Tools 11 documentation (https://clang.llvm.org/extra/clang-tidy/).

clang-tidy supports more than 200 rules. About twenty of them are dedicated to the C++ Core Guidelines. Here are the steps to detect the issues with the program gslCheck.cpp.

  1. Apply the C++ Core Guidelines checks.

    The command line

    clang-tidy -checks=-*,cppcoreguidelines-*gslCheck.cpp

    checks the C++ Core Guidelines exclusively (see Figure A.5). The option -checks expects comma-separated values of glob patterns and means the following in this case:

    Images

    Figure A.5 Check the C++ Core Guidelines exclusively

    • -*: Disable the default checks of clang-tidy.

    • cppcoreguidelines-*: Enable the C++ Core Guidelines checks.

      These checks detected only the type-safety issues in the program gslCheck.cpp.

  2. Apply the clang-tidy checks and the C++ Core Guidelines checks.

    The slightly simplified command line

    clang-tidy -checks=cppcoreguidelines-*gslCheck.cpp

    also applies the clang-tidy checks (see Figure A.6). Now, the lifetime-safety issue is detected.

Images

Figure A.6 Check the C++ Core Guidelines with clang-tidy

In contrast to Visual Studio, I could not detect the boundary-safety issue with clang-tidy.