void TraverseFunctionBody(Stmt *S, Method *m) { // perform depth first traversal of all children for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E; ++CI) { if (*CI) TraverseFunctionBody(*CI, m); } // if it's a function call, register it if (CallExpr *CE = dyn_cast<CallExpr>(S)) { FunctionDecl *fd = CE->getDirectCallee(); if (fd != 0) { QualType type = fd->getResultType(); std::string rtype = type.getAsString(); std::string qname = fd->getQualifiedNameAsString(); std::string param = ""; param += "("; for (FunctionDecl::param_iterator I = fd->param_begin(), E = fd->param_end(); I != E; ++I) { if(ParmVarDecl *PD = dyn_cast<ParmVarDecl>(*I)) { QualType type = PD->getType(); param += type.getAsString() + ","; } else assert(0); // case of interest! } if (param != "(") param.erase(param.end() - 1); // remove the last comma param += ")"; std::string callee = rtype + " " + qname + param; m->callexprs.insert(callee); } } }
void ReplaceCallExpr::getParmPosVector(ParameterPosVector &PosVector, ReturnStmt *RS, CallExpr *CE) { DenseMap<ReturnStmt *, ParmRefsVector *>::iterator RI = ReturnStmtToParmRefs.find(RS); if (RI == ReturnStmtToParmRefs.end()) return; ParmRefsVector *PVector = (*RI).second; FunctionDecl *FD = CE->getDirectCallee(); for (ParmRefsVector::const_iterator PI = PVector->begin(), PE = PVector->end(); PI != PE; ++PI) { const ValueDecl *OrigDecl = (*PI)->getDecl(); const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(OrigDecl); unsigned int Pos = 0; for(FunctionDecl::param_const_iterator I = FD->param_begin(), E = FD->param_end(); I != E; ++I) { if (PD == (*I)) break; Pos++; } PosVector.push_back(Pos); } }
void ReplaceCallExpr::getNewParmRefStr(const DeclRefExpr *DE, std::string &ParmRefStr) { const ValueDecl *OrigDecl = DE->getDecl(); const ParmVarDecl *PD = dyn_cast<ParmVarDecl>(OrigDecl); TransAssert(PD && "Bad ParmVarDecl!"); FunctionDecl *FD = TheCallExpr->getDirectCallee(); unsigned int Pos = 0; for(FunctionDecl::param_const_iterator I = FD->param_begin(), E = FD->param_end(); I != E; ++I) { TransAssert((Pos < TheCallExpr->getNumArgs()) && "Unmatched Parm and Arg!"); if (PD != (*I)) { Pos++; continue; } const Expr *Arg = TheCallExpr->getArg(Pos)->IgnoreParenImpCasts(); RewriteHelper->getExprString(Arg, ParmRefStr); ParmRefStr = "(" + ParmRefStr + ")"; const Type *ParmT = PD->getType().getTypePtr(); const Type *CanParmT = Context->getCanonicalType(ParmT); const Type *ArgT = Arg->getType().getTypePtr(); const Type *CanArgT = Context->getCanonicalType(ArgT); if (CanParmT != CanArgT) { std::string TypeCastStr = PD->getType().getAsString(); ParmRefStr = "(" + TypeCastStr + ")" + ParmRefStr; } return; } TransAssert(0 && "Unreachable Code!"); }
void FunctionArgsByRef::VisitDecl(Decl *decl) { FunctionDecl *functionDecl = dyn_cast<FunctionDecl>(decl); if (functionDecl == nullptr || !functionDecl->hasBody() || shouldIgnoreFunction(functionDecl->getNameAsString()) || !functionDecl->isThisDeclarationADefinition()) return; Stmt *body = functionDecl->getBody(); for (auto it = functionDecl->param_begin(), end = functionDecl->param_end(); it != end; ++it) { const ParmVarDecl *param = *it; QualType paramQt = param->getType(); const Type *paramType = paramQt.getTypePtrOrNull(); if (paramType == nullptr || paramType->isDependentType()) continue; const int size_of_T = m_ci.getASTContext().getTypeSize(paramQt) / 8; const bool isSmall = size_of_T <= 16; // TODO: What about arm ? CXXRecordDecl *recordDecl = paramType->getAsCXXRecordDecl(); const bool isUserNonTrivial = recordDecl && (recordDecl->hasUserDeclaredCopyConstructor() || recordDecl->hasUserDeclaredDestructor()); const bool isReference = paramType->isLValueReferenceType(); const bool isConst = paramQt.isConstQualified(); if (recordDecl && shouldIgnoreClass(recordDecl->getQualifiedNameAsString())) continue; std::string error; if (isConst && !isReference) { if (!isSmall) { error += warningMsgForSmallType(size_of_T, paramQt.getAsString()); } else if (isUserNonTrivial) { error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString(); } } else if (isConst && isReference && !isUserNonTrivial && isSmall) { //error += "Don't use by-ref on small trivial type"; } else if (!isConst && !isReference && (!isSmall || isUserNonTrivial)) { if (Utils::containsNonConstMemberCall(body, param) || Utils::containsCallByRef(body, param)) continue; if (!isSmall) { error += warningMsgForSmallType(size_of_T, paramQt.getAsString()); } else if (isUserNonTrivial) { error += "Missing reference on non-trivial type " + recordDecl->getQualifiedNameAsString(); } } if (!error.empty()) { emitWarning(param->getLocStart(), error.c_str()); } } }
void NSErrorChecker::CheckSignature(const FunctionDecl& F, QualType& ResultTy, llvm::SmallVectorImpl<VarDecl*>& ErrorParams) { ResultTy = F.getResultType(); for (FunctionDecl::param_const_iterator I = F.param_begin(), E = F.param_end(); I != E; ++I) { QualType T = (*I)->getType(); if (isNSErrorWarning) { if (CheckNSErrorArgument(T)) ErrorParams.push_back(*I); } else if (CheckCFErrorArgument(T)) ErrorParams.push_back(*I); } }