Clang import: Better handling of methods that are defined after declaration
This commit is contained in:
parent
8fd0839fea
commit
66ee3a0afc
|
@ -214,6 +214,10 @@ namespace clangimport {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasDecl(const std::string &addr) const {
|
||||||
|
return mDeclMap.find(addr) != mDeclMap.end();
|
||||||
|
}
|
||||||
|
|
||||||
// "}" tokens that are not end-of-scope
|
// "}" tokens that are not end-of-scope
|
||||||
std::set<Token *> mNotScope;
|
std::set<Token *> mNotScope;
|
||||||
private:
|
private:
|
||||||
|
@ -678,6 +682,10 @@ Token *clangimport::AstNode::createTokens(TokenList *tokenList)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (nodeType == CXXMethodDecl) {
|
if (nodeType == CXXMethodDecl) {
|
||||||
|
for (int i = 0; i+1 < mExtTokens.size(); ++i) {
|
||||||
|
if (mExtTokens[i] == "prev" && !mData->hasDecl(mExtTokens[i+1]))
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
createTokensFunctionDecl(tokenList);
|
createTokensFunctionDecl(tokenList);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1053,19 +1061,38 @@ Token * clangimport::AstNode::createTokensCall(TokenList *tokenList)
|
||||||
|
|
||||||
void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
||||||
{
|
{
|
||||||
|
const bool prev = (std::find(mExtTokens.begin(), mExtTokens.end(), "prev") != mExtTokens.end());
|
||||||
|
const bool hasBody = mFile == 0 && !children.empty() && children.back()->nodeType == CompoundStmt;
|
||||||
|
|
||||||
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
|
SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
|
||||||
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
addTypeTokens(tokenList, '\'' + getType() + '\'');
|
||||||
Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
|
Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
|
||||||
Scope *nestedIn = const_cast<Scope *>(nameToken->scope());
|
Scope *nestedIn = const_cast<Scope *>(nameToken->scope());
|
||||||
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn));
|
|
||||||
Scope &scope = symbolDatabase->scopeList.back();
|
if (!prev) {
|
||||||
nestedIn->functionList.push_back(Function(nameToken));
|
nestedIn->functionList.push_back(Function(nameToken));
|
||||||
scope.function = &nestedIn->functionList.back();
|
mData->funcDecl(mExtTokens.front(), nameToken, &nestedIn->functionList.back());
|
||||||
scope.type = Scope::ScopeType::eFunction;
|
} else {
|
||||||
scope.className = nameToken->str();
|
const std::string addr = *(std::find(mExtTokens.begin(), mExtTokens.end(), "prev") + 1);
|
||||||
mData->funcDecl(mExtTokens.front(), nameToken, scope.function);
|
mData->ref(addr, nameToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
Function * const function = const_cast<Function*>(nameToken->function());
|
||||||
|
|
||||||
|
Scope *scope = nullptr;
|
||||||
|
if (hasBody) {
|
||||||
|
symbolDatabase->scopeList.push_back(Scope(nullptr, nullptr, nestedIn));
|
||||||
|
scope = &symbolDatabase->scopeList.back();
|
||||||
|
scope->function = function;
|
||||||
|
scope->type = Scope::ScopeType::eFunction;
|
||||||
|
scope->className = nameToken->str();
|
||||||
|
nestedIn->nestedList.push_back(scope);
|
||||||
|
function->hasBody(true);
|
||||||
|
}
|
||||||
|
|
||||||
Token *par1 = addtoken(tokenList, "(");
|
Token *par1 = addtoken(tokenList, "(");
|
||||||
// Function arguments
|
// Function arguments
|
||||||
|
function->argumentList.clear();
|
||||||
for (int i = 0; i < children.size(); ++i) {
|
for (int i = 0; i < children.size(); ++i) {
|
||||||
AstNodePtr child = children[i];
|
AstNodePtr child = children[i];
|
||||||
if (child->nodeType != ParmVarDecl)
|
if (child->nodeType != ParmVarDecl)
|
||||||
|
@ -1077,24 +1104,25 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList)
|
||||||
Token *vartok = nullptr;
|
Token *vartok = nullptr;
|
||||||
if (!spelling.empty())
|
if (!spelling.empty())
|
||||||
vartok = child->addtoken(tokenList, spelling);
|
vartok = child->addtoken(tokenList, spelling);
|
||||||
scope.function->argumentList.push_back(Variable(vartok, child->getType(), nullptr, i, AccessControl::Argument, nullptr, &scope));
|
function->argumentList.push_back(Variable(vartok, child->getType(), nullptr, i, AccessControl::Argument, nullptr, scope));
|
||||||
if (vartok) {
|
if (vartok) {
|
||||||
const std::string addr = child->mExtTokens[0];
|
const std::string addr = child->mExtTokens[0];
|
||||||
mData->varDecl(addr, vartok, &scope.function->argumentList.back());
|
mData->varDecl(addr, vartok, &function->argumentList.back());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Token *par2 = addtoken(tokenList, ")");
|
Token *par2 = addtoken(tokenList, ")");
|
||||||
par1->link(par2);
|
par1->link(par2);
|
||||||
par2->link(par1);
|
par2->link(par1);
|
||||||
|
|
||||||
// Function body
|
// Function body
|
||||||
if (mFile == 0 && !children.empty() && children.back()->nodeType == CompoundStmt) {
|
if (hasBody) {
|
||||||
symbolDatabase->functionScopes.push_back(&scope);
|
symbolDatabase->functionScopes.push_back(scope);
|
||||||
Token *bodyStart = addtoken(tokenList, "{");
|
Token *bodyStart = addtoken(tokenList, "{");
|
||||||
bodyStart->scope(&scope);
|
bodyStart->scope(scope);
|
||||||
children.back()->createTokens(tokenList);
|
children.back()->createTokens(tokenList);
|
||||||
Token *bodyEnd = addtoken(tokenList, "}");
|
Token *bodyEnd = addtoken(tokenList, "}");
|
||||||
scope.bodyStart = bodyStart;
|
scope->bodyStart = bodyStart;
|
||||||
scope.bodyEnd = bodyEnd;
|
scope->bodyEnd = bodyEnd;
|
||||||
bodyStart->link(bodyEnd);
|
bodyStart->link(bodyEnd);
|
||||||
bodyEnd->link(bodyStart);
|
bodyEnd->link(bodyStart);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -50,7 +50,9 @@ private:
|
||||||
TEST_CASE(cxxForRangeStmt1);
|
TEST_CASE(cxxForRangeStmt1);
|
||||||
TEST_CASE(cxxForRangeStmt2);
|
TEST_CASE(cxxForRangeStmt2);
|
||||||
TEST_CASE(cxxMemberCall);
|
TEST_CASE(cxxMemberCall);
|
||||||
TEST_CASE(cxxMethodDecl);
|
TEST_CASE(cxxMethodDecl1);
|
||||||
|
TEST_CASE(cxxMethodDecl2);
|
||||||
|
TEST_CASE(cxxMethodDecl3);
|
||||||
TEST_CASE(cxxNewExpr);
|
TEST_CASE(cxxNewExpr);
|
||||||
TEST_CASE(cxxNullPtrLiteralExpr);
|
TEST_CASE(cxxNullPtrLiteralExpr);
|
||||||
TEST_CASE(cxxOperatorCallExpr);
|
TEST_CASE(cxxOperatorCallExpr);
|
||||||
|
@ -435,7 +437,7 @@ private:
|
||||||
ASSERT_EQUALS("void bar ( ) { C<int> c@1 ( C<int> ( ) ) ; c@1 . foo ( ) ; }", parse(clang));
|
ASSERT_EQUALS("void bar ( ) { C<int> c@1 ( C<int> ( ) ) ; c@1 . foo ( ) ; }", parse(clang));
|
||||||
}
|
}
|
||||||
|
|
||||||
void cxxMethodDecl() {
|
void cxxMethodDecl1() {
|
||||||
const char clang[] = "|-CXXMethodDecl 0x55c786f5ad60 <line:56:5, col:179> col:10 analyzeFile '_Bool (const std::string &, const std::string &, const std::string &, unsigned long long, std::list<ErrorLogger::ErrorMessage> *)'\n"
|
const char clang[] = "|-CXXMethodDecl 0x55c786f5ad60 <line:56:5, col:179> col:10 analyzeFile '_Bool (const std::string &, const std::string &, const std::string &, unsigned long long, std::list<ErrorLogger::ErrorMessage> *)'\n"
|
||||||
"| |-ParmVarDecl 0x55c786f5a4c8 <col:22, col:41> col:41 buildDir 'const std::string &'\n"
|
"| |-ParmVarDecl 0x55c786f5a4c8 <col:22, col:41> col:41 buildDir 'const std::string &'\n"
|
||||||
"| |-ParmVarDecl 0x55c786f5a580 <col:51, col:70> col:70 sourcefile 'const std::string &'\n"
|
"| |-ParmVarDecl 0x55c786f5a580 <col:51, col:70> col:70 sourcefile 'const std::string &'\n"
|
||||||
|
@ -446,6 +448,34 @@ private:
|
||||||
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
|
||||||
|
const char clang[] = "`-CXXMethodDecl 0x220ecb0 parent 0x21e4c28 prev 0x21e5338 <line:11:1, line:18:1> line:14:1 find 'const typename char_traits<_CharT>::char_type *(const char_traits::char_type *, int, const char_traits::char_type &)'\n"
|
||||||
|
" `-CompoundStmt 0x220ede0 <line:15:1, line:18:1>\n"
|
||||||
|
" `-ReturnStmt 0x220edd0 <line:17:5, col:12>\n"
|
||||||
|
" `-IntegerLiteral 0x220edb0 <col:12> 'int' 0";
|
||||||
|
ASSERT_EQUALS("", parse(clang));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cxxMethodDecl3() {
|
||||||
|
const char clang[] = "|-CXXRecordDecl 0x21cca40 <2.cpp:2:1, line:4:1> line:2:7 class Fred 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 0x21ccb58 <col:1, col:7> col:7 implicit class Fred\n"
|
||||||
|
"| `-CXXMethodDecl 0x21ccc68 <line:3:1, col:10> col:6 foo 'void ()'\n"
|
||||||
|
"`-CXXMethodDecl 0x21ccd60 parent 0x21cca40 prev 0x21ccc68 <line:6:1, col:19> col:12 foo 'void ()'\n"
|
||||||
|
" `-CompoundStmt 0x21cce50 <col:18, col:19>";
|
||||||
|
ASSERT_EQUALS("class Fred\n"
|
||||||
|
"{ void foo ( ) ; }\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
"void foo ( ) { }", parse(clang));
|
||||||
|
}
|
||||||
|
|
||||||
void cxxNewExpr() {
|
void cxxNewExpr() {
|
||||||
const char clang[] = "|-VarDecl 0x3a97680 <1.cpp:2:1, col:14> col:6 i 'int *' cinit\n"
|
const char clang[] = "|-VarDecl 0x3a97680 <1.cpp:2:1, col:14> col:6 i 'int *' cinit\n"
|
||||||
"| `-CXXNewExpr 0x3a97d18 <col:10, col:14> 'int *' Function 0x3a97778 'operator new' 'void *(unsigned long)'\n"
|
"| `-CXXNewExpr 0x3a97d18 <col:10, col:14> 'int *' Function 0x3a97778 'operator new' 'void *(unsigned long)'\n"
|
||||||
|
|
Loading…
Reference in New Issue