[clang] [alpha.webkit.UncountedCallArgsChecker] Support more trivial expressions. (PR #90414)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 28 13:32:51 PDT 2024
https://github.com/rniwa created https://github.com/llvm/llvm-project/pull/90414
Treat a compound operator such as |=, array subscription, sizeof, and non-type template parameter as trivial so long as subexpressions are also trivial.
Also treat true/false boolean literal as trivial.
>From cc3b7f6c4d75aab856a8c31cc7ccfbcb5c6626e8 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Sun, 28 Apr 2024 13:17:48 -0700
Subject: [PATCH] [alpha.webkit.UncountedCallArgsChecker] Support more trivial
expressions.
Treat a compound operator such as |=, array subscription, sizeof, and non-type
template parameter as trivial so long as subexpressions are also trivial.
Also treat true/false boolean literal as trivial.
---
.../Checkers/WebKit/PtrTypesSemantics.cpp | 23 ++++++++++++++++++-
.../WebKit/UncountedCallArgsChecker.cpp | 2 +-
.../Checkers/WebKit/uncounted-obj-arg.cpp | 20 ++++++++++++++++
3 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 287f6a52870056..98ddf02bed9a78 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -311,7 +311,7 @@ class TrivialFunctionAnalysisVisitor
bool VisitUnaryOperator(const UnaryOperator *UO) {
// Operator '*' and '!' are allowed as long as the operand is trivial.
auto op = UO->getOpcode();
- if (op == UO_Deref || op == UO_AddrOf || op == UO_LNot)
+ if (op == UO_Deref || op == UO_AddrOf || op == UO_LNot || op == UO_Not)
return Visit(UO->getSubExpr());
if (UO->isIncrementOp() || UO->isDecrementOp()) {
@@ -331,6 +331,16 @@ class TrivialFunctionAnalysisVisitor
return Visit(BO->getLHS()) && Visit(BO->getRHS());
}
+ bool VisitCompoundAssignOperator(const CompoundAssignOperator *CAO) {
+ // Compound assignment operator such as |= is trivial if its
+ // subexpresssions are trivial.
+ return VisitChildren(CAO);
+ }
+
+ bool VisitArraySubscriptExpr(const ArraySubscriptExpr* ASE) {
+ return VisitChildren(ASE);
+ }
+
bool VisitConditionalOperator(const ConditionalOperator *CO) {
// Ternary operators are trivial if their conditions & values are trivial.
return VisitChildren(CO);
@@ -360,6 +370,16 @@ class TrivialFunctionAnalysisVisitor
return TrivialFunctionAnalysis::isTrivialImpl(Callee, Cache);
}
+ bool VisitSubstNonTypeTemplateParmExpr(
+ const SubstNonTypeTemplateParmExpr* E) {
+ // Non-type template paramter is trivial if the replacement is trivial.
+ return Visit(E->getReplacement());
+ }
+
+ bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr* E) {
+ return VisitChildren(E);
+ }
+
bool VisitPredefinedExpr(const PredefinedExpr *E) {
// A predefined identifier such as "func" is considered trivial.
return true;
@@ -463,6 +483,7 @@ class TrivialFunctionAnalysisVisitor
bool VisitFixedPointLiteral(const FixedPointLiteral *E) { return true; }
bool VisitCharacterLiteral(const CharacterLiteral *E) { return true; }
bool VisitStringLiteral(const StringLiteral *E) { return true; }
+ bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) { return true; }
bool VisitConstantExpr(const ConstantExpr *CE) {
// Constant expressions are trivial.
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
index 741f336761589f..96bae0de65a5b1 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
@@ -54,7 +54,7 @@ class UncountedCallArgsChecker
bool shouldVisitImplicitCode() const { return false; }
bool TraverseDecl(Decl *D) {
- if (isa<ClassTemplateDecl>(D) && isRefType(safeGetName(D)))
+ if (D && isa<ClassTemplateDecl>(D) && isRefType(safeGetName(D)))
return true;
return RecursiveASTVisitor<LocalVisitor>::TraverseDecl(D);
}
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
index 80a9a263dab140..472be2dc2b978a 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp
@@ -201,6 +201,12 @@ class RefCounted {
unsigned trivial25() const { return __c11_atomic_load((volatile _Atomic(unsigned) *)&v, __ATOMIC_RELAXED); }
bool trivial26() { bool hasValue = v; return !hasValue; }
bool trivial27(int v) { bool value; value = v ? 1 : 0; return value; }
+ bool trivial28() { return true; }
+ bool trivial29() { return false; }
+ unsigned trivial30() { return ~0xff; }
+ template <unsigned v> unsigned trivial31() { return v; }
+ unsigned trivial32(unsigned v) { unsigned r = 0xff; r |= v; return r; }
+ unsigned trivial33() { return sizeof(int); }
static RefCounted& singleton() {
static RefCounted s_RefCounted;
@@ -273,6 +279,9 @@ class RefCounted {
return val;
}
+ int nonTrivial13() { return ~otherFunction(); }
+ int nonTrivial14() { int r = 0xff; r |= otherFunction(); return r; }
+
unsigned v { 0 };
Number* number { nullptr };
Enum enumValue { Enum::Value1 };
@@ -322,6 +331,13 @@ class UnrelatedClass {
getFieldTrivial().trivial25(); // no-warning
getFieldTrivial().trivial26(); // no-warning
getFieldTrivial().trivial27(5); // no-warning
+ getFieldTrivial().trivial28(); // no-warning
+ getFieldTrivial().trivial29(); // no-warning
+ getFieldTrivial().trivial30(); // no-warning
+ getFieldTrivial().trivial31<7>(); // no-warning
+ getFieldTrivial().trivial32(9); // no-warning
+ getFieldTrivial().trivial33(); // no-warning
+
RefCounted::singleton().trivial18(); // no-warning
RefCounted::singleton().someFunction(); // no-warning
@@ -351,6 +367,10 @@ class UnrelatedClass {
// expected-warning at -1{{Call argument for 'this' parameter is uncounted and unsafe}}
getFieldTrivial().nonTrivial12();
// expected-warning at -1{{Call argument for 'this' parameter is uncounted and unsafe}}
+ getFieldTrivial().nonTrivial13();
+ // expected-warning at -1{{Call argument for 'this' parameter is uncounted and unsafe}}
+ getFieldTrivial().nonTrivial14();
+ // expected-warning at -1{{Call argument for 'this' parameter is uncounted and unsafe}}
}
};
More information about the cfe-commits
mailing list