diff --git a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql index 3b6e436c56..e6852d7d39 100644 --- a/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql +++ b/cpp/autosar/src/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.ql @@ -16,23 +16,237 @@ import cpp import codingstandards.cpp.autosar -from Variable v, Expr aexp +newtype TTemplateElement = + TTemplateClass(TemplateClass c) or + TTemplateFunction(TemplateFunction f) or + TTemplateVariable(TemplateVariable v) + +/** + * A templated element. These are either templated classes, templated functions, + * or templated variables. + */ +class TemplateElement extends TTemplateElement { + TemplateClass asTemplateClass() { this = TTemplateClass(result) } + + TemplateFunction asTemplateFunction() { this = TTemplateFunction(result) } + + TemplateVariable asTemplateVariable() { this = TTemplateVariable(result) } + + string toString() { + result = this.asTemplateClass().toString() or + result = this.asTemplateFunction().toString() or + result = this.asTemplateVariable().toString() + } + + Location getLocation() { + result = this.asTemplateClass().getLocation() or + result = this.asTemplateFunction().getLocation() or + result = this.asTemplateVariable().getLocation() + } + + string getName() { + result = this.asTemplateClass().getName() or + result = this.asTemplateFunction().getName() or + result = this.asTemplateVariable().getName() + } +} + +newtype TTemplateInstantiation = + TClassTemplateInstantiation(ClassTemplateInstantiation c) or + TFunctionTemplateInstantiation(FunctionTemplateInstantiation f) or + TVariableTemplateInstantiation(VariableTemplateInstantiation v) + +/** + * An instantiation of a templated element, either a templated class, templated + * function, or templated variable. + */ +class TemplateInstantiation extends TTemplateInstantiation { + ClassTemplateInstantiation asClassTemplateInstantiation() { + this = TClassTemplateInstantiation(result) + } + + FunctionTemplateInstantiation asFunctionTemplateInstantiation() { + this = TFunctionTemplateInstantiation(result) + } + + VariableTemplateInstantiation asVariableTemplateInstantiation() { + this = TVariableTemplateInstantiation(result) + } + + string toString() { + result = this.asClassTemplateInstantiation().toString() or + result = this.asFunctionTemplateInstantiation().toString() or + result = this.asVariableTemplateInstantiation().toString() + } + + Location getLocation() { + result = this.asClassTemplateInstantiation().getLocation() or + result = this.asFunctionTemplateInstantiation().getLocation() or + result = this.asVariableTemplateInstantiation().getLocation() + } + + Element asElement() { + result = this.asClassTemplateInstantiation() or + result = this.asFunctionTemplateInstantiation() or + result = this.asVariableTemplateInstantiation() + } + + /** + * Gets the template this instantiation is from, depending on the kind of the element + * this instantiation is for. + */ + TemplateElement getTemplate() { + result.asTemplateClass() = this.asClassTemplateInstantiation().getTemplate() or + result.asTemplateFunction() = this.asFunctionTemplateInstantiation().getTemplate() or + result.asTemplateVariable() = this.asVariableTemplateInstantiation().getTemplate() + } + + /** + * Gets a use of an instantiation of this template. i.e. + * 1. For a class template, it's where the instantiated type is used by the name. + * 2. For a function template, it's where the instantiated function is called. + * 3. For a variable template, it's where the instantiated variable is initialized. + */ + Element getAUse() { + result = this.asClassTemplateInstantiation().getATypeNameUse() or + result = this.asFunctionTemplateInstantiation().getACallToThisFunction() or + result = this.asVariableTemplateInstantiation() + } +} + +/** + * An implicit conversion from a plain char type to an explicitly signed or unsigned char + * type. `std::uint8_t` and `std::int8_t` are also considered as these char types. + * + * Note that this class only includes implicit conversions and does not include explicit + * type conversions, i.e. casts. + */ +class ImplicitConversionFromPlainCharType extends Conversion { + ImplicitConversionFromPlainCharType() { + this.isImplicit() and + this.getExpr().getUnspecifiedType() instanceof PlainCharType and + ( + this.getUnspecifiedType() instanceof SignedCharType or + this.getUnspecifiedType() instanceof UnsignedCharType + ) + } +} + +newtype TImplicitConversionElement = + TImplicitConversionOutsideTemplate(ImplicitConversionFromPlainCharType implicitConversion) { + not exists(TemplateInstantiation instantiation | + implicitConversion.isFromTemplateInstantiation(instantiation.asElement()) + ) + } or + TInstantiationOfImplicitConversionTemplate( + TemplateInstantiation templateInstantiation, + ImplicitConversionFromPlainCharType implicitConversion + ) { + implicitConversion.getEnclosingElement+() = templateInstantiation.asElement() + } + +/** + * The locations where the implicit conversion from a plain char to an explicitly signed / unsigned + * char is taking place on a high level. It splits case on whether the conversion is caused by + * instantiating a template: + * + * - For conversions not due to template usage (i.e. outside a templated element), this refers to + * the same element as the one associated with the conversion. + * - For conversions due to template usage, this refers to the element that uses the instantiation + * of a template where an implicit char conversion happens. + */ +class ImplicitConversionLocation extends TImplicitConversionElement { + ImplicitConversionFromPlainCharType asImplicitConversionOutsideTemplate() { + this = TImplicitConversionOutsideTemplate(result) + } + + TemplateInstantiation asInstantiationOfImplicitConversionTemplate( + ImplicitConversionFromPlainCharType implicitConversion + ) { + this = TInstantiationOfImplicitConversionTemplate(result, implicitConversion) + } + + /** + * Holds if this is a location of a conversion happening outside of a template. + */ + predicate isImplicitConversionOutsideTemplate() { + exists(this.asImplicitConversionOutsideTemplate()) + } + + /** + * Holds if this is a location of a conversion happening due to instantiating a + * template. + */ + predicate isInstantiationOfImplicitConversionTemplate() { + exists( + TemplateInstantiation templateInstantiation, + ImplicitConversionFromPlainCharType implicitConversion + | + templateInstantiation = this.asInstantiationOfImplicitConversionTemplate(implicitConversion) + ) + } + + /** + * Gets the implicit conversion that this location is associated with. + * - In cases of conversions not involving a template, this is the same as the + * location associated with the conversion. + * - In cases of conversions due to using a template, this is the conversion that + * happens in the instantiated template. + */ + ImplicitConversionFromPlainCharType getImplicitConversion() { + result = this.asImplicitConversionOutsideTemplate() or + exists(TemplateInstantiation templateInstantiation | + this = TInstantiationOfImplicitConversionTemplate(templateInstantiation, result) + ) + } + + string toString() { + result = this.asImplicitConversionOutsideTemplate().toString() or + exists(ImplicitConversionFromPlainCharType implicitConversion | + result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).toString() + ) + } + + Location getLocation() { + result = this.asImplicitConversionOutsideTemplate().getLocation() or + exists(ImplicitConversionFromPlainCharType implicitConversion | + result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getLocation() + ) + } + + Element asElement() { + result = this.asImplicitConversionOutsideTemplate() or + exists(ImplicitConversionFromPlainCharType implicitConversion | + result = this.asInstantiationOfImplicitConversionTemplate(implicitConversion).getAUse() + ) + } +} + +string getMessageTemplate(ImplicitConversionLocation implicitConversionLocation) { + exists(ImplicitConversionFromPlainCharType implicitConversion | + implicitConversion = implicitConversionLocation.getImplicitConversion() + | + implicitConversionLocation.isImplicitConversionOutsideTemplate() and + result = + "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + "'." + or + implicitConversionLocation.isInstantiationOfImplicitConversionTemplate() and + result = + "Implicit conversion of plain char $@ to '" + implicitConversion.getType().getName() + + "' from instantiating template '" + + implicitConversionLocation + .asInstantiationOfImplicitConversionTemplate(implicitConversion) + .getTemplate() + .getName() + "'." + ) +} + +from + ImplicitConversionLocation implicitConversionLocation, + ImplicitConversionFromPlainCharType implicitConversion where - not isExcluded(v, + not isExcluded(implicitConversionLocation.asElement(), StringsPackage::signedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValuesQuery()) and - // We find cases where it is an explicitly signed char type with an assignment - // to a non-numeric type. NOTE: This rule addresses cases where the char type - // is used character data only, the rule does not explicitly cover this. - // Please see M5-0-11 for explicit handling of this case. Get types that are - // char, except for ones that are 'plain', meaning the sign is explicit. - ( - v.getUnspecifiedType() instanceof SignedCharType or - v.getUnspecifiedType() instanceof UnsignedCharType - ) and - // Identify places where these explicitly signed types are being assigned to a - // non-numeric type. - aexp = v.getAnAssignedValue() and - aexp.getUnspecifiedType() instanceof CharType -select aexp, - "Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type", - v, v.getName() + implicitConversion = implicitConversionLocation.getImplicitConversion() +select implicitConversionLocation.asElement(), getMessageTemplate(implicitConversionLocation), + implicitConversion.getExpr(), "expression" diff --git a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected index 1be5b7b9fc..ad1f57935e 100644 --- a/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected +++ b/cpp/autosar/test/rules/M5-0-12/SignedCharAndUnsignedCharTypeShallOnlyBeUsedForTheStorageAndUseOfNumericValues.expected @@ -1,4 +1,28 @@ -| test.cpp:4:22:4:24 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:4:17:4:18 | a1 | a1 | -| test.cpp:6:20:6:22 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:6:15:6:16 | a3 | a3 | -| test.cpp:9:20:9:22 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:9:15:9:16 | a5 | a5 | -| test.cpp:12:21:12:23 | 99 | Assignment of an non-integer type to variable $@ which is a variable with an explicitly signed char type | test.cpp:12:16:12:17 | a7 | a7 | +| test.cpp:93:7:93:9 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:93:7:93:9 | 118 | expression | +| test.cpp:94:21:94:23 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:94:21:94:23 | 118 | expression | +| test.cpp:102:7:102:9 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:102:7:102:9 | 118 | expression | +| test.cpp:103:21:103:23 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:103:21:103:23 | 118 | expression | +| test.cpp:121:7:121:8 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:121:7:121:8 | x3 | expression | +| test.cpp:124:20:124:21 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:124:20:124:21 | x4 | expression | +| test.cpp:134:21:134:22 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:134:21:134:22 | x7 | expression | +| test.cpp:137:20:137:21 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:137:20:137:21 | x8 | expression | +| test.cpp:147:17:147:18 | definition of c3 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'C1'. | test.cpp:5:12:5:12 | 120 | expression | +| test.cpp:150:17:150:18 | definition of c4 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'C2'. | test.cpp:13:12:13:12 | 120 | expression | +| test.cpp:160:15:160:16 | definition of c7 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'C5'. | test.cpp:22:12:22:12 | 1 | expression | +| test.cpp:163:15:163:16 | definition of c8 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'C6'. | test.cpp:30:12:30:12 | 1 | expression | +| test.cpp:180:7:180:10 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:180:7:180:10 | * ... | expression | +| test.cpp:185:7:185:10 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:185:7:185:10 | * ... | expression | +| test.cpp:200:7:200:10 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:200:7:200:10 | * ... | expression | +| test.cpp:205:7:205:10 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:205:7:205:10 | * ... | expression | +| test.cpp:219:6:219:7 | (unsigned char)... | Implicit conversion of plain char $@ to 'unsigned char'. | test.cpp:219:6:219:7 | a3 | expression | +| test.cpp:222:6:222:7 | (signed char)... | Implicit conversion of plain char $@ to 'signed char'. | test.cpp:222:6:222:7 | a4 | expression | +| test.cpp:232:6:232:7 | (uint8_t)... | Implicit conversion of plain char $@ to 'uint8_t'. | test.cpp:232:6:232:7 | a7 | expression | +| test.cpp:235:7:235:8 | (int8_t)... | Implicit conversion of plain char $@ to 'int8_t'. | test.cpp:235:7:235:8 | a8 | expression | +| test.cpp:249:3:249:4 | call to f5 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'f5'. | test.cpp:43:56:43:56 | x | expression | +| test.cpp:253:3:253:4 | call to f6 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'f6'. | test.cpp:44:54:44:54 | x | expression | +| test.cpp:266:3:266:5 | call to f13 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'f13'. | test.cpp:47:56:47:56 | x | expression | +| test.cpp:270:3:270:5 | call to f14 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'f14'. | test.cpp:48:55:48:55 | x | expression | +| test.cpp:287:12:287:14 | definition of c11 | Implicit conversion of plain char $@ to 'unsigned char' from instantiating template 'C9'. | test.cpp:52:15:52:15 | y | expression | +| test.cpp:292:13:292:15 | definition of c12 | Implicit conversion of plain char $@ to 'signed char' from instantiating template 'C10'. | test.cpp:60:16:60:16 | y | expression | +| test.cpp:307:13:307:15 | definition of c15 | Implicit conversion of plain char $@ to 'uint8_t' from instantiating template 'C13'. | test.cpp:69:16:69:16 | y | expression | +| test.cpp:311:13:311:15 | definition of c16 | Implicit conversion of plain char $@ to 'int8_t' from instantiating template 'C14'. | test.cpp:77:16:77:16 | y | expression | diff --git a/cpp/autosar/test/rules/M5-0-12/test.cpp b/cpp/autosar/test/rules/M5-0-12/test.cpp index 453c37bf1e..3e9a21ae17 100644 --- a/cpp/autosar/test/rules/M5-0-12/test.cpp +++ b/cpp/autosar/test/rules/M5-0-12/test.cpp @@ -1,16 +1,313 @@ #include -void f1() { - unsigned char a1 = 'c'; // NON_COMPLIANT - unsigned char a2 = 10; - signed char a3 = 'c'; // NON_COMPLIANT - signed char a4 = 10; +template class C1 { +public: + C1() : x(y) {} - std::int8_t a5 = 'c'; // NON_COMPLIANT - std::int8_t a6 = 10; +private: + unsigned char x; +}; - std::uint8_t a7 = 'c'; // NON_COMPLIANT - std::uint8_t a8 = 10; +template class C2 { +public: + C2() : x(y) {} - char a9 = 'c'; -} \ No newline at end of file +private: + signed char x; +}; + +/* Twin templates for std::uint8_t and std::int8_t */ +template class C5 { +public: + C5() : x(y) {} + +private: + std::uint8_t x; +}; + +template class C6 { +public: + C6() : x(y) {} + +private: + std::int8_t x; +}; + +void f1(unsigned char x) {} +void f2(signed char x) {} + +/* Twin functions for std::uint8_t and std::int8_t */ +void f9(std::uint8_t x) {} +void f10(std::int8_t x) {} + +template void f5(T x) { unsigned char y = x; } +template void f6(T x) { signed char y = x; } + +/* Twin template functions for std::uint8_t and std::int8_t */ +template void f13(T x) { std::uint8_t y = x; } +template void f14(T x) { std::int8_t y = x; } + +template class C9 { +public: + C9(T y) : x(y) {} + +private: + unsigned char x; +}; + +template class C10 { +public: + C10(T y) : x(y) {} + +private: + signed char x; +}; + +/* Twin template classes for std::uint8_t and std::int8_t */ +template class C13 { +public: + C13(T y) : x(y) {} + +private: + std::uint8_t x; +}; + +template class C14 { +public: + C14(T y) : x(y) {} + +private: + std::int8_t x; +}; + +template T v1; +template T v2; + +void instantiateTemplateVariables() { + v1 = + 1; // COMPLIANT: unsigned char assigned to an unsigned char + v2 = 1; // COMPLIANT: signed char assigned to a signed char + v2 = 'v'; // COMPLIANT: plain char assigned to a plain char + + v1 = + 'v'; // NON-COMPLIANT: plain char assigned to an unsigned char + v2 = 'v'; // NON-COMPLIANT: plain char assigned to a signed char + + /* Twin cases with std::uint8_t and std::int8_t */ + v1 = 1; // COMPLIANT: std::uint8_t assigned to a std::uint8_t + v2 = 1; // COMPLIANT: std::int8_t assigned to a std::int8_t + v2 = 'v'; // COMPLIANT: plain char assigned to a plain char + + v1 = + 'v'; // NON-COMPLIANT: plain char assigned to a std::uint8_t + v2 = 'v'; // NON-COMPLIANT: plain char assigned to a std::int8_t +} + +int main() { + + /* ========== 1. Assigning a char to another char ========== */ + + /* ===== 1-1. Assigning a char to a char variable ===== */ + + unsigned char x1 = 1; + unsigned char y1 = + x1; // COMPLIANT: unsigned char assigned to an unsigned char + + signed char x2 = 1; + signed char y2 = x2; // COMPLIANT: signed char assigned to a signed char + + char x3 = 'x'; + unsigned char y3 = + x3; // NON-COMPLIANT: plain char assigned to a unsigned char + + char x4 = 'x'; + signed char y4 = x4; // NON-COMPLIANT: plain char assigned to a signed char + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t x5 = 1; + std::uint8_t y5 = x5; // COMPLIANT: std::uint8_t assigned to a std::uint8_t + + std::int8_t x6 = 1; + std::int8_t y6 = x6; // COMPLIANT: std::int8_t assigned to a std::int8_t + + char x7 = 'x'; + std::uint8_t y7 = x7; // NON-COMPLIANT: plain char assigned to a std::uint8_t + + char x8 = 'x'; + std::int8_t y8 = x8; // NON-COMPLIANT: plain char assigned to a std::int8_t + + /* ===== 1-2. Assigning a char to a char member ===== */ + + C1 c1; // COMPLIANT: unsigned char arg passed to an unsigned + // char member through a template + + C2 c2; // COMPLIANT: signed char arg passed to a signed char + // member through a template + + C1 c3; // NON-COMPLIANT: plain char arg passed to an unsigned char + // member through a template + + C2 c4; // NON-COMPLIANT: plain char arg passed to a signed char + // member through a template + + /* Twin cases with std::uint8_t and std::int8_t */ + C5 c5; // COMPLIANT: std::uint8_t arg passed to a + // std::uint8_t member through a template + + C6 c6; // COMPLIANT: std::int8_t arg passed to a std::int8_t + // member through a template + + C5 c7; // NON-COMPLIANT: plain char arg passed to a + // std::uint8_t member through a template + + C6 c8; // NON-COMPLIANT: plain char arg passed to a std::int8_t + // member through a template + + /* ========== 1-3. Assigning a char to a char through a pointer ========== */ + + unsigned char x9 = 1; + unsigned char *y9 = &x9; + unsigned char z1 = + *y9; // COMPLIANT: unsigned char assigned to an *&unsigned char + + signed char x10 = 1; + signed char *y10 = &x10; + signed char z2 = *y10; // COMPLIANT: signed char assigned to an *&signed char + + char x11 = 1; + char *y11 = &x11; + unsigned char z3 = + *y11; // NON-COMPLIANT: plain char assigned to an *&unsigned char + + char x12 = 1; + char *y12 = &x12; + signed char z4 = + *y12; // NON-COMPLIANT: plain char assigned to an *&signed char + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t x13 = 1; + std::uint8_t *y13 = &x13; + std::uint8_t z5 = + *y13; // COMPLIANT: std::uint8_t assigned to a *&std::uint8_t + + std::int8_t x14 = 1; + std::int8_t *y14 = &x14; + std::int8_t z6 = *y14; // COMPLIANT: std::int8_t assigned to an *&std::int8_t + + char x15 = 1; + char *y15 = &x15; + std::uint8_t z7 = + *y15; // NON-COMPLIANT: plain char assigned to an *&std::uint8_t + + char x16 = 1; + char *y16 = &x16; + std::int8_t z8 = + *y16; // NON-COMPLIANT: plain char assigned to an *&std::int8_t + + /* ========== 2. Passing a char argument to a char parameter ========== */ + + /* ===== 2-1. Passing char argument to a char parameter of a regular function + * ===== */ + + unsigned char a1 = 1; + f1(a1); // COMPLIANT: unsigned char arg passed to an unsigned char parameter + + signed char a2 = 1; + f2(a2); // COMPLIANT: signed char arg passed to a signed char parameter + + char a3 = 'a'; + f1(a3); // NON-COMPLIANT: plain char arg passed to an unsigned char parameter + + char a4 = 'a'; + f2(a4); // NON-COMPLIANT: plain char arg passed to a signed char parameter + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t a5 = 1; + f9(a5); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter + + std::int8_t a6 = 1; + f10(a6); // COMPLIANT: std::int8_t arg passed to a std::int8_t parameter + + char a7 = 'a'; + f9(a7); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter + + char a8 = 'a'; + f10(a8); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter + + /* ===== 2-2. Passing char argument to a char parameter through a template + * ===== */ + + unsigned char a9 = 1; + f5(a9); // COMPLIANT: unsigned char arg passed to an unsigned char parameter + // through a template + + signed char a10 = 1; + f6(a10); // COMPLIANT: signed char arg passed to a signed char parameter + // through a template + + char a11 = 'a'; + f5(a11); // NON-COMPLIANT: plain char arg passed to an unsigned char parameter + // through a template + + char a12 = 'a'; + f6(a12); // NON-COMPLIANT: plain char arg passed to a signed char parameter + // through a template + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t a13 = 1; + f13(a13); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter + // through a template + + std::int8_t a14 = 1; + f14(a14); // COMPLIANT: std::int8_t arg passed to a std::int8_t parameter + // through a template + + char a15 = 'a'; + f13(a15); // NON-COMPLIANT: plain char arg passed to a std::uint8_t parameter + // through a template + + char a16 = 'a'; + f14(a16); // NON-COMPLIANT: plain char arg passed to a std::int8_t parameter + // through a template + + /* ========== 2-3. Passing a char argument to a char parameter through a + * template ========== */ + + unsigned char a17 = 1; + C9 c9( + a17); // COMPLIANT: unsigned char arg passed to an unsigned char parameter + // of a constructor through a template + + signed char a18 = 1; + C10 c10( + a18); // COMPLIANT: signed char arg passed to an signed + // char parameter of a constructor through a template + + char a19 = 'a'; + C9 c11( + a19); // NON-COMPLIANT: plain char arg passed to an unsigned signed char + // parameter of a constructor through a template + + char a20 = 'a'; + C10 c12(a20); // NON-COMPLIANT: plain char arg passed to an signed char + // parameter of a constructor through a template + + /* Twin cases with std::uint8_t and std::int8_t */ + std::uint8_t a21 = 1; + C13 c13( + a21); // COMPLIANT: std::uint8_t arg passed to a std::uint8_t parameter + // of a constructor through a template + + std::int8_t a22 = 1; + C14 c14( + a22); // COMPLIANT: std::int8_t arg passed to a std::int8_t + // parameter of a constructor through a template + + char a23 = 'a'; + C13 c15(a23); // NON-COMPLIANT: plain char arg passed to a std::uint8_t + // parameter of a constructor through a template + + char a24 = 'a'; + C14 c16(a24); // NON-COMPLIANT: plain char arg passed to a std::int8_t + // parameter of a constructor through a template +}