aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergio Martins <sergio.martins@kdab.com>2019-06-10 19:21:32 +0100
committerSergio Martins <sergio.martins@kdab.com>2019-06-10 19:21:32 +0100
commit019f936ee7377e21c9649415efce399933adf7a1 (patch)
treee07f03d87c252210fb232d7d46e6c072e0c6f0ce
parentc7bcc9dbce2b72a37f5aff0e22b2bb51b24413ea (diff)
Handle templates and built-in functions too
-rwxr-xr-xdev-scripts/miniAstDumper.py66
-rw-r--r--src/MiniAstDumper.cpp51
-rw-r--r--src/MiniAstDumper.h1
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);