diff --git a/plugins/cpp/parser/src/clangastvisitor.h b/plugins/cpp/parser/src/clangastvisitor.h index 0321f66ef..6977fde62 100644 --- a/plugins/cpp/parser/src/clangastvisitor.h +++ b/plugins/cpp/parser/src/clangastvisitor.h @@ -335,6 +335,14 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor return b; } + bool TraverseStmt(clang::Stmt* s_) + { + _statements.push(s_); + bool b = Base::TraverseStmt(s_); + _statements.pop(); + return b; + } + bool VisitTypedefTypeLoc(clang::TypedefTypeLoc tl_) { const clang::TypedefType* type = tl_.getTypePtr(); @@ -435,15 +443,13 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor cppRecord->entityHash = astNode->entityHash; cppRecord->name = rd_->getNameAsString(); cppRecord->qualifiedName = rd_->getQualifiedNameAsString(); + if (const clang::CXXRecordDecl* crd - = llvm::dyn_cast(rd_)) + = llvm::dyn_cast(rd_)) { cppRecord->isAbstract = crd->isAbstract(); cppRecord->isPOD = crd->isPOD(); - } - if (clang::CXXRecordDecl* crd = llvm::dyn_cast(rd_)) - { //--- CppInheritance ---// for (auto it = crd->bases_begin(); it != crd->bases_end(); ++it) @@ -514,6 +520,28 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor friendship->theFriend = util::fnvHash(getUSR(friendDecl)); } } + + // --- Destructor --- // + + const clang::NamedDecl* ref = crd; + model::FileLoc location = getFileLoc(crd->getEndLoc(), crd->getEndLoc()); + if (clang::CXXDestructorDecl* dd = crd->getDestructor()) + { + ref = dd; + if (crd->hasUserDeclaredDestructor()) + { + clang::Stmt* body = dd->getBody(); + location = body + ? getFileLoc(body->getEndLoc(), body->getEndLoc()) + : getFileLoc(dd->getEndLoc(), dd->getEndLoc()); + } + } + + for (auto it = crd->field_begin(); it != crd->field_end(); ++it) + { + clang::FieldDecl* fd = *it; + addDestructorUsage(fd->getType(), location, ref); + } } return true; @@ -921,6 +949,27 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor return true; } + bool VisitDeclStmt(clang::DeclStmt* ds_) + { + assert(_statements.top() == ds_ && + "ds_ was expected to be the top-level statement."); + _statements.pop(); + clang::Stmt* scopeSt = _statements.top(); + _statements.push(ds_); + + for (auto it = ds_->decl_begin(); it != ds_->decl_end(); ++it) + { + if (clang::VarDecl* vd = llvm::dyn_cast(*it)) + { + model::FileLoc loc = + getFileLoc(scopeSt->getEndLoc(), scopeSt->getEndLoc()); + addDestructorUsage(vd->getType(), loc, vd); + } + } + + return true; + } + bool VisitNamespaceDecl(clang::NamespaceDecl* nd_) { //--- CppAstNode ---// @@ -1036,6 +1085,8 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor if (insertToCache(de_, astNode)) _astNodes.push_back(astNode); + addDestructorUsage(de_->getDestroyedType(), astNode->location, de_); + return true; } @@ -1089,9 +1140,6 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor { astNode = std::make_shared(); - model::FileLoc location = - getFileLoc(vd->getLocation(), vd->getLocation()); - if (!_contextStatementStack.empty()) { clang::Stmt* context = _contextStatementStack.top(); @@ -1205,6 +1253,30 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor private: using Base = clang::RecursiveASTVisitor; + void addDestructorUsage( + clang::QualType type_, + const model::FileLoc& location_, + const void* clangPtr_) + { + if (clang::CXXRecordDecl* rd = type_->getAsCXXRecordDecl()) + { + if (clang::CXXDestructorDecl* dd = rd->getDestructor()) + { + model::CppAstNodePtr astNode = std::make_shared(); + + astNode->astValue = getSignature(dd); + astNode->location = location_; + astNode->entityHash = util::fnvHash(getUSR(dd)); + astNode->symbolType = model::CppAstNode::SymbolType::Function; + astNode->astType = model::CppAstNode::AstType::Usage; + astNode->id = model::createIdentifier(*astNode); + + if (insertToCache(clangPtr_, astNode)) + _astNodes.push_back(astNode); + } + } + } + /** * This function inserts a model::CppAstNodeId to a cache in a thread-safe * way. The cache is static so the parsers in each thread can use the same. @@ -1508,6 +1580,8 @@ class ClangASTVisitor : public clang::RecursiveASTVisitor std::unordered_map _locToAstType; std::unordered_map _locToAstValue; + // This stack contains the parent chain of the current Stmt. + std::stack _statements; // This stack has the same role as _locTo* maps. In case of // clang::DeclRefExpr objects we need to determine the contect of the given // expression. In this stack we store the deepest statement node in AST which