| 3931 | } |
| 3932 | |
| 3933 | bool Variable::arrayDimensions(const Settings& settings, bool& isContainer) |
| 3934 | { |
| 3935 | isContainer = false; |
| 3936 | const Library::Container* container = (mTypeStartToken && mTypeStartToken->isCpp()) ? settings.library.detectContainer(mTypeStartToken) : nullptr; |
| 3937 | if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) { |
| 3938 | const Token* tok = mTypeStartToken; |
| 3939 | while (Token::Match(tok, "%name%|::")) |
| 3940 | tok = tok->next(); |
| 3941 | if (tok && tok->str() == "<") { |
| 3942 | isContainer = true; |
| 3943 | Dimension dimension_; |
| 3944 | tok = tok->next(); |
| 3945 | for (int i = 0; i < container->size_templateArgNo && tok; i++) { |
| 3946 | tok = tok->nextTemplateArgument(); |
| 3947 | } |
| 3948 | if (Token::Match(tok, "%num% [,>]")) { |
| 3949 | dimension_.tok = tok; |
| 3950 | dimension_.known = true; |
| 3951 | dimension_.num = MathLib::toBigNumber(tok); |
| 3952 | } else if (tok) { |
| 3953 | dimension_.tok = tok; |
| 3954 | dimension_.known = false; |
| 3955 | } |
| 3956 | mDimensions.push_back(dimension_); |
| 3957 | return true; |
| 3958 | } |
| 3959 | } |
| 3960 | |
| 3961 | const Token *dim = mNameToken; |
| 3962 | if (!dim) { |
| 3963 | // Argument without name |
| 3964 | dim = mTypeEndToken; |
| 3965 | // back up to start of array dimensions |
| 3966 | while (dim && dim->str() == "]") |
| 3967 | dim = dim->link()->previous(); |
| 3968 | } |
| 3969 | if (dim) |
| 3970 | dim = dim->next(); |
| 3971 | if (dim && dim->str() == ")") |
| 3972 | dim = dim->next(); |
| 3973 | |
| 3974 | bool arr = false; |
| 3975 | while (dim && dim->next() && dim->str() == "[") { |
| 3976 | Dimension dimension_; |
| 3977 | dimension_.known = false; |
| 3978 | // check for empty array dimension [] |
| 3979 | if (dim->strAt(1) != "]") { |
| 3980 | dimension_.tok = dim->astOperand2(); |
| 3981 | // TODO: only perform when ValueFlow is enabled |
| 3982 | // TODO: collect timing information for this call? |
| 3983 | ValueFlow::valueFlowConstantFoldAST(const_cast<Token *>(dimension_.tok), settings); |
| 3984 | if (dimension_.tok) { |
| 3985 | if (const ValueFlow::Value* v = dimension_.tok->getKnownValue(ValueFlow::Value::ValueType::INT)) { |
| 3986 | dimension_.num = v->intvalue; |
| 3987 | dimension_.known = true; |
| 3988 | } |
| 3989 | else if (dimension_.tok->isTemplateArg() && !dimension_.tok->values().empty()) { |
| 3990 | assert(dimension_.tok->values().size() == 1); |
nothing calls this directly
no test coverage detected