Skip to content

Commit

Permalink
Fixed an issue for rewriting record decls
Browse files Browse the repository at this point in the history
When we have a record decl through its definition, we can only
rewrite its definition once.
  • Loading branch information
chenyang78 committed Aug 28, 2018
1 parent 921324f commit d5bb977
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 28 deletions.
48 changes: 35 additions & 13 deletions clang_delta/CommonRenameClassRewriteVisitor.h
Expand Up @@ -14,18 +14,22 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "clang/AST/RecursiveASTVisitor.h"

class Transformation;

namespace clang_delta_common_visitor {

using namespace clang;

template<typename T>
class CommonRenameClassRewriteVisitor : public RecursiveASTVisitor<T> {
public:
CommonRenameClassRewriteVisitor(Rewriter *RT,
CommonRenameClassRewriteVisitor(Transformation *Instance,
Rewriter *RT,
RewriteUtils *Helper,
const CXXRecordDecl *CXXRD,
const std::string &Name)
: TheRewriter(RT),
: ConsumerInstance(Instance),
TheRewriter(RT),
RewriteHelper(Helper),
TheCXXRecordDecl(CXXRD),
NewNameStr(Name)
Expand Down Expand Up @@ -74,6 +78,8 @@ class CommonRenameClassRewriteVisitor : public RecursiveASTVisitor<T> {

LocPtrSet VisitedLocs;

Transformation *ConsumerInstance;

Rewriter *TheRewriter;

RewriteUtils *RewriteHelper;
Expand Down Expand Up @@ -177,7 +183,18 @@ bool CommonRenameClassRewriteVisitor<T>::VisitCXXRecordDecl(
CXXRecordDecl *CXXRD)
{
std::string Name;
if (getNewName(CXXRD, Name)) {
if (!getNewName(CXXRD, Name))
return true;

void *LocPtr = CXXRD->getLocation().getPtrEncoding();
if (VisitedLocs.count(LocPtr))
return true;
VisitedLocs.insert(LocPtr);

if (ConsumerInstance->isDeclaringRecordDecl(CXXRD)) {
RewriteHelper->replaceRecordDeclDef(CXXRD, Name);
}
else {
RewriteHelper->replaceRecordDeclName(CXXRD, Name);
}

Expand Down Expand Up @@ -279,16 +296,21 @@ bool CommonRenameClassRewriteVisitor<T>::VisitRecordTypeLoc(RecordTypeLoc RTLoc)
return true;

std::string Name;
if (getNewName(RD, Name)) {
// Avoid duplicated rewrites to Decls from the same DeclGroup, e.g.,
// struct S s1, s2
SourceLocation LocStart = RTLoc.getLocStart();
void *LocPtr = LocStart.getPtrEncoding();
if (VisitedLocs.count(LocPtr))
return true;
VisitedLocs.insert(LocPtr);
RewriteHelper->replaceRecordType(RTLoc, Name);
}
if (!getNewName(RD, Name))
return true;

// Let VisitCXXRecordDecl handle this case.
if (ConsumerInstance->isDeclaringRecordDecl(RD))
return true;

// Avoid duplicated rewrites to Decls from the same DeclGroup, e.g.,
// struct S s1, s2
SourceLocation LocStart = RTLoc.getLocStart();
void *LocPtr = LocStart.getPtrEncoding();
if (VisitedLocs.count(LocPtr))
return true;
VisitedLocs.insert(LocPtr);
RewriteHelper->replaceRecordType(RTLoc, Name);
return true;
}

Expand Down
15 changes: 8 additions & 7 deletions clang_delta/RemoveBaseClass.cpp
Expand Up @@ -60,16 +60,17 @@ bool RemoveBaseClassBaseVisitor::VisitCXXRecordDecl(
return true;
}

class RemoveBaseClassRewriteVisitor : public
class RemoveBaseClassRewriteVisitor : public
CommonRenameClassRewriteVisitor<RemoveBaseClassRewriteVisitor>
{
public:
RemoveBaseClassRewriteVisitor(Rewriter *RT,
RewriteUtils *Helper,
const CXXRecordDecl *CXXRD,
const std::string &Name)
RemoveBaseClassRewriteVisitor(Transformation *Instance,
Rewriter *RT,
RewriteUtils *Helper,
const CXXRecordDecl *CXXRD,
const std::string &Name)
: CommonRenameClassRewriteVisitor<RemoveBaseClassRewriteVisitor>
(RT, Helper, CXXRD, Name)
(Instance, RT, Helper, CXXRD, Name)
{ }
};

Expand Down Expand Up @@ -102,7 +103,7 @@ void RemoveBaseClass::HandleTranslationUnit(ASTContext &Ctx)
Ctx.getDiagnostics().setSuppressAllDiagnostics(false);

RewriteVisitor =
new RemoveBaseClassRewriteVisitor(&TheRewriter, RewriteHelper,
new RemoveBaseClassRewriteVisitor(this, &TheRewriter, RewriteHelper,
TheBaseClass->getCanonicalDecl(),
TheDerivedClass->getNameAsString());

Expand Down
9 changes: 5 additions & 4 deletions clang_delta/RenameClass.cpp
Expand Up @@ -51,15 +51,16 @@ class RenameClassASTVisitor : public
};

class RenameClassRewriteVisitor : public
CommonRenameClassRewriteVisitor<RenameClassRewriteVisitor>
CommonRenameClassRewriteVisitor<RenameClassRewriteVisitor>
{
public:
RenameClassRewriteVisitor(Rewriter *RT,
RenameClassRewriteVisitor(Transformation *Instance,
Rewriter *RT,
RewriteUtils *Helper,
const CXXRecordDecl *CXXRD,
const std::string &Name)
: CommonRenameClassRewriteVisitor<RenameClassRewriteVisitor>
(RT, Helper, CXXRD, Name)
(Instance, RT, Helper, CXXRD, Name)
{ }
};

Expand Down Expand Up @@ -101,7 +102,7 @@ void RenameClass::HandleTranslationUnit(ASTContext &Ctx)
Ctx.getDiagnostics().setSuppressAllDiagnostics(false);

RewriteVisitor =
new RenameClassRewriteVisitor(&TheRewriter, RewriteHelper,
new RenameClassRewriteVisitor(this, &TheRewriter, RewriteHelper,
TheCXXRecordDecl, NewNameStr);

TransAssert(RewriteVisitor && "NULL RewriteVisitor!");
Expand Down
11 changes: 7 additions & 4 deletions clang_delta/ReplaceDerivedClass.cpp
Expand Up @@ -49,12 +49,13 @@ class ReplaceDerivedClassRewriteVisitor : public
CommonRenameClassRewriteVisitor<ReplaceDerivedClassRewriteVisitor>
{
public:
ReplaceDerivedClassRewriteVisitor(Rewriter *RT,
ReplaceDerivedClassRewriteVisitor(Transformation *Instance,
Rewriter *RT,
RewriteUtils *Helper,
const CXXRecordDecl *CXXRD,
const std::string &Name)
: CommonRenameClassRewriteVisitor<ReplaceDerivedClassRewriteVisitor>
(RT, Helper, CXXRD, Name)
(Instance, RT, Helper, CXXRD, Name)
{ }
};

Expand Down Expand Up @@ -93,7 +94,7 @@ void ReplaceDerivedClass::HandleTranslationUnit(ASTContext &Ctx)
Ctx.getDiagnostics().setSuppressAllDiagnostics(false);

RewriteVisitor =
new ReplaceDerivedClassRewriteVisitor(&TheRewriter, RewriteHelper,
new ReplaceDerivedClassRewriteVisitor(this, &TheRewriter, RewriteHelper,
TheDerivedClass->getCanonicalDecl(),
TheBaseClass->getNameAsString());
TransAssert(RewriteVisitor && "NULL RewriteVisitor!");
Expand Down Expand Up @@ -177,7 +178,9 @@ void ReplaceDerivedClass::doRewrite(void)
RewriteHelper->removeClassTemplateDecls(TmplD);
}
else {
RewriteHelper->removeClassDecls(TheDerivedClass);
if (!isDeclaringRecordDecl(TheDerivedClass)) {
RewriteHelper->removeClassDecls(TheDerivedClass);
}
}
}

Expand Down
15 changes: 15 additions & 0 deletions clang_delta/RewriteUtils.cpp
Expand Up @@ -1026,6 +1026,21 @@ bool RewriteUtils::replaceRecordDeclName(const RecordDecl *RD,
NameStr);
}

bool RewriteUtils::replaceRecordDeclDef(const RecordDecl *RD,
const std::string &NameStr)
{
if (RD->isThisDeclarationADefinition()) {
SourceLocation RBLoc = RD->getBraceRange().getEnd();
if (RBLoc.isInvalid()) {
return !TheRewriter->ReplaceText(RD->getSourceRange(), NameStr);
}
else {
SourceLocation StartLoc = RD->getSourceRange().getBegin();
return !TheRewriter->ReplaceText(SourceRange(StartLoc, RBLoc), NameStr);
}
}
}

bool RewriteUtils::replaceVarTypeName(const VarDecl *VD,
const std::string &NameStr)
{
Expand Down
3 changes: 3 additions & 0 deletions clang_delta/RewriteUtils.h
Expand Up @@ -127,6 +127,9 @@ class RewriteUtils {
bool replaceRecordDeclName(const clang::RecordDecl *RD,
const std::string &NameStr);

bool replaceRecordDeclDef(const clang::RecordDecl *RD,
const std::string &NameStr);

bool replaceVarTypeName(const clang::VarDecl *VD,
const std::string &NameStr);

Expand Down
11 changes: 11 additions & 0 deletions clang_delta/Transformation.cpp
Expand Up @@ -1076,6 +1076,17 @@ bool Transformation::isInIncludedFile(const Stmt *S) const
return isInIncludedFile(S->getLocStart());
}

bool Transformation::isDeclaringRecordDecl(const RecordDecl *RD)
{
SourceLocation SemiLoc =
Lexer::findLocationAfterToken(RD->getSourceRange().getEnd(),
tok::semi,
*SrcManager,
Context->getLangOpts(),
/*SkipTrailingWhitespaceAndNewLine=*/true);
return SemiLoc.isInvalid();
}

Transformation::~Transformation(void)
{
RewriteUtils::Finalize();
Expand Down
11 changes: 11 additions & 0 deletions clang_delta/Transformation.h
Expand Up @@ -57,8 +57,17 @@ typedef enum {
TransToCounterTooBigError
} TransformationError;

namespace clang_delta_common_visitor {

template<typename T> class CommonRenameClassRewriteVisitor;

}

class Transformation : public clang::ASTConsumer {

template<typename T>
friend class clang_delta_common_visitor::CommonRenameClassRewriteVisitor;

public:

Transformation(const char *TransName, const char *Desc)
Expand Down Expand Up @@ -290,6 +299,8 @@ class Transformation : public clang::ASTConsumer {

bool isInIncludedFile(const clang::Stmt *S) const;

bool isDeclaringRecordDecl(const clang::RecordDecl *RD);

const std::string Name;

int TransformationCounter;
Expand Down
15 changes: 15 additions & 0 deletions clang_delta/tests/replace-derived-class/replace-derived1.cpp
@@ -0,0 +1,15 @@
// RUN: %clang_delta --transformation=replace-derived-class --counter=1 %s 2>&1 | %remove_lit_checks | FileCheck %s

struct a {
~a();
};
// CHECK-NOT: struct X
struct X : a {};
// CHECK: foo() {
void foo() {
// CHECK-NEXT: a *b;
X *b;
// CHECK-NEXT: b->~a();
b->~X();
// CHECK-NEXT: }
}
16 changes: 16 additions & 0 deletions clang_delta/tests/replace-derived-class/replace-derived2.cpp
@@ -0,0 +1,16 @@
// RUN: %clang_delta --transformation=replace-derived-class --counter=1 %s 2>&1 | %remove_lit_checks | FileCheck %s

// CHECK: struct a {
struct a {
// CHECK-NEXT: ~a();
~a();
// CHECK-NEXT: };
};
// CHECK-NEXT: a *b;
struct X : a {} *b;
// CHECK-NEXT: void foo() {
void foo() {
// CHECK-NEXT: b->~a();
b->~X();
// CHECK-NEXT: }
}
16 changes: 16 additions & 0 deletions clang_delta/tests/replace-derived-class/replace-derived3.cpp
@@ -0,0 +1,16 @@
// RUN: %clang_delta --transformation=replace-derived-class --counter=1 %s 2>&1 | %remove_lit_checks | FileCheck %s

// CHECK: struct a {
struct a {
// CHECK-NEXT: ~a();
~a();
// CHECK-NEXT: };
};
// CHECK-NEXT: a *b;
struct abcabcabcabcabcabcabca : a {} *b;
// CHECK-NEXT: void foo() {
void foo() {
// CHECK-NEXT: b->~a();
b->~abcabcabcabcabcabcabca();
// CHECK-NEXT: }
}

0 comments on commit d5bb977

Please sign in to comment.