| 1876 | } |
| 1877 | |
| 1878 | void CheckOtherImpl::checkConstPointer() |
| 1879 | { |
| 1880 | if (!mSettings.severity.isEnabled(Severity::style) && |
| 1881 | !mSettings.isPremiumEnabled("constParameter") && |
| 1882 | !mSettings.isPremiumEnabled("constParameterPointer") && |
| 1883 | !mSettings.isPremiumEnabled("constParameterReference") && |
| 1884 | !mSettings.isPremiumEnabled("constVariablePointer")) |
| 1885 | return; |
| 1886 | |
| 1887 | logChecker("CheckOther::checkConstPointer"); // style |
| 1888 | |
| 1889 | std::set<const Variable*, CompareVariables> pointers, nonConstPointers; |
| 1890 | for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { |
| 1891 | const Variable* const var = tok->variable(); |
| 1892 | if (!var) |
| 1893 | continue; |
| 1894 | if (!var->isLocal() && !var->isArgument()) |
| 1895 | continue; |
| 1896 | if (var->isArgument() && var->scope() && var->scope()->type == ScopeType::eLambda && !Token::simpleMatch(var->scope()->bodyEnd, "} (")) |
| 1897 | continue; |
| 1898 | const Token* const nameTok = var->nameToken(); |
| 1899 | if (tok == nameTok && var->isLocal() && !astIsRangeBasedForDecl(nameTok)) { |
| 1900 | if (var->isReference() && var->isPointer()) { |
| 1901 | nonConstPointers.emplace(var); |
| 1902 | continue; |
| 1903 | } |
| 1904 | // declarations of (static) pointers are (not) split up, array declarations are never split up |
| 1905 | if ((!var->isStatic() || Token::simpleMatch(nameTok->next(), "["))) |
| 1906 | continue; |
| 1907 | } |
| 1908 | // Skip function pointers |
| 1909 | if (Token::Match(nameTok, "%name% ) (")) |
| 1910 | continue; |
| 1911 | const ValueType* const vt = tok->valueType(); |
| 1912 | if (!vt) |
| 1913 | continue; |
| 1914 | if ((vt->pointer != 1 && !(vt->pointer == 2 && var->isArray())) || (vt->constness & 1)) |
| 1915 | continue; |
| 1916 | if (var->typeStartToken()->isTemplateArg()) |
| 1917 | continue; |
| 1918 | if (std::find(nonConstPointers.cbegin(), nonConstPointers.cend(), var) != nonConstPointers.cend()) |
| 1919 | continue; |
| 1920 | pointers.emplace(var); |
| 1921 | const Token* parent = tok->astParent(); |
| 1922 | enum Deref : std::uint8_t { NONE, DEREF, MEMBER } deref = NONE; |
| 1923 | bool hasIncDecPlus = false; |
| 1924 | if (parent && (parent->isUnaryOp("*") || (((hasIncDecPlus = parent->isIncDecOp()) || (hasIncDecPlus = (parent->str() == "+"))) && |
| 1925 | parent->astParent() && parent->astParent()->isUnaryOp("*")))) |
| 1926 | deref = DEREF; |
| 1927 | else if (Token::simpleMatch(parent, "[") && parent->astOperand1() == tok && tok != nameTok) |
| 1928 | deref = DEREF; |
| 1929 | else if (Token::Match(parent, "%op%") && Token::simpleMatch(parent->astParent(), ".")) |
| 1930 | deref = MEMBER; |
| 1931 | else if (Token::simpleMatch(parent, ".")) |
| 1932 | deref = MEMBER; |
| 1933 | else if (astIsRangeBasedForDecl(tok)) |
| 1934 | continue; |
| 1935 | else if (isCastToInteger(parent)) |
no test coverage detected