summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2018-02-15 14:01:04 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2018-02-16 08:28:50 +0200
commitda2f9c20f61033caa29757942b4f3e709a48ed7c (patch)
tree60a0cd565f913457672a9603c9613ef9c85ea959
parent28753a11d4d5198d473660f386176cec5a1b4533 (diff)
loplugin:changetoolsgen various improvements
- use AdjustFoo variants of methods on Rect/Size/Point - ignore double assignments - improve error messages - handle expressions that include macros by using getExpansionLoc - replace ++X() with X() + 1 Change-Id: Ida6b06b2a92e9226168aff6b1b8031f5867687b4
-rw-r--r--compilerplugins/clang/changetoolsgen.cxx179
-rw-r--r--compilerplugins/clang/plugin.cxx6
2 files changed, 130 insertions, 55 deletions
diff --git a/compilerplugins/clang/changetoolsgen.cxx b/compilerplugins/clang/changetoolsgen.cxx
index 93856ca311f6..53246226eff8 100644
--- a/compilerplugins/clang/changetoolsgen.cxx
+++ b/compilerplugins/clang/changetoolsgen.cxx
@@ -37,10 +37,12 @@ public:
private:
bool ChangeAssignment(Stmt const* parent, std::string const& methodName,
std::string const& setPrefix);
- bool ChangeBinaryOperator(BinaryOperator const* parent, CXXMemberCallExpr const* call,
- std::string const& methodName, std::string const& setPrefix);
+ bool ChangeBinaryOperatorPlusMinus(BinaryOperator const* parent, CXXMemberCallExpr const* call,
+ std::string const& methodName);
+ bool ChangeBinaryOperatorOther(BinaryOperator const* parent, CXXMemberCallExpr const* call,
+ std::string const& methodName, std::string const& setPrefix);
bool ChangeUnaryOperator(UnaryOperator const* parent, CXXMemberCallExpr const* call,
- std::string const& methodName, std::string const& setPrefix);
+ std::string const& methodName);
std::string extractCode(SourceLocation startLoc, SourceLocation endLoc);
};
@@ -108,31 +110,58 @@ bool ChangeToolsGen::VisitCXXMemberCallExpr(CXXMemberCallExpr const* call)
return true;
if (auto unaryOp = dyn_cast<UnaryOperator>(parent))
{
- if (!ChangeUnaryOperator(unaryOp, call, methodName, setPrefix))
- report(DiagnosticsEngine::Warning, "Could not fix this one1", call->getLocStart());
+ if (!ChangeUnaryOperator(unaryOp, call, methodName))
+ report(DiagnosticsEngine::Warning, "Could not fix, unary", call->getLocStart());
return true;
}
auto binaryOp = dyn_cast<BinaryOperator>(parent);
if (!binaryOp)
{
- // parent->dump();
- // report(DiagnosticsEngine::Warning, "Could not fix this one3", call->getLocStart());
+ // normal getter
return true;
}
auto opcode = binaryOp->getOpcode();
if (opcode == BO_Assign)
{
+ // Check for assignments embedded inside other expressions
+ auto parent2 = getParentStmt(parent);
+ if (dyn_cast_or_null<ExprWithCleanups>(parent2))
+ parent2 = getParentStmt(parent2);
+ if (parent2 && isa<Expr>(parent2))
+ {
+ report(DiagnosticsEngine::Warning, "Could not fix, embedded assign",
+ call->getLocStart());
+ return true;
+ }
+ // Check for
+ // X.Width() = X.Height() = 1;
+ if (auto rhs = dyn_cast<BinaryOperator>(binaryOp->getRHS()->IgnoreParenImpCasts()))
+ if (rhs->getOpcode() == BO_Assign)
+ {
+ report(DiagnosticsEngine::Warning, "Could not fix, double assign",
+ call->getLocStart());
+ return true;
+ }
if (!ChangeAssignment(parent, methodName, setPrefix))
- report(DiagnosticsEngine::Warning, "Could not fix this one4", call->getLocStart());
+ report(DiagnosticsEngine::Warning, "Could not fix, assign", call->getLocStart());
return true;
}
- if (opcode == BO_RemAssign || opcode == BO_AddAssign || opcode == BO_SubAssign
- || opcode == BO_MulAssign || opcode == BO_DivAssign)
+ if (opcode == BO_AddAssign || opcode == BO_SubAssign)
{
- if (!ChangeBinaryOperator(binaryOp, call, methodName, setPrefix))
- report(DiagnosticsEngine::Warning, "Could not fix this one5", call->getLocStart());
+ if (!ChangeBinaryOperatorPlusMinus(binaryOp, call, methodName))
+ report(DiagnosticsEngine::Warning, "Could not fix, assign-and-change",
+ call->getLocStart());
return true;
}
+ else if (opcode == BO_RemAssign || opcode == BO_MulAssign || opcode == BO_DivAssign)
+ {
+ if (!ChangeBinaryOperatorOther(binaryOp, call, methodName, setPrefix))
+ report(DiagnosticsEngine::Warning, "Could not fix, assign-and-change",
+ call->getLocStart());
+ return true;
+ }
+ else
+ assert(false);
return true;
}
@@ -144,8 +173,8 @@ bool ChangeToolsGen::ChangeAssignment(Stmt const* parent, std::string const& met
// and replace with
// aRect.SetLeft( ... );
SourceManager& SM = compiler.getSourceManager();
- SourceLocation startLoc = parent->getLocStart();
- SourceLocation endLoc = parent->getLocEnd();
+ SourceLocation startLoc = SM.getExpansionLoc(parent->getLocStart());
+ SourceLocation endLoc = SM.getExpansionLoc(parent->getLocEnd());
const char* p1 = SM.getCharacterData(startLoc);
const char* p2 = SM.getCharacterData(endLoc);
unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts());
@@ -154,7 +183,7 @@ bool ChangeToolsGen::ChangeAssignment(Stmt const* parent, std::string const& met
std::string callText(p1, p2 - p1 + n);
auto originalLength = callText.size();
- auto newText = std::regex_replace(callText, std::regex(methodName + "\\(\\) *="),
+ auto newText = std::regex_replace(callText, std::regex(methodName + " *\\( *\\) *="),
setPrefix + methodName + "(");
if (newText == callText)
return false;
@@ -163,18 +192,61 @@ bool ChangeToolsGen::ChangeAssignment(Stmt const* parent, std::string const& met
return replaceText(startLoc, originalLength, newText);
}
-bool ChangeToolsGen::ChangeBinaryOperator(BinaryOperator const* binaryOp,
- CXXMemberCallExpr const* call,
- std::string const& methodName,
- std::string const& setPrefix)
+bool ChangeToolsGen::ChangeBinaryOperatorPlusMinus(BinaryOperator const* binaryOp,
+ CXXMemberCallExpr const* call,
+ std::string const& methodName)
+{
+ // Look for expressions like
+ // aRect.Left() += ...;
+ // and replace with
+ // aRect.MoveLeft( ... );
+ SourceManager& SM = compiler.getSourceManager();
+ SourceLocation startLoc = SM.getExpansionLoc(binaryOp->getLocStart());
+ SourceLocation endLoc = SM.getExpansionLoc(binaryOp->getLocEnd());
+ const char* p1 = SM.getCharacterData(startLoc);
+ const char* p2 = SM.getCharacterData(endLoc);
+ if (p2 < p1) // clang is misbehaving, appears to be macro constant related
+ return false;
+ unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts());
+ std::string callText(p1, p2 - p1 + n);
+ auto originalLength = callText.size();
+
+ std::string newText;
+ if (binaryOp->getOpcode() == BO_AddAssign)
+ {
+ newText = std::regex_replace(callText, std::regex(methodName + " *\\( *\\) +\\+= *"),
+ "Adjust" + methodName + "(");
+ newText += " )";
+ }
+ else
+ {
+ newText = std::regex_replace(callText, std::regex(methodName + " *\\( *\\) +\\-= *"),
+ "Adjust" + methodName + "( -(");
+ newText += ") )";
+ }
+
+ if (newText == callText)
+ {
+ report(DiagnosticsEngine::Warning, "binaryop-plusminus regex match failed",
+ call->getLocStart());
+ return false;
+ }
+
+ return replaceText(startLoc, originalLength, newText);
+}
+
+bool ChangeToolsGen::ChangeBinaryOperatorOther(BinaryOperator const* binaryOp,
+ CXXMemberCallExpr const* call,
+ std::string const& methodName,
+ std::string const& setPrefix)
{
// Look for expressions like
// aRect.Left() += ...;
// and replace with
// aRect.SetLeft( aRect.GetLeft() + ... );
SourceManager& SM = compiler.getSourceManager();
- SourceLocation startLoc = binaryOp->getLocStart();
- SourceLocation endLoc = binaryOp->getLocEnd();
+ SourceLocation startLoc = SM.getExpansionLoc(binaryOp->getLocStart());
+ SourceLocation endLoc = SM.getExpansionLoc(binaryOp->getLocEnd());
const char* p1 = SM.getCharacterData(startLoc);
const char* p2 = SM.getCharacterData(endLoc);
if (p2 < p1) // clang is misbehaving, appears to be macro constant related
@@ -191,14 +263,6 @@ bool ChangeToolsGen::ChangeBinaryOperator(BinaryOperator const* binaryOp,
regexOpname = "\\%=";
replaceOpname = "%";
break;
- case BO_AddAssign:
- regexOpname = "\\+=";
- replaceOpname = "+";
- break;
- case BO_SubAssign:
- regexOpname = "\\-=";
- replaceOpname = "-";
- break;
case BO_MulAssign:
regexOpname = "\\*=";
replaceOpname = "*";
@@ -213,32 +277,39 @@ bool ChangeToolsGen::ChangeBinaryOperator(BinaryOperator const* binaryOp,
auto implicitObjectText = extractCode(call->getImplicitObjectArgument()->getExprLoc(),
call->getImplicitObjectArgument()->getExprLoc());
- auto newText = std::regex_replace(callText, std::regex(methodName + "\\(\\) *" + regexOpname),
+ std::string reString(methodName + " *\\( *\\) *" + regexOpname);
+ auto newText = std::regex_replace(callText, std::regex(reString),
setPrefix + methodName + "( " + implicitObjectText + "."
- + methodName + "() " + replaceOpname + " ");
+ + methodName + "() " + replaceOpname + " (");
if (newText == callText)
+ {
+ report(DiagnosticsEngine::Warning, "binaryop-other regex match failed %0",
+ call->getLocStart())
+ << reString;
return false;
+ }
// sometimes we end up with duplicate spaces after the opname
newText
= std::regex_replace(newText, std::regex(methodName + "\\(\\) \\" + replaceOpname + " "),
methodName + "() " + replaceOpname + " ");
- newText += " )";
+ newText += ") )";
return replaceText(startLoc, originalLength, newText);
}
bool ChangeToolsGen::ChangeUnaryOperator(UnaryOperator const* unaryOp,
CXXMemberCallExpr const* call,
- std::string const& methodName,
- std::string const& setPrefix)
+ std::string const& methodName)
{
// Look for expressions like
// aRect.Left()++;
+ // ++aRect.Left();
// and replace with
- // aRect.SetLeft( ++aRect.GetLeft() );
+ // aRect.MoveLeft( 1 );
+
SourceManager& SM = compiler.getSourceManager();
- SourceLocation startLoc = unaryOp->getLocStart();
- SourceLocation endLoc = unaryOp->getLocEnd();
+ SourceLocation startLoc = SM.getExpansionLoc(unaryOp->getLocStart());
+ SourceLocation endLoc = SM.getExpansionLoc(unaryOp->getLocEnd());
const char* p1 = SM.getCharacterData(startLoc);
const char* p2 = SM.getCharacterData(endLoc);
if (p2 < p1) // clang is misbehaving, appears to be macro constant related
@@ -251,45 +322,49 @@ bool ChangeToolsGen::ChangeUnaryOperator(UnaryOperator const* unaryOp,
call->getImplicitObjectArgument()->getExprLoc());
auto op = unaryOp->getOpcode();
std::string regexOpname;
- std::string replaceOpname;
+ std::string replaceOp;
switch (op)
{
case UO_PostInc:
case UO_PreInc:
- replaceOpname = "++";
+ replaceOp = "1";
regexOpname = "\\+\\+";
break;
case UO_PostDec:
case UO_PreDec:
- replaceOpname = "--";
+ replaceOp = "-1";
regexOpname = "\\-\\-";
break;
default:
assert(false);
}
+ std::string newText;
+ std::string reString;
if (op == UO_PostInc || op == UO_PostDec)
{
- auto newText
- = std::regex_replace(callText, std::regex(methodName + "\\(\\) *" + regexOpname),
- setPrefix + methodName + "( " + replaceOpname + implicitObjectText
- + "." + methodName + "()");
- return replaceText(startLoc, originalLength, newText);
+ reString = methodName + " *\\( *\\) *" + regexOpname;
+ newText = std::regex_replace(callText, std::regex(reString),
+ "Adjust" + methodName + "( " + replaceOp);
}
else
{
- auto newText
- = std::regex_replace(callText, std::regex(regexOpname + " *" + methodName + "\\(\\)"),
- setPrefix + methodName + "( " + replaceOpname + implicitObjectText
- + "." + methodName + "()");
- return replaceText(startLoc, originalLength, newText);
+ newText = implicitObjectText + "." + "Adjust" + methodName + "( " + replaceOp;
}
+ if (newText == callText)
+ {
+ report(DiagnosticsEngine::Warning, "unaryop regex match failed %0", call->getLocStart())
+ << reString;
+ return false;
+ }
+ newText += " )";
+ return replaceText(startLoc, originalLength, newText);
}
std::string ChangeToolsGen::extractCode(SourceLocation startLoc, SourceLocation endLoc)
{
SourceManager& SM = compiler.getSourceManager();
- const char* p1 = SM.getCharacterData(startLoc);
- const char* p2 = SM.getCharacterData(endLoc);
+ const char* p1 = SM.getCharacterData(SM.getExpansionLoc(startLoc));
+ const char* p2 = SM.getCharacterData(SM.getExpansionLoc(endLoc));
unsigned n = Lexer::MeasureTokenLength(endLoc, SM, compiler.getLangOpts());
return std::string(p1, p2 - p1 + n);
}
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 984c9e13d759..07f1edecf4c7 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -543,7 +543,7 @@ bool RewritePlugin::replaceText( SourceLocation Start, unsigned OrigLength, Stri
SourceRange Range(Start, Start.getLocWithOffset(std::max<size_t>(OrigLength, NewStr.size())));
if( OrigLength != 0 && !handler.checkOverlap( Range ) )
{
- report( DiagnosticsEngine::Warning, "double code replacement, possible plugin error", Start );
+ report( DiagnosticsEngine::Warning, "overlapping code replacement, possible plugin error", Start );
return false;
}
if( rewriter->ReplaceText( Start, OrigLength, NewStr ))
@@ -561,7 +561,7 @@ bool RewritePlugin::replaceText( SourceRange range, StringRef NewStr )
return reportEditFailure( range.getBegin());
if( !handler.checkOverlap( range ) )
{
- report( DiagnosticsEngine::Warning, "double code replacement, possible plugin error", range.getBegin());
+ report( DiagnosticsEngine::Warning, "overlapping code replacement, possible plugin error", range.getBegin());
return false;
}
if( rewriter->ReplaceText( range, NewStr ))
@@ -579,7 +579,7 @@ bool RewritePlugin::replaceText( SourceRange range, SourceRange replacementRange
return reportEditFailure( range.getBegin());
if( !handler.checkOverlap( range ) )
{
- report( DiagnosticsEngine::Warning, "double code replacement, possible plugin error", range.getBegin());
+ report( DiagnosticsEngine::Warning, "overlapping code replacement, possible plugin error", range.getBegin());
return false;
}
if( rewriter->ReplaceText( range, replacementRange ))