Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions cpp/common/src/codingstandards/cpp/exclusions/cpp/Classes3.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/
import cpp
import RuleMetadata
import codingstandards.cpp.exclusions.RuleMetadata

newtype Classes3Query =
TImproperlyProvidedSpecialMemberFunctionsQuery() or
TImproperlyProvidedSpecialMemberFunctionsAuditQuery()

predicate isClasses3QueryMetadata(Query query, string queryId, string ruleId, string category) {
query =
// `Query` instance for the `improperlyProvidedSpecialMemberFunctions` query
Classes3Package::improperlyProvidedSpecialMemberFunctionsQuery() and
queryId =
// `@id` for the `improperlyProvidedSpecialMemberFunctions` query
"cpp/misra/improperly-provided-special-member-functions" and
ruleId = "RULE-15-0-1" and
category = "required"
or
query =
// `Query` instance for the `improperlyProvidedSpecialMemberFunctionsAudit` query
Classes3Package::improperlyProvidedSpecialMemberFunctionsAuditQuery() and
queryId =
// `@id` for the `improperlyProvidedSpecialMemberFunctionsAudit` query
"cpp/misra/improperly-provided-special-member-functions-audit" and
ruleId = "RULE-15-0-1" and
category = "required"
}

module Classes3Package {
Query improperlyProvidedSpecialMemberFunctionsQuery() {
//autogenerate `Query` type
result =
// `Query` type for `improperlyProvidedSpecialMemberFunctions` query
TQueryCPP(TClasses3PackageQuery(TImproperlyProvidedSpecialMemberFunctionsQuery()))
}

Query improperlyProvidedSpecialMemberFunctionsAuditQuery() {
//autogenerate `Query` type
result =
// `Query` type for `improperlyProvidedSpecialMemberFunctionsAudit` query
TQueryCPP(TClasses3PackageQuery(TImproperlyProvidedSpecialMemberFunctionsAuditQuery()))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import BannedSyntax
import BannedTypes
import Classes
import Classes2
import Classes3
import Classes4
import Comments
import Concurrency
Expand Down Expand Up @@ -126,6 +127,7 @@ newtype TCPPQuery =
TBannedTypesPackageQuery(BannedTypesQuery q) or
TClassesPackageQuery(ClassesQuery q) or
TClasses2PackageQuery(Classes2Query q) or
TClasses3PackageQuery(Classes3Query q) or
TClasses4PackageQuery(Classes4Query q) or
TCommentsPackageQuery(CommentsQuery q) or
TConcurrencyPackageQuery(ConcurrencyQuery q) or
Expand Down Expand Up @@ -234,6 +236,7 @@ predicate isQueryMetadata(Query query, string queryId, string ruleId, string cat
isBannedTypesQueryMetadata(query, queryId, ruleId, category) or
isClassesQueryMetadata(query, queryId, ruleId, category) or
isClasses2QueryMetadata(query, queryId, ruleId, category) or
isClasses3QueryMetadata(query, queryId, ruleId, category) or
isClasses4QueryMetadata(query, queryId, ruleId, category) or
isCommentsQueryMetadata(query, queryId, ruleId, category) or
isConcurrencyQueryMetadata(query, queryId, ruleId, category) or
Expand Down
70 changes: 70 additions & 0 deletions cpp/misra/src/rules/RULE-15-0-1/AnalyzableClass.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import cpp

Comment thread
MichaelRFairhurst marked this conversation as resolved.
private predicate isUsable(MemberFunction f) {
not f.isDeleted() and
f.isPublic()
}

private predicate isMemberCustomized(MemberFunction f) {
exists(f.getDefinition()) and
not f.isDefaulted() and
not f.isDeleted() and
not f.isCompilerGenerated()
}

newtype TSpecialMember =
TMoveConstructor() or
TMoveAssignmentOperator() or
TCopyConstructor() or
TCopyAssignmentOperator() or
TDestructor()

class AnalyzableClass extends Class {
MoveConstructor moveCtor;
MoveAssignmentOperator moveAssign;
CopyConstructor copyCtor;
CopyAssignmentOperator copyAssign;
Destructor dtor;

AnalyzableClass() {
moveCtor = this.getAConstructor() and
copyCtor = this.getAConstructor() and
moveAssign = this.getAMemberFunction() and
copyAssign = this.getAMemberFunction() and
dtor = this.getDestructor()
}

predicate exposes(TSpecialMember m) {
m instanceof TMoveConstructor and moveConstructible()
or
m instanceof TMoveAssignmentOperator and moveAssignable()
or
m instanceof TCopyConstructor and copyConstructible()
or
m instanceof TCopyAssignmentOperator and copyAssignable()
or
m instanceof TDestructor and destructible()
}

predicate moveConstructible() { isUsable(moveCtor) }

predicate copyConstructible() { isUsable(copyCtor) }

predicate moveAssignable() { isUsable(moveAssign) }

predicate copyAssignable() { isUsable(copyAssign) }

predicate destructible() { isUsable(dtor) }

predicate isCustomized(TSpecialMember s) {
s instanceof TMoveConstructor and isMemberCustomized(moveCtor)
or
s instanceof TMoveAssignmentOperator and isMemberCustomized(moveAssign)
or
s instanceof TCopyConstructor and isMemberCustomized(copyCtor)
or
s instanceof TCopyAssignmentOperator and isMemberCustomized(copyAssign)
or
s instanceof TDestructor and isMemberCustomized(dtor)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/**
* @id cpp/misra/improperly-provided-special-member-functions
* @name RULE-15-0-1: Special member functions shall be provided appropriately
* @description Incorrect provision of special member functions can lead to unexpected or undefined
* behavior when objects of the class are copied, moved, or destroyed.
* @kind problem
* @precision medium
* @problem.severity warning
* @tags external/misra/id/rule-15-0-1
* scope/single-translation-unit
* correctness
* maintainability
* external/misra/enforcement/decidable
* external/misra/obligation/required
*/

import cpp
import codingstandards.cpp.misra
import AnalyzableClass

predicate isCopyEnabled(AnalyzableClass c) {
c.moveConstructible() and
not c.moveAssignable() and
c.copyConstructible() and
not c.copyAssignable()
or
c.moveConstructible() and
c.moveAssignable() and
c.copyConstructible() and
c.copyAssignable()
}

predicate isMoveOnly(AnalyzableClass c) {
c.moveConstructible() and
not c.moveAssignable() and
not c.copyConstructible() and
not c.copyAssignable()
or
c.moveConstructible() and
c.moveAssignable() and
not c.copyConstructible() and
not c.copyAssignable()
}

predicate isUnmovable(AnalyzableClass c) {
not c.moveConstructible() and
not c.moveAssignable() and
not c.copyConstructible() and
not c.copyAssignable()
}

predicate isValidCategory(AnalyzableClass c) {
isCopyEnabled(c) or
isMoveOnly(c) or
isUnmovable(c)
}

string specialMemberName(TSpecialMember f) {
f = TCopyConstructor() and result = "copy constructor"
or
f = TMoveConstructor() and result = "move constructor"
or
f = TCopyAssignmentOperator() and result = "copy assignment operator"
or
f = TMoveAssignmentOperator() and result = "move assignment operator"
}

predicate violatesCustomizedMoveOrCopyRequirements(AnalyzableClass c, string reason) {
not c.isCustomized(TDestructor()) and
exists(string concatenated |
concatenated =
strictconcat(TSpecialMember f |
not f = TDestructor() and
c.isCustomized(f)
|
specialMemberName(f), ", "
) and
reason = "has customized " + concatenated + ", but does not customize the destructor."
)
}

predicate violatesCustomizedDestructorRequirements(AnalyzableClass c, string reason) {
c.isCustomized(TDestructor()) and
(
c.moveConstructible() and
not c.isCustomized(TMoveConstructor()) and
reason = "has customized the destructor, but does not customize the move constructor."
or
c.moveAssignable() and
not c.isCustomized(TMoveAssignmentOperator()) and
reason = "has customized the destructor, but does not customize the move assignment operator."
or
c.copyConstructible() and
not c.isCustomized(TCopyConstructor()) and
reason = "has customized the destructor, but does not customize the copy constructor."
or
c.copyAssignable() and
not c.isCustomized(TCopyAssignmentOperator()) and
reason = "has customized the destructor, but does not customize the copy assignment operator."
)
}
Comment on lines +82 to +115
Copy link
Copy Markdown
Collaborator

@jeongsoolee09 jeongsoolee09 Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was a bit hard for me to follow the logic of this requirement check. Since these come in the form of

isCopyEnabled(class) -> {some_condition}

wouldn't it be simpler to check it using by taking the negation of the above?

isCopyEnabled(class) and ~{some_condition}

For example, the last requirement translates to

c.copyAssignable() implies (
  c.isCustomized(TCopyAssignmentOperator()) and
  (
    c.isCustomized(TMoveConstructor()) and c.isCustomized(TMoveAssignmentOperator()) or
    not isUserDeclared(getMoveConstructor(c)) and not isUserDeclared(getMoveAssign(c))
  )
)

So the check becomes:

c.copyAssignable() and not (
  c.isCustomized(TCopyAssignmentOperator()) and
  (
    c.isCustomized(TMoveConstructor()) and c.isCustomized(TMoveAssignmentOperator()) or
    not isUserDeclared(getMoveConstructor(c)) and not isUserDeclared(getMoveAssign(c))
  )
)

Rewriting above gives an arguably more readable version:

c.copyAssignable() and (
  /* 1. The copy assignment operator is not customized. */
  not c.isCustomized(TCopyAssignmentOperator()) or
  (
    /* 2. Any one (or both) of the move operations is not customized. */
    not c.isCustomized(TMoveConstructor() or not c.isCustomized(TMoveAssignmentOperator()) and
    /* 3. Any one (or both) of the move operations are user-declared. */
    (isUserDeclared(getMoveConstructor(c)) or isUserDeclared(getMoveAssign(c)))
  )
)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm understanding correctly, I think this is simpler.

The bullet points 2 and 3 can essentially be rephrased as:

  • in the presence of a customized destructor
  • if it's copy constructible the copy constructor must be customized, and
  • if it's copy assignable the copy assignment operator must be customized, and
  • if it's move constructible, the move constructor must be customized, and
  • if it's move assignable, the the move assignment operator must be customized

The only exceptions are:

  • copy enabled, not copy-assignable classes may leave the move constructor undeclared
  • copy assignable classes may leave both move ctor & assign undeclared

This matches my implementation above.

We can prove each item:

if it's copy constructible, the copy constructor must be customized

If it is copy constructible, it can only be copy enabled or copy assignable. Copy enabled classes must have a customized copy constructor, and copy assignable classes must have a customized copy constructor.

Erg, all copy constructible classes must have a customized copy constructor.

Inversely, if it must have a customized copy constructor, it must be either copy constructible or copy assignable -- the other three categories have no restrictions on the copy constructor.

if it's copy assignable, the copy assignment operator must be customized

This one is a direct quote: "if it is copy-assignable it shall also have a customized copy assignment operator." No other categories place any requirements on the copy assignment operator.

if it's move constructible, the move constructor must be customized

If it's move constructible, it can belong to any category except unmovable. If it is move-only or move-assignable, it must have a customized move constructor (bullet 2).

If it is copy-enabled, it may be undeclared (exception 1) or customized. If it is copy-assignable, both move operation may be undeclared (exception 2) or the the move constructor must be customized along with the copy constructor

Ergo, all move constructible classes must fulfill either exception 1 or exception 2 or have a customized move constructor.

Inversely, the unmovable category places no requirements on the move constructor.

if it's move assignable, the move assignment operator must be customized

if its move assignable, it may be move-only. Move only and assignable classes must have a customized move assignment operator.

If it is copy-enabled, the move assignment operator may be undeclared if the move constructor is (exception 2). Otherwise, it has to be customized.

Ergo, all move assignable classes must fulfill exception 2 or have a customized move assignment operator.

Inversely, a class may be:

  • unmovable, in which case there are no requirements on the move assignment operator, or
  • move-only but not move assignable, in which case there are no requirements on the move assignment operator, or
  • copy-enabled but not assignable, in which case there are no requirements on the move assignment operator.

brief pause

...To me, this is just much simpler overall. Not only is easier to remember that "x-operatable requires x operation is customized."

But it also makes pragmatic sense. A customized destructor indicates that you're managing a resource. Copying and moving a class requires care, during both construction and during assignment.

class Owner {
  Resource *resource;
  Owner() : resource(get_a_resource()) {}
  ~Owner() {
    release(resource);
  }
}

In the above code, the default copy operations will copy the handle, and the resource will be freed twice (once by the original, once by the copy). The default move operations will move the handle, which will typically have copy semantics.

It isn't enough to customize just the move constructor, or just the move assignment operator. Every available operation must be either customized or deleted....with one exception! If you leave the move operations undeclared, then moving will call your copy operations, so its ok to leave move operations undeclared and instead customize your copy operations.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're proposing something closer to this, right?

This is more verbose, but its absolutely possible to make the case that it has better error messages. It is also a pretty clear 1:1 mapping to the misra spec.

predicate violatesCustomizedDestructorRequirements(AnalyzableClass c, string reason) {
  c.isCustomized(TDestructor()) and
  (
    isMoveOnly(c) and
    (
      not c.isCustomized(TMoveConstructor()) and
      reason =
        "is move-only with a customized the destructor, but does not customize the move constructor."
      or
      c.moveAssignable() and
      not c.isCustomized(TMoveAssignmentOperator()) and
      reason =
        "is move-only and move-assignable with a customized the destructor, but does not customize the move assignment operator."
    )
    or
    isCopyEnabled(c) and
    (
      not c.isCustomized(TCopyConstructor()) and
      reason =
        "is copy-enabled with a customized the destructor, but does not customize the copy constructor."
      or
      not c.copyAssignable() and
      c.declaresMoveConstructor() and
      not c.isCustomized(TMoveConstructor()) and
      reason =
        "is copy-enabled with a customized the destructor, but declares a move constructor and does not customize it."
    )
    or
    c.copyAssignable() and
    (
      /* 1. The copy assignment operator is not customized. */
      not c.isCustomized(TCopyAssignmentOperator()) and
      reason =
        "is copy-assignable with a customized destructor but doesn't have a customized copy assignment operator"
      or
      /* 2. Only one of the move operations is customized. */
      c.declaresMoveConstructor() and
      not c.declaresMoveAssignmentOperator() and
      reason =
        "is copy assignable with a customized destructor, but declaring a move constructor implies that the move assignment operator should also be declared"
      or
      not c.declaresMoveConstructor() and
      c.declaresMoveAssignmentOperator() and
      reason =
        "is copy assignable with a customized destructor, but declaring a move assignment operator implies that the move constructor should also be declared"
      or
      /* 3. A move operation is declared but not customized. */
      c.declaresMoveConstructor() and
      not c.isCustomized(TMoveConstructor()) and
      reason =
        "has a customized destructor and declares a move constructor but does not customize it"
      or
      c.declaresMoveAssignmentOperator() and
      not c.isCustomized(TMoveAssignmentOperator()) and
      reason =
        "has a customized destructor and declares a move assignment operator but does not customize it"
    )
  )
}

The above version passes our current tests (just with different alert messages).

We shouldn't keep the old version unless we can clarify it. I don't know if its enough, but we could add a comment like this:

// If you follow the logic of each case in the rule specification, you'll find that all classes in a valid
// category that have a customized destructor, must customize every "x-operation" when the
// class is "x-operatable."
//
// This is logic makes perfect sense. A customized destructor indicates the class manages a
// resource, and such classes must customize every supported operation to prevent unwanted
// sharing, such as double frees.
//
// The only exception is that copy-enabled classes may sometimes omit move declarations. This
// also makes sense: when these operations aren't declared, the corresponding copy operation
// will be used instead.

Hopefully this comment:

  • explains that this is intentionally formulated differently than the rule text
  • explains the value of this formulation over the spec's formulation
  • makes it easier for a reader verify that the code does what it intends to do
  • makes the code easier to maintain

Copy link
Copy Markdown
Collaborator Author

@MichaelRFairhurst MichaelRFairhurst May 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, one last thought, and I don't really know which method this supports.

The original/current version will report errors for cases that are not one of the valid categories (not unmovable, or move-only, or copy-enabled), while the rewrite I posted above will not.

Usually this is a bad thing. We don't want to give two alerts when we could give one.

In this case, you could argue the reverse, that a class with a customized destructor and an otherwise defaulted operation should always get a warning. If a user intentionally writes a class that doesn't fit one of the categories (unmovable, move-only, copy-enabled), they might ignore that alert, and then they'll never get a warning that they forgot to customize their move assignment constructor.

Interesting to consider. Maybe not an issue in practice. On qlx, these two versions give the exact same results.


predicate isPublicBase(AnalyzableClass c) {
exists(ClassDerivation d |
d.getBaseClass() = c and
d.hasSpecifier("public")
)
}

predicate satisfiesInheritanceRequirements(AnalyzableClass c) {
not isPublicBase(c)
or
isUnmovable(c) and
c.getDestructor().isPublic() and
c.getDestructor().isVirtual()
or
c.getDestructor().isProtected() and
not c.getDestructor().isVirtual()
}

from AnalyzableClass c, string message
where
not isExcluded(c, Classes3Package::improperlyProvidedSpecialMemberFunctionsQuery()) and
(
not isValidCategory(c) and
message = "does not fall into a valid category (isUnmovable, move-only, or copy-enabled)."
or
violatesCustomizedMoveOrCopyRequirements(c, message)
or
violatesCustomizedDestructorRequirements(c, message)
or
not satisfiesInheritanceRequirements(c) and
message = "violates inheritance requirements for special member functions."
)
select c, "Class '" + c.getName() + "' " + message
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @id cpp/misra/improperly-provided-special-member-functions-audit
* @name RULE-15-0-1: Special member functions shall be provided appropriately, Audit
* @description Audit: incorrect provision of special member functions can lead to unexpected or
* undefined behavior when objects of the class are copied, moved, or destroyed.
* @kind problem
* @precision low
* @problem.severity warning
* @tags external/misra/id/rule-15-0-1
* scope/single-translation-unit
* correctness
* external/misra/audit
* maintainability
* external/misra/enforcement/decidable
* external/misra/obligation/required
*/

import cpp
import codingstandards.cpp.misra
import AnalyzableClass

string missingKind(Class c) {
not c.getAConstructor() instanceof MoveConstructor and
result = "move constructor"
or
not c.getAMemberFunction() instanceof MoveAssignmentOperator and
result = "move assignment operator"
or
not c.getAConstructor() instanceof CopyConstructor and
result = "copy constructor"
or
not c.getAMemberFunction() instanceof CopyAssignmentOperator and
result = "copy assignment operator"
or
not c.getAMemberFunction() instanceof Destructor and
result = "destructor"
}

string missingKinds(Class c) { result = concat(missingKind(c), " and ") }
Comment thread
MichaelRFairhurst marked this conversation as resolved.

from Class c, string kinds
where
not isExcluded(c, Classes3Package::improperlyProvidedSpecialMemberFunctionsAuditQuery()) and
not c instanceof AnalyzableClass and
not c.isPod() and
kinds = missingKinds(c)
select c,
"Class '" + c.getName() + "' is not analyzable because the " + kinds +
" are not present in the CodeQL database."
Comment thread
MichaelRFairhurst marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
| test.cpp:71:11:71:12 | C2 | Class 'C2' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:72:11:72:12 | C3 | Class 'C3' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:74:11:74:12 | C5 | Class 'C5' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:76:11:76:12 | C7 | Class 'C7' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:78:11:78:12 | C9 | Class 'C9' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:79:11:79:13 | C10 | Class 'C10' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:80:11:80:13 | C11 | Class 'C11' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:81:11:81:13 | C12 | Class 'C12' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:82:11:82:13 | C13 | Class 'C13' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:83:11:83:13 | C14 | Class 'C14' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:84:11:84:13 | C15 | Class 'C15' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:102:7:102:21 | PrivateCopyCtor | Class 'PrivateCopyCtor' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:115:7:115:21 | PrivateMoveCtor | Class 'PrivateMoveCtor' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:128:7:128:23 | PrivateCopyAssign | Class 'PrivateCopyAssign' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:141:7:141:23 | PrivateMoveAssign | Class 'PrivateMoveAssign' does not fall into a valid category (isUnmovable, move-only, or copy-enabled). |
| test.cpp:181:7:181:45 | CustomizedCopyCtorDefaultedNonCompliant | Class 'CustomizedCopyCtorDefaultedNonCompliant' has customized copy constructor, but does not customize the destructor. |
| test.cpp:188:7:188:43 | CustomizedCopyCtorDeletedNonCompliant | Class 'CustomizedCopyCtorDeletedNonCompliant' has customized copy constructor, but does not customize the destructor. |
| test.cpp:194:7:194:36 | CustomizedMoveCtorNonCompliant | Class 'CustomizedMoveCtorNonCompliant' has customized move constructor, but does not customize the destructor. |
| test.cpp:200:7:200:38 | CustomizedCopyAssignNonCompliant | Class 'CustomizedCopyAssignNonCompliant' has customized copy assignment operator, but does not customize the destructor. |
| test.cpp:206:7:206:38 | CustomizedMoveAssignNonCompliant | Class 'CustomizedMoveAssignNonCompliant' has customized copy constructor, move assignment operator, move constructor, but does not customize the destructor. |
| test.cpp:213:7:213:39 | MoveOnlyNotCustomizedNonCompliant | Class 'MoveOnlyNotCustomizedNonCompliant' has customized the destructor, but does not customize the move constructor. |
| test.cpp:220:7:220:49 | MoveOnlyAssignableNotCustomizedNonCompliant | Class 'MoveOnlyAssignableNotCustomizedNonCompliant' has customized the destructor, but does not customize the move assignment operator. |
| test.cpp:220:7:220:49 | MoveOnlyAssignableNotCustomizedNonCompliant | Class 'MoveOnlyAssignableNotCustomizedNonCompliant' has customized the destructor, but does not customize the move constructor. |
| test.cpp:251:7:251:43 | CopyEnabledCustomizedDtorNonCompliant | Class 'CopyEnabledCustomizedDtorNonCompliant' has customized the destructor, but does not customize the copy assignment operator. |
| test.cpp:251:7:251:43 | CopyEnabledCustomizedDtorNonCompliant | Class 'CopyEnabledCustomizedDtorNonCompliant' has customized the destructor, but does not customize the copy constructor. |
| test.cpp:251:7:251:43 | CopyEnabledCustomizedDtorNonCompliant | Class 'CopyEnabledCustomizedDtorNonCompliant' has customized the destructor, but does not customize the move assignment operator. |
| test.cpp:251:7:251:43 | CopyEnabledCustomizedDtorNonCompliant | Class 'CopyEnabledCustomizedDtorNonCompliant' has customized the destructor, but does not customize the move constructor. |
| test.cpp:270:7:270:33 | UnmovableBaseNonvirtualDtor | Class 'UnmovableBaseNonvirtualDtor' violates inheritance requirements for special member functions. |
| test.cpp:291:7:291:33 | UnmovablePrivateVirtualDtor | Class 'UnmovablePrivateVirtualDtor' violates inheritance requirements for special member functions. |
| test.cpp:318:7:318:30 | BaseVirtualProtectedDtor | Class 'BaseVirtualProtectedDtor' violates inheritance requirements for special member functions. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-15-0-1/ImproperlyProvidedSpecialMemberFunctions.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
| test.cpp:276:7:276:32 | UnmovableNonvirtualDerived | Class 'UnmovableNonvirtualDerived' is not analyzable because the destructor and move assignment operator and move constructor are not present in the CodeQL database. |
| test.cpp:288:7:288:39 | UnmovableDerivedPublicVirtualDtor | Class 'UnmovableDerivedPublicVirtualDtor' is not analyzable because the move assignment operator and move constructor are not present in the CodeQL database. |
| test.cpp:302:7:302:40 | UnmovablePrivateVirtualDtorDerived | Class 'UnmovablePrivateVirtualDtorDerived' is not analyzable because the move assignment operator and move constructor are not present in the CodeQL database. |
| test.cpp:316:7:316:26 | ProtectedDtorDerived | Class 'ProtectedDtorDerived' is not analyzable because the destructor and move assignment operator are not present in the CodeQL database. |
| test.cpp:329:7:329:33 | VirtualProtectedDtorDerived | Class 'VirtualProtectedDtorDerived' is not analyzable because the move assignment operator are not present in the CodeQL database. |
| test.cpp:342:8:342:19 | TrivialClass | Class 'TrivialClass' is not analyzable because the destructor and move assignment operator and move constructor are not present in the CodeQL database. |
| test.cpp:348:7:348:21 | NonTrivialClass | Class 'NonTrivialClass' is not analyzable because the move assignment operator and move constructor are not present in the CodeQL database. |
| test.cpp:362:7:362:14 | CopyOnly | Class 'CopyOnly' is not analyzable because the destructor are not present in the CodeQL database. |
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rules/RULE-15-0-1/ImproperlyProvidedSpecialMemberFunctionsAudit.ql
Loading
Loading