Skip to content

No assumptions for structs in return AND in parameters [BUG] #425

@belous-dp

Description

@belous-dp

Description
When struct is passed to a function by reference, and this function returns struct, assumptions are generated only for the parameter. No assumptions are generated for the result.

To Reproduce
Steps to reproduce the behavior:

  1. Generate tests for these CPP files (from belous-dp/bitfields integration-tests/cpp-example/cxx_lib/structs)
// bitfields.h

#ifndef CPP_EXAMPLE_BITFIELDS_H
#define CPP_EXAMPLE_BITFIELDS_H

struct CppSpecificStruct {
    // will **usually** occupy 40 bytes:
    // 7  bits: value of b1
    // 57 bits: unused
    // 64 bits: value of breaking
    // 17 bits: value of b2
    // 1  bit:  value of b3
    // 22 bits: value of b4
    // 24 bits: unused
    // 32 bits: value of b5
    // 34 bits: unused
    // 4  bits: value of b6
    // 58 bits: unused
    unsigned b1 : 7;    // from 0 to 127
    long long breaking; // from LLONG_MIN to LLONG_MAX
    signed b2 : 17;     // from -65536 to 65535
    bool b3 : 1;        // from 0 to 1
    int b4 : 22;        // from -2097152 to 2097151
    unsigned : 0;       // starts a new allocation unit
    signed b5 : 66;     // from INT_MIN to INT_MAX
    signed b6 : 4;      // from -8 to 7
};

CppSpecificStruct modify_and_return_copy(CppSpecificStruct& s);

#endif //CPP_EXAMPLE_BITFIELDS_H
// bitfields.cpp

#include "bitfields.h"
#include <cassert>
#include <limits>

CppSpecificStruct modify_and_return_copy(CppSpecificStruct& s) {
    assert(s.b1 >= 0 && s.b1 <= 127);
    assert(s.breaking >= std::numeric_limits<long long>::min());
    assert(s.breaking <= std::numeric_limits<long long>::max());
    assert(s.b2 >= -65536 && s.b2 <= 65535);
    assert(s.b4 >= -2097152 && s.b4 <= 2097151);
    assert(s.b5 >= std::numeric_limits<int>::min());
    assert(s.b5 <= std::numeric_limits<int>::max());
    assert(s.b6 >= -8 && s.b6 <= 7);
    s.b1 = s.b1 * 2 + 1;
    s.breaking = std::numeric_limits<long long>::max();
    if (s.b2 != -65536) {
        s.b2 = -s.b2;
    }
    s.b3 ^= 1;
    if (s.b5 > 0) {
        s.b5 = 10;
    } else {
        s.b5 = -10;
    }
    s.b6 = (s.b1 > 0) + (s.b2 > 0) + (s.b3 > 0) + (s.b4 > 0) + (s.b5 > 0) + (s.b6 > 0);
    return CppSpecificStruct(s);
}

Expected behavior
Assumptions for result checking AND for parameter checking are supposed to be generated.

Actual behavior
Assumptions only for parameter checking are generated:

TEST(regression, modify_and_return_copy_test_1)
{
    struct CppSpecificStruct s = {
        .b1 = 0U,
        .breaking = 0LL,
        .b2 = 0,
        .b3 = true,
        .b4 = 0,
        .b5 = 1,
        .b6 = 2};
    struct CppSpecificStruct actual = modify_and_return_copy(s);
    CppSpecificStruct expected = {
        .b1 = 1U,
        .breaking = 9223372036854775807LL,
        .b2 = 0,
        .b3 = false,
        .b4 = 0,
        .b5 = 10,
        .b6 = 3};
    struct CppSpecificStruct expected_s = {
        .b1 = 1U,
        .breaking = 9223372036854775807LL,
        .b2 = 0,
        .b3 = false,
        .b4 = 0,
        .b5 = 10,
        .b6 = 3};
    EXPECT_EQ(expected_s.b1, s.b1);
    EXPECT_EQ(expected_s.breaking, s.breaking);
    EXPECT_EQ(expected_s.b2, s.b2);
    EXPECT_EQ(expected_s.b3, s.b3);
    EXPECT_EQ(expected_s.b4, s.b4);
    EXPECT_EQ(expected_s.b5, s.b5);
    EXPECT_EQ(expected_s.b6, s.b6);
}

Environment
UTBotCpp 57f94d5 (belous-dp/bitfields "tests added"), based on 6d24365 (main "#216 UTBotCpp does not support test generation for 32bit projects (#373)")

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions