diff options
author | Sergio Martins <sergio.martins@kdab.com> | 2019-06-10 19:21:32 +0100 |
---|---|---|
committer | Sergio Martins <sergio.martins@kdab.com> | 2019-06-10 19:21:32 +0100 |
commit | 019f936ee7377e21c9649415efce399933adf7a1 (patch) | |
tree | e07f03d87c252210fb232d7d46e6c072e0c6f0ce | |
parent | c7bcc9dbce2b72a37f5aff0e22b2bb51b24413ea (diff) |
Handle templates and built-in functions too
-rwxr-xr-x | dev-scripts/miniAstDumper.py | 66 | ||||
-rw-r--r-- | src/MiniAstDumper.cpp | 51 | ||||
-rw-r--r-- | src/MiniAstDumper.h | 1 |
3 files changed, 105 insertions, 13 deletions
diff --git a/dev-scripts/miniAstDumper.py b/dev-scripts/miniAstDumper.py index dee73549..43577659 100755 --- a/dev-scripts/miniAstDumper.py +++ b/dev-scripts/miniAstDumper.py @@ -31,11 +31,10 @@ class FunctionCall: print("FunctionCall::check_sanity: callee_id is -1!") self.loc_start.check_sanity() -class CXXMethod: +class Function: def __init__(self): self.id = 0 self.qualified_name = "" - self.method_flags = 0 def check_sanity(self): if self.id == -1: @@ -44,6 +43,11 @@ class CXXMethod: if not self.qualified_name: print("CXXMethod::check_sanity: qualified_name is empty!") +class CXXMethod(Function): + def __init__(self): + Function.__init__(self) + self.method_flags = 0 + class CXXClass: def __init__(self): @@ -66,6 +70,7 @@ class CXXClass: class GlobalAST: def __init__(self): self.cxx_classes = [] + self.functions = [] self.function_calls = [] @@ -76,6 +81,13 @@ class GlobalAST: f.check_sanity() _globalAST = GlobalAST() +_next_function_id = 1 +def next_function_id(): + global _next_function_id + result = _next_function_id + _next_function_id += 1 + return result + def parse_loc(cborLoc, file_map, tu_cwd): loc = SourceLocation() @@ -109,6 +121,9 @@ def load_cbor(filename, globalAST): current_tu_cwd = cborData['cwd'] + tu_function_map = {} + + # populate the file map if 'files' in cborData: for fileId in cborData['files'].keys(): @@ -116,6 +131,7 @@ def load_cbor(filename, globalAST): if 'stuff' in cborData: + # Process classes and methods for stuff in cborData['stuff']: if 'type' in stuff: if stuff['type'] == 31: # CXXRecordDecl @@ -126,15 +142,46 @@ def load_cbor(filename, globalAST): if 'methods' in stuff: for m in stuff['methods']: method = CXXMethod() - method.id = m['id'] + method.id = next_function_id() # Attribute a sequential id, that's unique across TUs + method.qualified_name = m['name'] cxxclass.methods.append(method) + local_id_in_tu = m['id'] + + if local_id_in_tu in tu_function_map.keys(): + print('method is duplicated! ' + method.qualified_name) + tu_function_map[local_id_in_tu] = method + globalAST.cxx_classes.append(cxxclass) - elif stuff['type'] == 48: # CallExpr - funccall = FunctionCall() - funccall.callee_id = stuff['calleeId'] - funccall.loc_start = parse_loc(stuff['loc'], file_map, current_tu_cwd) + + if stuff['type'] == 48: # FunctionDecl + func = Function() + func.id = next_function_id() # Attribute a sequential id, that's unique across TUs + func.qualified_name = stuff['name'] + globalAST.functions.append(func) + local_id_in_tu = stuff['id'] + if local_id_in_tu in tu_function_map.keys(): + print('function is duplicated! ' + method.qualified_name) + tu_function_map[local_id_in_tu] = func + + if func.qualified_name == 'qBound': + print("qBound has id=" + str(local_id_in_tu)) + + + # Process CallExprs + for stuff in cborData['stuff']: + if 'stmt_type' in stuff and stuff['stmt_type'] == 48: # CallExpr + funccall = FunctionCall() + local_callee_id_in_tu = stuff['calleeId'] + source_loc = parse_loc(stuff['loc'], file_map, current_tu_cwd); + + if local_callee_id_in_tu not in tu_function_map.keys(): + print("Could not find function with local tu id=" + str(local_callee_id_in_tu) + ", loc=" + source_loc.asString()) + else: + method = tu_function_map[local_callee_id_in_tu] + funccall.callee_id = method.id + funccall.loc_start = source_loc globalAST.function_calls.append(funccall) #def get_class_by_name(qualified_name): @@ -153,7 +200,10 @@ def load_cbor(filename, globalAST): load_cbor(sys.argv[1], _globalAST) -_globalAST.check_sanity() + +print ("Functions: " + str(len(_globalAST.functions))) + +#_globalAST.check_sanity() #string_class = get_class_by_name("QString")[0] diff --git a/src/MiniAstDumper.cpp b/src/MiniAstDumper.cpp index 9c889c73..c6ddaaf2 100644 --- a/src/MiniAstDumper.cpp +++ b/src/MiniAstDumper.cpp @@ -94,7 +94,7 @@ MiniASTDumperConsumer::~MiniASTDumperConsumer() bool MiniASTDumperConsumer::VisitDecl(Decl *decl) { if (auto tsd = dyn_cast<ClassTemplateSpecializationDecl>(decl)) { - //llvm::errs() << "ClassTemplateSpecializationDecl: " + tsd->getQualifiedNameAsString() + "\n"; + // llvm::errs() << "ClassTemplateSpecializationDecl: " + tsd->getQualifiedNameAsString() + "\n"; } else if (auto rec = dyn_cast<CXXRecordDecl>(decl)) { if (!rec->isThisDeclarationADefinition()) { // No forward-declarations @@ -110,15 +110,32 @@ bool MiniASTDumperConsumer::VisitDecl(Decl *decl) } else if (auto ctd = dyn_cast<ClassTemplateDecl>(decl)) { /*llvm::errs() << "Found template: " << ctd->getNameAsString() << "; this=" << ctd - << "\n";*/ + << "\n"; for (auto s : ctd->specializations()) { - /* llvm::errs() << "Found specialization: " << s->getQualifiedNameAsString() << "\n"; + llvm::errs() << "Found specialization: " << s->getQualifiedNameAsString() << "\n"; auto &args = s->getTemplateArgs(); const unsigned int count = args.size(); for (unsigned int i = 0; i < count; ++i) { args.get(i).print(PrintingPolicy({}), llvm::errs()); llvm::errs() << "\n"; - }*/ + } + } */ + } else if (auto func = dyn_cast<FunctionDecl>(decl)) { + if (isa<CXXMethodDecl>(decl)) // Methods are handled when processing the class + return true; + + if (func->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) { + // Already handled when catching FunctionTemplateDecl. When we write func->getTemplatedDecl(). + return true; + } + + dumpFunctionDecl(func, &m_cborStuffArray); + } else if (auto func = dyn_cast<FunctionTemplateDecl>(decl)) { + + dumpFunctionDecl(func->getTemplatedDecl(), &m_cborStuffArray); + + for (auto s : func->specializations()) { + dumpFunctionDecl(s, &m_cborStuffArray); } } @@ -153,6 +170,23 @@ void MiniASTDumperConsumer::dumpCXXMethodDecl(CXXMethodDecl *method, CborEncoder cborCloseContainer(encoder, &recordMap); } +void MiniASTDumperConsumer::dumpFunctionDecl(FunctionDecl *func, CborEncoder *encoder) +{ + CborEncoder recordMap; + cborCreateMap(encoder, &recordMap, 3); + + cborEncodeString(recordMap, "name"); + cborEncodeString(recordMap, func->getQualifiedNameAsString().c_str()); + + cborEncodeString(recordMap, "type"); + cborEncodeInt(recordMap, func->FunctionDecl::getDeclKind()); + + cborEncodeString(recordMap, "id"); + cborEncodeInt(recordMap, int64_t(func)); + + cborCloseContainer(encoder, &recordMap); +} + void MiniASTDumperConsumer::dumpCXXRecordDecl(CXXRecordDecl *rec, CborEncoder *encoder) { if (rec->isUnion()) @@ -182,6 +216,7 @@ void MiniASTDumperConsumer::dumpCXXRecordDecl(CXXRecordDecl *rec, CborEncoder *e for (auto method : rec->methods()) { dumpCXXMethodDecl(method, &cborMethodList); } + cborCloseContainer(&recordMap, &cborMethodList); cborCloseContainer(&m_cborStuffArray, &recordMap); @@ -197,10 +232,16 @@ void MiniASTDumperConsumer::dumpCallExpr(CallExpr *callExpr, CborEncoder *encode if (!func || !func->getDeclName().isIdentifier()) return; + const bool isBuiltin = func->getBuiltinID() != 0; + if (isBuiltin) //We don't need them now + return; + + func = func->getCanonicalDecl(); + CborEncoder callMap; cborCreateMap(encoder, &callMap, 3); - cborEncodeString(callMap, "type"); + cborEncodeString(callMap, "stmt_type"); cborEncodeInt(callMap, callExpr->getStmtClass()); cborEncodeString(callMap, "calleeId"); diff --git a/src/MiniAstDumper.h b/src/MiniAstDumper.h index 53ac3f3c..3a1cd85f 100644 --- a/src/MiniAstDumper.h +++ b/src/MiniAstDumper.h @@ -66,6 +66,7 @@ public: private: MiniASTDumperConsumer(const MiniASTDumperConsumer &) = delete; void dumpCXXMethodDecl(clang::CXXMethodDecl *, CborEncoder *encoder); + void dumpFunctionDecl(clang::FunctionDecl *, CborEncoder *encoder); void dumpCXXRecordDecl(clang::CXXRecordDecl *, CborEncoder *encoder); void dumpCallExpr(clang::CallExpr *, CborEncoder *encoder); void dumpLocation(clang::SourceLocation, CborEncoder *encoder); |