Skip to content

Commit 4f8a06e

Browse files
committed
Initial work for class and member function/variable list in tokenizer.
1 parent bcab694 commit 4f8a06e

5 files changed

Lines changed: 207 additions & 0 deletions

File tree

cppcheck.cbp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
<Unit filename="src/checkstl.h" />
8888
<Unit filename="src/checkunusedfunctions.cpp" />
8989
<Unit filename="src/checkunusedfunctions.h" />
90+
<Unit filename="src/classinfo.h" />
9091
<Unit filename="src/cppcheck.cpp" />
9192
<Unit filename="src/cppcheck.h" />
9293
<Unit filename="src/cppcheckexecutor.cpp" />

src/classinfo.h

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Cppcheck - A tool for static C/C++ code analysis
3+
* Copyright (C) 2007-2009 Daniel Marjamäki and 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 classInfoH
22+
#define classInfoH
23+
//---------------------------------------------------------------------------
24+
25+
#include <string>
26+
#include <vector>
27+
#include "token.h"
28+
29+
/// @addtogroup Core
30+
/// @{
31+
32+
/** @brief Holds information about a single class in checked source code. Contains member function and member variable lists. */
33+
class ClassInfo
34+
{
35+
public:
36+
37+
enum MemberType {PRIVATE, PROTECTED, PUBLIC};
38+
39+
/**
40+
* Base class for both member functions and member variables.
41+
* Contains variable name, token where name was declared and type
42+
* private/protected/public.
43+
*/
44+
class MemberInfo
45+
{
46+
public:
47+
48+
MemberInfo() : _declaration(0), _name(), _type(ClassInfo::PRIVATE)
49+
{
50+
51+
}
52+
53+
virtual ~MemberInfo() {}
54+
55+
const Token *_declaration;
56+
std::string _name;
57+
ClassInfo::MemberType _type;
58+
};
59+
60+
/**
61+
* Information about a single member function of a class.
62+
*/
63+
class MemberFunctionInfo : public MemberInfo
64+
{
65+
public:
66+
MemberFunctionInfo() : _implementation(0)
67+
{
68+
69+
}
70+
71+
const Token *_implementation;
72+
};
73+
74+
/**
75+
* Information about a single member variable of a class.
76+
*/
77+
class MemberVariableInfo : public MemberInfo
78+
{
79+
};
80+
81+
/**
82+
* List of member functions
83+
*/
84+
std::vector<MemberFunctionInfo> _memberFunctions;
85+
86+
/**
87+
* List of member variables
88+
*/
89+
std::vector<MemberVariableInfo> _memberVariables;
90+
};
91+
92+
93+
/// @}
94+
95+
//---------------------------------------------------------------------------
96+
#endif

src/tokenize.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,70 @@ void Tokenizer::simplifyTemplates()
725725
}
726726
//---------------------------------------------------------------------------
727727

728+
void Tokenizer::updateClassList()
729+
{
730+
const char pattern_class[] = "class %var% [{:]";
731+
_classInfoList.clear();
732+
733+
// Locate class
734+
const Token *tok1 = tokens();
735+
while ((tok1 = Token::findmatch(tok1, pattern_class)))
736+
{
737+
const char *className;
738+
className = tok1->strAt(1);
739+
tok1 = tok1->next();
740+
741+
ClassInfo::MemberType memberType = ClassInfo::PRIVATE;
742+
int indentlevel = 0;
743+
for (const Token *tok = tok1; tok; tok = tok->next())
744+
{
745+
// Indentation
746+
if (tok->str() == "{")
747+
{
748+
++indentlevel;
749+
continue;
750+
}
751+
752+
else if (tok->str() == "}")
753+
{
754+
--indentlevel;
755+
if (indentlevel <= 0)
756+
break;
757+
758+
continue;
759+
}
760+
761+
// Parse class contents (indentlevel == 1)..
762+
if (indentlevel == 1)
763+
{
764+
if (tok->str() == "private:")
765+
memberType = ClassInfo::PRIVATE;
766+
else if (tok->str() == "protected:")
767+
memberType = ClassInfo::PROTECTED;
768+
else if (tok->str() == "public:")
769+
memberType = ClassInfo::PUBLIC;
770+
771+
else if (Token::Match(tok, "typedef %type% ("))
772+
tok = tok->tokAt(2);
773+
774+
else if (Token::Match(tok, "[:,] %var% ("))
775+
tok = tok->tokAt(2);
776+
777+
else if (Token::Match(tok, "%var% ("))
778+
{
779+
// member function
780+
ClassInfo::MemberFunctionInfo func;
781+
func._declaration = tok;
782+
func._name = tok->str();
783+
func._type = memberType;
784+
785+
_classInfoList[className]._memberFunctions.push_back(func);
786+
}
787+
}
788+
}
789+
}
790+
}
791+
728792

729793
void Tokenizer::setVarId()
730794
{

src/tokenize.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <string>
2626
#include <map>
2727
#include <vector>
28+
#include "classinfo.h"
2829

2930
class Token;
3031
class ErrorLogger;
@@ -105,6 +106,12 @@ class Tokenizer
105106
*/
106107
static const Token *findClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel);
107108

109+
/**
110+
* List of classes in currently checked source code and
111+
* their member functions and member variables.
112+
*/
113+
std::map<std::string, ClassInfo> _classInfoList;
114+
108115
private:
109116

110117
/**
@@ -280,6 +287,12 @@ class Tokenizer
280287

281288
void syntaxError(const Token *tok, char c);
282289

290+
/**
291+
* Update _classInfoList to contain class names and member
292+
* functions and member variables.
293+
*/
294+
void updateClassList();
295+
283296
Token *_tokens, *_tokensBack;
284297
std::map<std::string, unsigned int> _typeSize;
285298
std::vector<std::string> _files;

test/testtokenize.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ class TestTokenizer : public TestFixture
143143

144144
// unsigned i; => unsigned int i;
145145
TEST_CASE(unsigned1);
146+
TEST_CASE(testUpdateClassList);
146147
}
147148

148149

@@ -2387,6 +2388,38 @@ class TestTokenizer : public TestFixture
23872388

23882389
}
23892390

2391+
void tokenizeAndUpdateClassList(const char code[])
2392+
{
2393+
// tokenize..
2394+
Tokenizer tokenizer;
2395+
std::istringstream istr(code);
2396+
tokenizer.tokenize(istr, "test.cpp");
2397+
tokenizer.updateClassList();
2398+
}
2399+
2400+
void testUpdateClassList()
2401+
{
2402+
const char code[] = "class A{\n"
2403+
" void f() {}\n"
2404+
" public:\n"
2405+
" void g() {}\n"
2406+
"};";
2407+
Tokenizer tokenizer;
2408+
std::istringstream istr(code);
2409+
tokenizer.tokenize(istr, "test.cpp");
2410+
tokenizer.updateClassList();
2411+
ASSERT_EQUALS(2, tokenizer._classInfoList["A"]._memberFunctions.size());
2412+
if (tokenizer._classInfoList["A"]._memberFunctions.size() > 1)
2413+
{
2414+
ASSERT_EQUALS(std::string("f"), tokenizer._classInfoList["A"]._memberFunctions[0]._name);
2415+
ASSERT_EQUALS(std::string("f"), tokenizer._classInfoList["A"]._memberFunctions[0]._declaration->str());
2416+
ASSERT_EQUALS(ClassInfo::PRIVATE, tokenizer._classInfoList["A"]._memberFunctions[0]._type);
2417+
ASSERT_EQUALS(std::string("g"), tokenizer._classInfoList["A"]._memberFunctions[1]._name);
2418+
ASSERT_EQUALS(std::string("g"), tokenizer._classInfoList["A"]._memberFunctions[1]._declaration->str());
2419+
ASSERT_EQUALS(ClassInfo::PUBLIC, tokenizer._classInfoList["A"]._memberFunctions[1]._type);
2420+
}
2421+
}
2422+
23902423
};
23912424

23922425
REGISTER_TEST(TestTokenizer)

0 commit comments

Comments
 (0)