Skip to content

Commit

Permalink
fix: Split various rules and fix formatting
Browse files Browse the repository at this point in the history
- Split A6-5-3 and A6-5-4
- Split A12-8-1 and A12-8-2
- Split M5-0-4 and M5-0-5
- Split M5-0-14 and M5-0-15
- Split M7-3-2 and M7-3-3
- Fix code formatting
  • Loading branch information
JoelMueller authored and sbmueller committed May 18, 2024
1 parent efbb018 commit 99f19d7
Show file tree
Hide file tree
Showing 13 changed files with 230 additions and 256 deletions.
185 changes: 37 additions & 148 deletions src/A12-8-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,70 +22,63 @@ copied (e.g. caches, debug information).
class A
{
public:
// Implementation
A(A const& oth) : x(oth.x) // Compliant
{
}
// Implementation
A(A const& oth) : x(oth.x) // Compliant
{
}

private:
std::int32_t x;

std::int32_t x;
};
class B
{
public:
// Implementation
B(B&& oth) : ptr(std::move(oth.ptr)) // Compliant
{
oth.ptr = nullptr; // Compliant - this is not a side-effect, in this
// case it is
essential to leave moved-from object
// in a valid state, otherwise double deletion will

// occur.

}
~B() { delete ptr; }
// Implementation
B(B&& oth) : ptr(std::move(oth.ptr)) // Compliant
{
oth.ptr = nullptr; // Compliant - this is not a side-effect, in this
// case it is essential to leave moved-from object
// in a valid state, otherwise double deletion will
// occur.
}
~B() { delete ptr; }

private:

std::int32_t* ptr;

std::int32_t* ptr;
};
class C
{
public:
// Implementation
C(C const& oth) : x(oth.x)
{
// ...
x = x % 2; // Non-compliant - unrelated side-effect
}
// Implementation
C(C const& oth) : x(oth.x)
{
// ...
x = x % 2; // Non-compliant - unrelated side-effect
}

private:
std::int32_t x;

std::int32_t x;
};

class D
{
public:
explicit D(std::uint32_t a) : a(a), noOfModifications(0) {}
D(const D& d) : D(d.a) {} //compliant, not copying the debug information about number of
modifications
void SetA(std::uint32_t aa)
{
++noOfModifications;
a = aa;
}
std::uint32_t GetA() const noexcept
{
return a;
}
explicit D(std::uint32_t a) : a(a), noOfModifications(0) {}
D(const D& d) : D(d.a) {} // compliant, not copying the debug information
// about number of modifications
void SetA(std::uint32_t aa)
{
++noOfModifications;
a = aa;
}
std::uint32_t GetA() const noexcept
{
return a;
}

private:
std::uint32_t a;
std::uint64_t noOfModifications;
std::uint32_t a;
std::uint64_t noOfModifications;
};

```
Expand All @@ -94,114 +87,10 @@ std::uint64_t noOfModifications;

MISRA C++ 2008 [7]: Rule 12-8-1 A copy constructor shall only initialize its
base classes and the nonstatic members of the class of which it is a member.

HIC++ v4.0 [9]: 12.5.3 Ensure that a user defined move/copy constructor only
moves/copies base and member objects.

JSF December 2005 [8]: AV Rule 77: A copy constructor shall copy all data
members and bases that affect the class invariant (a data element representing
a cache, for example, would not need to be copied).
Rule A12-8-2 (advisory, implementation, automated) User-defined copy and
move assignment operators should use user-defined no-throw swap
function.
## Rationale
Using a non-throwing swap operation in the copy and move assignment operators
helps to achieve Strong Exception Safety. Each assignment operator is also
simplified because it does not require check for assignment to itself.
## Example
```cpp
// $Id: A12-8-2.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $
#include <cstdint>
#include <utility>
class A
{
public:
A(const A& oth)
{
// ...
}
A(A&& oth) noexcept
{
// ...
}
A& operator=(const A& oth) & // Compliant
{
A tmp(oth);
Swap(*this, tmp);
return *this;
}
A& operator=(A&& oth) & noexcept // Compliant
{
A tmp(std::move(oth));
Swap(*this, tmp);
return *this;
}
static void Swap(A& lhs, A& rhs) noexcept
{
std::swap(lhs.ptr1, rhs.ptr1);
std::swap(lhs.ptr2, rhs.ptr2);
}
private:
std::int32_t* ptr1;
std::int32_t* ptr2;
};
class B
{
public:
B& operator=(const B& oth) & // Non-compliant
{
if (this != &oth)
{
ptr1
ptr2
= new std::int32_t(*oth.ptr1);
= new std::int32_t(
*oth.ptr2); // Exception thrown here results in
// a memory leak of ptr1
}
return *this;
}
B& operator=(B&& oth) & noexcept // Non-compliant
{
if (this != &oth)
{
ptr1 = std::move(oth.ptr1);
ptr2 = std::move(oth.ptr2);
oth.ptr1
= nullptr;
oth.ptr2
= nullptr;
}
return *this;
}
private:
std::int32_t* ptr1;
std::int32_t* ptr2;
};
```

## See also

HIC++ v4.0 [9]: 12.5.6 Use an atomic, non-throwing swap operation to
implement the copy and move assignment operators
90 changes: 90 additions & 0 deletions src/A12-8-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
> **Rule A12-8-2 (advisory, implementation, automated)**
>
> User-defined copy and move assignment operators should use user-defined
> no-throw swap function.
## Rationale

Using a non-throwing swap operation in the copy and move assignment operators
helps to achieve Strong Exception Safety. Each assignment operator is also
simplified because it does not require check for assignment to itself.

## Example

```cpp
// $Id: A12-8-2.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $
#include <cstdint>
#include <utility>
class A
{
public:
A(const A& oth)
{
// ...
}
A(A&& oth) noexcept
{
// ...
}
A& operator=(const A& oth) & // Compliant
{
A tmp(oth);
Swap(*this, tmp);
return *this;
}
A& operator=(A&& oth) & noexcept // Compliant
{
A tmp(std::move(oth));
Swap(*this, tmp);
return *this;
}
static void Swap(A& lhs, A& rhs) noexcept
{
std::swap(lhs.ptr1, rhs.ptr1);
std::swap(lhs.ptr2, rhs.ptr2);
}

private:
std::int32_t* ptr1;
std::int32_t* ptr2;
};

class B
{
public:
B& operator=(const B& oth) & // Non-compliant
{
if (this != &oth)
{
ptr1 = new std::int32_t(*oth.ptr1);
ptr2 = new std::int32_t(
*oth.ptr2); // Exception thrown here results in
// a memory leak of ptr1
}

return *this;

}
B& operator=(B&& oth) & noexcept // Non-compliant
{
if (this != &oth)
{
ptr1 = std::move(oth.ptr1);
ptr2 = std::move(oth.ptr2);
oth.ptr1 = nullptr;
oth.ptr2 = nullptr;
}

return *this;
}

private:
std::int32_t* ptr1;
std::int32_t* ptr2;
};
```

## See also

HIC++ v4.0 [9]: 12.5.6 Use an atomic, non-throwing swap operation to
implement the copy and move assignment operators
Loading

0 comments on commit 99f19d7

Please sign in to comment.