void Bookkeeper::record_type_with_bitfields(const Type *typ) { if (!typ->is_aggregate()) return; if (typ->has_bitfields()) { Bookkeeper::structs_with_bitfields++; size_t len = typ->bitfields_length_.size(); assert(len == typ->fields.size()); for (size_t i = 0; i < len; ++i) { if (!typ->is_bitfield(i)) continue; Bookkeeper::bitfields_in_total++; if (typ->bitfields_length_[i] == 0) Bookkeeper::unamed_bitfields_in_total++; CVQualifiers qual = typ->qfers_[i]; if (qual.is_const()) Bookkeeper::const_bitfields_in_total++; if (qual.is_volatile()) Bookkeeper::volatile_bitfields_in_total++; } } }
CVQualifiers FunctionInvocation::get_qualifiers(void) const { CVQualifiers qfer; if (invoke_type == eFuncCall) { const FunctionInvocationUser* func_call = dynamic_cast<const FunctionInvocationUser*>(this); assert(func_call->get_func()); assert(func_call->get_func()->rv); qfer = func_call->get_func()->rv->qfer; } // for binary and unary operations, they only yield integers right now (no pointer arithmatic // supported yet!), we assume they return non-const non-volatile int else { qfer.add_qualifiers(false, false); } return qfer; }
static void GenerateParameterListFromString(Function &currFunc, const string ¶ms_string) { vector<string> vs; StringUtils::split_string(params_string, vs, ","); int params_cnt = vs.size(); assert((params_cnt > 0) && "Invalid params_string!"); if ((params_cnt == 1) && (vs[0] == "Void")) { return; } for (int i = 0; i < params_cnt; i++) { assert((vs[i] != "Void") && "Invalid parameter type!"); CVQualifiers qfer; qfer.add_qualifiers(false, false); const Type *ty = Type::get_type_from_string(vs[0]); Variable *v = VariableSelector::GenerateParameterVariable(ty, &qfer); assert(v); currFunc.param.push_back(v); } }
StatementAssign * StatementAssign::make_random(CGContext &cg_context, const Type* type, const CVQualifiers* qf) { // decide assignment operator eAssignOps op = AssignOpsProbability(type); // bool stand_alone_assign = false; // decide type if (type == NULL) { // stand_alone_assign = true; type = Type::SelectLType(!cg_context.get_effect_context().is_side_effect_free(), op); } assert(!type->is_const_struct_union()); FactMgr* fm = get_fact_mgr(&cg_context); assert(fm); // pre-generation initializations Lhs *lhs = NULL; Expression *e = NULL; Effect running_eff_context(cg_context.get_effect_context()); Effect rhs_accum, lhs_accum; CGContext rhs_cg_context(cg_context, running_eff_context, &rhs_accum); CVQualifiers qfer; if (qf) qfer = *qf; if (need_no_rhs(op)) { e = Constant::make_int(1); // if we are creating standalone statements like x++, any qualifers fit if (qf == NULL) qfer.wildcard = true; } else if (CGOptions::strict_volatile_rule()) { if (type->is_volatile_struct_union()) return NULL; e = Expression::make_random(rhs_cg_context, type, qf); ERROR_GUARD_AND_DEL1(NULL, e); if (!qf) { qfer = e->get_qualifiers(); // lhs should not has "const" qualifier qfer.accept_stricter = true; } // for compound assignment, generate LHS in the effect context of RHS if (op != eSimpleAssign) { running_eff_context.add_effect(rhs_accum); // for now, just use non-volatile as LHS for compound assignments qfer.set_volatile(false); } running_eff_context.add_effect(rhs_accum); // if the rhs is volatile, almost came from dereferencing a pointer, // then make sure lhs is not a vol if (qfer.get_volatiles().size() && qfer.is_volatile()) qfer.set_volatile(false); } else { e = Expression::make_random(rhs_cg_context, type, qf); ERROR_GUARD_AND_DEL1(NULL, e); if (!qf) { qfer = e->get_qualifiers(); // lhs should not has "const" qualifier qfer.accept_stricter = true; } // for compound assignment, generate LHS in the effect context of RHS if (op != eSimpleAssign) { running_eff_context.add_effect(rhs_accum); // for now, just use non-volatile as LHS for compound assignments qfer.set_volatile(false); } } cg_context.merge_param_context(rhs_cg_context, true); running_eff_context.write_var_set(rhs_accum.get_lhs_write_vars()); CGContext lhs_cg_context(cg_context, running_eff_context, &lhs_accum); lhs_cg_context.get_effect_stm() = rhs_cg_context.get_effect_stm(); lhs_cg_context.curr_rhs = e; bool prev_flag = CGOptions::match_exact_qualifiers(); // keep a copy of previous flag if (qf) CGOptions::match_exact_qualifiers(true); // force exact qualifier match when selecting vars lhs = Lhs::make_random(lhs_cg_context, type, &qfer, op != eSimpleAssign, need_no_rhs(op)); if (qf) CGOptions::match_exact_qualifiers(prev_flag); // restore flag ERROR_GUARD_AND_DEL2(NULL, e, lhs); // typecast, if needed. e->check_and_set_cast(type); if (CGOptions::ccomp() && lhs->get_var()->isBitfield_) { e->cast_type = type; } // e can be of float type. So, we reset its if ((lhs->get_var()->type->get_base_type()->is_float() || e->get_type().get_base_type()->is_float()) && !StatementAssign::AssignOpWorksForFloat(op)) { op = eSimpleAssign; } if (CompatibleChecker::compatible_check(e, lhs)) { Error::set_error(COMPATIBLE_CHECK_ERROR); delete e; delete lhs; return NULL; } cg_context.merge_param_context(lhs_cg_context, true); ERROR_GUARD_AND_DEL2(NULL, e, lhs); StatementAssign *stmt_assign = make_possible_compound_assign(cg_context, type, *lhs, op, *e); ERROR_GUARD_AND_DEL2(NULL, e, lhs); return stmt_assign; }