Skip to content

Commit 35df852

Browse files
committed
Merge branch 'main' into rvermeulen/fix-396
2 parents 4017b39 + 34d836f commit 35df852

File tree

107 files changed

+1077
-368
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+1077
-368
lines changed

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@ This repository contains CodeQL queries and libraries which support various Codi
66

77
_Carnegie Mellon and CERT are registered trademarks of Carnegie Mellon University._
88

9-
This repository contains CodeQL queries and libraries which support various Coding Standards for the [C++14](https://www.iso.org/standard/64029.html) programming language.
9+
This repository contains CodeQL queries and libraries which support various Coding Standards for the [C++14](https://www.iso.org/standard/64029.html), [C99](https://www.iso.org/standard/29237.html) and [C11](https://www.iso.org/standard/57853.html) programming languages.
1010

1111
The following coding standards are supported:
1212
- [AUTOSAR - Guidelines for the use of C++14 language in critical and safety-related systems (Releases R22-11, R20-11, R19-11 and R19-03)](https://www.autosar.org/fileadmin/standards/R22-11/AP/AUTOSAR_RS_CPP14Guidelines.pdf).
1313
- [MISRA C++:2008](https://www.misra.org.uk) (support limited to the rules specified in AUTOSAR).
1414
- [SEI CERT C++ Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems (2016 Edition)](https://resources.sei.cmu.edu/library/asset-view.cfm?assetID=494932)
15-
16-
In addition, the following Coding Standards for the C programming language are under development:
17-
1815
- [SEI CERT C Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems (2016 Edition)](https://resources.sei.cmu.edu/downloads/secure-coding/assets/sei-cert-c-coding-standard-2016-v01.pdf)
1916
- [MISRA C 2012](https://www.misra.org.uk/product/misra-c2012-third-edition-first-revision/).
2017

c/misra/src/rules/RULE-20-8/ControllingExpressionIfDirective.ql

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,35 @@
1414

1515
import cpp
1616
import codingstandards.c.misra
17+
import codingstandards.cpp.PreprocessorDirective
1718

1819
/* A controlling expression is evaluated if it is not excluded (guarded by another controlling expression that is not taken). This translates to it either being taken or not taken. */
1920
predicate isEvaluated(PreprocessorBranch b) { b.wasTaken() or b.wasNotTaken() }
2021

21-
class IfOrElifPreprocessorBranch extends PreprocessorBranch {
22-
IfOrElifPreprocessorBranch() {
23-
this instanceof PreprocessorIf or this instanceof PreprocessorElif
24-
}
25-
}
26-
2722
/**
2823
* Looks like it contains a single macro, which may be undefined
2924
*/
30-
class SimpleMacroPreprocessorBranch extends IfOrElifPreprocessorBranch {
25+
class SimpleMacroPreprocessorBranch extends PreprocessorIfOrElif {
3126
SimpleMacroPreprocessorBranch() { this.getHead().regexpMatch("[a-zA-Z_][a-zA-Z0-9_]+") }
3227
}
3328

34-
class SimpleNumericPreprocessorBranch extends IfOrElifPreprocessorBranch {
29+
class SimpleNumericPreprocessorBranch extends PreprocessorIfOrElif {
3530
SimpleNumericPreprocessorBranch() { this.getHead().regexpMatch("[0-9]+") }
3631
}
3732

3833
class ZeroOrOnePreprocessorBranch extends SimpleNumericPreprocessorBranch {
3934
ZeroOrOnePreprocessorBranch() { this.getHead().regexpMatch("[0|1]") }
4035
}
4136

42-
predicate containsOnlySafeOperators(IfOrElifPreprocessorBranch b) {
37+
predicate containsOnlySafeOperators(PreprocessorIfOrElif b) {
4338
containsOnlyDefinedOperator(b)
4439
or
4540
//logic: comparison operators eval last, so they make it safe?
4641
b.getHead().regexpMatch(".*[\\&\\&|\\|\\||>|<|==].*")
4742
}
4843

4944
//all defined operators is definitely safe
50-
predicate containsOnlyDefinedOperator(IfOrElifPreprocessorBranch b) {
45+
predicate containsOnlyDefinedOperator(PreprocessorIfOrElif b) {
5146
forall(string portion |
5247
portion =
5348
b.getHead()
@@ -65,7 +60,7 @@ class BinaryValuedMacro extends Macro {
6560
BinaryValuedMacro() { this.getBody().regexpMatch("\\(?(0|1)\\)?") }
6661
}
6762

68-
from IfOrElifPreprocessorBranch b, string msg
63+
from PreprocessorIfOrElif b, string msg
6964
where
7065
not isExcluded(b, Preprocessor3Package::controllingExpressionIfDirectiveQuery()) and
7166
isEvaluated(b) and
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
`M8-5-2` - `AggregateLiteralEnhancements.qll`:
2+
- recognise aggregate literals initialized with parameters from variadic templates.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `A2-10-1`, `RULE-5-3`:
2+
- Reduce false positives by considering point of declaration for local variables.
3+
- Reduce false negatives by considering catch block parameters to be in scope in the catch block.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `M6-5-5`:
2+
- Reduce false positives by no longer considering the taking of a const reference as a modification.
3+
- Improve detection of non-local modification of loop iteration variables to reduce false positives.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- `M16-1-1` - `DefinedPreProcessorOperatorGeneratedFromExpansionFound.ql`:
2+
- Optimize query to improve performance
3+
- Improve detection of macros whose body contains the `defined` operator after the start of the macro (e.g. `#define X Y || defined(Z)`).
4+
- Enable exclusions to be applied for this rule.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- The following queries have been updated to address issues with applying deviations:
2+
- `A18-5-11`, `A23-0-1`, `A9-3-1`, `M0-1-2`, `M3-1-2`, `M3-2-1`, `M3-2-3`, `M3-9-1`, `M4-5-3`, `M5-0-2`, `M5-2-10`, `A23-0-2`, `CTR51-CPP`, `STR52-CPP`
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
`M5-2-10` - `IncrementAndDecrementOperatorsMixedWithOtherOperatorsInExpression.ql`:
2+
- only report use of the increment and decrement operations in conjunction with arithmetic operators, as specified by the rule. Notably we no longer report the expressions of the form `*p++`, which combine increment and dereferencing operations.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- `A8-4-8` - `OutParametersUsed.ql`
2+
- Fixes #370 - Non-member user-defined assignment operator and stream insertion/extraction parameters that are required to be out parameters are excluded.
3+
- Broadens the definition of out parameter by considering assignment and crement operators as modifications to an out parameter candidate.
4+
- `FIO51-CPP` - `CloseFilesWhenTheyAreNoLongerNeeded.ql`:
5+
- Broadened definition of `IStream` and `OStream` types may result in reduced false negatives.
6+
- `A5-1-1` - `LiteralValueUsedOutsideTypeInit.ql`:
7+
- Broadened definition of `IStream` types may result in reduced false positives because more file stream function calls may be detected as logging operations that will be excluded from the results.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `A18-0-1` - `CLibraryFacilitiesNotAccessedThroughCPPLibraryHeaders.ql`:
2+
- Fix issue #7 - improve query logic to only match on exact standard library names (e.g., now excludes sys/header.h type headers from the results as those are not C standard libraries).
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-`A15-4-4` - `MissingNoExcept.ql`:
2+
- Fix FP reported in #424. Exclude functions calling `std::string::reserve` or `std::string::append` that may throw even if their signatures don't specify it.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- `M0-1-3` - `UnusedMemberVariable.ql`, `UnusedGlobalOrNamespaceVariable.ql`:
2+
- Address FP reported in #384. Exclude variables with compile time values that may have been used as a template argument.
3+
- Exclude uninstantiated template members.
4+
- Reformat the alert message to adhere to the style-guide.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- `A5-1-1` - `LiteralValueUsedOutsideTypeInit.ql`:
2+
- Address FP reported in #371. Exclude literals generated by uses of constexpr variables.
3+
- Exclude literals used in class template instantiations.
4+
- Update the alert message to adhere to the style-guide.
5+
- Exclude boolean literals used as template arguments.
6+
- Exclude `u` and `U` prefixed char literals.
7+
- Exclude literals part of a class aggregate literal.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- `A5-0-2` - `NonBooleanIterationCondition.ql`:
2+
- Address FP reported in #10. Exclude conditions in uninstantiated templates.
3+
- `M5-3-1` - `EachOperandOfTheOperatorTheLogicalAndOrTheLogicalOperatorsShallHaveTypeBool.ql`:
4+
- Adjust the alert message to comply with the style guide.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `M5-14-1` - `RightHandOperandOfALogicalAndOperatorsContainSideEffects.ql`:
2+
- Fix FP reported in #375. Addresses incorrect detection of side effects in unevaluated contexts.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `A16-2-2` - `UnusedIncludeDirectives.ql`:
2+
- Address FP reported in #453. Exclude reporting of redundant include directives indirectly included by included files.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- `A8-4-7` - `InParametersForNotCheapToCopyTypesNotPassedByReference.ql`, `InParametersForCheapToCopyTypesNotPassedByValue.ql`:
2+
- Improve coverage of the query by additionally alerting to non-trivially-copyable types being passed by value.
3+
- Non-trivially-copyable types not passed by value will no longer be incorrectly reported.

cpp/autosar/src/rules/A16-2-2/UnusedIncludeDirectives.ql

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,19 @@ private predicate firstReliableProvide(File f, File g, int line) {
223223

224224
cached
225225
predicate mayProvideFirst(IncludeDepends i, File g) {
226-
// i may provide g and does not come after a reliable include of g.
226+
// i may provide g
227227
i.provides(g) and
228-
not exists(int line | firstReliableProvide(i.getFile(), g, line) |
229-
line < i.getLocation().getStartLine()
228+
(
229+
// and does not come after a reliable include of g.
230+
not exists(int line | firstReliableProvide(i.getFile(), g, line) |
231+
line < i.getLocation().getStartLine()
232+
)
233+
or
234+
// or it comes after a reliable include of g, and although redundant,
235+
// is not necessarily an issue e.g. in the case of libraries with
236+
// public header forwards to an internal header.
237+
// therefore, hold for transitive includes as well to exclude those results.
238+
not i.getIncludedFile() = g
230239
)
231240
}
232241

cpp/autosar/src/rules/A18-0-1/CLibraryFacilitiesNotAccessedThroughCPPLibraryHeaders.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ where
2828
* not use any of 'signal.h's facilities, for example.
2929
*/
3030

31-
filename = i.getIncludedFile().getBaseName() and
31+
filename = i.getIncludeText().substring(1, i.getIncludeText().length() - 1) and
3232
filename in [
3333
"assert.h", "ctype.h", "errno.h", "fenv.h", "float.h", "inttypes.h", "limits.h", "locale.h",
3434
"math.h", "setjmp.h", "signal.h", "stdarg.h", "stddef.h", "stdint.h", "stdio.h", "stdlib.h",

cpp/autosar/src/rules/A18-5-11/OperatorNewAndOperatorDeleteNotDefinedLocally.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import codingstandards.cpp.autosar
1919

2020
from MemberFunction operator_new, Class c
2121
where
22-
not isExcluded(operator_new) and
22+
not isExcluded(operator_new,
23+
DeclarationsPackage::operatorNewAndOperatorDeleteNotDefinedLocallyQuery()) and
2324
not isExcluded(c, DeclarationsPackage::operatorNewAndOperatorDeleteNotDefinedLocallyQuery()) and
2425
operator_new.hasName("operator new") and
2526
operator_new.getDeclaringType() = c and

cpp/autosar/src/rules/A23-0-1/IteratorImplicitlyConvertedToConstIterator.ql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ import codingstandards.cpp.Iterators
4040

4141
from ConstIteratorVariable v, STLContainer c, Expr e
4242
where
43-
not isExcluded(v) and
44-
not isExcluded(e) and
43+
not isExcluded(v, IteratorsPackage::iteratorImplicitlyConvertedToConstIteratorQuery()) and
44+
not isExcluded(e, IteratorsPackage::iteratorImplicitlyConvertedToConstIteratorQuery()) and
4545
e = v.getAnAssignedValue() and
4646
e.getAChild*() = /* see note at top of query */ c.getANonConstIteratorFunctionCall()
4747
select e, "Non-const version of container call immediately converted to a `const_iterator`."

cpp/autosar/src/rules/A5-1-1/LiteralValueUsedOutsideTypeInit.ql

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import cpp
1818
import codingstandards.cpp.autosar
1919
import codingstandards.cpp.LoggingOperation
2020
import codingstandards.cpp.Literals
21+
import codingstandards.cpp.Cpp14Literal
2122

2223
from Literal l
2324
where
@@ -35,11 +36,11 @@ where
3536
// Exclude literal 0
3637
not l.getValue() = "0" and
3738
// Exclude character literals
38-
not l instanceof CharLiteral and
39+
not l instanceof Cpp14Literal::CharLiteral and
3940
// Exclude `nullptr`
4041
not l.getType() instanceof NullPointerType and
4142
// Exclude boolean `true` and `false`
42-
not l.getType() instanceof BoolType and
43+
not l instanceof BoolLiteral and
4344
// Exclude empty string
4445
not l.getValue() = "" and
4546
// Template functions use literals to represent calls which are unknown
@@ -51,7 +52,14 @@ where
5152
// Aggregate literal
5253
not l = any(ArrayOrVectorAggregateLiteral aal).getAnElementExpr(_).getAChild*() and
5354
// Ignore x - 1 expressions
54-
not exists(SubExpr se | se.getRightOperand() = l and l.getValue() = "1")
55-
select l,
56-
"Literal value " + getTruncatedLiteralText(l) + " used outside of type initialization " +
57-
l.getAPrimaryQlClass()
55+
not exists(SubExpr se | se.getRightOperand() = l and l.getValue() = "1") and
56+
// Exclude compile time computed integral literals as they can appear as integral literals
57+
// when used as non-type template arguments.
58+
// We limit ourselves to integral literals, because floating point literals as non-type
59+
// template arguments are not supported in C++ 14. Those are supported shince C++ 20.
60+
not l instanceof CompileTimeComputedIntegralLiteral and
61+
// Exclude literals to instantiate a class template per example in the standard
62+
// where an type of std::array is intialized with size 5.
63+
not l = any(ClassTemplateInstantiation cti).getATemplateArgument() and
64+
not l = any(ClassAggregateLiteral cal).getAFieldExpr(_)
65+
select l, "Literal value '" + getTruncatedLiteralText(l) + "' used outside of type initialization."

cpp/autosar/src/rules/A8-4-7/InParametersForCheapToCopyTypesNotPassedByValue.ql

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import cpp
1717
import codingstandards.cpp.autosar
18-
import TriviallySmallType
18+
import TriviallyCopyableSmallType
1919
import codingstandards.cpp.CommonTypes as CommonTypes
2020
import codingstandards.cpp.Class
2121

@@ -26,7 +26,7 @@ import codingstandards.cpp.Class
2626
* In this rule, we will look cases where a "cheap to copy" type is not passed by value.
2727
*/
2828

29-
from Parameter v, TriviallySmallType t
29+
from Parameter v, TriviallyCopyableSmallType t
3030
where
3131
not isExcluded(v, ClassesPackage::inParametersForCheapToCopyTypesNotPassedByValueQuery()) and
3232
exists(ReferenceType rt |
@@ -40,5 +40,6 @@ where
4040
not v.isFromUninstantiatedTemplate(_) and
4141
not v.isFromTemplateInstantiation(_)
4242
select v,
43-
"Parameter '" + v.getName() + "' is the trivially copyable type '" + t.getName() +
44-
"' but it is passed by reference instead of by value."
43+
"Parameter '" + v.getName() +
44+
"' is the trivially copyable type $@ but it is passed by reference instead of by value.", t,
45+
t.getName()

cpp/autosar/src/rules/A8-4-7/InParametersForNotCheapToCopyTypesNotPassedByReference.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import cpp
1717
import codingstandards.cpp.autosar
18-
import TriviallySmallType
18+
import TriviallyCopyableSmallType
1919
import codingstandards.cpp.CommonTypes as CommonTypes
2020

2121
/*
@@ -28,12 +28,12 @@ import codingstandards.cpp.CommonTypes as CommonTypes
2828
from Parameter v
2929
where
3030
not isExcluded(v, ClassesPackage::inParametersForNotCheapToCopyTypesNotPassedByReferenceQuery()) and
31-
not v.getType() instanceof TriviallySmallType and
31+
not v.getType() instanceof TriviallyCopyableSmallType and
3232
not v.getType().getUnderlyingType() instanceof ReferenceType and
3333
not exists(CatchBlock cb | cb.getParameter() = v) and
3434
not v.isFromUninstantiatedTemplate(_) and
3535
not v.isFromTemplateInstantiation(_)
3636
select v,
37-
"Parameter " + v.getName() +
38-
" is the trivially non-copyable type $@ but it is passed by value instead of by reference.",
37+
"Parameter '" + v.getName() +
38+
"' is the trivially non-copyable type $@ but it is passed by value instead of by reference.",
3939
v.getType(), v.getType().getName()

cpp/autosar/src/rules/A8-4-7/TriviallySmallType.qll renamed to cpp/autosar/src/rules/A8-4-7/TriviallyCopyableSmallType.qll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import cpp
22
import codingstandards.cpp.autosar
3+
import codingstandards.cpp.TrivialType
34

45
/**
56
* Get the largest word size, in bytes. Some projects may have multiple different
@@ -13,6 +14,9 @@ int wordSize() { result = max(VoidPointerType v | | v.getSize()) }
1314
bindingset[bytes]
1415
int bytesToWords(int bytes) { result = bytes / wordSize() }
1516

16-
class TriviallySmallType extends Type {
17-
TriviallySmallType() { exists(int size | size = this.getSize() | bytesToWords(size) <= 2) }
17+
class TriviallyCopyableSmallType extends Type {
18+
TriviallyCopyableSmallType() {
19+
isTriviallyCopyableType(this) and
20+
exists(int size | size = this.getSize() | bytesToWords(size) <= 2)
21+
}
1822
}

cpp/autosar/src/rules/A8-4-8/OutputParametersUsed.ql

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,60 @@ import codingstandards.cpp.ConstHelpers
2323
import codingstandards.cpp.Operator
2424

2525
/**
26-
* Non-const T& and T* `Parameter`s to `Function`s
26+
* Holds if p is passed as a non-const reference or pointer and is modified.
27+
* This holds for in-out or out-only parameters.
2728
*/
28-
class NonConstReferenceOrPointerParameterCandidate extends FunctionParameter {
29-
NonConstReferenceOrPointerParameterCandidate() {
30-
this instanceof NonConstReferenceParameter
31-
or
32-
this instanceof NonConstPointerParameter
33-
}
29+
predicate isOutParameter(NonConstPointerorReferenceParameter p) {
30+
any(VariableEffect ve).getTarget() = p
31+
}
32+
33+
/**
34+
* Holds if parameter `p` is a parameter to a user defined assignment operator that
35+
* is defined outside of a class body.
36+
* These require an in-out parameter as the first argument.
37+
*/
38+
predicate isNonMemberUserAssignmentParameter(NonConstPointerorReferenceParameter p) {
39+
p.getFunction() instanceof UserAssignmentOperator and
40+
not p.isMember()
41+
}
42+
43+
/**
44+
* Holds if parameter `p` is a parameter to a stream insertion operator that
45+
* is defined outside of a class body.
46+
* These require an in-out parameter as the first argument.
47+
*
48+
* e.g., `std::ostream& operator<<(std::ostream& os, const T& obj)`
49+
*/
50+
predicate isStreamInsertionStreamParameter(NonConstPointerorReferenceParameter p) {
51+
exists(StreamInsertionOperator op | not op.isMember() | op.getParameter(0) = p)
3452
}
3553

36-
pragma[inline]
37-
predicate isFirstAccess(VariableAccess va) {
38-
not exists(VariableAccess otherVa |
39-
otherVa.getTarget() = va.getTarget() or
40-
otherVa.getQualifier().(VariableAccess).getTarget() = va.getTarget()
41-
|
42-
otherVa.getASuccessor() = va
54+
/**
55+
* Holds if parameter `p` is a parameter to a stream insertion operator that
56+
* is defined outside of a class body.
57+
* These require an in-out parameter as the first argument and an out parameter for the second.
58+
*
59+
* e.g., `std::istream& operator>>(std::istream& is, T& obj)`
60+
*/
61+
predicate isStreamExtractionParameter(NonConstPointerorReferenceParameter p) {
62+
exists(StreamExtractionOperator op | not op.isMember() |
63+
op.getParameter(0) = p
64+
or
65+
op.getParameter(1) = p
4366
)
4467
}
4568

46-
from NonConstReferenceOrPointerParameterCandidate p, VariableEffect ve
69+
predicate isException(NonConstPointerorReferenceParameter p) {
70+
isNonMemberUserAssignmentParameter(p) and p.getIndex() = 0
71+
or
72+
isStreamInsertionStreamParameter(p)
73+
or
74+
isStreamExtractionParameter(p)
75+
}
76+
77+
from NonConstPointerorReferenceParameter p
4778
where
4879
not isExcluded(p, ConstPackage::outputParametersUsedQuery()) and
49-
ve.getTarget() = p and
50-
isFirstAccess(ve.getAnAccess()) and
51-
not ve instanceof AnyAssignOperation and
52-
not ve instanceof CrementOperation
53-
select p, "Out parameter " + p.getName() + " that is modified before being read."
80+
isOutParameter(p) and
81+
not isException(p)
82+
select p, "Out parameter '" + p.getName() + "' used."

0 commit comments

Comments
 (0)