Skip to content

Commit c4ff0b0

Browse files
committed
Split declaration statements with ExternalRewriter (version 1)
1 parent 1c3d727 commit c4ff0b0

File tree

2 files changed

+72
-36
lines changed

2 files changed

+72
-36
lines changed

include/tsar/Transform/Clang/SplitDecls.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@
3232
#include <bcl/utility.h>
3333
#include <llvm/Pass.h>
3434

35+
#include "tsar/Analysis/Clang/GlobalInfoExtractor.h"
36+
#include <clang/AST/RecursiveASTVisitor.h>
37+
#include <clang/AST/TypeLoc.h>
38+
#include <llvm/ADT/BitmaskEnum.h>
39+
#include <llvm/ADT/DenseMapInfo.h>
40+
#include <llvm/ADT/StringMap.h>
41+
#include <llvm/ADT/StringSet.h>
42+
#include <map>
43+
#include <memory>
44+
#include <vector>
45+
3546
namespace llvm {
3647
/// This pass separates variable declaration statements that contain multiple
3748
/// variable declarations at once into single declarations.

lib/Transform/Clang/SplitDecls.cpp

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "tsar/Frontend/Clang/Pragma.h"
3131
#include "tsar/Frontend/Clang/TransformationContext.h"
3232
#include "tsar/Support/Clang/Diagnostic.h"
33+
#include "tsar/Support/Clang/Utils.h"
3334
#include <clang/AST/Decl.h>
3435
#include <clang/AST/RecursiveASTVisitor.h>
3536
#include <clang/AST/Stmt.h>
@@ -45,6 +46,8 @@
4546
#include <vector>
4647
#include <string>
4748
#include <stack>
49+
#include <iostream>
50+
#include <deque>
4851

4952
using namespace llvm;
5053
using namespace clang;
@@ -79,6 +82,7 @@ namespace {
7982
/// after it. It also checks absence a macros in this scope and print some
8083
/// other warnings.
8184
bool isNotSingleFlag = false;
85+
bool isAfterNotSingleFlag = false;
8286
class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
8387
public:
8488
ClangSplitter(TransformationContext &TfmCtx, const ASTImportInfo &ImportInfo,
@@ -94,16 +98,6 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
9498
}
9599
Pragma P(*S); // the Pragma class is used to check if a statement is a pragma or not
96100
if (findClause(P, ClauseId::SplitDeclaration, mClauses)) { // mClauses contains all SplitDeclaration pragmas
97-
std::vector<std::string> inits;
98-
while (starts.size()) {
99-
SourceRange toInsert(starts.top(), ends.top());
100-
CharSourceRange txtToInsert(toInsert, true);
101-
starts.pop();
102-
ends.pop();
103-
txtStr = mRewriter.getRewrittenText(txtToInsert);
104-
txtStr += ";\n";
105-
inits.push_back(txtStr);
106-
}
107101
llvm::SmallVector<clang::CharSourceRange, 8> ToRemove; // a vector of statements that will match the root in the tree
108102
auto IsPossible = pragmaRangeToRemove(P, mClauses, mSrcMgr, mLangOpts,
109103
mImportInfo, ToRemove); // ToRemove - the range of positions we want to remove
@@ -124,21 +118,18 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
124118
for (auto SR : ToRemove)
125119
mRewriter.RemoveText(SR, RemoveEmptyLine); // delete each range
126120
if (isNotSingleFlag) {
127-
SourceRange toInsert(start, end);
121+
SourceRange toInsert(notSingleDeclStart, notSingleDeclEnd);
128122
mRewriter.RemoveText(toInsert, RemoveEmptyLine);
129123
}
130-
//Rewriter::RewriteOptions RemoveEmptyLine;
131-
for (std::vector<std::string>::iterator it = inits.begin(); it != inits.end(); ++it) {
132-
mRewriter.InsertTextAfterToken(end, *it);
133-
}
134124
return true;
135125
}
136126
Rewriter::RewriteOptions RemoveEmptyLine;
137127
RemoveEmptyLine.RemoveLineIfEmpty = false;
138128

139129
if (isNotSingleFlag) {
140-
SourceRange toInsert(start, end);
130+
SourceRange toInsert(notSingleDeclStart, notSingleDeclEnd);
141131
mRewriter.RemoveText(toInsert, RemoveEmptyLine);
132+
142133
}
143134
if (mClauses.empty() || !isa<CompoundStmt>(S) &&
144135
!isa<ForStmt>(S) && !isa<DoStmt>(S) && !isa<WhileStmt>(S))
@@ -190,30 +181,62 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
190181
}
191182
}
192183

184+
// bool VisitVarDecl(VarDecl *S) { // to traverse the parse tree and visit each statement
185+
// if (isNotSingleFlag) {
186+
// std::string varType = S->getType().getAsString();
187+
// SourceLocation locat = S->getLocation();
188+
// CharSourceRange txtToInsert(locat, true);
189+
// std::string varName = S->getName().str();
190+
// int n = varType.length();
191+
// char char_array[n + 1];
192+
// strcpy(char_array, varType.c_str());
193+
// if (strchr(char_array, '[')) {
194+
// buildTxtStr(varType, varName);
195+
// } else {
196+
// txtStr = varType + " " + varName + ";\n";
197+
// }
198+
// mRewriter.InsertTextAfterToken(notSingleDeclEnd, txtStr);
199+
// }
200+
// return true;
201+
// }
202+
193203
bool VisitVarDecl(VarDecl *S) { // to traverse the parse tree and visit each statement
194204
if (isNotSingleFlag) {
195-
std::string varType = S->getType().getAsString();
196-
SourceLocation locat = S->getLocation();
197-
CharSourceRange txtToInsert(locat, true);
198-
std::string varName = S->getName().str();
199-
int n = varType.length();
200-
char char_array[n + 1];
201-
strcpy(char_array, varType.c_str());
202-
if (strchr(char_array, '[')) {
203-
buildTxtStr(varType, varName);
204-
} else {
205-
txtStr = varType + " " + varName + ";\n";
205+
varDeclsNum++;
206+
SourceRange toInsert(notSingleDeclStart, notSingleDeclEnd);
207+
ExternalRewriter Canvas(toInsert, mSrcMgr, mLangOpts);
208+
SourceRange Range(S->getLocation());
209+
varDeclsStarts.push_front(S->getBeginLoc());
210+
varDeclsEnds.push_front(S->getEndLoc());
211+
SourceRange varDeclRange(S->getBeginLoc(), S->getEndLoc());
212+
if (varDeclsNum == 1) {
213+
SourceRange toInsert2(Range.getBegin(), S->getEndLoc());
214+
txtStr = Canvas.getRewrittenText(varDeclRange).str();
215+
Canvas.RemoveText(toInsert2);
216+
varDeclType = Canvas.getRewrittenText(varDeclRange);
217+
}
218+
if (varDeclsNum > 1) {
219+
SourceRange prevVarDeclRange(varDeclsStarts.back(), varDeclsEnds.back());
220+
varDeclsStarts.pop_back();
221+
varDeclsEnds.pop_back();
222+
Canvas.ReplaceText(prevVarDeclRange, varDeclType);
223+
txtStr = Canvas.getRewrittenText(varDeclRange).str();
224+
auto it = std::remove(txtStr.begin(), txtStr.end(), ',');
225+
txtStr.erase(it, txtStr.end());
206226
}
207-
mRewriter.InsertTextAfterToken(end, txtStr);
227+
mRewriter.InsertTextAfterToken(notSingleDeclEnd, txtStr + ";\n");
208228
}
209229
return true;
210230
}
211231

212232
bool TraverseDeclStmt(DeclStmt *S) {
213-
if(!S->isSingleDecl()) {
233+
bool tmp;
234+
if(!(S->isSingleDecl())) {
235+
if (!isNotSingleFlag)
236+
varDeclsNum = 0;
214237
isNotSingleFlag = true;
215-
start = S->getBeginLoc();
216-
end = S->getEndLoc();
238+
notSingleDeclStart = S->getBeginLoc();
239+
notSingleDeclEnd = S->getEndLoc();
217240
} else {
218241
isNotSingleFlag = false;
219242
}
@@ -248,11 +271,13 @@ class ClangSplitter : public RecursiveASTVisitor<ClangSplitter> {
248271
SmallVector<Stmt *, 1> mClauses;
249272
bool mActiveSplit = false;
250273
DenseSet<DeclStmt*> mMultipleDecls;
251-
std::stack<SourceLocation> starts;
252-
std::stack<SourceLocation> ends;
253-
SourceLocation start;
254-
SourceLocation end;
274+
std::deque<SourceLocation> varDeclsStarts;
275+
std::deque<SourceLocation> varDeclsEnds;
276+
int varDeclsNum = 0;
277+
SourceLocation notSingleDeclStart;
278+
SourceLocation notSingleDeclEnd;
255279
std::string txtStr;
280+
std::string varDeclType;
256281
};
257282
}
258283

@@ -272,4 +297,4 @@ bool ClangSplitDeclsPass::runOnModule(llvm::Module &M) {
272297
ClangSplitter Vis(*TfmCtx, *ImportInfo, GIP.getRawInfo());
273298
Vis.TraverseDecl(TfmCtx->getContext().getTranslationUnitDecl());
274299
return false;
275-
}
300+
}

0 commit comments

Comments
 (0)