SonarSource Rules
  • Products

    In-IDE

    Code Quality and Security in your IDE with SonarQube Ide

    IDE extension that lets you fix coding issues before they exist!

    Discover SonarQube for IDE

    SaaS

    Code Quality and Security in the cloud with SonarQube Cloud

    Setup is effortless and analysis is automatic for most languages

    Discover SonarQube Cloud

    Self-Hosted

    Code Quality and Security Self-Hosted with SonarQube Server

    Fast, accurate analysis; enterprise scalability

    Discover SonarQube Server
  • SecretsSecrets
  • ABAPABAP
  • AnsibleAnsible
  • ApexApex
  • AzureResourceManagerAzureResourceManager
  • CC
  • C#C#
  • C++C++
  • CloudFormationCloudFormation
  • COBOLCOBOL
  • CSSCSS
  • DartDart
  • DockerDocker
  • FlexFlex
  • GitHub ActionsGitHub Actions
  • GoGo
  • HTMLHTML
  • JavaJava
  • JavaScriptJavaScript
  • JSONJSON
  • JCLJCL
  • KotlinKotlin
  • KubernetesKubernetes
  • Objective CObjective C
  • PHPPHP
  • PL/IPL/I
  • PL/SQLPL/SQL
  • PythonPython
  • RPGRPG
  • RubyRuby
  • RustRust
  • ScalaScala
  • ShellShell
  • SwiftSwift
  • TerraformTerraform
  • TextText
  • TypeScriptTypeScript
  • T-SQLT-SQL
  • VB.NETVB.NET
  • VB6VB6
  • XMLXML
  • YAMLYAML
C++

C++ static code analysis

Unique rules to find Bugs, Vulnerabilities, Security Hotspots, and Code Smells in your C++ code

  • All rules 674
  • Vulnerability13
  • Bug139
  • Security Hotspot19
  • Code Smell503

  • Quick Fix 91
Filtered: 81 rules found
cppcoreguidelines
    Impact
      Clean code attribute
        1. Function-like macros should not be used

           Code Smell
        2. Array type function arguments should not decay to pointers

           Code Smell
        3. The unary "&" operator should not be overloaded

           Code Smell
        4. Boolean operations should not have numeric operands, and vice versa

           Bug
        5. A cast shall not remove any const or volatile qualification from the type of a pointer or reference

           Code Smell
        6. "std::jthread" should be used instead of "std::thread"

           Code Smell
        7. Structured binding should be used

           Code Smell
        8. "dynamic_cast" should be used for downcasting

           Code Smell
        9. Threads should not be detached

           Code Smell
        10. Loop variables should be declared in the minimal possible scope

           Code Smell
        11. "shared_ptr" should not be taken by rvalue reference

           Code Smell
        12. Inheriting constructors should be used

           Code Smell
        13. Return type of functions shouldn't be const qualified value

           Code Smell
        14. "make_unique" and "make_shared" should be used to construct "unique_ptr" and "shared_ptr"

           Code Smell
        15. "std::endl" should not be used

           Code Smell
        16. C-style array should not be used

           Code Smell
        17. Objects should not be sliced

           Bug
        18. "auto" should be used to avoid repetition of types

           Code Smell
        19. Relational and subtraction operators should not be used with pointers to different arrays

           Bug
        20. Arguments evaluation order should not be relied on

           Bug
        21. STL algorithms and range-based for loops should be preferred to traditional for loops

           Code Smell
        22. Multiple mutexes should not be acquired with individual locks

           Code Smell
        23. Local variables should be initialized immediately

           Code Smell
        24. Pointers or references obtained from aliased smart pointers should not be used as function parameters

           Code Smell
        25. "try_lock", "lock" and "unlock" should not be directly used for mutexes

           Code Smell
        26. A single statement should not have more than one resource allocation

           Code Smell
        27. Function parameters that are rvalue references should be moved

           Code Smell
        28. Capture by reference in lambdas used locally

           Code Smell
        29. "Forwarding references" parameters should be used only to forward parameters

           Code Smell
        30. Non-const global variables should not be used

           Code Smell
        31. The order for arguments of the same type in a function call should be obvious

           Code Smell
        32. "std::move" and "std::forward" should not be confused

           Bug
        33. "using" should be preferred for type aliasing

           Code Smell
        34. "std::move" should only be used where moving can happen

           Code Smell
        35. Classes should not contain both public and private data members

           Code Smell
        36. Functions that throw exceptions should not be used as hash functions

           Code Smell
        37. A call to "wait()" on a "std::condition_variable" should have a condition

           Bug
        38. "std::move" should not inhibit optimizations

           Code Smell
        39. User-defined types should not be passed as variadic arguments

           Bug
        40. Template parameters should be preferred to "std::function" when configuring behavior at compile time

           Code Smell
        41. Function pointers should not be used as function parameters

           Code Smell
        42. RAII objects should not be temporary

           Bug
        43. Macros should not be used to define constants

           Code Smell
        44. Memory should not be managed manually

           Code Smell
        45. Lambdas that capture "this" should capture everything explicitly

           Code Smell
        46. Move and swap operations should be "noexcept"

           Code Smell
        47. "void *" should not be used in typedefs, member variables, function parameters or return type

           Code Smell
        48. Function parameters should not be of type "std::unique_ptr<T> const &"

           Code Smell
        49. "nullptr" should be used to denote the null pointer

           Code Smell
        50. Non-exception types should not be caught

           Code Smell
        51. Comparison operators should not be virtual

           Code Smell
        52. Local variables and member data should not be volatile

           Code Smell
        53. Assignment operators should not be "virtual"

           Code Smell
        54. Member variables should not be "protected"

           Code Smell
        55. Destructors should be "noexcept"

           Bug
        56. Types and variables should be declared in separate statements

           Code Smell
        57. Scoped enumerations should be used

           Code Smell
        58. "reinterpret_cast" should not be used

           Code Smell
        59. Special member function should not be defined unless a non standard behavior is required

           Code Smell
        60. "override" or "final" should be used instead of "virtual"

           Code Smell
        61. Member data should be initialized in-class or in a constructor initialization list

           Code Smell
        62. Members should be initialized in the order they are declared

           Code Smell
        63. Binary operators should be overloaded as hidden friend functions

           Code Smell
        64. Child class fields should not shadow parent class fields

           Code Smell
        65. Exception specifications should not be used

           Code Smell
        66. Type specifiers should be listed in a standard order

           Code Smell
        67. "explicit" should be used on single-parameter constructors and conversion operators

           Code Smell
        68. Functions without parameters should not use "(void)"

           Code Smell
        69. "operator delete" should be written along with "operator new"

           Bug
        70. Inherited functions should not be hidden

           Code Smell
        71. Pass by reference to const should be used for large input parameters

           Code Smell
        72. Assignment operators should return non-"const" reference to the assigned object

           Code Smell
        73. Polymorphic base class destructor should be either public virtual or protected non-virtual

           Code Smell
        74. C-style memory allocation routines should not be used

           Code Smell
        75. Generic exceptions should not be caught

           Code Smell
        76. "empty()" should be used to test for emptiness

           Code Smell
        77. Generic exceptions should never be thrown

           Code Smell
        78. Exception classes should be caught by reference

           Bug
        79. Function templates should not be specialized

           Code Smell
        80. Parameters in an overriding virtual function shall either use the same default arguments as the function they override, or else shall not specify any default arguments

           Code Smell
        81. "using namespace" directives should not be used in header files

           Code Smell

        Binary operators should be overloaded as hidden friend functions

        consistency - conventional
        maintainability
        Code Smell
        • cppcoreguidelines
        • api-design

        This rule raises issues for overloaded binary mathematical and relational operators that are not declared as hidden friends.

        Why is this an issue?

        How can I fix it?

        More Info

        When overloading binary or relational operators, it is recommended that they be declared hidden friends of the class.

        The hidden friend pattern

        The hidden friend pattern consists of declaring and defining a function directly as a friend inside the class body. This reduces the function’s visibility to argument-dependent lookup only. Approximately, such a function is considered only when called on an object of the enclosing class.

        struct MyClass {
          friend void function(MyClass const& arg) { // This function is a hidden friend of MyClass
            ...
          }
        };
        

        Benefits of hidden friends

        Using hidden friends provides the following benefits:

        • in contrast to the member function, it allows conversion to be applied to both operands
        • in contrast to free functions, it is considered only if one of the operands is an object of the given class

        This rule raises issues for these overloaded binary operators:

        • mathematical operators: +, -, *, /, %, ^, &, |, <<, >>
        • until C++20, all relational operators: ==, !=, <, >, <=, >=
        • since C++20, non-members key relational operators: ==, <=>
        struct MyClass {
          MyClass operator+(const MyClass& rhs) // Noncompliant
          { /* ... */ }
        };
        
        bool operator==(const MyClass &lhs, const MyClass& rhs) // Noncompliant
        { /* ... */ }
        

        Why are hidden friends preferred over free functions?

        The overloaded operators that are declared as hidden friends are found only by argument-dependent lookup (ADL) for a given class. Roughly, this means that the hidden friend of class C is considered a candidate only if one of the arguments of the call is an object of type C or one derived from it. In contrast, a free function is considered for any class declared in the same namespace.

        For illustration, let’s consider the following example which defines operator/ as a free function.

        namespace lib {
          class Path {
          public:
            Path(char const*);
            Path(std::string_view);
            Path& operator/=(Path const&);
          };
        
          Path operator/(Path const& lhs, Path const& rhs) {
            auto result = lhs;
            result /= rhs;
            return result;
          }
        }
        

        The operator/ will be considered as a candidate for any call a / b when either a or b are of a type declared in the namespace lib. This not only makes compilation slower but also lists the function as a candidate in case of a compilation error, making such a message less readable.

        Furthermore, when such an operator is visible via normal lookup, it may be invoked when both arguments are of the type that is convertible to lib::Path. This may happen for code in the lib namespace or after using using namespace lib;. However, such code will not compile or, even worse, select different overloads when placed in a different namespace.

        namespace lib {
          void insideLib(std::string_view sv) {
            sv / "dir"; // Compiles, converts both arg to lib::Path
          }
        } // namespace lib
        
        namespace otherNS {
          void withoutUsing(std::string_view sv) {
            sv / "dir"; // Either does not compile or calls a different operator
          }
          void withUsing(std::string_view sv) {
            using namespace lib;
            sv / "dir"; // Compiles, converts both arg to lib::Path
          }
        } // namespace otherNS
        

        Such conversion for both arguments will not be allowed when the operator is declared as a hidden friend, as none of the operands are of lib::Path type:

        namespace lib {
          class Path {
          public:
            Path(char const*);
            Path(std::string_view);
            Path& operator/=(Path const&);
        
            friend Path operator/(Path const& lhs, Path const& rhs) {
              auto result = lhs;
              result /= rhs;
              return result;
            }
          };
        }
        

        Why are hidden friends preferred over member functions?

        When the overloaded operator is declared as a class member, it can be invoked only for objects of that class or classes derived from it. These restrictions also apply when operator syntax (a op b) is used and disallows implicit conversion for left operands while allowing them for right operands.

        For example, given the object i of class Integer that defines operator+ as a member:

        class Integer {
        public:
          Integer(long long int);
          Integer& operator+=(Integer const& rhs);
          Integer operator+(Integer const& rhs) const { // Noncompliant
            Integer res = *this;
            res += rhs;
            return res;
          }
        };
        

        The call i + 10 is well-formed and resolves to i.operator+(10), which will convert 10 to an Integer object using the implicit converting constructor. However, 10 + i is ill-formed.

        If hidden friend functions were used, the expressions i + 10 and 10 + i, would resolve to operator+(i, 10) and operator+(10, i) respectively, allowing conversion to be performed symmetrically on the integer literal.

        class Integer {
        public:
          Integer(long long int);
          Integer& operator+=(Integer const& rhs);
          friend Integer operator+(Integer const& lhs, Integer const& rhs) { // Compliant
            Integer res = lhs;
            res += rhs;
            return res;
          }
        };
        

        Why relational operators are treated differently since C++20?

        C++20 has introduced a three-way comparison operator <=> (also known as spaceship) in addition to the mechanism that considers additional functions when interpreting relational operations:

        • a < b (also >, <=, >=) is also interpreted as operator<=>(a, b) < 0, a.operator<=>(b) < 0, or 0 < operator<=>(b, a), 0 < b.operator<=>(a),
        • a != b is also intepreted as !operator==(a, b), !a.operator==(b), or !operator==(b, a), !b.operator==(a),
        • a == b is also intepreted as operator==(a, b), a.operator==(b), or operator==(b, a), b.operator==(a).

        The above mechanism makes overloads for !=, <, >, <=, >= replacable with <=> and == (see S6187). As these overloads will usually be removed, we do not suggest replacing them with hidden friends.

        Additionally, such rewrites consider calls of overloads with the order of argument as spelled (a, b), and reversed (b, a). This makes the behavior of expression consistent regardless of the order of operands. Given the following example:

        struct MyString {
          MyString(char const* cstr);
          bool
          operator==(MyString const& other) const;  // Compliant since C++20: see below
        
          std::strong_ordering
          operator<=>(MyString const& other) const; // Compliant: only available since C++20
        };
        
        const MySting ms;
        

        The expression ms == "Some string" and "SomeString" == ms both compile, and the latter calls operator== with the argument reversed. This removes the drawbacks of declaring all combinations of such operators as members, and the issue is not raised for them for C++20 and later.

        Note, that hidden friends are still preferred over free functions:

        struct MyString {
          MyString(char const* cstr);
        };
        
        bool
        operator==(MyString const& lhs, MyString const& rhs)  // Noncompliant
        { /* ... */ }
        
        std::strong_ordering
        operator<=>(MyString const& lhs, MyString const& rhs) // Noncompliant
        { /* ... */ }
        
          Available In:
        • SonarQube IdeCatch issues on the fly,
          in your IDE
        • SonarQube CloudDetect issues in your GitHub, Azure DevOps Services, Bitbucket Cloud, GitLab repositories
        • SonarQube ServerAnalyze code in your
          on-premise CI
          Developer Edition
          Available Since
          9.1

        © 2008-2025 SonarSource SA. All rights reserved.

        Privacy Policy | Cookie Policy | Terms of Use