================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits