@@ -1081,7 +1081,7 @@ expr State::FnCallOutput::refines(const FnCallOutput &rhs,
10811081 return ret;
10821082}
10831083
1084- StateValue
1084+ State::FnCallResult
10851085State::addFnCall (const string &name, vector<StateValue> &&inputs,
10861086 vector<PtrInput> &&ptr_inputs,
10871087 const Type &out_type, StateValue &&ret_arg,
@@ -1090,7 +1090,8 @@ State::addFnCall(const string &name, vector<StateValue> &&inputs,
10901090 bool noret = attrs.has (FnAttrs::NoReturn);
10911091 bool willret = attrs.has (FnAttrs::WillReturn);
10921092 bool noundef = attrs.has (FnAttrs::NoUndef);
1093- bool noalias = attrs.has (FnAttrs::NoAlias);
1093+ bool noalias = (attrs.has (FnAttrs::NoAlias)) ||
1094+ (attrs.has (AllocKind::Alloc) && !attrs.has (FnAttrs::AllocSize));
10941095 bool is_indirect = name.starts_with (" #indirect_call" );
10951096
10961097 expr fn_ptr_bid;
@@ -1278,8 +1279,17 @@ State::addFnCall(const string &name, vector<StateValue> &&inputs,
12781279 addUB (I->second .ub );
12791280 addNoReturn (I->second .noreturns );
12801281 retval = I->second .retval ;
1282+
1283+ optional<expr> alloc_size;
1284+ if (noalias && out_type.isPtrType () && !I->second .ret_data .empty ()) {
1285+ alloc_size = I->second .ret_data [0 ].size ;
1286+ }
1287+
12811288 memory.setState (I->second .callstate , memaccess, I->first .args_ptr ,
12821289 inaccessible_bid);
1290+
1291+
1292+ return { std::move (retval), std::move (alloc_size) };
12831293 }
12841294 else {
12851295 // target: this fn call must match one from the source, otherwise it's UB
@@ -1336,15 +1346,23 @@ State::addFnCall(const string &name, vector<StateValue> &&inputs,
13361346 fn_call_pre &= pre ;
13371347 if (qvar.isValid ())
13381348 fn_call_qvars.emplace (std::move (qvar));
1349+
1350+ // Extract allocation size for noalias functions returning pointers
1351+ optional<expr> alloc_size;
1352+ if (noalias && out_type.isPtrType () && !d.ret_data .empty ()) {
1353+ alloc_size = d.ret_data [0 ].size ;
1354+ }
1355+
1356+ analysis.ranges_fn_calls .inc (name, memaccess);
1357+ return { std::move (retval), std::move (alloc_size) };
13391358 } else {
13401359 addUB (expr (false ));
13411360 retval = out_type.getDummyValue (false );
1361+
1362+ analysis.ranges_fn_calls .inc (name, memaccess);
1363+ return { std::move (retval), std::nullopt };
13421364 }
13431365 }
1344-
1345- analysis.ranges_fn_calls .inc (name, memaccess);
1346-
1347- return retval;
13481366}
13491367
13501368void State::doesApproximation (string &&name, optional<expr> e,
0 commit comments