diff options
Diffstat (limited to 'compilerplugins/clang/unnecessaryparen.cxx')
-rw-r--r-- | compilerplugins/clang/unnecessaryparen.cxx | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/compilerplugins/clang/unnecessaryparen.cxx b/compilerplugins/clang/unnecessaryparen.cxx index 55dac9523870..40faa88b3157 100644 --- a/compilerplugins/clang/unnecessaryparen.cxx +++ b/compilerplugins/clang/unnecessaryparen.cxx @@ -56,16 +56,50 @@ public: bool VisitWhileStmt(const WhileStmt *); bool VisitSwitchStmt(const SwitchStmt *); bool VisitCallExpr(const CallExpr *); + bool TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *); + bool TraverseCaseStmt(CaseStmt *); + bool TraverseConditionalOperator(ConditionalOperator *); private: void VisitSomeStmt(const Stmt *parent, const Expr* cond, StringRef stmtName); + Expr* insideCaseStmt = nullptr; + Expr* insideConditionalOperator = nullptr; }; +bool UnnecessaryParen::TraverseUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *) +{ + // for some reason, the parentheses in an expression like "sizeof(x)" actually show up + // in the AST, so just ignore that part of the AST + return true; +} + +bool UnnecessaryParen::TraverseCaseStmt(CaseStmt * caseStmt) +{ + auto old = insideCaseStmt; + insideCaseStmt = caseStmt->getLHS()->IgnoreImpCasts(); + bool ret = RecursiveASTVisitor::TraverseCaseStmt(caseStmt); + insideCaseStmt = old; + return ret; +} + +bool UnnecessaryParen::TraverseConditionalOperator(ConditionalOperator * conditionalOperator) +{ + auto old = insideConditionalOperator; + insideConditionalOperator = conditionalOperator->getCond()->IgnoreImpCasts(); + bool ret = RecursiveASTVisitor::TraverseConditionalOperator(conditionalOperator); + insideConditionalOperator = old; + return ret; +} + bool UnnecessaryParen::VisitParenExpr(const ParenExpr* parenExpr) { if (ignoreLocation(parenExpr)) return true; if (parenExpr->getLocStart().isMacroID()) return true; + if (insideCaseStmt && parenExpr == insideCaseStmt) + return true; + if (insideConditionalOperator && parenExpr == insideConditionalOperator) + return true; auto subParenExpr = dyn_cast<ParenExpr>(parenExpr->getSubExpr()->IgnoreImpCasts()); if (subParenExpr) { @@ -76,6 +110,24 @@ bool UnnecessaryParen::VisitParenExpr(const ParenExpr* parenExpr) parenExpr->getLocStart()) << parenExpr->getSourceRange(); } + + auto declRefExpr = dyn_cast<DeclRefExpr>(parenExpr->getSubExpr()->IgnoreImpCasts()); + if (declRefExpr) { + if (declRefExpr->getLocStart().isMacroID()) + return true; + + // hack for BAD_CAST macro + SourceManager& SM = compiler.getSourceManager(); + const char *p1 = SM.getCharacterData( declRefExpr->getLocStart().getLocWithOffset(-10) ); + const char *p2 = SM.getCharacterData( declRefExpr->getLocStart() ); + if ( std::string(p1, p2 - p1).find("BAD_CAST") != std::string::npos ) + return true; + + report( + DiagnosticsEngine::Warning, "unnecessary parentheses around identifier", + parenExpr->getLocStart()) + << parenExpr->getSourceRange(); + } return true; } |