Clang import: better handling of templates

This commit is contained in:
Daniel Marjamäki 2020-11-24 22:02:59 +01:00
parent aa9281515d
commit 96392aa212
2 changed files with 43 additions and 6 deletions

View File

@ -103,11 +103,12 @@ static std::string unquote(const std::string &s)
return (s[0] == '\'') ? s.substr(1, s.size() - 2) : s;
}
static std::vector<std::string> splitString(const std::string &line)
{
std::vector<std::string> ret;
std::string::size_type pos1 = line.find_first_not_of(" ");
while (pos1 != std::string::npos) {
while (pos1 < line.size()) {
std::string::size_type pos2;
if (line[pos1] == '*') {
ret.push_back("*");
@ -123,6 +124,24 @@ static std::vector<std::string> splitString(const std::string &line)
if (pos2 < (int)line.size() - 3 && line.compare(pos2, 3, "\':\'", 0, 3) == 0)
pos2 = line.find("\'", pos2 + 3);
} else {
pos2 = pos1;
while (pos2 < line.size() && (line[pos2] == '_' || line[pos2] == ':' || std::isalnum((unsigned char)line[pos2])))
++pos2;
if (pos2 > pos1 && pos2 < line.size() && line[pos2] == '<' && std::isalpha(line[pos1])) {
int tlevel = 1;
while (++pos2 < line.size() && tlevel > 0) {
if (line[pos2] == '<')
++tlevel;
else if (line[pos2] == '>')
--tlevel;
}
if (tlevel == 0 && pos2 < line.size() && line[pos2] == ' ') {
ret.push_back(line.substr(pos1, pos2-pos1));
pos1 = pos2 + 1;
continue;
}
}
pos2 = line.find(" ", pos1) - 1;
if ((std::isalpha(line[pos1]) || line[pos1] == '_') &&
line.find("::", pos1) < pos2 &&
@ -1323,7 +1342,8 @@ void clangimport::AstNode::createTokensForCXXRecord(TokenList *tokenList)
child->nodeType == CXXMethodDecl ||
child->nodeType == FieldDecl ||
child->nodeType == VarDecl ||
child->nodeType == AccessSpecDecl)
child->nodeType == AccessSpecDecl ||
child->nodeType == TypedefDecl)
children2.push_back(child);
}
Scope *scope = createScope(tokenList, isStruct ? Scope::ScopeType::eStruct : Scope::ScopeType::eClass, children2, classToken);

View File

@ -66,6 +66,7 @@ private:
TEST_CASE(cxxRecordDeclDerived);
TEST_CASE(cxxStaticCastExpr1);
TEST_CASE(cxxStaticCastExpr2);
TEST_CASE(cxxStaticCastExpr3);
TEST_CASE(cxxStdInitializerListExpr);
TEST_CASE(cxxThrowExpr);
TEST_CASE(defaultStmt);
@ -318,7 +319,7 @@ private:
void cxxConstructorDecl2() {
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"
" `-ParmVarDecl 0x1c209f0 <col:11> col:11 'std::basic_string<char> &&'";
ASSERT_EQUALS("basic_string ( std :: basic_string<char> && ) = default ;", parse(clang));
ASSERT_EQUALS("basic_string ( std::basic_string<char> && ) = default ;", parse(clang));
}
void cxxConstructExpr1() {
@ -482,7 +483,7 @@ private:
"| |-ParmVarDecl 0x55c786f5a6a8 <col:106, col:125> col:125 checksum 'unsigned long long'\n"
"| |-ParmVarDecl 0x55c786f5ac00 <col:135, col:173> col:173 errors 'std::list<ErrorLogger::ErrorMessage> *'\n"
" `-CompoundStmt 0x0 <>";
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));
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));
}
void cxxMethodDecl2() { // "unexpanded" template method
@ -514,8 +515,6 @@ private:
"| |-TemplateArgument type 'char'\n"
"| | `-BuiltinType 0x15984c0 'char'\n"
"| |-CXXRecordDecl 0x15d8520 <col:5, col:12> col:12 implicit struct char_traits\n"
"| |-TypedefDecl 0x15d85c0 <line:10:7, col:20> col:20 referenced char_type 'char'\n"
"| | `-BuiltinType 0x15984c0 'char'\n"
"| |-CXXMethodDecl 0x15d8738 <line:12:7, line:16:7> line:13:7 move 'char *(char *)' static\n"
"| | |-ParmVarDecl 0x15d8630 <col:12, col:18> col:18 used __s1 'char *'\n"
"| | `-CompoundStmt 0x15d88e8 <line:14:7, line:16:7>\n";
@ -601,6 +600,24 @@ private:
ASSERT_EQUALS("int a@1 = static_cast<structstd::_Rb_tree_iterator<structstd::pair<constclassstd::__cxx11::basic_string<char>,structLibrary::AllocFunc>>&&> ( <NoName> ) ;", parse(clang));
}
void cxxStaticCastExpr3() {
const char clang[] = "`-ClassTemplateSpecializationDecl 0xd842d8 <line:4:3, line:7:3> line:4:21 struct char_traits definition\n"
" |-TemplateArgument type 'char'\n"
" | `-BuiltinType 0xd444c0 'char'\n"
" |-CXXRecordDecl 0xd84500 <col:14, col:21> col:21 implicit struct char_traits\n"
" |-TypedefDecl 0xd845a0 <line:5:7, col:20> col:20 referenced char_type 'char'\n"
" | `-BuiltinType 0xd444c0 'char'\n"
" `-CXXMethodDecl 0xd847b0 <line:6:7, col:80> col:18 assign 'char_traits<char>::char_type *(char_traits<char>::char_type *)'\n"
" |-ParmVarDecl 0xd84670 <col:25, col:36> col:36 used __s 'char_traits<char>::char_type *'\n"
" `-CompoundStmt 0xd848f8 <col:41, col:80>\n"
" `-ReturnStmt 0xd848e8 <col:43, col:77>\n"
" `-CXXStaticCastExpr 0xd848b8 <col:50, col:77> 'char_traits<char>::char_type *' static_cast<char_traits<char>::char_type *> <NoOp>\n"
" `-ImplicitCastExpr 0xd848a0 <col:74> 'char_traits<char>::char_type *' <LValueToRValue> part_of_explicit_cast\n"
" `-DeclRefExpr 0xd84870 <col:74> 'char_traits<char>::char_type *' lvalue ParmVar 0xd84670 '__s' 'char_traits<char>::char_type *'\n";
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));
}
void cxxStdInitializerListExpr() {
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"
" `-ExprWithCleanups 0x2fb0b40 <col:18, col:25> 'std::vector<int>':'std::vector<int, std::allocator<int> >'\n"