-
Notifications
You must be signed in to change notification settings - Fork 77
Initial implementation of rule 4-1-1, must be standard C++17 #1106
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,4 +8,216 @@ abstract class CompilerExtension extends Locatable { } | |
| /** | ||
| * Common base class for modeling compiler extensions in CPP. | ||
| */ | ||
| abstract class CPPCompilerExtension extends CompilerExtension { } | ||
| abstract class CPPCompilerExtension extends CompilerExtension { | ||
| abstract string getMessage(); | ||
| } | ||
|
|
||
| /** | ||
| * An `Attribute` that may be a `GnuAttribute` or `Declspec`, or `MicrosoftAttribute`, etc. | ||
| * | ||
| * There are language extensions such as GNU `__attribute__`, Microsoft `__declspec` or | ||
| * `[attribute]` syntax. | ||
| */ | ||
| class CPPAttributeExtension extends CPPCompilerExtension, Attribute { | ||
| CPPAttributeExtension() { not this instanceof StdAttribute and not this instanceof AlignAs } | ||
|
|
||
| override string getMessage() { | ||
| result = | ||
| "Use of attribute '" + getName() + | ||
| "' is a compiler extension and is not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * An `Attribute` within a compiler specific namespace such as `[[gnu::weak]]`. | ||
| */ | ||
| class CppNamespacedStdAttributeExtension extends CPPCompilerExtension, StdAttribute { | ||
| CppNamespacedStdAttributeExtension() { exists(this.getNamespace()) and not getNamespace() = "" } | ||
|
|
||
| override string getMessage() { | ||
| result = | ||
| "Use of attribute '" + getName() + "' in namespace '" + getNamespace() + | ||
| "' is a compiler extension and is not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| class CppUnrecognizedAttributeExtension extends CPPCompilerExtension, StdAttribute { | ||
| CppUnrecognizedAttributeExtension() { | ||
| not this instanceof CppNamespacedStdAttributeExtension and | ||
| not getName() in [ | ||
| "maybe_unused", "nodiscard", "noreturn", "deprecated", "carries_dependency", "fallthrough" | ||
| ] | ||
| } | ||
|
Comment on lines
+44
to
+50
|
||
|
|
||
| override string getMessage() { | ||
| result = "Use of unrecognized or non-C++17 attribute '" + getName() + "'." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Compiler-specific builtin functions. | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html | ||
| */ | ||
| class CPPBuiltinFunctionExtension extends CPPCompilerExtension, FunctionCall { | ||
| CPPBuiltinFunctionExtension() { | ||
| getTarget().getName().indexOf("__builtin_") = 0 or | ||
| getTarget().getName().indexOf("__sync_") = 0 or | ||
| getTarget().getName().indexOf("__atomic_") = 0 | ||
| } | ||
|
|
||
| override string getMessage() { | ||
| result = | ||
| "Call to builtin function '" + getTarget().getName() + | ||
| "' is a compiler extension and is not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Statement expressions: ({ ... }) syntax. | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html | ||
| */ | ||
| class CPPStmtExprExtension extends CPPCompilerExtension, StmtExpr { | ||
| override string getMessage() { | ||
| result = | ||
| "Statement expressions are a compiler extension and are not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Ternary expressions with omitted middle operand: x ?: y | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/Conditionals.html | ||
| */ | ||
| class CPPTerseTernaryExtension extends CPPCompilerExtension, ConditionalExpr { | ||
| CPPTerseTernaryExtension() { getCondition() = getElse() or getCondition() = getThen() } | ||
|
|
||
| override string getMessage() { | ||
| result = | ||
| "Ternaries with omitted middle operands are a compiler extension and are not portable to other compilers." | ||
| } | ||
|
Comment on lines
+93
to
+96
|
||
| } | ||
|
|
||
| /** | ||
| * Extended integer types: __int128, etc. | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/__int128.html | ||
| */ | ||
| class CPPExtendedIntegerTypeExtension extends CPPCompilerExtension, DeclarationEntry { | ||
| CPPExtendedIntegerTypeExtension() { getType() instanceof Int128Type } | ||
|
|
||
| override string getMessage() { | ||
| result = "128-bit integers are a compiler extension and are not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Extended floating-point types: __float128, _Decimal32, etc. | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html | ||
| */ | ||
| class CPPExtendedFloatTypeExtension extends CPPCompilerExtension, DeclarationEntry { | ||
| CPPExtendedFloatTypeExtension() { | ||
| getType() instanceof Decimal128Type or | ||
| getType() instanceof Decimal32Type or | ||
| getType() instanceof Decimal64Type or | ||
| getType() instanceof Float128Type | ||
| } | ||
|
|
||
| override string getMessage() { | ||
| result = | ||
| "Extended floating-point types are a compiler extension and are not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Zero-length arrays (flexible array members must be last). | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html | ||
| */ | ||
| class CPPZeroLengthArraysExtension extends CPPCompilerExtension, DeclarationEntry { | ||
| CPPZeroLengthArraysExtension() { getType().(ArrayType).getArraySize() = 0 } | ||
|
|
||
| override string getMessage() { | ||
| result = "Zero length arrays are a compiler extension and are not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Variable-length arrays in struct members (not C++17 compliant). | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html | ||
| */ | ||
| class CPPVariableLengthArraysExtension extends CPPCompilerExtension, Field { | ||
| CPPVariableLengthArraysExtension() { | ||
| getType() instanceof ArrayType and | ||
| not getType().(ArrayType).hasArraySize() and | ||
| // Not the final member of the struct, which is allowed in some contexts | ||
| not exists(int lastIndex, Class declaringStruct | | ||
| declaringStruct = getDeclaringType() and | ||
| lastIndex = count(declaringStruct.getACanonicalMember()) - 1 and | ||
| this = declaringStruct.getCanonicalMember(lastIndex) | ||
| ) | ||
| } | ||
|
|
||
| override string getMessage() { | ||
| result = | ||
| "Variable length arrays are a compiler extension and are not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * __alignof__ operator (use alignof from C++11 instead). | ||
| */ | ||
| class CPPAlignofExtension extends CPPCompilerExtension, AlignofExprOperator { | ||
| CPPAlignofExtension() { exists(getValueText().indexOf("__alignof__")) } | ||
|
|
||
| override string getMessage() { | ||
| result = "'__alignof__' is a compiler extension and is not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Preprocessor extensions for feature detection. | ||
| * Reference: https://clang.llvm.org/docs/LanguageExtensions.html | ||
| */ | ||
| class CPPConditionalDefineExtension extends CPPCompilerExtension, PreprocessorIfdef { | ||
| string feature; | ||
|
|
||
| CPPConditionalDefineExtension() { | ||
| feature = | ||
| [ | ||
| "__has_builtin", "__has_constexpr_builtin", "__has_feature", "__has_extension", | ||
| "__has_attribute", "__has_declspec_attribute", "__is_identifier", "__has_include", | ||
| "__has_include_next", "__has_warning", "__has_cpp_attribute" | ||
| ] and | ||
| exists(toString().indexOf(feature)) | ||
| } | ||
|
|
||
| override string getMessage() { | ||
| result = | ||
| "Call to builtin preprocessor feature '" + feature + | ||
| "' is a compiler extension and is not portable to other compilers." | ||
| } | ||
| } | ||
|
|
||
| class CPPPreprocessorDirectiveExtension extends CPPCompilerExtension, PreprocessorDirective { | ||
| string kind; | ||
|
|
||
| CPPPreprocessorDirectiveExtension() { | ||
| this instanceof PreprocessorPragma and kind = "#pragma " + getHead() | ||
| or | ||
| this instanceof PreprocessorError and kind = "#error" | ||
| or | ||
| this instanceof PreprocessorWarning and kind = "#warning" | ||
| } | ||
|
|
||
| override string getMessage() { | ||
| result = "Use of non-standard preprocessor directive '" + kind + "' is a compiler extension." | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Built-in type traits and operations such as `__is_abstract`, `__is_same`, etc. | ||
| * | ||
| * Reference: https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html | ||
| */ | ||
| class CPPBuiltinOperationExtension extends CPPCompilerExtension, BuiltInOperation { | ||
| override string getMessage() { | ||
| result = "Use of built-in operation '" + toString() + "' is a compiler extension." | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| //** THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY. **/ | ||
| import cpp | ||
| import RuleMetadata | ||
| import codingstandards.cpp.exclusions.RuleMetadata | ||
|
|
||
| newtype Toolchain2Query = TCompilerLanguageExtensionsUsedQuery() | ||
|
|
||
| predicate isToolchain2QueryMetadata(Query query, string queryId, string ruleId, string category) { | ||
| query = | ||
| // `Query` instance for the `compilerLanguageExtensionsUsed` query | ||
| Toolchain2Package::compilerLanguageExtensionsUsedQuery() and | ||
| queryId = | ||
| // `@id` for the `compilerLanguageExtensionsUsed` query | ||
| "cpp/misra/compiler-language-extensions-used" and | ||
| ruleId = "RULE-4-1-1" and | ||
| category = "required" | ||
| } | ||
|
|
||
| module Toolchain2Package { | ||
| Query compilerLanguageExtensionsUsedQuery() { | ||
| //autogenerate `Query` type | ||
| result = | ||
| // `Query` type for `compilerLanguageExtensionsUsed` query | ||
| TQueryCPP(TToolchain2PackageQuery(TCompilerLanguageExtensionsUsedQuery())) | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -62,6 +62,20 @@ template <typename T, unsigned int N> struct remove_extent<T[N]> { | |||||||||||||||||||||||||||||||||||||
| typedef T type; | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| template <typename T> struct is_abstract { | ||||||||||||||||||||||||||||||||||||||
| const static bool value = false; | ||||||||||||||||||||||||||||||||||||||
| constexpr operator bool() { return value; } | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| template <typename T> bool is_abstract_v = is_abstract<T>::value; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| template <typename T, typename U> struct is_same { | ||||||||||||||||||||||||||||||||||||||
| const static bool value = false; | ||||||||||||||||||||||||||||||||||||||
| constexpr operator bool() { return value; } | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| template <typename T, typename U> bool is_same_v = is_same<T, U>::value; | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+70
to
+77
|
||||||||||||||||||||||||||||||||||||||
| template <typename T> bool is_abstract_v = is_abstract<T>::value; | |
| template <typename T, typename U> struct is_same { | |
| const static bool value = false; | |
| constexpr operator bool() { return value; } | |
| }; | |
| template <typename T, typename U> bool is_same_v = is_same<T, U>::value; | |
| template <typename T> | |
| inline constexpr bool is_abstract_v = is_abstract<T>::value; | |
| template <typename T, typename U> struct is_same { | |
| const static bool value = false; | |
| constexpr operator bool() { return value; } | |
| }; | |
| template <typename T, typename U> | |
| inline constexpr bool is_same_v = is_same<T, U>::value; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,25 @@ | ||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||
| * @id cpp/misra/compiler-language-extensions-used | ||||||||||||||||||||||||||||||||||||
| * @name RULE-4-1-1: A program shall conform to ISO/IEC 14882:2017 (C++17) | ||||||||||||||||||||||||||||||||||||
| * @description Language extensions are compiler-specific features that are not part of the C++17 | ||||||||||||||||||||||||||||||||||||
| * standard. Using these extensions reduces portability and may lead to unpredictable | ||||||||||||||||||||||||||||||||||||
| * behavior when code is compiled with different compilers or compiler versions. | ||||||||||||||||||||||||||||||||||||
| * @kind problem | ||||||||||||||||||||||||||||||||||||
| * @precision high | ||||||||||||||||||||||||||||||||||||
| * @problem.severity error | ||||||||||||||||||||||||||||||||||||
| * @tags external/misra/id/rule-4-1-1 | ||||||||||||||||||||||||||||||||||||
| * scope/system | ||||||||||||||||||||||||||||||||||||
| * maintainability | ||||||||||||||||||||||||||||||||||||
| * portability | ||||||||||||||||||||||||||||||||||||
| * external/misra/enforcement/undecidable | ||||||||||||||||||||||||||||||||||||
| * external/misra/obligation/required | ||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| import cpp | ||||||||||||||||||||||||||||||||||||
| import codingstandards.cpp.misra | ||||||||||||||||||||||||||||||||||||
| import codingstandards.cpp.Extensions | ||||||||||||||||||||||||||||||||||||
| import codingstandards.cpp.AlertReporting | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| from CPPCompilerExtension e | ||||||||||||||||||||||||||||||||||||
| where not isExcluded(e, Toolchain2Package::compilerLanguageExtensionsUsedQuery()) | ||||||||||||||||||||||||||||||||||||
| select MacroUnwrapper<CPPCompilerExtension>::unwrapElement(e), e.getMessage() | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+25
|
||||||||||||||||||||||||||||||||||||
| from CPPCompilerExtension e | |
| where not isExcluded(e, Toolchain2Package::compilerLanguageExtensionsUsedQuery()) | |
| select MacroUnwrapper<CPPCompilerExtension>::unwrapElement(e), e.getMessage() | |
| from CPPCompilerExtension e, Element report | |
| where | |
| not isExcluded(e, Toolchain2Package::compilerLanguageExtensionsUsedQuery()) and | |
| ( | |
| report = MacroUnwrapper<CPPCompilerExtension>::unwrapElement(e) and | |
| not isExcluded(report, Toolchain2Package::compilerLanguageExtensionsUsedQuery()) | |
| or | |
| report = e and | |
| isExcluded( | |
| MacroUnwrapper<CPPCompilerExtension>::unwrapElement(e), | |
| Toolchain2Package::compilerLanguageExtensionsUsedQuery() | |
| ) | |
| ) | |
| select report, e.getMessage() |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,25 @@ | ||||
| | file:///Users/michaelrfairhurst/projects/codeql-coding-standards/cpp/common/test/includes/standard-library/stdarg.h:5:1:5:47 | #define va_start(v,l) __builtin_va_start(v, l) | Use of built-in operation '__builtin_va_start' is a compiler extension. | | ||||
|
||||
| | file:///Users/michaelrfairhurst/projects/codeql-coding-standards/cpp/common/test/includes/standard-library/stdarg.h:5:1:5:47 | #define va_start(v,l) __builtin_va_start(v, l) | Use of built-in operation '__builtin_va_start' is a compiler extension. | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| rules/RULE-4-1-1/CompilerLanguageExtensionsUsed.ql |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CppNamespacedStdAttributeExtension/CppUnrecognizedAttributeExtensionuse a differentCpp...prefix than the rest of the newly introducedCPP...extension classes in this module. Align the naming (for example, consistently useCPP...) so the API is easier to discover and search.