Skip to content

Commit 96392aa

Browse files
committed
Clang import: better handling of templates
1 parent aa92815 commit 96392aa

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

lib/clangimport.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,12 @@ static std::string unquote(const std::string &s)
103103
return (s[0] == '\'') ? s.substr(1, s.size() - 2) : s;
104104
}
105105

106+
106107
static std::vector<std::string> splitString(const std::string &line)
107108
{
108109
std::vector<std::string> ret;
109110
std::string::size_type pos1 = line.find_first_not_of(" ");
110-
while (pos1 != std::string::npos) {
111+
while (pos1 < line.size()) {
111112
std::string::size_type pos2;
112113
if (line[pos1] == '*') {
113114
ret.push_back("*");
@@ -123,6 +124,24 @@ static std::vector<std::string> splitString(const std::string &line)
123124
if (pos2 < (int)line.size() - 3 && line.compare(pos2, 3, "\':\'", 0, 3) == 0)
124125
pos2 = line.find("\'", pos2 + 3);
125126
} else {
127+
pos2 = pos1;
128+
while (pos2 < line.size() && (line[pos2] == '_' || line[pos2] == ':' || std::isalnum((unsigned char)line[pos2])))
129+
++pos2;
130+
if (pos2 > pos1 && pos2 < line.size() && line[pos2] == '<' && std::isalpha(line[pos1])) {
131+
int tlevel = 1;
132+
while (++pos2 < line.size() && tlevel > 0) {
133+
if (line[pos2] == '<')
134+
++tlevel;
135+
else if (line[pos2] == '>')
136+
--tlevel;
137+
}
138+
if (tlevel == 0 && pos2 < line.size() && line[pos2] == ' ') {
139+
ret.push_back(line.substr(pos1, pos2-pos1));
140+
pos1 = pos2 + 1;
141+
continue;
142+
}
143+
}
144+
126145
pos2 = line.find(" ", pos1) - 1;
127146
if ((std::isalpha(line[pos1]) || line[pos1] == '_') &&
128147
line.find("::", pos1) < pos2 &&
@@ -1323,7 +1342,8 @@ void clangimport::AstNode::createTokensForCXXRecord(TokenList *tokenList)
13231342
child->nodeType == CXXMethodDecl ||
13241343
child->nodeType == FieldDecl ||
13251344
child->nodeType == VarDecl ||
1326-
child->nodeType == AccessSpecDecl)
1345+
child->nodeType == AccessSpecDecl ||
1346+
child->nodeType == TypedefDecl)
13271347
children2.push_back(child);
13281348
}
13291349
Scope *scope = createScope(tokenList, isStruct ? Scope::ScopeType::eStruct : Scope::ScopeType::eClass, children2, classToken);

test/testclangimport.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class TestClangImport: public TestFixture {
6666
TEST_CASE(cxxRecordDeclDerived);
6767
TEST_CASE(cxxStaticCastExpr1);
6868
TEST_CASE(cxxStaticCastExpr2);
69+
TEST_CASE(cxxStaticCastExpr3);
6970
TEST_CASE(cxxStdInitializerListExpr);
7071
TEST_CASE(cxxThrowExpr);
7172
TEST_CASE(defaultStmt);
@@ -318,7 +319,7 @@ class TestClangImport: public TestFixture {
318319
void cxxConstructorDecl2() {
319320
const char clang[] = "`-CXXConstructorDecl 0x1c208c0 <col:11> col:11 implicit constexpr basic_string 'void (std::basic_string<char> &&)' inline default trivial noexcept-unevaluated 0x1c208c0\n"
320321
" `-ParmVarDecl 0x1c209f0 <col:11> col:11 'std::basic_string<char> &&'";
321-
ASSERT_EQUALS("basic_string ( std :: basic_string<char> && ) = default ;", parse(clang));
322+
ASSERT_EQUALS("basic_string ( std::basic_string<char> && ) = default ;", parse(clang));
322323
}
323324

324325
void cxxConstructExpr1() {
@@ -482,7 +483,7 @@ class TestClangImport: public TestFixture {
482483
"| |-ParmVarDecl 0x55c786f5a6a8 <col:106, col:125> col:125 checksum 'unsigned long long'\n"
483484
"| |-ParmVarDecl 0x55c786f5ac00 <col:135, col:173> col:173 errors 'std::list<ErrorLogger::ErrorMessage> *'\n"
484485
" `-CompoundStmt 0x0 <>";
485-
ASSERT_EQUALS("_Bool analyzeFile ( const std :: string & buildDir@1 , const std :: string & sourcefile@2 , const std :: string & cfg@3 , unsigned long long checksum@4 , std :: list<ErrorLogger::ErrorMessage> * errors@5 ) { }", parse(clang));
486+
ASSERT_EQUALS("_Bool analyzeFile ( const std :: string & buildDir@1 , const std :: string & sourcefile@2 , const std :: string & cfg@3 , unsigned long long checksum@4 , std::list<ErrorLogger::ErrorMessage> * errors@5 ) { }", parse(clang));
486487
}
487488

488489
void cxxMethodDecl2() { // "unexpanded" template method
@@ -514,8 +515,6 @@ class TestClangImport: public TestFixture {
514515
"| |-TemplateArgument type 'char'\n"
515516
"| | `-BuiltinType 0x15984c0 'char'\n"
516517
"| |-CXXRecordDecl 0x15d8520 <col:5, col:12> col:12 implicit struct char_traits\n"
517-
"| |-TypedefDecl 0x15d85c0 <line:10:7, col:20> col:20 referenced char_type 'char'\n"
518-
"| | `-BuiltinType 0x15984c0 'char'\n"
519518
"| |-CXXMethodDecl 0x15d8738 <line:12:7, line:16:7> line:13:7 move 'char *(char *)' static\n"
520519
"| | |-ParmVarDecl 0x15d8630 <col:12, col:18> col:18 used __s1 'char *'\n"
521520
"| | `-CompoundStmt 0x15d88e8 <line:14:7, line:16:7>\n";
@@ -601,6 +600,24 @@ class TestClangImport: public TestFixture {
601600
ASSERT_EQUALS("int a@1 = static_cast<structstd::_Rb_tree_iterator<structstd::pair<constclassstd::__cxx11::basic_string<char>,structLibrary::AllocFunc>>&&> ( <NoName> ) ;", parse(clang));
602601
}
603602

603+
void cxxStaticCastExpr3() {
604+
const char clang[] = "`-ClassTemplateSpecializationDecl 0xd842d8 <line:4:3, line:7:3> line:4:21 struct char_traits definition\n"
605+
" |-TemplateArgument type 'char'\n"
606+
" | `-BuiltinType 0xd444c0 'char'\n"
607+
" |-CXXRecordDecl 0xd84500 <col:14, col:21> col:21 implicit struct char_traits\n"
608+
" |-TypedefDecl 0xd845a0 <line:5:7, col:20> col:20 referenced char_type 'char'\n"
609+
" | `-BuiltinType 0xd444c0 'char'\n"
610+
" `-CXXMethodDecl 0xd847b0 <line:6:7, col:80> col:18 assign 'char_traits<char>::char_type *(char_traits<char>::char_type *)'\n"
611+
" |-ParmVarDecl 0xd84670 <col:25, col:36> col:36 used __s 'char_traits<char>::char_type *'\n"
612+
" `-CompoundStmt 0xd848f8 <col:41, col:80>\n"
613+
" `-ReturnStmt 0xd848e8 <col:43, col:77>\n"
614+
" `-CXXStaticCastExpr 0xd848b8 <col:50, col:77> 'char_traits<char>::char_type *' static_cast<char_traits<char>::char_type *> <NoOp>\n"
615+
" `-ImplicitCastExpr 0xd848a0 <col:74> 'char_traits<char>::char_type *' <LValueToRValue> part_of_explicit_cast\n"
616+
" `-DeclRefExpr 0xd84870 <col:74> 'char_traits<char>::char_type *' lvalue ParmVar 0xd84670 '__s' 'char_traits<char>::char_type *'\n";
617+
618+
ASSERT_EQUALS("struct char_traits<char> { typedef char char_type ; char_traits<char>::char_type * assign ( char_traits<char>::char_type * __s@1 ) { return static_cast<char_traits<char>::char_type*> ( __s@1 ) ; } } ;", parse(clang));
619+
}
620+
604621
void cxxStdInitializerListExpr() {
605622
const char clang[] = "`-VarDecl 0x2f92060 <1.cpp:3:1, col:25> col:18 x 'std::vector<int>':'std::vector<int, std::allocator<int> >' listinit\n"
606623
" `-ExprWithCleanups 0x2fb0b40 <col:18, col:25> 'std::vector<int>':'std::vector<int, std::allocator<int> >'\n"

0 commit comments

Comments
 (0)