-
Notifications
You must be signed in to change notification settings - Fork 5
Adds duplicate feature #375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
#ifndef LLVM_DUPLICATE_H | ||
#define LLVM_DUPLICATE_H | ||
|
||
#include "ProgramInfo.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/AST/Decl.h" | ||
#include "clang/AST/Stmt.h" | ||
#include "clang/Rewrite/Core/Rewriter.h" | ||
#include <getopt.h> | ||
|
||
typedef std::function<bool (clang::VarDecl*)> selector; | ||
|
||
// Create a duplicate of a variable. | ||
// ToScan is the context to search for the variable | ||
// P is a predicate that decides which variable to make a duplicate of | ||
// Returns the name of the newly created variable | ||
// or None if no variable matching P is found | ||
Option<std::string> createDuplicate(clang::ASTContext &Context, | ||
clang::Rewriter &R, ProgramInfo &Info, | ||
clang::Decl *ToScan, selector P); | ||
|
||
|
||
|
||
#endif //LLVM_DUPLICATE_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#include "clang/3C/Duplicate.h" | ||
#include "clang/AST/ASTContext.h" | ||
#include "clang/AST/Decl.h" | ||
#include "clang/3C/ProgramInfo.h" | ||
#include "clang/Rewrite/Core/Rewriter.h" | ||
|
||
using namespace clang; | ||
using namespace llvm; | ||
using namespace std; | ||
|
||
|
||
// Recursive Visitor | ||
class FindVarDecl : public RecursiveASTVisitor<FindVarDecl> { | ||
public: | ||
explicit FindVarDecl(ASTContext &Context, Rewriter &R, | ||
ProgramInfo &I, selector P) | ||
: Context(Context), R(R), Info(I), P(P) {} | ||
|
||
|
||
bool VisitVarDecl(VarDecl *VD) { | ||
// If the selector matches execute the duplicate function | ||
// and store the new name in the optional | ||
if(P(VD)){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens if this is true twice? I imagine you expect it won't be, but is there a reason it couldn't? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
auto NewName = addDuplicate(VD); | ||
Replacement = { NewName }; | ||
return false; | ||
} else { | ||
return true; | ||
} | ||
} | ||
|
||
Option<string> didReplace(void) { | ||
return Replacement; | ||
} | ||
|
||
private: | ||
// Insert the duplicate into the rewriter | ||
// Returns the new var's name | ||
string addDuplicate(VarDecl *VD) { | ||
SourceLocation End = VD->getEndLoc(); | ||
auto Dup = createDuplicateString(VD); | ||
R.InsertTextAfterToken(End, Dup.second); | ||
return Dup.first; | ||
} | ||
|
||
// Create the text for the new variable | ||
// Returns a pair containing the new name | ||
// and the new line containing declaration and assignment | ||
pair<string,string> createDuplicateString(VarDecl *VD) { | ||
auto CV = Info.getVariable(VD, &Context); | ||
auto Type = | ||
CV.hasValue() ? | ||
CV.getValue() | ||
.mkString(Info.getConstraints().getVariables(), | ||
false) | ||
: VD->getType().getAsString(); | ||
auto TargetName = VD->getNameAsString(); | ||
auto NewName = "__" + TargetName + "_copy"; | ||
return make_pair(NewName, ";\n" + Type + " " + NewName + "= " + TargetName + ""); | ||
} | ||
|
||
|
||
|
||
ASTContext &Context; | ||
Rewriter &R; | ||
ProgramInfo &Info; | ||
// Predicate for finding the variable to duplicate | ||
selector P; | ||
// Duplicate's name or none if var not found | ||
Option<string> Replacement = {}; | ||
}; | ||
|
||
// Main entrypoint | ||
Option<string> createDuplicate(ASTContext &Context, Rewriter &R, | ||
ProgramInfo &Info, | ||
Decl *FD, selector P) { | ||
auto V = FindVarDecl(Context, R, Info, P); | ||
V.TraverseDecl(FD); | ||
return V.didReplace(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering: Why this interface for determining the variable to duplicate? That is, I could imagine just specifying a single Decl and duplicating that. Or I could imagine providing a variable name, and you'd search for the proper decl. Just curious.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just seemed like the most general interface in case this becomes useful for other modules down the line. One change could be adding some top level helpers for simpler functionality.