diff --git a/lib/clangastdump.cpp b/lib/clangastdump.cpp index 1f2f29f20..183ce30f7 100644 --- a/lib/clangastdump.cpp +++ b/lib/clangastdump.cpp @@ -32,6 +32,8 @@ static const std::string BreakStmt = "BreakStmt"; static const std::string CallExpr = "CallExpr"; static const std::string CompoundStmt = "CompoundStmt"; static const std::string ContinueStmt = "ContinueStmt"; +static const std::string CXXMethodDecl = "CXXMethodDecl"; +static const std::string CXXRecordDecl = "CXXRecordDecl"; static const std::string DeclRefExpr = "DeclRefExpr"; static const std::string DeclStmt = "DeclStmt"; static const std::string FieldDecl = "FieldDecl"; @@ -158,6 +160,7 @@ namespace clangastdump { void addTypeTokens(TokenList *tokenList, const std::string &str); Scope *createScope(TokenList *tokenList, Scope::ScopeType scopeType, AstNodePtr astNode); Scope *createScope(TokenList *tokenList, Scope::ScopeType scopeType, const std::vector &children); + void createTokensFunctionDecl(TokenList *tokenList); Token *createTokensVarDecl(TokenList *tokenList); std::string getSpelling() const; std::string getType() const; @@ -344,6 +347,25 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList) } if (nodeType == ContinueStmt) return addtoken(tokenList, "continue"); + if (nodeType == CXXMethodDecl) { + createTokensFunctionDecl(tokenList); + return nullptr; + } + if (nodeType == CXXRecordDecl) { + Token *classToken = addtoken(tokenList, "class"); + Token *nameToken = addtoken(tokenList, mExtTokens[mExtTokens.size() - 2]); + std::vector children2; + for (auto child: children) { + if (child->nodeType == "CXXMethodDecl") + children2.push_back(child); + } + Scope *scope = createScope(tokenList, Scope::ScopeType::eClass, children2); + scope->classDef = classToken; + scope->className = nameToken->str(); + mData->mSymbolDatabase->typeList.push_back(Type(classToken, scope, classToken->scope())); + scope->definedType = &mData->mSymbolDatabase->typeList.back(); + return nullptr; + } if (nodeType == DeclStmt) return children[0]->createTokens(tokenList); if (nodeType == DeclRefExpr) { @@ -374,52 +396,7 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList) return nullptr; } if (nodeType == FunctionDecl) { - SymbolDatabase *symbolDatabase = mData->mSymbolDatabase; - const int nameIndex = (mExtTokens.back() == "extern") ? - (mExtTokens.size() - 3) : - (mExtTokens.size() - 2); - const int retTypeIndex = nameIndex + 1; - addTypeTokens(tokenList, mExtTokens[retTypeIndex]); - Token *nameToken = addtoken(tokenList, mExtTokens[nameIndex]); - Scope *nestedIn = const_cast(nameToken->scope()); - symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn)); - Scope &scope = symbolDatabase->scopeList.back(); - symbolDatabase->functionScopes.push_back(&scope); - nestedIn->functionList.push_back(Function(nameToken)); - scope.function = &nestedIn->functionList.back(); - scope.type = Scope::ScopeType::eFunction; - scope.className = nameToken->str(); - mData->funcDecl(mExtTokens.front(), nameToken, scope.function); - Token *par1 = addtoken(tokenList, "("); - // Function arguments - for (AstNodePtr child: children) { - if (child->nodeType != ParmVarDecl) - continue; - if (tokenList->back() != par1) - addtoken(tokenList, ","); - addTypeTokens(tokenList, child->mExtTokens.back()); - const std::string spelling = child->getSpelling(); - if (!spelling.empty()) { - const std::string addr = child->mExtTokens[0]; - Token *vartok = addtoken(tokenList, spelling); - scope.function->argumentList.push_back(Variable(vartok, nullptr, nullptr, 0, AccessControl::Argument, nullptr, &scope, nullptr)); - mData->varDecl(addr, vartok, &scope.function->argumentList.back()); - } - } - Token *par2 = addtoken(tokenList, ")"); - par1->link(par2); - // Function body - if (!children.empty() && children.back()->nodeType == CompoundStmt) { - Token *bodyStart = addtoken(tokenList, "{"); - bodyStart->scope(&scope); - children.back()->createTokens(tokenList); - Token *bodyEnd = addtoken(tokenList, "}"); - scope.bodyStart = bodyStart; - scope.bodyEnd = bodyEnd; - bodyStart->link(bodyEnd); - } else { - addtoken(tokenList, ";"); - } + createTokensFunctionDecl(tokenList); return nullptr; } if (nodeType == IfStmt) { @@ -515,6 +492,56 @@ Token *clangastdump::AstNode::createTokens(TokenList *tokenList) return addtoken(tokenList, "?" + nodeType + "?"); } +void clangastdump::AstNode::createTokensFunctionDecl(TokenList *tokenList) +{ + SymbolDatabase *symbolDatabase = mData->mSymbolDatabase; + const int nameIndex = (mExtTokens.back() == "extern") ? + (mExtTokens.size() - 3) : + (mExtTokens.size() - 2); + const int retTypeIndex = nameIndex + 1; + addTypeTokens(tokenList, mExtTokens[retTypeIndex]); + Token *nameToken = addtoken(tokenList, mExtTokens[nameIndex]); + Scope *nestedIn = const_cast(nameToken->scope()); + symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn)); + Scope &scope = symbolDatabase->scopeList.back(); + symbolDatabase->functionScopes.push_back(&scope); + nestedIn->functionList.push_back(Function(nameToken)); + scope.function = &nestedIn->functionList.back(); + scope.type = Scope::ScopeType::eFunction; + scope.className = nameToken->str(); + mData->funcDecl(mExtTokens.front(), nameToken, scope.function); + Token *par1 = addtoken(tokenList, "("); + // Function arguments + for (AstNodePtr child: children) { + if (child->nodeType != ParmVarDecl) + continue; + if (tokenList->back() != par1) + addtoken(tokenList, ","); + addTypeTokens(tokenList, child->mExtTokens.back()); + const std::string spelling = child->getSpelling(); + if (!spelling.empty()) { + const std::string addr = child->mExtTokens[0]; + Token *vartok = addtoken(tokenList, spelling); + scope.function->argumentList.push_back(Variable(vartok, nullptr, nullptr, 0, AccessControl::Argument, nullptr, &scope, nullptr)); + mData->varDecl(addr, vartok, &scope.function->argumentList.back()); + } + } + Token *par2 = addtoken(tokenList, ")"); + par1->link(par2); + // Function body + if (!children.empty() && children.back()->nodeType == CompoundStmt) { + Token *bodyStart = addtoken(tokenList, "{"); + bodyStart->scope(&scope); + children.back()->createTokens(tokenList); + Token *bodyEnd = addtoken(tokenList, "}"); + scope.bodyStart = bodyStart; + scope.bodyEnd = bodyEnd; + bodyStart->link(bodyEnd); + } else { + addtoken(tokenList, ";"); + } +} + Token * clangastdump::AstNode::createTokensVarDecl(TokenList *tokenList) { const std::string addr = mExtTokens.front(); diff --git a/test/testclangastdump.cpp b/test/testclangastdump.cpp index 88b81e93e..b393df973 100644 --- a/test/testclangastdump.cpp +++ b/test/testclangastdump.cpp @@ -30,6 +30,7 @@ public: private: void run() OVERRIDE { TEST_CASE(breakStmt); + TEST_CASE(class1); TEST_CASE(continueStmt); TEST_CASE(forStmt); TEST_CASE(funcdecl1); @@ -49,9 +50,6 @@ private: TEST_CASE(vardecl4); TEST_CASE(vardecl5); TEST_CASE(whileStmt); - - // C++.. - TEST_CASE(namespaceDecl); } std::string parse(const char clang[]) { @@ -72,6 +70,21 @@ private: ASSERT_EQUALS("void foo ( ) { while ( 0 ) { break ; } ; }", parse(clang)); } + void class1() { + const char clang[] = "`-CXXRecordDecl 0x274c638 col:7 class C definition\n" + " |-DefinitionData pass_in_registers empty aggregate standard_layout trivially_copyable pod trivial literal has_constexpr_non_copy_move_ctor can_const_default_init\n" + " | |-DefaultConstructor exists trivial constexpr needs_implicit defaulted_is_constexpr\n" + " | |-CopyConstructor simple trivial has_const_param needs_implicit implicit_has_const_param\n" + " | |-MoveConstructor exists simple trivial needs_implicit\n" + " | |-CopyAssignment trivial has_const_param needs_implicit implicit_has_const_param\n" + " | |-MoveAssignment exists simple trivial needs_implicit\n" + " | `-Destructor simple irrelevant trivial needs_implicit\n" + " |-CXXRecordDecl 0x274c758 col:7 implicit class C\n" + " `-CXXMethodDecl 0x274c870 col:16 foo 'void ()'\n" + " `-CompoundStmt 0x274c930 "; + ASSERT_EQUALS("class C { void foo ( ) { } }", parse(clang)); + } + void continueStmt() { const char clang[] = "`-FunctionDecl 0x2c31b18 <1.c:1:1, col:34> col:6 foo 'void ()'\n" " `-CompoundStmt 0x2c31c40 \n"