From d2143eacaf8b9799a1abd9bf1ce54df9bf73d29a Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Tue, 6 Sep 2016 12:01:29 +0200 Subject: teach loplugin constantparam about default param values Change-Id: I334622bd34d8349f5b3988122d282b1062b225bb --- compilerplugins/clang/constantparam.cxx | 72 +++++++++++++++++++++------------ compilerplugins/clang/constantparam.py | 12 +++--- 2 files changed, 52 insertions(+), 32 deletions(-) (limited to 'compilerplugins') diff --git a/compilerplugins/clang/constantparam.cxx b/compilerplugins/clang/constantparam.cxx index 2a44939a4b60..62a79494dd7d 100644 --- a/compilerplugins/clang/constantparam.cxx +++ b/compilerplugins/clang/constantparam.cxx @@ -96,11 +96,11 @@ public: bool VisitDeclRefExpr( const DeclRefExpr* ); bool VisitCXXConstructExpr( const CXXConstructExpr* ); private: - MyCallSiteInfo niceName(const FunctionDecl* functionDecl, int paramIndex, const ParmVarDecl* parmVarDecl, const std::string& callValue); + MyCallSiteInfo niceName(const FunctionDecl* functionDecl, int paramIndex, llvm::StringRef paramName, const std::string& callValue); std::string getCallValue(const Expr* arg); }; -MyCallSiteInfo ConstantParam::niceName(const FunctionDecl* functionDecl, int paramIndex, const ParmVarDecl* parmVarDecl, const std::string& callValue) +MyCallSiteInfo ConstantParam::niceName(const FunctionDecl* functionDecl, int paramIndex, llvm::StringRef paramName, const std::string& callValue) { if (functionDecl->getInstantiatedFromMemberFunction()) functionDecl = functionDecl->getInstantiatedFromMemberFunction(); @@ -133,7 +133,7 @@ MyCallSiteInfo ConstantParam::niceName(const FunctionDecl* functionDecl, int par if (isa(functionDecl) && dyn_cast(functionDecl)->isConst()) { aInfo.nameAndParams += " const"; } - aInfo.paramName = parmVarDecl->getName(); + aInfo.paramName = paramName; aInfo.paramIndex = paramIndex; aInfo.callValue = callValue; @@ -146,17 +146,24 @@ MyCallSiteInfo ConstantParam::niceName(const FunctionDecl* functionDecl, int par std::string ConstantParam::getCallValue(const Expr* arg) { + arg = arg->IgnoreParenCasts(); + if (isa(arg)) { + arg = dyn_cast(arg)->getExpr(); + } arg = arg->IgnoreParenCasts(); // ignore this, it seems to trigger an infinite recursion if (isa(arg)) { - return "unknown"; + return "unknown1"; } APSInt x1; if (arg->EvaluateAsInt(x1, compiler.getASTContext())) { return x1.toString(10); } - return "unknown"; + if (isa(arg)) { + return "0"; + } + return "unknown2"; } bool ConstantParam::VisitCallExpr(const CallExpr * callExpr) { @@ -193,22 +200,30 @@ bool ConstantParam::VisitCallExpr(const CallExpr * callExpr) { functionDecl = functionDecl->getTemplateInstantiationPattern(); #endif + if (!functionDecl->getNameInfo().getLoc().isValid() || ignoreLocation(functionDecl)) { + return true; + } // ignore stuff that forms part of the stable URE interface if (isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc( functionDecl->getNameInfo().getLoc()))) { return true; } - if (functionDecl->getNameInfo().getLoc().isValid() && ignoreLocation(functionDecl)) { - return true; - } - for (unsigned i = 0; i < callExpr->getNumArgs(); ++i) { - if (i >= functionDecl->getNumParams()) // can happen in template code - break; - const Expr* arg = callExpr->getArg(i); - std::string callValue = getCallValue(arg); - const ParmVarDecl* parmVarDecl = functionDecl->getParamDecl(i); - MyCallSiteInfo funcInfo = niceName(functionDecl, i, parmVarDecl, callValue); + unsigned len = std::max(callExpr->getNumArgs(), functionDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) { + const Expr* valExpr; + if (i < callExpr->getNumArgs()) + valExpr = callExpr->getArg(i); + else if (i < functionDecl->getNumParams() && functionDecl->getParamDecl(i)->hasDefaultArg()) + valExpr = functionDecl->getParamDecl(i)->getDefaultArg(); + else + // can happen in template code + continue; + std::string callValue = getCallValue(valExpr); + std::string paramName = i < functionDecl->getNumParams() + ? functionDecl->getParamDecl(i)->getName() + : llvm::StringRef("###" + std::to_string(i)); + MyCallSiteInfo funcInfo = niceName(functionDecl, i, paramName, callValue); callSet.insert(funcInfo); } return true; @@ -224,7 +239,7 @@ bool ConstantParam::VisitDeclRefExpr( const DeclRefExpr* declRefExpr ) const FunctionDecl* functionDecl = dyn_cast(decl); for (unsigned i = 0; i < functionDecl->getNumParams(); ++i) { - MyCallSiteInfo funcInfo = niceName(functionDecl, i, functionDecl->getParamDecl(i), "unknown"); + MyCallSiteInfo funcInfo = niceName(functionDecl, i, functionDecl->getParamDecl(i)->getName(), "unknown3"); callSet.insert(funcInfo); } return true; @@ -240,18 +255,25 @@ bool ConstantParam::VisitCXXConstructExpr( const CXXConstructExpr* constructExpr constructorDecl->getNameInfo().getLoc()))) { return true; } - if (constructorDecl->getNameInfo().getLoc().isValid() && ignoreLocation(constructorDecl)) { + if (!constructorDecl->getNameInfo().getLoc().isValid() || ignoreLocation(constructorDecl)) { return true; } - for (unsigned i = 0; i < constructExpr->getNumArgs(); ++i) - { - if (i >= constructorDecl->getNumParams()) // can happen in template code - break; - const Expr* arg = constructExpr->getArg(i); - std::string callValue = getCallValue(arg); - const ParmVarDecl* parmVarDecl = constructorDecl->getParamDecl(i); - MyCallSiteInfo funcInfo = niceName(constructorDecl, i, parmVarDecl, callValue); + unsigned len = std::max(constructExpr->getNumArgs(), constructorDecl->getNumParams()); + for (unsigned i = 0; i < len; ++i) { + const Expr* valExpr; + if (i < constructExpr->getNumArgs()) + valExpr = constructExpr->getArg(i); + else if (i < constructorDecl->getNumParams() && constructorDecl->getParamDecl(i)->hasDefaultArg()) + valExpr = constructorDecl->getParamDecl(i)->getDefaultArg(); + else + // can happen in template code + continue; + std::string callValue = getCallValue(valExpr); + std::string paramName = i < constructorDecl->getNumParams() + ? constructorDecl->getParamDecl(i)->getName() + : llvm::StringRef("###" + std::to_string(i)); + MyCallSiteInfo funcInfo = niceName(constructorDecl, i, paramName, callValue); callSet.insert(funcInfo); } return true; diff --git a/compilerplugins/clang/constantparam.py b/compilerplugins/clang/constantparam.py index 21aca1ee1c16..ae2b2433ae54 100755 --- a/compilerplugins/clang/constantparam.py +++ b/compilerplugins/clang/constantparam.py @@ -37,16 +37,14 @@ for callInfo, callValues in callParamSet.iteritems(): nameAndParams = callInfo[1] if len(callValues) != 1: continue - if "unknown" in callValues: + callValue = next(iter(callValues)) + if "unknown" in callValue: continue - # ignore anything with only one parameter, normally just setter methods - if nameAndParams.find(",") == -1: - continue - # if it contains anything other than this set, ignore it - if len(callValues - set(["0", "1", "-1", "nullptr"])) > 0: + # try and ignore setter methods + if ("," not in nameAndParams) and (("::set" in nameAndParams) or ("::Set" in nameAndParams)): continue v0 = callInfo[0] + " " + callInfo[1] - v1 = callInfo[2] + " " + (",".join(callValues)) + v1 = callInfo[2] + " " + callValue v2 = definitionToSourceLocationMap[callInfo] tmp1list.append((v0,v1,v2)) -- cgit