diff --git a/clang/include/clang/3C/Duplicate.h b/clang/include/clang/3C/Duplicate.h new file mode 100644 index 000000000000..beb50f30de76 --- /dev/null +++ b/clang/include/clang/3C/Duplicate.h @@ -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 + +typedef std::function 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 createDuplicate(clang::ASTContext &Context, + clang::Rewriter &R, ProgramInfo &Info, + clang::Decl *ToScan, selector P); + + + +#endif //LLVM_DUPLICATE_H diff --git a/clang/lib/3C/CMakeLists.txt b/clang/lib/3C/CMakeLists.txt index 6027224db916..0cd1c308c8da 100644 --- a/clang/lib/3C/CMakeLists.txt +++ b/clang/lib/3C/CMakeLists.txt @@ -40,6 +40,7 @@ set( LLVM_LINK_COMPONENTS StructInit.cpp TypeVariableAnalysis.cpp Utils.cpp + Duplicate.cpp ${five_c_source} LINK_LIBS clangAST diff --git a/clang/lib/3C/Duplicate.cpp b/clang/lib/3C/Duplicate.cpp new file mode 100644 index 000000000000..e653ded1fe02 --- /dev/null +++ b/clang/lib/3C/Duplicate.cpp @@ -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 { +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)){ + auto NewName = addDuplicate(VD); + Replacement = { NewName }; + return false; + } else { + return true; + } + } + + Option 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 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 Replacement = {}; +}; + +// Main entrypoint +Option createDuplicate(ASTContext &Context, Rewriter &R, + ProgramInfo &Info, + Decl *FD, selector P) { + auto V = FindVarDecl(Context, R, Info, P); + V.TraverseDecl(FD); + return V.didReplace(); +}