"Fossies" - the Fresh Open Source Software Archive

Member "cppcheck-1.89/lib/astutils.h" (1 Sep 2019, 11266 Bytes) of package /windows/misc/cppcheck-1.89.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "astutils.h" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.88_vs_1.89.

    1 /*
    2  * Cppcheck - A tool for static C/C++ code analysis
    3  * Copyright (C) 2007-2019 Cppcheck team.
    4  *
    5  * This program is free software: you can redistribute it and/or modify
    6  * it under the terms of the GNU General Public License as published by
    7  * the Free Software Foundation, either version 3 of the License, or
    8  * (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   17  */
   18 
   19 
   20 //---------------------------------------------------------------------------
   21 #ifndef astutilsH
   22 #define astutilsH
   23 //---------------------------------------------------------------------------
   24 
   25 #include <functional>
   26 #include <string>
   27 #include <vector>
   28 
   29 #include "errorlogger.h"
   30 #include "utils.h"
   31 
   32 class Library;
   33 class Settings;
   34 class Scope;
   35 class Token;
   36 class Variable;
   37 
   38 enum class ChildrenToVisit {
   39     none,
   40     op1,
   41     op2,
   42     op1_and_op2,
   43     done  // found what we looked for, don't visit any more children
   44 };
   45 
   46 /**
   47  * Visit AST nodes recursively. The order is not "well defined"
   48  */
   49 void visitAstNodes(const Token *ast, std::function<ChildrenToVisit(const Token *)> visitor);
   50 
   51 std::vector<const Token*> astFlatten(const Token* tok, const char* op);
   52 
   53 bool astHasToken(const Token* root, const Token * tok);
   54 
   55 bool astHasVar(const Token * tok, nonneg int varid);
   56 
   57 /** Is expression a 'signed char' if no promotion is used */
   58 bool astIsSignedChar(const Token *tok);
   59 /** Is expression a 'char' if no promotion is used? */
   60 bool astIsUnknownSignChar(const Token *tok);
   61 /** Is expression of integral type? */
   62 bool astIsIntegral(const Token *tok, bool unknown);
   63 /** Is expression of floating point type? */
   64 bool astIsFloat(const Token *tok, bool unknown);
   65 /** Is expression of boolean type? */
   66 bool astIsBool(const Token *tok);
   67 
   68 bool astIsPointer(const Token *tok);
   69 
   70 bool astIsIterator(const Token *tok);
   71 
   72 bool astIsContainer(const Token *tok);
   73 
   74 /**
   75  * Get canonical type of expression. const/static/etc are not included and neither *&.
   76  * For example:
   77  * Expression type      Return
   78  * std::string          std::string
   79  * int *                int
   80  * static const int     int
   81  * std::vector<T>       std::vector
   82  */
   83 std::string astCanonicalType(const Token *expr);
   84 
   85 /** Is given syntax tree a variable comparison against value */
   86 const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr);
   87 
   88 const Token * nextAfterAstRightmostLeaf(const Token * tok);
   89 
   90 Token* astParentSkipParens(Token* tok);
   91 const Token* astParentSkipParens(const Token* tok);
   92 
   93 bool precedes(const Token * tok1, const Token * tok2);
   94 
   95 bool isSameExpression(bool cpp, bool macro, const Token *tok1, const Token *tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr);
   96 
   97 bool isEqualKnownValue(const Token * const tok1, const Token * const tok2);
   98 
   99 bool isDifferentKnownValues(const Token * const tok1, const Token * const tok2);
  100 
  101 /**
  102  * Are two conditions opposite
  103  * @param isNot  do you want to know if cond1 is !cond2 or if cond1 and cond2 are non-overlapping. true: cond1==!cond2  false: cond1==true => cond2==false
  104  * @param cpp    c++ file
  105  * @param cond1  condition1
  106  * @param cond2  condition2
  107  * @param library files data
  108  * @param pure boolean
  109  */
  110 bool isOppositeCond(bool isNot, bool cpp, const Token * const cond1, const Token * const cond2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr);
  111 
  112 bool isOppositeExpression(bool cpp, const Token * const tok1, const Token * const tok2, const Library& library, bool pure, bool followVar, ErrorPath* errors=nullptr);
  113 
  114 bool isConstExpression(const Token *tok, const Library& library, bool pure, bool cpp);
  115 
  116 bool isWithoutSideEffects(bool cpp, const Token* tok);
  117 
  118 bool isUniqueExpression(const Token* tok);
  119 
  120 /** Is scope a return scope (scope will unconditionally return) */
  121 bool isReturnScope(const Token *endToken, const Settings * settings = nullptr, bool functionScope=false);
  122 
  123 /** Is variable changed by function call?
  124  * In case the answer of the question is inconclusive, e.g. because the function declaration is not known
  125  * the return value is false and the output parameter inconclusive is set to true
  126  *
  127  * @param tok           ast tree
  128  * @param varid         Variable Id
  129  * @param settings      program settings
  130  * @param inconclusive  pointer to output variable which indicates that the answer of the question is inconclusive
  131  */
  132 bool isVariableChangedByFunctionCall(const Token *tok, int indirect, nonneg int varid, const Settings *settings, bool *inconclusive);
  133 
  134 /** Is variable changed by function call?
  135  * In case the answer of the question is inconclusive, e.g. because the function declaration is not known
  136  * the return value is false and the output parameter inconclusive is set to true
  137  *
  138  * @param tok           token of variable in function call
  139  * @param settings      program settings
  140  * @param inconclusive pointer to output variable which indicates that the answer of the question is inconclusive
  141  */
  142 bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Settings *settings, bool *inconclusive);
  143 
  144 /** Is variable changed in block of code? */
  145 bool isVariableChanged(const Token *start, const Token *end, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
  146 
  147 bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, bool cpp, int depth = 20);
  148 
  149 bool isVariableChanged(const Variable * var, const Settings *settings, bool cpp, int depth = 20);
  150 
  151 const Token* findVariableChanged(const Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
  152 Token* findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int varid, bool globalvar, const Settings *settings, bool cpp, int depth = 20);
  153 
  154 bool isAliased(const Variable *var);
  155 
  156 /** Determines the number of arguments - if token is a function call or macro
  157  * @param start token which is supposed to be the function/macro name.
  158  * \return Number of arguments
  159  */
  160 int numberOfArguments(const Token *start);
  161 
  162 /**
  163  * Get arguments (AST)
  164  */
  165 std::vector<const Token *> getArguments(const Token *ftok);
  166 
  167 const Token *findLambdaStartToken(const Token *last);
  168 
  169 /**
  170  * find lambda function end token
  171  * \param first The [ token
  172  * \return nullptr or the }
  173  */
  174 const Token *findLambdaEndToken(const Token *first);
  175 
  176 bool isLikelyStream(bool cpp, const Token *stream);
  177 
  178 /**
  179  * do we see a likely write of rhs through overloaded operator
  180  *   s >> x;
  181  *   a & x;
  182  */
  183 bool isLikelyStreamRead(bool cpp, const Token *op);
  184 
  185 bool isCPPCast(const Token* tok);
  186 
  187 bool isConstVarExpression(const Token *tok);
  188 
  189 const Variable *getLHSVariable(const Token *tok);
  190 
  191 struct PathAnalysis {
  192     enum class Progress {
  193         Continue,
  194         Break
  195     };
  196     PathAnalysis(const Token* start, const Library& library)
  197         : start(start), library(&library)
  198     {}
  199     const Token * start;
  200     const Library * library;
  201 
  202     struct Info {
  203         const Token* tok;
  204         ErrorPath errorPath;
  205         bool known;
  206     };
  207 
  208     void forward(const std::function<Progress(const Info&)>& f) const;
  209     template<class F>
  210     void forwardAll(F f) {
  211         forward([&](const Info& info) {
  212             f(info);
  213             return Progress::Continue;
  214         });
  215     }
  216     template<class Predicate>
  217     Info forwardFind(Predicate pred) {
  218         Info result{};
  219         forward([&](const Info& info) {
  220             if (pred(info)) {
  221                 result = info;
  222                 return Progress::Break;
  223             }
  224             return Progress::Continue;
  225         });
  226         return result;
  227     }
  228 private:
  229 
  230     Progress forwardRecursive(const Token* tok, Info info, const std::function<PathAnalysis::Progress(const Info&)>& f) const;
  231     Progress forwardRange(const Token* startToken, const Token* endToken, Info info, const std::function<Progress(const Info&)>& f) const;
  232 
  233     static const Scope* findOuterScope(const Scope * scope);
  234 
  235     static std::pair<bool, bool> checkCond(const Token * tok, bool& known);
  236 };
  237 
  238 /**
  239  * @brief Returns true if there is a path between the two tokens
  240  *
  241  * @param start Starting point of the path
  242  * @param dest The path destination
  243  * @param errorPath Adds the path traversal to the errorPath
  244  */
  245 bool reaches(const Token * start, const Token * dest, const Library& library, ErrorPath* errorPath);
  246 
  247 /**
  248  * Forward data flow analysis for checks
  249  *  - unused value
  250  *  - redundant assignment
  251  *  - valueflow analysis
  252  */
  253 class FwdAnalysis {
  254 public:
  255     FwdAnalysis(bool cpp, const Library &library) : mCpp(cpp), mLibrary(library), mWhat(What::Reassign), mValueFlowKnown(true) {}
  256 
  257     bool hasOperand(const Token *tok, const Token *lhs) const;
  258 
  259     /**
  260      * Check if "expr" is reassigned. The "expr" can be a tree (x.y[12]).
  261      * @param expr Symbolic expression to perform forward analysis for
  262      * @param startToken First token in forward analysis
  263      * @param endToken Last token in forward analysis
  264      * @return Token where expr is reassigned. If it's not reassigned then nullptr is returned.
  265      */
  266     const Token *reassign(const Token *expr, const Token *startToken, const Token *endToken);
  267 
  268     /**
  269      * Check if "expr" is used. The "expr" can be a tree (x.y[12]).
  270      * @param expr Symbolic expression to perform forward analysis for
  271      * @param startToken First token in forward analysis
  272      * @param endToken Last token in forward analysis
  273      * @return true if expr is used.
  274      */
  275     bool unusedValue(const Token *expr, const Token *startToken, const Token *endToken);
  276 
  277     struct KnownAndToken {
  278         bool known;
  279         const Token *token;
  280     };
  281 
  282     std::vector<KnownAndToken> valueFlow(const Token *expr, const Token *startToken, const Token *endToken);
  283 
  284     /** Is there some possible alias for given expression */
  285     bool possiblyAliased(const Token *expr, const Token *startToken) const;
  286 
  287     static bool isNullOperand(const Token *expr);
  288 private:
  289     static bool isEscapedAlias(const Token* expr);
  290 
  291     /** Result of forward analysis */
  292     struct Result {
  293         enum class Type { NONE, READ, WRITE, BREAK, RETURN, BAILOUT } type;
  294         explicit Result(Type type) : type(type), token(nullptr) {}
  295         Result(Type type, const Token *token) : type(type), token(token) {}
  296         const Token *token;
  297     };
  298 
  299     struct Result check(const Token *expr, const Token *startToken, const Token *endToken);
  300     struct Result checkRecursive(const Token *expr, const Token *startToken, const Token *endToken, const std::set<int> &exprVarIds, bool local, bool inInnerClass);
  301 
  302     // Is expression a l-value global data?
  303     bool isGlobalData(const Token *expr) const;
  304 
  305     const bool mCpp;
  306     const Library &mLibrary;
  307     enum class What { Reassign, UnusedValue, ValueFlow } mWhat;
  308     std::vector<KnownAndToken> mValueFlow;
  309     bool mValueFlowKnown;
  310 };
  311 
  312 #endif // astutilsH