-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathfunctiondecomposer.cpp
More file actions
128 lines (120 loc) · 5.53 KB
/
functiondecomposer.cpp
File metadata and controls
128 lines (120 loc) · 5.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Tooling/Tooling.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Lex/Lexer.h"
using namespace clang;
class RecursiveFunctionDecomposerVisitor
: public RecursiveASTVisitor<RecursiveFunctionDecomposerVisitor> {
public:
explicit RecursiveFunctionDecomposerVisitor(ASTContext *Context)
: Context(Context) {}
bool VisitDecl(Decl *Declaration)
{
if(FunctionDecl *funcDecl = dyn_cast<FunctionDecl>(Declaration))
{
llvm::outs() << "function name: " << funcDecl->getNameAsString() << " (return type = " << funcDecl->getResultType().getAsString() << ")\n";
unsigned paramCount = funcDecl->getNumParams();
llvm::outs() << "function param count: " << paramCount << "\n";
for(unsigned i = 0; i < paramCount; ++i)
{
llvm::outs() << "-param #" << i << "\n";
const ParmVarDecl *currentParam = funcDecl->getParamDecl(i);
QualType userType = currentParam->getType();
while(userType->isPointerType())
{
llvm::outs() << "\tpointer to" << "\n";
userType = userType->getPointeeType();
}
if(userType.isConstQualified())
{
llvm::outs() << "\tconst" << "\n";
}
if(userType->isReferenceType())
{
llvm::outs() << "\treference to" << "\n";
}
userType = userType.getNonReferenceType().getUnqualifiedType();
llvm::outs() << "\t(type = " << userType.getAsString() << ", name = " << currentParam->getNameAsString() << ")\n";
}
llvm::outs() << "\n";
}
if(VarDecl *varDecl = dyn_cast<VarDecl>(Declaration))
{
if(!dyn_cast<ParmVarDecl>(Declaration)) //parameter variables already output with functions above
{
llvm::outs() << "variable type: " << varDecl->getType().getAsString() << ", variable name: " << varDecl->getNameAsString();
if(varDecl->hasInit())
{
const Expr* varInit = varDecl->getInit();
if(varInit->isRValue())
{
SourceRange varSourceRange = varInit->getSourceRange();
if(!varSourceRange.isValid())
return true;
CharSourceRange charSourceRange(varSourceRange, true);
StringRef sourceText = Lexer::getSourceText(charSourceRange, Context->getSourceManager(), Context->getLangOpts(), 0);
llvm::outs() << ", initialization value: " << sourceText.str();
}
}
llvm::outs() << "\n";
}
}
return true;
}
private:
ASTContext *Context;
};
class FunctionDecomposerConsumer : public clang::ASTConsumer {
public:
explicit FunctionDecomposerConsumer(ASTContext *Context)
: Visitor(Context) {}
virtual void HandleTranslationUnit(clang::ASTContext &Context) {
Visitor.TraverseDecl(Context.getTranslationUnitDecl());
}
private:
RecursiveFunctionDecomposerVisitor Visitor;
};
//error handler
struct FunctionDecomposerDiagnosticConsumer : clang::DiagnosticConsumer {
llvm::OwningPtr<DiagnosticConsumer> Proxy;
FunctionDecomposerDiagnosticConsumer(DiagnosticConsumer *Previous) : Proxy(Previous) {}
void BeginSourceFile(const clang::LangOptions& LangOpts, const clang::Preprocessor* PP = 0) { Proxy->BeginSourceFile(LangOpts, PP); }
void clear(){ Proxy->clear(); }
void EndSourceFile() { Proxy->EndSourceFile(); }
void finish() { Proxy->finish(); }
void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic& Info) {
if(DiagLevel == DiagnosticsEngine::Error)
{
const unsigned diagId = Info.getID();
const unsigned numDiagArgs = Info.getNumArgs();
if(numDiagArgs < 1) return;
if(diagId == clang::diag::err_unknown_typename)
{
llvm::outs() << "Unknown type detected: " << Info.getArgIdentifier(0)->getName().str() << "\n";
}
else if(diagId == clang::diag::err_unknown_typename_suggest && Info.getNumFixItHints() > 0)
{
llvm::outs() << "Unknown type (with suggestion) detected: " << Info.getArgIdentifier(0)->getName().str() << " (suggestion: " << Info.getFixItHint(0).CodeToInsert << ")\n";
}
}
DiagnosticConsumer::HandleDiagnostic(DiagLevel, Info);
Proxy->HandleDiagnostic(DiagLevel, Info);
}
};
class FunctionDecomposerFrontendAction : public clang::ASTFrontendAction {
public:
virtual clang::ASTConsumer *CreateASTConsumer(
clang::CompilerInstance &Compiler, llvm::StringRef InFile)
{
Compiler.getDiagnostics().setClient(new FunctionDecomposerDiagnosticConsumer(Compiler.getDiagnostics().takeClient()));
return new FunctionDecomposerConsumer(&Compiler.getASTContext());
}
};
int main(int argc, char **argv) {
clang::tooling::runToolOnCode(new FunctionDecomposerFrontendAction, ((argc > 1) ? argv[1] : "int someFunc(int x, char **y); bool b; int x = 0; int y(x); inz /*typo*/ hi = y;"));
}