Skip to content

Do you think it'd be possible to integrate the ASSERT() expressions with C++ contracts? #37

@GavinRay97

Description

@GavinRay97

A few weeks ago, C++ Contracts support was merged into GCC:

One thing I keep thinking is how great it would be to be able to use libassert for the contract violation messages.

You are allowed to write your own assertion handler for failure, see below for an example with GCC Trunk and libassert v1.1:

Program returned: 139
contract violation: /app/example.cpp:30: num > 0 is false [with contract level=default]
violation occurs here:
./output.s[0x40356d]
./output.s[0x403728]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x7f14fa9a4083]
./output.s[0x4032be]
[0x0]
end of violation
terminate called without an active exception

Could it be possible to somehow integrate libassert here, so that you get the much nicer debug message?
If you try to use DEBUG_ASSERT or ASSERT in the [[pre: ]] or post expression themselves, it fails:

<source>:30:12: error: statement-expressions are not allowed outside functions nor in template-argument lists
   30 |     [[pre: ASSERT(num > 0)]]

You have access to the original assertion expression text, ie num > 0, but I don't know that you have access to the value of IE num in the violation handler.

void handle_contract_violation(const std::experimental::contract_violation &violation) {
  size_t _backtraceSize{0};
  void *_backtrace[MAX_BACKTRACE_DEPTH]{};

  _backtraceSize = backtrace(_backtrace, MAX_BACKTRACE_DEPTH);
  if(_backtraceSize == MAX_BACKTRACE_DEPTH)
    std::cerr << "warning: backtrace may have been truncated" << std::endl;

  std::cerr << "contract violation: " << violation.file_name()
    << ":" << violation.line_number()
    << ": " << violation.comment() << " is false"
    << " [with contract level=" << violation.assertion_level() << "]" << std::endl
    << "violation occurs here:" << std::endl;
  // skip the stack frame of handle_contract_violation and
  // on_contract_violation to get to wherever the assert was
  backtrace_symbols_fd(_backtrace + 2, _backtraceSize - 1, STDERR_FILENO);
  std::cerr << "end of violation" << std::endl;
}

int square(int num)
    [[pre: num > 0]]
    [[post res: res < 100]]
{
    DEBUG_ASSERT(num * num < 50);
    return num * num;
}


int main()
{
    // Trigger PRE
    square(-1);
    // Trigger DEBUG_ASSERT
    // square(8);
    // Trigger POST
    // square(10);
    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions