diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 2f58af662..aa04b6b97 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -131,6 +131,24 @@ bool astIsFloat(const Token *tok, bool unknown) return unknown; } +std::string astCanonicalType(const Token *expr) +{ + if (!expr) + return ""; + if (expr->variable()) { + const Variable *var = expr->variable(); + std::string ret; + for (const Token *type = var->typeStartToken(); Token::Match(type,"%name%|::") && type != var->nameToken(); type = type->next()) { + if (!Token::Match(type, "const|static")) + ret += type->str(); + } + return ret; + + } + // TODO: handle expressions + return ""; +} + const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok) { if (!tok) diff --git a/lib/astutils.h b/lib/astutils.h index e5899d733..88ac062a5 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -35,6 +35,17 @@ bool astIsIntegral(const Token *tok, bool unknown); /** Is expression of floating point type? */ bool astIsFloat(const Token *tok, bool unknown); +/** + * Get canonical type of expression. const/static/etc are not included and neither *&. + * For example: + * Expression type Return + * std::string std::string + * int * int + * static const int int + * std::vector std::vector + */ +std::string astCanonicalType(const Token *expr); + /** Is given syntax tree a variable comparison against value */ const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const std::string &rhs, const Token **vartok=nullptr); diff --git a/lib/library.cpp b/lib/library.cpp index 412ec5be6..4a104bf03 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -23,6 +23,7 @@ #include "mathlib.h" #include "token.h" #include "symboldatabase.h" +#include "astutils.h" #include #include @@ -626,8 +627,45 @@ bool Library::isargvalid(const Token *ftok, int argnr, const MathLib::bigint arg return false; } +static std::string functionName(const Token *ftok, bool *error) +{ + if (!ftok) { + *error = true; + return ""; + } + if (ftok->isName()) + return ftok->str(); + if (ftok->str() == "::") { + if (!ftok->astOperand2()) + return functionName(ftok->astOperand1(), error); + return functionName(ftok->astOperand1(),error) + "::" + functionName(ftok->astOperand2(),error); + } + if (ftok->str() == "." && ftok->astOperand1()) { + const std::string type = astCanonicalType(ftok->astOperand1()); + if (type.empty()) { + *error = true; + return ""; + } + + return type + "::" + functionName(ftok->astOperand2(),error); + } + *error = true; + return ""; +} + static std::string functionName(const Token *ftok) { + if (!Token::Match(ftok, "%name% (")) + return ""; + + // Lookup function name using AST.. + if (ftok->astParent()) { + bool error = false; + std::string ret = functionName(ftok->next()->astOperand1(), &error); + return error ? std::string() : ret; + } + + // Lookup function name without using AST.. if (Token::simpleMatch(ftok->previous(), ".")) return ""; if (!Token::Match(ftok->tokAt(-2), "%name% ::")) @@ -715,10 +753,6 @@ const Library::Container* Library::detectContainer(const Token* typeStart) const // returns true if ftok is not a library function bool Library::isNotLibraryFunction(const Token *ftok) const { - // methods are not library functions - // called from tokenizer, ast is not created properly yet - if (Token::simpleMatch(ftok->previous(),".")) - return true; if (ftok->function() && ftok->function()->nestedIn && ftok->function()->nestedIn->type != Scope::eGlobal) return true;