2

I need to write a utility to refactoring source code in c / c ++. For this I use the Clang. Clang built on windows 7 x64 with visual studio 2012.

Below is the code that needs to be inverted conditions IF and swap code blocks THEN and ELSE.

void foo(int* a, int *b) 
{
  if (a[0] > 1) 
  {
      b[0] = 2;
  }
  else
  {
      b[0] = 3;
  }
}

For the base, I use the example https://github.com/eliben/llvm-clang-samples/blob/master/src_clang/tooling_sample.cpp To do this, I bypass all the conditions and change each of them.

class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor> {
public:
    MyASTVisitor(Rewriter &R) : TheRewriter(R) {}

    bool VisitStmt(Stmt *s) 
    {
        if (isa<IfStmt>(s)) 
        {
            IfStmt * IfStatement = cast<IfStmt>(s);

            Stmt * Then = IfStatement->getThen();
            Stmt * Else = IfStatement->getElse();

            Expr * ifCondition = IfStatement->getCond();
            SourceRange conditionRange = IfStatement->getCond()->getSourceRange();

            stringstream invertConditionStream;
            invertConditionStream << " !( " << TheRewriter.ConvertToString(ifCondition) << " ) ";

            TheRewriter.ReplaceText(conditionRange, invertConditionStream.str());
            TheRewriter.ReplaceStmt(Then, Else);
            TheRewriter.ReplaceStmt(Else, Then);
        }

        return true;
    }

Result refactoring example is shown below:

void foo(int* a, int *b) 
{
  if ( !( a[0] > 1 ) ) 
  {
    b[0] = 3;
}

  else
  {
    b[0] = 2;
}

}

Not so nice as I like but works. But if you engage in refactoring the program below is obtained at the output of the application porridge.

void foo(int* a, int *b) 
{
  if (a[0] > 1) 
  {
      b[0] = 2;

      if (a[0] > 1)
      {
          b[0] = 2;
      }
      else
      {
          b[0] = 3;
      }
  }
  else
  {
      b[0] = 3;
  }
}

The result of my utilities:

vo !( a[0] > 1 ) nt* a{
    b[0] = 3;
}
!( a[0] > 1 {
    b[0] = 2;
}
;
}


    else

    {
    b[0] = 2;
    if (a[0] > 1) {
        b[0] = 2;
    } else {
        b[0] = 3;
    }
}


}

Tell me, what am I doing wrong? Does Clang's some other functionality for refactoring such as renaming variables and goto labels? Thanks in advance.

Dmitry
  • 93
  • 1
  • 6
  • 1
    I think you get this because Clang's rewrite doesn't work on the actual trees. There are other tools that can do this, called "program transformation engines", that make the changes directly to trees, check out wikipedia. I have one; you can write the following rule: *rule_swap_then_else(c: expression, b1: block, b2: block): statement->statement = " if (\c) \b1 else \b2 " -> "if (!(\c)) \b2 else \b1"* to produce the effect you want. You don't get porridge. yes, works on C++. – Ira Baxter Sep 25 '14 at 09:54

0 Answers0