void ReturnSynthesizer::Transform() { if (!getTransaction()->getCompilationOpts().ResultEvaluation) return; FunctionDecl* FD = getTransaction()->getWrapperFD(); int foundAtPos = -1; Expr* lastExpr = utils::Analyze::GetOrCreateLastExpr(FD, &foundAtPos, /*omitDS*/false, m_Sema); if (lastExpr) { QualType RetTy = lastExpr->getType(); if (!RetTy->isVoidType() && RetTy.isTriviallyCopyableType(*m_Context)) { // Change the void function's return type // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, FD); FunctionProtoType::ExtProtoInfo EPI; QualType FnTy = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(), EPI); FD->setType(FnTy); CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); assert(CS && "Missing body?"); // Change it to a return stmt (Avoid dealloc/alloc of all el.) *(CS->body_begin() + foundAtPos) = m_Sema->ActOnReturnStmt(lastExpr->getExprLoc(), lastExpr).take(); } } else if (foundAtPos >= 0) { // check for non-void return statement CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); Stmt* CSS = *(CS->body_begin() + foundAtPos); if (ReturnStmt* RS = dyn_cast<ReturnStmt>(CSS)) { if (Expr* RetV = RS->getRetValue()) { QualType RetTy = RetV->getType(); // Any return statement will have been "healed" by Sema // to correspond to the original void return type of the // wrapper, using a ImplicitCastExpr 'void' <ToVoid>. // Remove that. if (RetTy->isVoidType()) { ImplicitCastExpr* VoidCast = dyn_cast<ImplicitCastExpr>(RetV); if (VoidCast) { RS->setRetValue(VoidCast->getSubExpr()); RetTy = VoidCast->getSubExpr()->getType(); } } if (!RetTy->isVoidType() && RetTy.isTriviallyCopyableType(*m_Context)) { Sema::ContextRAII pushedDC(*m_Sema, FD); FunctionProtoType::ExtProtoInfo EPI; QualType FnTy = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(), EPI); FD->setType(FnTy); } // not returning void } // have return value } // is a return statement } // have a statement }
void NetworkDriverRewriteVisitor::InstrumentEntryPoints(FunctionDecl* funcDecl, string fdFile) { if (funcDecl->getStorageClass() == SC_Static) RW.RemoveText(funcDecl->getInnerLocStart(), 7); if (DI->getInstance().GetInitFunction() == funcDecl->getNameInfo().getName().getAsString()) return; if (funcDecl->getParamDecl(0)->getOriginalType().getAsString() != "struct device *" && funcDecl->getParamDecl(0)->getOriginalType().getAsString() != "struct pci_dev *") return; SourceRange sr = funcDecl->getParamDecl(0)->getSourceRange(); RW.InsertTextBefore(sr.getBegin(), "struct net_device *dev, "); Stmt *body = funcDecl->getBody(); list<DeclStmt*> stmtsToRewrite; for (auto i = body->child_begin(), e = body->child_end(); i != e; ++i) { if (!isa<DeclStmt>(*i)) continue; DeclStmt *declStmt = cast<DeclStmt>(*i); if (!declStmt->isSingleDecl() && !isa<VarDecl>(declStmt->getSingleDecl())) continue; VarDecl *var = cast<VarDecl>(declStmt->getSingleDecl()); if (!var->hasInit()) continue; Expr *expr = var->getInit(); if (!isa<ImplicitCastExpr>(expr)) continue; ImplicitCastExpr *implicit = cast<ImplicitCastExpr>(expr); if (!isa<CallExpr>(implicit->getSubExpr())) continue; CallExpr *call = cast<CallExpr>(implicit->getSubExpr()); DeclRefExpr *callee = cast<DeclRefExpr>(cast<ImplicitCastExpr>(call->getCallee())->getSubExpr()); if (callee->getNameInfo().getName().getAsString() == "to_pci_dev" || callee->getNameInfo().getName().getAsString() == "pci_get_drvdata") { stmtsToRewrite.push_back(declStmt); } } while (!stmtsToRewrite.empty()) { DeclStmt *stmt = stmtsToRewrite.back(); RW.RemoveText(stmt->getSourceRange()); stmtsToRewrite.pop_back(); } }
bool Utils::isImplicitCastTo(Stmt *s, const string &className) { ImplicitCastExpr *expr = dyn_cast<ImplicitCastExpr>(s); if (!expr) return false; auto record = expr->getBestDynamicClassType(); return record && record->getNameAsString() == className; }
bool isCharLiteral(Expr *expr, string &selectorString) { if (selectorString == "numberWithChar:" && expr && isa<ImplicitCastExpr>(expr)) { ImplicitCastExpr *implicitCastExpr = dyn_cast<ImplicitCastExpr>(expr); Expr *subExpr = implicitCastExpr->getSubExpr(); return subExpr && isa<CharacterLiteral>(subExpr); } return false; }
NamedDecl* RedundantLocalVariableRule::extractFromReturnStmt(Stmt *stmt) { ReturnStmt *returnStmt = dyn_cast<ReturnStmt>(stmt); if (returnStmt) { Expr *returnValue = returnStmt->getRetValue(); if (returnValue) { ImplicitCastExpr *implicitCastExpr = dyn_cast<ImplicitCastExpr>(returnValue); if (implicitCastExpr) { DeclRefExpr *returnExpr = dyn_cast<DeclRefExpr>(implicitCastExpr->getSubExpr()); if (returnExpr) { return returnExpr->getFoundDecl(); } } } } return NULL; }
void IsEmptyVSCount::VisitStmt(clang::Stmt *stmt) { ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(stmt); if (!cast || cast->getCastKind() != clang::CK_IntegralToBoolean) return; CXXMemberCallExpr *memberCall = dyn_cast<CXXMemberCallExpr>(*(cast->child_begin())); CXXMethodDecl *method = memberCall ? memberCall->getMethodDecl() : nullptr; if (!StringUtils::functionIsOneOf(method, {"size", "count", "length"})) return; if (!StringUtils::classIsOneOf(method->getParent(), QtUtils::qtContainers())) return; emitWarning(stmt->getLocStart(), "use isEmpty() instead"); }
string NetworkDriverRewriteVisitor::GetSharedStructStr(CallExpr *callExpr) { string shared_struct_str = ""; Expr *callee = callExpr->getCallee(); if (!isa<ImplicitCastExpr>(callee)) return shared_struct_str; ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); if (!isa<DeclRefExpr>(calleeImplExpr->getSubExpr())) return shared_struct_str; DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); Stmt *body = callExpr->getCalleeDecl()->getBody(); if (calleeDeclExpr->getNameInfo().getAsString() != "alloc_etherdev") shared_struct_str = GetSharedStructStrInFunctionBody(body, false); if (calleeDeclExpr->getNameInfo().getAsString() != "alloc_etherdev") return shared_struct_str; for (auto i = callExpr->arg_begin(), e = callExpr->arg_end(); i != e; ++i) { if (!isa<ImplicitCastExpr>(*i)) continue; ImplicitCastExpr *argImplExpr = cast<ImplicitCastExpr>(*i); if (!isa<UnaryExprOrTypeTraitExpr>(argImplExpr->getSubExpr())) continue; UnaryExprOrTypeTraitExpr *argExpr = cast<UnaryExprOrTypeTraitExpr>(argImplExpr->getSubExpr()); ParenExpr *parenExpr = cast<ParenExpr>(argExpr->getArgumentExpr()); UnaryOperator *uop = cast<UnaryOperator>(parenExpr->getSubExpr()); ImplicitCastExpr *implExpr = cast<ImplicitCastExpr>(uop->getSubExpr()); DeclRefExpr *declExpr = cast<DeclRefExpr>(implExpr->getSubExpr()); ValueDecl *valueDecl = cast<ValueDecl>(declExpr->getDecl()); shared_struct_str = valueDecl->getType().getAsString(Context->getPrintingPolicy()); break; } return shared_struct_str; }
string NetworkDriverRewriteVisitor::GetSharedStructStrInFunctionBody(Stmt *body, bool doLog) { string shared_struct_str = ""; for (auto i = body->child_begin(), e = body->child_end(); i != e; ++i) { if (isa<DeclStmt>(*i)) { DeclStmt *declStmt = cast<DeclStmt>(*i); if (!declStmt->isSingleDecl() && !isa<VarDecl>(declStmt->getSingleDecl())) continue; VarDecl *varDecl = cast<VarDecl>(declStmt->getSingleDecl()); if (!isa<ValueDecl>(varDecl)) continue; ValueDecl *value = cast<ValueDecl>(varDecl); if (value->getType().getAsString(Context->getPrintingPolicy()) != "struct net_device *") continue; if (!isa<NamedDecl>(varDecl)) continue; if (varDecl->getInit() == 0 || !isa<CallExpr>(varDecl->getInit())) continue; CallExpr *callExpr = cast<CallExpr>(varDecl->getInit()); shared_struct_str = GetSharedStructStr(callExpr); if (shared_struct_str != "") { if (doLog) { Expr *callee = callExpr->getCallee(); ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); DI->getInstance().AddSharedStructInformation("whoop_network_shared_struct", calleeDeclExpr->getNameInfo().getAsString()); } break; } } else if (isa<BinaryOperator>(*i)) { BinaryOperator *binOp = cast<BinaryOperator>(*i); if (!isa<CallExpr>(binOp->getRHS())) continue; CallExpr *callExpr = cast<CallExpr>(binOp->getRHS()); shared_struct_str = GetSharedStructStr(callExpr); if (shared_struct_str != "") { if (doLog) { Expr *callee = callExpr->getCallee(); ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); DI->getInstance().AddSharedStructInformation("whoop_network_shared_struct", calleeDeclExpr->getNameInfo().getAsString()); } break; } } } return shared_struct_str; }
void ICEVisitor::VisitBinaryOperator(BinaryOperator *BO) { const NamedDecl *ACD = dyn_cast_or_null<NamedDecl>(AC->getDecl()); VisitChildren(BO); std::string ename = "EventNumber_t"; clang::Expr *LHS = BO->getLHS(); clang::Expr *RHS = BO->getRHS(); if (!LHS || !RHS) return; std::string lname = LHS->getType().getAsString(); std::string rname = RHS->getType().getAsString(); if (IntegerLiteral::classof(LHS->IgnoreCasts()) || IntegerLiteral::classof(RHS->IgnoreCasts())) return; if (!(lname == ename || rname == ename)) return; if (lname == ename && rname == ename) return; clang::QualType OTy; clang::QualType TTy; if (lname == ename && ImplicitCastExpr::classof(RHS)) { ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(RHS); TTy = BR.getContext().getCanonicalType(LHS->getType()); OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType()); } if (rname == ename && ImplicitCastExpr::classof(LHS)) { ImplicitCastExpr *ICE = dyn_cast_or_null<ImplicitCastExpr>(LHS); TTy = BR.getContext().getCanonicalType(RHS->getType()); OTy = BR.getContext().getCanonicalType(ICE->getSubExprAsWritten()->getType()); } if (TTy.isNull() || OTy.isNull()) return; QualType ToTy = TTy.getUnqualifiedType(); QualType OrigTy = OTy.getUnqualifiedType(); if (!(ToTy->isIntegerType() || ToTy->isFloatingType())) return; if (ToTy->isBooleanType()) return; CharUnits size_otype = BR.getContext().getTypeSizeInChars(OrigTy); CharUnits size_ttype = BR.getContext().getTypeSizeInChars(ToTy); std::string oname = OrigTy.getAsString(); std::string tname = ToTy.getAsString(); if (ToTy->isFloatingType()) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << " . " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC); BR.EmitBasicReport(ACD, CheckName(), "implicit cast of int type to float type", "CMS code rules", os.str(), CELoc, BO->getSourceRange()); } if ((size_otype > size_ttype)) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Cast may result in truncation. " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC); BR.EmitBasicReport(ACD, CheckName(), "implicit cast of int type to smaller int type could truncate", "CMS code rules", os.str(), CELoc, BO->getSourceRange()); } if ((size_otype == size_ttype) && (ToTy->hasSignedIntegerRepresentation() && OrigTy->hasUnsignedIntegerRepresentation() || ToTy->hasUnsignedIntegerRepresentation() && OrigTy->hasSignedIntegerRepresentation())) { llvm::SmallString<100> buf; llvm::raw_svector_ostream os(buf); os << "Cast-to type, " << tname << ". Cast-from type, " << oname << ". Changes int sign type. " << support::getQualifiedName(*(ACD)); clang::ento::PathDiagnosticLocation CELoc = clang::ento::PathDiagnosticLocation::createBegin(BO, BR.getSourceManager(), AC); BR.EmitBasicReport( ACD, CheckName(), "implicit cast ins sign type", "CMS code rules", os.str(), CELoc, BO->getSourceRange()); } return; return; }