diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index a0c95b1fce8c..28d6c04808f8 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -253,6 +253,25 @@ public: /// within CFGs. bool hasImplicitControlFlow() const; + /// contains* - Useful recursive methods to see if a statement contains an + /// element somewhere. Used in static analysis to reduce false positives. + static bool containsMacro(const Stmt *S); + static bool containsEnum(const Stmt *S); + static bool containsZeroConstant(const Stmt *S); + static bool containsOneConstant(const Stmt *S); + template static bool containsStmt(const Stmt *S) { + if (isa(S)) + return true; + + for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end(); ++I) + if (const Stmt *child = *I) + if (containsStmt(child)) + return true; + + return false; + } + + /// Child Iterators: All subclasses must implement child_begin and child_end /// to permit easy iteration over the substatements/subexpessions of an /// AST node. This permits easy iteration over all nodes in the AST. diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 6dbe8f4d18c1..d1084327a200 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -127,6 +127,72 @@ bool Stmt::hasImplicitControlFlow() const { } } +// Recursively find any substatements containing macros +bool Stmt::containsMacro(const Stmt *S) { + if (S->getLocStart().isMacroID()) + return true; + + if (S->getLocEnd().isMacroID()) + return true; + + for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end(); ++I) + if (const Stmt *child = *I) + if (containsMacro(child)) + return true; + + return false; +} + +// Recursively find any substatements containing enum constants +bool Stmt::containsEnum(const Stmt *S) { + const DeclRefExpr *DR = dyn_cast(S); + + if (DR && isa(DR->getDecl())) + return true; + + for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end(); ++I) + if (const Stmt *child = *I) + if (containsEnum(child)) + return true; + + return false; +} + +bool Stmt::containsZeroConstant(const Stmt *S) { + const IntegerLiteral *IL = dyn_cast(S); + if (IL && IL->getValue() == 0) + return true; + + const FloatingLiteral *FL = dyn_cast(S); + if (FL && FL->getValue().isZero()) + return true; + + for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end(); ++I) + if (const Stmt *child = *I) + if (containsZeroConstant(child)) + return true; + + return false; +} + +bool Stmt::containsOneConstant(const Stmt *S) { + const IntegerLiteral *IL = dyn_cast(S); + if (IL && IL->getValue() == 1) + return true; + + const FloatingLiteral *FL = dyn_cast(S); + const llvm::APFloat one(1.0); + if (FL && FL->getValue().compare(one) == llvm::APFloat::cmpEqual) + return true; + + for (Stmt::const_child_iterator I = S->child_begin(); I != S->child_end(); ++I) + if (const Stmt *child = *I) + if (containsOneConstant(child)) + return true; + + return false; +} + Expr *AsmStmt::getOutputExpr(unsigned i) { return cast(Exprs[i]); }