[clang] [alpha.webkit.UncountedCallArgsChecker] Detect & ignore trivial function calls. (PR #81808)
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 14 17:26:22 PST 2024
================
@@ -222,4 +223,210 @@ bool isPtrConversion(const FunctionDecl *F) {
return false;
}
+bool isSingleton(const FunctionDecl *F) {
+ assert(F);
+ // FIXME: check # of params == 1
+ if (auto *MethodDecl = dyn_cast<CXXMethodDecl>(F)) {
+ if (!MethodDecl->isStatic())
+ return false;
+ }
+ const auto &Name = safeGetName(F);
+ std::string SingletonStr = "singleton";
+ auto index = Name.find(SingletonStr);
+ return index != std::string::npos &&
+ index == Name.size() - SingletonStr.size();
+}
+
+// We only care about statements so let's use the simple
+// (non-recursive) visitor.
+class TrivialFunctionAnalysisVisitor
+ : public ConstStmtVisitor<TrivialFunctionAnalysisVisitor, bool> {
+
+ // Returns false if at least one child is non-trivial.
+ bool VisitChildren(const Stmt *S) {
+ for (const Stmt *Child : S->children()) {
+ if (Child && !Visit(Child))
+ return false;
+ }
+
+ return true;
+ }
+
+public:
+ using CacheTy = TrivialFunctionAnalysis::CacheTy;
+
+ TrivialFunctionAnalysisVisitor(CacheTy &Cache) : Cache(Cache) {}
+
+ bool VisitStmt(const Stmt *S) {
+ // All statements are non-trivial unless overriden later.
+ // Don't even recurse into children by default.
+ return false;
+ }
+
+ bool VisitCompoundStmt(const CompoundStmt *CS) {
+ // A compound statement is allowed as long each individual sub-statement
+ // is trivial.
+ return VisitChildren(CS);
+ }
+
+ bool VisitReturnStmt(const ReturnStmt *RS) {
+ // A return statement is allowed as long as the return value is trivial.
+ return Visit(RS->getRetValue());
+ }
+
+ bool VisitDeclStmt(const DeclStmt *DS) { return VisitChildren(DS); }
+ bool VisitDoStmt(const DoStmt *DS) { return VisitChildren(DS); }
+ bool VisitIfStmt(const IfStmt *IS) { return VisitChildren(IS); }
+ bool VisitSwitchStmt(const SwitchStmt *SS) { return VisitChildren(SS); }
+ bool VisitCaseStmt(const CaseStmt *CS) { return VisitChildren(CS); }
+ bool VisitDefaultStmt(const DefaultStmt *DS) { return VisitChildren(DS); }
+
+ bool VisitUnaryOperator(const UnaryOperator *UO) {
+ // Operator '*' and '!' are allowed as long as the operand is trivial.
+ if (UO->getOpcode() == UO_Deref || UO->getOpcode() == UO_LNot)
+ return Visit(UO->getSubExpr());
+
+ // Other operators are non-trivial.
+ return false;
+ }
+
+ bool VisitBinaryOperator(const BinaryOperator *BO) {
+ // Binary operators are trivial if their operands are trivial.
+ return Visit(BO->getLHS()) && Visit(BO->getRHS());
+ }
+
+ bool VisitConditionalOperator(const ConditionalOperator *CO) {
+ // Ternary operators are trivial if their conditions & values are trivial.
+ return VisitChildren(CO);
+ }
+
+ bool VisitDeclRefExpr(const DeclRefExpr *DRE) {
+ if (auto *decl = DRE->getDecl()) {
+ if (isa<ParmVarDecl>(decl))
+ return true;
+ }
+ return false;
+ }
+
+ bool VisitStaticAssertDecl(const StaticAssertDecl *SAD) {
+ // Any static_assert is considered trivial.
+ return true;
+ }
+
+ bool VisitCallExpr(const CallExpr *CE) {
+ if (auto *MCE = dyn_cast<CXXMemberCallExpr>(CE))
+ return VisitCXXMemberCallExpr(MCE);
----------------
haoNoQ wrote:
This happens automatically, you don't need to do that manually. The visitor calls the most specialized user-defined method. (If it's not user-defined, it's defined by default to call the slightly less specialized method.)
On the other hand, it might make sense to call `VisitCallExpr()` from inside `VisitCXXMemberCallExpr()` to reuse some code. (Or you can define a common method called by both.)
https://github.com/llvm/llvm-project/pull/81808
More information about the cfe-commits
mailing list