forked from vgvassilev/creduce
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CommonParameterRewriteVisitor.h
172 lines (143 loc) · 5.26 KB
/
CommonParameterRewriteVisitor.h
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//===----------------------------------------------------------------------===//
//
// Copyright (c) 2012, 2013, 2014 The University of Utah
// All rights reserved.
//
// This file is distributed under the University of Illinois Open Source
// License. See the file COPYING for details.
//
//===----------------------------------------------------------------------===//
#ifndef COMMON_PARAMETER_REWRITE_VISITOR_H
#define COMMON_PARAMETER_REWRITE_VISITOR_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "clang/AST/RecursiveASTVisitor.h"
template<typename T, typename Trans>
class CommonParameterRewriteVisitor : public clang::RecursiveASTVisitor<T> {
public:
explicit CommonParameterRewriteVisitor(Trans *Instance)
: ConsumerInstance(Instance)
{ }
bool VisitCallExpr(clang::CallExpr *E);
bool VisitFunctionDecl(clang::FunctionDecl *FD);
bool VisitCXXConstructExpr(clang::CXXConstructExpr *CE);
void rewriteAllExprs(void);
protected:
clang::SmallVector<clang::CallExpr *, 10> AllCallExprs;
clang::SmallVector<const clang::CXXConstructExpr *, 5> AllConstructExprs;
typedef llvm::SmallPtrSet<const clang::DeclContext *, 20> DeclContextSet;
bool rewriteOneCallExpr(clang::CallExpr *E);
bool rewriteOneConstructExpr(const clang::CXXConstructExpr *CE);
Trans *ConsumerInstance;
};
template<typename T, typename Trans>
bool CommonParameterRewriteVisitor<T, Trans>::VisitCXXConstructExpr(
clang::CXXConstructExpr *CE)
{
const clang::CXXConstructorDecl *CtorD = CE->getConstructor();
if (CtorD->getCanonicalDecl() == ConsumerInstance->TheFuncDecl)
AllConstructExprs.push_back(CE);
return true;
}
template<typename T, typename Trans>
bool CommonParameterRewriteVisitor<T, Trans>::VisitFunctionDecl(
clang::FunctionDecl *FD)
{
clang::FunctionDecl *CanonicalFD = FD->getCanonicalDecl();
if (CanonicalFD == ConsumerInstance->TheFuncDecl)
return ConsumerInstance->rewriteFuncDecl(FD);
return true;
}
template<typename T, typename Trans>
bool CommonParameterRewriteVisitor<T, Trans>::rewriteOneCallExpr(
clang::CallExpr *E)
{
return ConsumerInstance->RewriteHelper->
removeArgFromCallExpr(E, ConsumerInstance->TheParamPos);
}
template<typename T, typename Trans>
bool CommonParameterRewriteVisitor<T, Trans>::rewriteOneConstructExpr(
const clang::CXXConstructExpr *CE)
{
return ConsumerInstance->RewriteHelper->
removeArgFromCXXConstructExpr(CE, ConsumerInstance->TheParamPos);
}
template<typename T, typename Trans>
void CommonParameterRewriteVisitor<T, Trans>::rewriteAllExprs(void)
{
while (!AllCallExprs.empty()) {
clang::CallExpr *CallE = AllCallExprs.pop_back_val();
rewriteOneCallExpr(CallE);
}
while (!AllConstructExprs.empty()) {
const clang::CXXConstructExpr *CE = AllConstructExprs.pop_back_val();
rewriteOneConstructExpr(CE);
}
}
template<typename T, typename Trans>
bool CommonParameterRewriteVisitor<T, Trans>::VisitCallExpr(
clang::CallExpr *CallE)
{
const clang::FunctionDecl *CalleeDecl = NULL;
const clang::Expr *E = CallE->getCallee();
if (const clang::UnresolvedLookupExpr *UE =
llvm::dyn_cast<clang::UnresolvedLookupExpr>(E)) {
clang::DeclarationName DName = UE->getName();
TransAssert(((DName.getNameKind() == clang::DeclarationName::Identifier) ||
(DName.getNameKind() ==
clang::DeclarationName::CXXOperatorName)) &&
"Not an indentifier!");
if (const clang::NestedNameSpecifier *NNS = UE->getQualifier()) {
if (const clang::DeclContext *Ctx =
ConsumerInstance->getDeclContextFromSpecifier(NNS)) {
DeclContextSet VisitedCtxs;
CalleeDecl =
ConsumerInstance->lookupFunctionDecl(DName, Ctx, VisitedCtxs);
}
}
if (!CalleeDecl) {
DeclContextSet VisitedCtxs;
CalleeDecl = ConsumerInstance->lookupFunctionDecl(DName,
ConsumerInstance->TheFuncDecl->getLookupParent(),
VisitedCtxs);
}
if (!CalleeDecl)
return true;
}
else {
CalleeDecl = CallE->getDirectCallee();
if (!CalleeDecl) {
return true;
}
}
if (clang::FunctionTemplateDecl *TheTmplFuncD =
ConsumerInstance->TheFuncDecl->getDescribedFunctionTemplate()) {
clang::FunctionTemplateDecl *TmplFuncD;
if (CalleeDecl->isTemplateInstantiation())
TmplFuncD = CalleeDecl->getPrimaryTemplate();
else
TmplFuncD = CalleeDecl->getDescribedFunctionTemplate();
if (!TmplFuncD ||
(TmplFuncD->getCanonicalDecl() != TheTmplFuncD->getCanonicalDecl()))
return true;
}
if (clang::FunctionDecl *InstFuncDecl =
CalleeDecl->getInstantiatedFromMemberFunction()) {
CalleeDecl = InstFuncDecl;
}
if (CalleeDecl->getCanonicalDecl() != ConsumerInstance->TheFuncDecl) {
return true;
}
// We now have a correct CallExpr
// Here we only collect these valid CallExprs, and
// will rewrite them later in a reverse order.
// The reason is that if we have code like below:
// foo(foo(1));
// we want to rewrite the nested foo(1) first.
// If we rewrite the outside foo first, we will
// end up with bad transformation when we try to
// rewrite foo(1), which has been removed.
AllCallExprs.push_back(CallE);
return true;
}
#endif