cppcoreguidelines Narrowing Conversions Check: detect narrowing conversions involving typedefs

The check 'cppcoreguidelines-narrowing-conversions' does not detect conversions
involving typedef. This notably includes the standard fixed-width integer types
like int32_t, uint64_t, etc. Now look through the typedefs at the desugared type.
This commit is contained in:
Eric Seidel 2020-12-08 13:09:12 -05:00 committed by Aaron Ballman
parent d7e71b5db8
commit c6348e8c95
2 changed files with 29 additions and 12 deletions

View File

@ -48,8 +48,10 @@ void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
traverse(
ast_type_traits::TK_AsIs,
implicitCastExpr(hasImplicitDestinationType(builtinType()),
hasSourceExpression(hasType(builtinType())),
implicitCastExpr(hasImplicitDestinationType(
hasUnqualifiedDesugaredType(builtinType())),
hasSourceExpression(hasType(
hasUnqualifiedDesugaredType(builtinType()))),
unless(hasSourceExpression(IsCeilFloorCallExpr)),
unless(hasParent(castExpr())),
unless(isInTemplateInstantiation()))
@ -58,16 +60,18 @@ void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) {
// Binary operators:
// i += 0.5;
Finder->addMatcher(binaryOperator(isAssignmentOperator(),
hasLHS(expr(hasType(builtinType()))),
hasRHS(expr(hasType(builtinType()))),
unless(hasRHS(IsCeilFloorCallExpr)),
unless(isInTemplateInstantiation()),
// The `=` case generates an implicit cast
// which is covered by the previous matcher.
unless(hasOperatorName("=")))
.bind("binary_op"),
this);
Finder->addMatcher(
binaryOperator(
isAssignmentOperator(),
hasLHS(expr(hasType(hasUnqualifiedDesugaredType(builtinType())))),
hasRHS(expr(hasType(hasUnqualifiedDesugaredType(builtinType())))),
unless(hasRHS(IsCeilFloorCallExpr)),
unless(isInTemplateInstantiation()),
// The `=` case generates an implicit cast
// which is covered by the previous matcher.
unless(hasOperatorName("=")))
.bind("binary_op"),
this);
}
static const BuiltinType *getBuiltinType(const Expr &E) {

View File

@ -343,4 +343,17 @@ void macro_context() {
DERP(i, .5l);
}
// We understand typedefs.
void typedef_context() {
typedef long long myint64_t;
int i;
myint64_t i64;
i64 = i64; // Okay, no conversion.
i64 = i; // Okay, no narrowing.
i = i64;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: narrowing conversion from 'myint64_t' (aka 'long long') to signed type 'int' is implementation-defined [cppcoreguidelines-narrowing-conversions]
}
} // namespace floats