* find an initializing value for a new variable * for non-pointers, we just use constants * for pointers we need to find another variable to take address with a random chance. * If no much variable is available, we have to create a suitable variable (which * might call this function again) *************************************************************************************/
| 815 | * might call this function again) |
| 816 | *************************************************************************************/ |
| 817 | Expression* |
| 818 | VariableSelector::make_init_value(Effect::Access access, const CGContext &cg_context, const Type* t, const CVQualifiers* qf, Block* b) |
| 819 | { |
| 820 | assert(qf && qf->sanity_check(t)); |
| 821 | CVQualifiers qfer(*qf); |
| 822 | // the initialzer should always be less restricting than the variable to be initialized |
| 823 | qfer.accept_stricter = false; |
| 824 | |
| 825 | if (t->eType != ePointer || rnd_flipcoin(20)) { |
| 826 | ERROR_GUARD(NULL); |
| 827 | if (t->eType == eSimple) |
| 828 | assert(t->simple_type != eVoid); |
| 829 | return Constant::make_random(t); |
| 830 | } |
| 831 | ERROR_GUARD(NULL); |
| 832 | // for pointers, take address of a random visible local variable |
| 833 | const Type* type = t->ptr_type; |
| 834 | assert(type); |
| 835 | |
| 836 | vector<Variable*> vars = find_all_visible_vars(b); |
| 837 | vector<const Variable*> dummy; |
| 838 | |
| 839 | Variable *var = NULL; |
| 840 | // b == NULL means we are generating init for globals |
| 841 | if (!b && CGOptions::ccomp()) { |
| 842 | get_all_array_vars(dummy); |
| 843 | var = choose_var(vars, access, cg_context, type, &qfer, eExact, dummy, true, true); |
| 844 | } |
| 845 | else { |
| 846 | if (!CGOptions::addr_taken_of_locals()) |
| 847 | get_all_local_vars(b, dummy); |
| 848 | var = choose_var(vars, access, cg_context, type, &qfer, eExact, dummy, true); |
| 849 | } |
| 850 | ERROR_GUARD(NULL); |
| 851 | |
| 852 | // if no such var, create a new one |
| 853 | if (var == 0) { |
| 854 | DEPTH_GUARD_BY_TYPE_RETURN(dtInitPointerValue, NULL); |
| 855 | // current context has no impact on variable initialization, which happens at declare time? |
| 856 | bool no_volatile = false; //!cg_context.get_effect_context().is_side_effect_free(); |
| 857 | if (CGOptions::strict_volatile_rule()) |
| 858 | no_volatile = !cg_context.get_effect_context().is_side_effect_free(); |
| 859 | CVQualifiers qfer_deref = qfer.random_loose_qualifiers(no_volatile, access, cg_context); |
| 860 | qfer_deref.remove_qualifiers(1); |
| 861 | qfer_deref.accept_stricter = false; |
| 862 | bool use_local = (!CGOptions::global_variables() || (b != 0 && type->eType == ePointer && !qfer_deref.is_volatile())); |
| 863 | const Type* tt = use_local ? Type::random_type_from_type(type, true, true) : Type::random_type_from_type(type, false, true); |
| 864 | ERROR_GUARD(NULL); |
| 865 | // create a local if it's not a volatile, and it's a pointer, and block is specified |
| 866 | if (CGOptions::addr_taken_of_locals() && use_local) { |
| 867 | var = GenerateNewParentLocal(*b, Effect::READ, cg_context, tt, &qfer_deref); |
| 868 | ERROR_GUARD(NULL); |
| 869 | Bookkeeper::record_volatile_access(var, var->type->get_indirect_level() - tt->get_indirect_level(), false); |
| 870 | } |
| 871 | else { |
| 872 | if (CGOptions::ccomp()) { |
| 873 | var = GenerateNewNonArrayGlobal(Effect::READ, cg_context, tt, &qfer_deref); |
| 874 | } |
nothing calls this directly
no test coverage detected