Skip to content

A7-1-3: Remove false positives where the typedef type is referenced in the initializer #748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 17, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions change_notes/2024-10-15-a7-1-3-multi-refs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- `A7-1-3` - `CvQualifiersNotPlacedOnTheRightHandSide.ql`:
- Removed false positives where a correctly CV-qualified typedef variable type was also referenced in the initializer.
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,50 @@ import cpp
import codingstandards.cpp.autosar

/**
* Holds if declaration `e` using a `TypedefType` is CV-qualified
*
* For example, given `using intconstptr = int * const`:
* the predicate holds for `const/volatile intconstptr ptr1`, but not for `intconstptr ptr2`
* Unwrap layers of indirection that occur on the right side of the type.
*/
predicate containsExtraSpecifiers(VariableDeclarationEntry e) {
e.getType().toString().matches("const %") or
e.getType().toString().matches("volatile %")
Type unwrapIndirection(Type type) {
if type instanceof DerivedType and not type instanceof SpecifiedType
then result = unwrapIndirection(type.(DerivedType).getBaseType())
else result = type
}

// DeclStmts that have a TypedefType name use (ie TypeMention) in them
//AND TypeMention.getStartColumn() - DeclStmt.getStartColumn() > len(const)
//AND the declared thing contains one of these "extra" specifiers in the DeclarationEntry Location
from VariableDeclarationEntry e, TypedefType t, TypeMention tm
from
VariableDeclarationEntry e, TypedefType t, TypeMention tm, string message, Element explainer,
string explainerMessage
where
not isExcluded(e, ConstPackage::cvQualifiersNotPlacedOnTheRightHandSideQuery()) and
containsExtraSpecifiers(e) and
// Variable type is specified, and has the typedef type as a base type
unwrapIndirection(e.getType()).(SpecifiedType).getBaseType() = t and
exists(string filepath, int startline |
e.getLocation().hasLocationInfo(filepath, startline, _, _, _) and
tm.getLocation().hasLocationInfo(filepath, startline, _, _, _) and
e = t.getATypeNameUse() and
tm.getMentionedType() = t and
// TypeMention occurs before the variable declaration
tm.getLocation().getStartColumn() < e.getLocation().getStartColumn() and
exists(DeclStmt s |
s.getDeclarationEntry(_) = e and
//const could fit in there
// TypeMention occurs after the start of the StmtDecl, with enough space for const/volatile
tm.getLocation().getStartColumn() - s.getLocation().getStartColumn() > 5
//volatile could fit in there
//but the above condition subsumes this one
//l.getStartColumn() - tm.getLocation().getStartColumn() > 8
)
) and
if exists(t.getFile().getRelativePath())
then
message =
"There is possibly a const or volatile specifier on the left hand side of typedef name $@." and
explainer = t and
explainerMessage = t.getName()
else (
// Type occurs outside source root, so don't link
message =
"There is possibly a const or volatile specifier on the left hand side of typedef name " +
t.getName() + "." and
// explainer not used in this case
explainer = e and
explainerMessage = ""
)
select e,
"There is possibly a const or volatile specifier on the left hand side of typedef name $@.", t,
t.getName()
select e, message, explainer, explainerMessage
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
| test.cpp:9:16:9:19 | definition of ptr1 | There is possibly a const or volatile specifier on the left hand side of typedef name $@. | test.cpp:1:7:1:12 | intptr | intptr |
| test.cpp:10:19:10:22 | definition of ptr2 | There is possibly a const or volatile specifier on the left hand side of typedef name $@. | test.cpp:1:7:1:12 | intptr | intptr |
| test.cpp:19:21:19:24 | definition of ptr8 | There is possibly a const or volatile specifier on the left hand side of typedef name $@. | test.cpp:3:7:3:17 | constintptr | constintptr |
| test.cpp:32:23:32:26 | definition of u32d | There is possibly a const or volatile specifier on the left hand side of typedef name uint32_t. | test.cpp:32:23:32:26 | definition of u32d | |
12 changes: 12 additions & 0 deletions cpp/autosar/test/rules/A7-1-3/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,16 @@ void f() {
constintptr const ptr7 = &l; // COMPLIANT
const constintptr ptr8 = &l; // NON_COMPLIANT
inttypedef ptr9 = l; // COMPLIANT
}

#include <cstdint>

void false_positive() {
std::uint8_t u8{0};

auto const u32 = static_cast<std::uint32_t>(u8); // COMPLIANT - auto ignored
std::uint32_t const u32b = static_cast<std::uint32_t>(u8); // COMPLIANT

const auto u32c = static_cast<std::uint32_t>(u8); // COMPLIANT - auto ignored
const std::uint32_t u32d = static_cast<std::uint32_t>(u8); // NON_COMPLIANT
}
Loading