diff --git a/change_notes/2023-10-04-a16-0-1-handle-else.md b/change_notes/2023-10-04-a16-0-1-handle-else.md new file mode 100644 index 0000000000..28aa27edb2 --- /dev/null +++ b/change_notes/2023-10-04-a16-0-1-handle-else.md @@ -0,0 +1 @@ + * `A16-0-1` - address false positives by permitting #else and #elif within an otherwise valid #if preprocessor conditional. \ No newline at end of file diff --git a/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql b/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql index a8e1e59839..bd731db3e9 100644 --- a/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql +++ b/cpp/autosar/src/rules/A16-0-1/PreProcessorShallOnlyBeUsedForCertainDirectivesPatterns.ql @@ -26,13 +26,14 @@ class PermittedDirectiveType extends PreprocessorDirective { //permissive listing in case directive types modelled in ql ever expands (example non valid directives) this instanceof MacroWrapper or this instanceof PreprocessorEndif or + this instanceof PreprocessorElse or this instanceof Include or this instanceof PermittedMacro } } pragma[noinline] -predicate isPreprocFileAndLine(Element pd, string filepath, int startLine) { +predicate isPreprocFileAndLine(Locatable pd, string filepath, int startLine) { pd.getLocation().hasLocationInfo(filepath, startLine, _, _, _) } @@ -49,7 +50,7 @@ predicate isPreprocConditionalRange( /** * An optimised version of `PreprocessorBranchDirective.getAGuard()`. */ -private PreprocessorBranch getAGuard(Element guardedElement) { +private PreprocessorBranch getAGuard(Locatable guardedElement) { exists(string filepath, int ifStartLine, int guardedElementStartLine, int endifStartLine | isPreprocConditionalRange(result, filepath, ifStartLine, endifStartLine) and isPreprocFileAndLine(guardedElement, filepath, guardedElementStartLine) and @@ -72,8 +73,11 @@ class MacroWrapper extends PreprocessorIfndef { class AcceptableWrapper extends PreprocessorBranch { AcceptableWrapper() { - forall(Element inner | not inner instanceof Comment and this = getAGuard(inner) | + forall(Locatable inner | not inner instanceof Comment and this = getAGuard(inner) | inner instanceof PermittedDirectiveType + or + // Ignore elifs, as they will be considered separately + inner instanceof PreprocessorElif ) } } diff --git a/cpp/autosar/test/rules/A16-0-1/test.cpp b/cpp/autosar/test/rules/A16-0-1/test.cpp index b1ee540032..b17d0daf52 100644 --- a/cpp/autosar/test/rules/A16-0-1/test.cpp +++ b/cpp/autosar/test/rules/A16-0-1/test.cpp @@ -17,3 +17,9 @@ int g; #ifndef TESTHEADER // COMPLIANT #include //COMPLIANT #endif // COMPLIANT + +#ifdef MACRO_ENABLED // COMPLIANT +#include "test1.h" //COMPLIANT +#else +#include "test2.h" //COMPLIANT +#endif \ No newline at end of file diff --git a/cpp/autosar/test/rules/A16-0-1/test.h b/cpp/autosar/test/rules/A16-0-1/test.h new file mode 100644 index 0000000000..a37243f616 --- /dev/null +++ b/cpp/autosar/test/rules/A16-0-1/test.h @@ -0,0 +1,4 @@ +#ifndef _TEST_HEADER_INCLUDE // COMPLIANT - header guard +#define _TEST_HEADER_INCLUDE // COMPLIANT +int x; +#endif // COMPLIANT \ No newline at end of file diff --git a/cpp/autosar/test/rules/A16-0-1/test2.h b/cpp/autosar/test/rules/A16-0-1/test2.h new file mode 100644 index 0000000000..e69de29bb2