Skip to content

Commit 00eb71f

Browse files
authored
Remove constexpr -> const simplification (cppcheck-opensource#3346)
1 parent 561e917 commit 00eb71f

12 files changed

Lines changed: 113 additions & 59 deletions

lib/astutils.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,11 +1410,11 @@ bool isConstFunctionCall(const Token* ftok, const Library& library)
14101410
if (const Function* f = ftok->function()) {
14111411
if (f->isAttributePure() || f->isAttributeConst())
14121412
return true;
1413-
if (Function::returnsVoid(f))
1414-
return false;
14151413
// Any modified arguments
14161414
if (functionModifiesArguments(f))
14171415
return false;
1416+
if (Function::returnsVoid(f))
1417+
return false;
14181418
// Member function call
14191419
if (Token::simpleMatch(ftok->previous(), ".")) {
14201420
if (f->isConst())
@@ -1437,8 +1437,7 @@ bool isConstFunctionCall(const Token* ftok, const Library& library)
14371437
}
14381438
return false;
14391439
} else if (f->argumentList.empty()) {
1440-
// TODO: Check for constexpr
1441-
return false;
1440+
return f->isConstexpr();
14421441
}
14431442
} else if (const Library::Function* f = library.getFunction(ftok)) {
14441443
if (f->ispure)

lib/symboldatabase.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,7 +1985,10 @@ void Variable::evaluate(const Settings* settings)
19851985
setFlag(fIsMutable, true);
19861986
else if (tok->str() == "const")
19871987
setFlag(fIsConst, true);
1988-
else if (tok->str() == "*") {
1988+
else if (tok->str() == "constexpr") {
1989+
setFlag(fIsConst, true);
1990+
setFlag(fIsStatic, true);
1991+
} else if (tok->str() == "*") {
19891992
setFlag(fIsPointer, !isArray() || Token::Match(tok->previous(), "( * %name% )"));
19901993
setFlag(fIsConst, false); // Points to const, isn't necessarily const itself
19911994
} else if (tok->str() == "&") {
@@ -2007,7 +2010,7 @@ void Variable::evaluate(const Settings* settings)
20072010
tok = tok->next();
20082011
}
20092012

2010-
while (Token::Match(mTypeStartToken, "static|const|volatile %any%"))
2013+
while (Token::Match(mTypeStartToken, "static|const|constexpr|volatile %any%"))
20112014
mTypeStartToken = mTypeStartToken->next();
20122015
while (mTypeEndToken && mTypeEndToken->previous() && Token::Match(mTypeEndToken, "const|volatile"))
20132016
mTypeEndToken = mTypeEndToken->previous();
@@ -2300,6 +2303,11 @@ const Token *Function::setFlags(const Token *tok1, const Scope *scope)
23002303
isFriend(true);
23012304
}
23022305

2306+
// constexpr function
2307+
else if (tok1->str() == "constexpr") {
2308+
isConstexpr(true);
2309+
}
2310+
23032311
// Function template
23042312
else if (tok1->link() && tok1->str() == ">" && Token::simpleMatch(tok1->link()->previous(), "template <")) {
23052313
templateDef = tok1->link()->previous();
@@ -4309,7 +4317,7 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, con
43094317
}
43104318

43114319
// skip const|volatile|static|mutable|extern
4312-
while (tok->isKeyword() && Token::Match(tok, "const|volatile|static|mutable|extern")) {
4320+
while (tok->isKeyword() && Token::Match(tok, "const|constexpr|volatile|static|mutable|extern")) {
43134321
tok = tok->next();
43144322
}
43154323

@@ -6126,7 +6134,7 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V
61266134
type->type() && type->type()->isTypeAlias() && type->type()->typeStart &&
61276135
type->type()->typeStart->str() != type->str() && type->type()->typeStart != previousType)
61286136
parsedecl(type->type()->typeStart, valuetype, defaultSignedness, settings);
6129-
else if (type->str() == "const")
6137+
else if (Token::Match(type, "const|constexpr"))
61306138
valuetype->constness |= (1 << (valuetype->pointer - pointer0));
61316139
else if (settings->clang && type->str().size() > 2 && type->str().find("::") < type->str().find("<")) {
61326140
TokenList typeTokens(settings);

lib/symboldatabase.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ class CPPCHECKLIB Function {
723723
fHasTrailingReturnType = (1 << 21), ///< @brief has trailing return type
724724
fIsEscapeFunction = (1 << 22), ///< @brief Function throws or exits
725725
fIsInlineKeyword = (1 << 23), ///< @brief Function has "inline" keyword
726+
fIsConstexpr = (1 << 24), ///< @brief is constexpr
726727
};
727728

728729
/**
@@ -889,6 +890,13 @@ class CPPCHECKLIB Function {
889890
void isEscapeFunction(bool state) {
890891
setFlag(fIsEscapeFunction, state);
891892
}
893+
894+
bool isConstexpr() const {
895+
return getFlag(fIsConstexpr);
896+
}
897+
void isConstexpr(bool state) {
898+
setFlag(fIsConstexpr, state);
899+
}
892900
bool isSafe(const Settings *settings) const;
893901

894902
const Token *tokenDef; ///< function name token in class definition

lib/tokenize.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7259,15 +7259,15 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
72597259

72607260
//check if variable is declared 'const' or 'static' or both
72617261
while (tok2) {
7262-
if (!Token::Match(tok2, "const|static") && Token::Match(tok2, "%type% const|static")) {
7262+
if (!Token::Match(tok2, "const|static|constexpr") && Token::Match(tok2, "%type% const|static")) {
72637263
tok2 = tok2->next();
72647264
++typelen;
72657265
}
72667266

7267-
if (tok2->str() == "const")
7267+
if (Token::Match(tok2, "const|constexpr"))
72687268
isconst = true;
72697269

7270-
else if (tok2->str() == "static")
7270+
else if (Token::Match(tok2, "static|constexpr"))
72717271
isstatic = true;
72727272

72737273
else if (Token::Match(tok2, "%type% :: %type%")) {
@@ -11202,11 +11202,6 @@ void Tokenizer::simplifyKeyword()
1120211202
}
1120311203

1120411204
else if (cpp11) {
11205-
if (tok->str() == "constexpr") {
11206-
tok->originalName(tok->str());
11207-
tok->str("const");
11208-
}
11209-
1121011205
// final:
1121111206
// 1) struct name final { }; <- struct is final
1121211207
if (Token::Match(tok->previous(), "struct|class|union %type% final [:{]")) {

lib/tokenlist.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ void TokenList::determineCppC()
123123
//mKeywords.insert("bool"); // type
124124
mKeywords.insert("catch");
125125
mKeywords.insert("class");
126+
mKeywords.insert("constexpr");
126127
mKeywords.insert("const_cast");
127128
mKeywords.insert("decltype");
128129
mKeywords.insert("delete");
@@ -666,7 +667,7 @@ static bool iscpp11init_impl(const Token * const tok)
666667
endtok = nameToken->linkAt(1);
667668
else
668669
return false;
669-
if (Token::Match(nameToken, "else|try|do|const|override|volatile|&|&&"))
670+
if (Token::Match(nameToken, "else|try|do|const|constexpr|override|volatile|&|&&"))
670671
return false;
671672
if (Token::simpleMatch(nameToken->previous(), "namespace"))
672673
return false;
@@ -956,7 +957,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
956957
if (Token::simpleMatch(squareBracket->link(), "] (")) {
957958
Token* const roundBracket = squareBracket->link()->next();
958959
Token* curlyBracket = roundBracket->link()->next();
959-
while (Token::Match(curlyBracket, "mutable|const"))
960+
while (Token::Match(curlyBracket, "mutable|const|constexpr"))
960961
curlyBracket = curlyBracket->next();
961962
if (Token::simpleMatch(curlyBracket, "noexcept ("))
962963
curlyBracket = curlyBracket->linkAt(1)->next();

lib/valueflow.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,9 +2178,8 @@ struct ValueFlowAnalyzer : Analyzer {
21782178

21792179
// bailout: global non-const variables
21802180
if (isGlobal() && Token::Match(tok, "%name% (") && !Token::simpleMatch(tok->linkAt(1), ") {")) {
2181-
// TODO: Check for constexpr functions
21822181
if (tok->function()) {
2183-
if (!isConstFunctionCall(tok, getSettings()->library))
2182+
if (!tok->function()->isConstexpr() && !isConstFunctionCall(tok, getSettings()->library))
21842183
return Action::Invalid;
21852184
} else if (getSettings()->library.getFunction(tok)) {
21862185
// Assume library function doesn't modify user-global variables

test/testsimplifytemplate.cpp

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,10 +2296,10 @@ class TestSimplifyTemplate : public TestFixture {
22962296
"long f1 = fib<1>;\n"
22972297
"long f2 = fib<2>;\n"
22982298
"long f3 = fib<3>;";
2299-
const char exp[] = "const long fib<2> = fib<1> + fib<0> ; "
2300-
"const long fib<3> = fib<2> + fib<1> ; "
2301-
"const long fib<0> = 0 ; "
2302-
"const long fib<1> = 1 ; "
2299+
const char exp[] = "constexpr long fib<2> = fib<1> + fib<0> ; "
2300+
"constexpr long fib<3> = fib<2> + fib<1> ; "
2301+
"constexpr long fib<0> = 0 ; "
2302+
"constexpr long fib<1> = 1 ; "
23032303
"long f0 ; f0 = fib<0> ; "
23042304
"long f1 ; f1 = fib<1> ; "
23052305
"long f2 ; f2 = fib<2> ; "
@@ -2314,12 +2314,12 @@ class TestSimplifyTemplate : public TestFixture {
23142314
"template<>\n"
23152315
" constexpr long fib<1> = 1;\n"
23162316
"long f5 = fib<5>;\n";
2317-
const char exp[] = "const long fib<5> = fib<4> + fib<3> ; "
2318-
"const long fib<4> = fib<3> + fib<2> ; "
2319-
"const long fib<3> = fib<2> + fib<1> ; "
2320-
"const long fib<2> = fib<1> + fib<0> ; "
2321-
"const long fib<0> = 0 ; "
2322-
"const long fib<1> = 1 ; "
2317+
const char exp[] = "constexpr long fib<5> = fib<4> + fib<3> ; "
2318+
"constexpr long fib<4> = fib<3> + fib<2> ; "
2319+
"constexpr long fib<3> = fib<2> + fib<1> ; "
2320+
"constexpr long fib<2> = fib<1> + fib<0> ; "
2321+
"constexpr long fib<0> = 0 ; "
2322+
"constexpr long fib<1> = 1 ; "
23232323
"long f5 ; f5 = fib<5> ;";
23242324
ASSERT_EQUALS(exp, tok(code));
23252325
}
@@ -2933,8 +2933,8 @@ class TestSimplifyTemplate : public TestFixture {
29332933
"constexpr auto funcBraced = [](auto x){ return T{x};};\n"
29342934
"double f(int x) { return func<double>(x); }\n"
29352935
"double fBraced(int x) { return funcBraced<int>(x); }";
2936-
const char exp[] = "const auto func<double> = [ ] ( auto x ) { return double ( x ) ; } ; "
2937-
"const auto funcBraced<int> = [ ] ( auto x ) { return int { x } ; } ; "
2936+
const char exp[] = "constexpr auto func<double> = [ ] ( auto x ) { return double ( x ) ; } ; "
2937+
"constexpr auto funcBraced<int> = [ ] ( auto x ) { return int { x } ; } ; "
29382938
"double f ( int x ) { return func<double> ( x ) ; } "
29392939
"double fBraced ( int x ) { return funcBraced<int> ( x ) ; }";
29402940
ASSERT_EQUALS(exp, tok(code));
@@ -2946,8 +2946,8 @@ class TestSimplifyTemplate : public TestFixture {
29462946
" func<int>(x);\n"
29472947
" func<double>(x);\n"
29482948
"}";
2949-
const char exp[] = "const auto func<int> = [ ] ( auto x ) { return int ( x ) ; } ; "
2950-
"const auto func<double> = [ ] ( auto x ) { return double ( x ) ; } ; "
2949+
const char exp[] = "constexpr auto func<int> = [ ] ( auto x ) { return int ( x ) ; } ; "
2950+
"constexpr auto func<double> = [ ] ( auto x ) { return double ( x ) ; } ; "
29512951
"void foo ( ) { "
29522952
"func<int> ( x ) ; "
29532953
"func<double> ( x ) ; "
@@ -3084,19 +3084,19 @@ class TestSimplifyTemplate : public TestFixture {
30843084
"a<int> c ; "
30853085
"template < typename d > "
30863086
"template < typename b > "
3087-
"const decltype ( auto ) a < d > :: operator() ( b && ) const { } "
3087+
"constexpr decltype ( auto ) a < d > :: operator() ( b && ) const { } "
30883088
"struct a<int> { "
3089-
"template < typename b > const decltype ( auto ) operator() ( b && ) const ; "
3089+
"template < typename b > constexpr decltype ( auto ) operator() ( b && ) const ; "
30903090
"} ;";
30913091
const char act[] = "struct a<int> ; "
30923092
"a<int> c ; "
30933093
"template < typename d > "
30943094
"template < typename b > "
3095-
"const decltype ( auto ) a < d > :: operator() ( b && ) const { } "
3095+
"constexpr decltype ( auto ) a < d > :: operator() ( b && ) const { } "
30963096
"struct a<int> { "
3097-
"template < typename b > const decltype ( auto ) operator() ( b && ) const ; "
3097+
"template < typename b > constexpr decltype ( auto ) operator() ( b && ) const ; "
30983098
"} ; "
3099-
"const decltype ( auto ) a<int> :: operator() ( b && ) const { }";
3099+
"constexpr decltype ( auto ) a<int> :: operator() ( b && ) const { }";
31003100
TODO_ASSERT_EQUALS(exp, act, tok(code));
31013101
}
31023102
{
@@ -3270,7 +3270,7 @@ class TestSimplifyTemplate : public TestFixture {
32703270
" return foo<TrueFalse>();\n"
32713271
"}";
32723272
const char exp[] = "struct TrueFalse { "
3273-
"static const bool v ( ) { return true ; } "
3273+
"static constexpr bool v ( ) { return true ; } "
32743274
"} ; "
32753275
"int global ; "
32763276
"int foo<TrueFalse> ( ) ; "
@@ -3538,11 +3538,11 @@ class TestSimplifyTemplate : public TestFixture {
35383538
"static_assert(!e<f<char>>());\n"
35393539
"}";
35403540
const char exp[] = "namespace a { "
3541-
"const bool e<f<char>> ( ) ; "
3541+
"constexpr bool e<f<char>> ( ) ; "
35423542
"class f<char> ; "
35433543
"static_assert ( ! e<f<char>> ( ) ) ; } "
35443544
"class a :: f<char> { f<char> ( a :: f < b :: d > ) ; } ; "
3545-
"const bool a :: e<f<char>> ( ) { return false ; }";
3545+
"constexpr bool a :: e<f<char>> ( ) { return false ; }";
35463546
ASSERT_EQUALS(exp, tok(code));
35473547
}
35483548
}
@@ -3584,7 +3584,7 @@ class TestSimplifyTemplate : public TestFixture {
35843584
"using A3 = enum B3 {b = 0;};\n"
35853585
"A3<int> a3;";
35863586
const char exp[] = "template < int N > "
3587-
"using A1 = struct B1 { static const auto value = N ; } ; "
3587+
"using A1 = struct B1 { static auto constexpr value = N ; } ; "
35883588
"A1 < 0 > a1 ; "
35893589
"template < class T > "
35903590
"using A2 = struct B2 { void f ( T ) { } } ; "
@@ -4807,7 +4807,7 @@ class TestSimplifyTemplate : public TestFixture {
48074807

48084808
//both of these should work but in cppcheck 2.1 only the first option will work (ticket #9843)
48094809
{
4810-
const std::string expected = "template < long Num > const bool foo < bar < Num > > = true ;";
4810+
const std::string expected = "template < long Num > constexpr bool foo < bar < Num > > = true ;";
48114811
ASSERT_EQUALS(expected,
48124812
tok("template <long Num>\n"
48134813
"constexpr bool foo<bar<Num> > = true;\n"));
@@ -5974,28 +5974,28 @@ class TestSimplifyTemplate : public TestFixture {
59745974
{
59755975
const char code[] = "template<class T> constexpr T pi = T(3.1415926535897932385L);\n"
59765976
"float x = pi<float>;";
5977-
const char expected[] = "const float pi<float> = float ( 3.1415926535897932385L ) ; "
5977+
const char expected[] = "constexpr float pi<float> = float ( 3.1415926535897932385L ) ; "
59785978
"float x ; x = pi<float> ;";
59795979
ASSERT_EQUALS(expected, tok(code));
59805980
}
59815981
{
59825982
const char code[] = "template<class> constexpr float pi = float(3.1415926535897932385L);\n"
59835983
"float x = pi<float>;";
5984-
const char expected[] = "const float pi<float> = float ( 3.1415926535897932385L ) ; "
5984+
const char expected[] = "constexpr float pi<float> = float ( 3.1415926535897932385L ) ; "
59855985
"float x ; x = pi<float> ;";
59865986
ASSERT_EQUALS(expected, tok(code));
59875987
}
59885988
{
59895989
const char code[] = "template<class T = float> constexpr T pi = T(3.1415926535897932385L);\n"
59905990
"float x = pi<float>;";
5991-
const char expected[] = "const float pi<float> = float ( 3.1415926535897932385L ) ; "
5991+
const char expected[] = "constexpr float pi<float> = float ( 3.1415926535897932385L ) ; "
59925992
"float x ; x = pi<float> ;";
59935993
ASSERT_EQUALS(expected, tok(code));
59945994
}
59955995
{
59965996
const char code[] = "template<class T = float> constexpr T pi = T(3.1415926535897932385L);\n"
59975997
"float x = pi<>;";
5998-
const char expected[] = "const float pi<float> = float ( 3.1415926535897932385L ) ; "
5998+
const char expected[] = "constexpr float pi<float> = float ( 3.1415926535897932385L ) ; "
59995999
"float x ; x = pi<float> ;";
60006000
ASSERT_EQUALS(expected, tok(code));
60016001
}
@@ -6005,35 +6005,35 @@ class TestSimplifyTemplate : public TestFixture {
60056005
{
60066006
const char code[] = "template<class T, int N> constexpr T foo = T(N*N);\n"
60076007
"float x = foo<float,7>;";
6008-
const char expected[] = "const float foo<float,7> = float ( 49 ) ; "
6008+
const char expected[] = "constexpr float foo<float,7> = float ( 49 ) ; "
60096009
"float x ; x = foo<float,7> ;";
60106010
ASSERT_EQUALS(expected, tok(code));
60116011
}
60126012
{
60136013
const char code[] = "template<class,int> constexpr float foo = float(7);\n"
60146014
"float x = foo<float,7>;";
6015-
const char expected[] = "const float foo<float,7> = float ( 7 ) ; "
6015+
const char expected[] = "constexpr float foo<float,7> = float ( 7 ) ; "
60166016
"float x ; x = foo<float,7> ;";
60176017
ASSERT_EQUALS(expected, tok(code));
60186018
}
60196019
{
60206020
const char code[] = "template<class T = float, int N = 7> constexpr T foo = T(7);\n"
60216021
"double x = foo<double, 14>;";
6022-
const char expected[] = "const double foo<double,14> = double ( 7 ) ; "
6022+
const char expected[] = "constexpr double foo<double,14> = double ( 7 ) ; "
60236023
"double x ; x = foo<double,14> ;";
60246024
ASSERT_EQUALS(expected, tok(code));
60256025
}
60266026
{
60276027
const char code[] = "template<class T = float, int N = 7> constexpr T foo = T(7);\n"
60286028
"float x = foo<>;";
6029-
const char expected[] = "const float foo<float,7> = float ( 7 ) ; "
6029+
const char expected[] = "constexpr float foo<float,7> = float ( 7 ) ; "
60306030
"float x ; x = foo<float,7> ;";
60316031
ASSERT_EQUALS(expected, tok(code));
60326032
}
60336033
{
60346034
const char code[] = "template<class T = float, int N = 7> constexpr T foo = T(7);\n"
60356035
"double x = foo<double>;";
6036-
const char expected[] = "const double foo<double,7> = double ( 7 ) ; "
6036+
const char expected[] = "constexpr double foo<double,7> = double ( 7 ) ; "
60376037
"double x ; x = foo<double,7> ;";
60386038
ASSERT_EQUALS(expected, tok(code));
60396039
}

0 commit comments

Comments
 (0)