From: Tom Care Date: Tue, 6 Jul 2010 17:28:49 +0000 (+0000) Subject: Added several helper functions to Stmt to recursively check for different elements... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7d6228fc77baf405c6554bb47904fc197e33b488;p=clang Added several helper functions to Stmt to recursively check for different elements (macros, enum constants, etc). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107675 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index a0c95b1fce..28d6c04808 100644 --- a/include/clang/AST/Stmt.h +++ b/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/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 6dbe8f4d18..d1084327a2 100644 --- a/lib/AST/Stmt.cpp +++ b/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]); }