|
4285 | 4285 | It expresses a condition that a function should ensure
|
4286 | 4286 | for the return value and/or the state of objects
|
4287 | 4287 | using a predicate that is intended to hold upon exit from the function.
|
| 4288 | +A postcondition may introduce an identifier to represent |
| 4289 | +the glvalue result or the prvalue result object of the function. |
| 4290 | +\begin{example} |
| 4291 | +\begin{codeblock} |
| 4292 | +int f(char * c) |
| 4293 | + [[ensures res: res > 0 && c != nullptr]]; |
| 4294 | + |
| 4295 | +int g(double * p) |
| 4296 | + [[ensures audit res: res != 0 && p != nullptr && *p <= 0.0]]; |
| 4297 | +\end{codeblock} |
| 4298 | +\end{example} |
4288 | 4299 |
|
4289 | 4300 | \pnum
|
4290 | 4301 | A \grammarterm{contract-attribute-specifier} using \tcode{assert}
|
|
4333 | 4344 | and template parameters.
|
4334 | 4345 |
|
4335 | 4346 | \pnum
|
4336 |
| -An assertion is checked by evaluating its predicate. |
4337 |
| -The predicate of an assertion is potentially evaluated\iref{basic.def.odr}. |
4338 |
| -The predicate of an assertion is evaluated |
4339 |
| -as part of the evaluation of the null statement\iref{stmt.expr} it applies to. |
| 4347 | +\begin{note} |
| 4348 | +A function pointer cannot include contract conditions. |
| 4349 | +\begin{example} |
| 4350 | +\begin{codeblock} |
| 4351 | +typedef int (*fpt)() [[ensures r: r != 0]]; // error: contract condition not on a function declaration |
| 4352 | + |
| 4353 | +int g(int x) |
| 4354 | + [[expects: x >= 0]] |
| 4355 | + [[ensures r: r > x]] |
| 4356 | +{ |
| 4357 | + return x+1; |
| 4358 | +} |
| 4359 | + |
| 4360 | +int (*pf)(int) = g; // OK |
| 4361 | +int x = pf(5); // contract conditions of \tcode{g} are checked |
| 4362 | +\end{codeblock} |
| 4363 | +\end{example} |
| 4364 | +\end{note} |
4340 | 4365 |
|
4341 | 4366 | \pnum
|
4342 |
| -The predicate of a contract condition |
4343 |
| -is potentially evaluated\iref{basic.def.odr} |
4344 |
| -and has the same semantic restrictions |
| 4367 | +The predicate of a contract is potentially evaluated\iref{basic.def.odr}. |
| 4368 | + |
| 4369 | +\pnum |
| 4370 | +The predicate of a contract condition has the same semantic restrictions |
4345 | 4371 | as if it appeared as the first \grammarterm{expression-statement}
|
4346 | 4372 | in the body of the function it applies to.
|
4347 | 4373 | Additional access restrictions apply to names appearing in
|
|
4391 | 4417 | \end{codeblock}
|
4392 | 4418 | \end{example}
|
4393 | 4419 |
|
| 4420 | +\pnum |
| 4421 | +A precondition is checked by evaluating its predicate |
| 4422 | +immediately before starting evaluation of the function body. |
| 4423 | +\begin{note} |
| 4424 | +The function body includes |
| 4425 | +the \grammarterm{function-try-block}\iref{except} and |
| 4426 | +the \grammarterm{ctor-initializer}\iref{class.base.init}. |
| 4427 | +\end{note} |
| 4428 | +A postcondition is checked by evaluating its predicate |
| 4429 | +immediately before returning control to the caller of the function. |
| 4430 | +\begin{note} |
| 4431 | +The lifetime of local variables and temporaries has ended. |
| 4432 | +Exiting via an exception or via \tcode{longjmp}\iref{csetjmp.syn} |
| 4433 | +is not considered returning control to the caller of the function. |
| 4434 | +\end{note} |
| 4435 | + |
| 4436 | +\pnum |
| 4437 | +If a function has multiple preconditions, |
| 4438 | +their evaluation (if any) will be performed |
| 4439 | +in the order they appear lexically. |
| 4440 | +If a function has multiple postconditions, |
| 4441 | +their evaluation (if any) will be performed |
| 4442 | +in the order they appear lexically. |
| 4443 | +\begin{example} |
| 4444 | +\begin{codeblock} |
| 4445 | +void f(int * p) |
| 4446 | + [[expects: p != nullptr]] // \#1 |
| 4447 | + [[ensures: *p == 1]] // \#3 |
| 4448 | + [[expects: *p == 0]] // \#2 |
| 4449 | +{ |
| 4450 | + *p = 1; |
| 4451 | +} |
| 4452 | +\end{codeblock} |
| 4453 | +\end{example} |
| 4454 | + |
| 4455 | +\pnum |
| 4456 | +An assertion is checked by evaluating its predicate |
| 4457 | +as part of the evaluation of the null statement\iref{stmt.expr} |
| 4458 | +it applies to. |
| 4459 | + |
4394 | 4460 | \pnum
|
4395 | 4461 | The only side effects of a predicate
|
4396 | 4462 | that are allowed in a \grammarterm{contract-attribute-specifier}
|
4397 | 4463 | are modifications of non-volatile objects
|
4398 | 4464 | whose lifetime began and ended within the evaluation of the predicate
|
4399 | 4465 | in functions invoked from that predicate.
|
| 4466 | +An evaluation of a predicate that exits via an exception |
| 4467 | +invokes \tcode{std::terminate()}\iref{except.terminate}. |
4400 | 4468 | The behavior of any other side effect is undefined.
|
4401 | 4469 | \begin{example}
|
4402 | 4470 | \begin{codeblock}
|
|
4424 | 4492 | \end{codeblock}
|
4425 | 4493 | \end{example}
|
4426 | 4494 |
|
| 4495 | +\pnum |
| 4496 | +If a postcondition odr-uses\iref{basic.def.odr} |
| 4497 | +a parameter value in its predicate |
| 4498 | +and the function body makes direct or indirect modifications of that value, |
| 4499 | +the behavior is undefined. |
| 4500 | +\begin{example} |
| 4501 | +\begin{codeblock} |
| 4502 | +int f(int x) |
| 4503 | + [[ensures r: r == x]] |
| 4504 | +{ |
| 4505 | + return ++x; // undefined behavior |
| 4506 | +} |
| 4507 | + |
| 4508 | +int g(int * p) |
| 4509 | + [[ensures r: p != nullptr]] |
| 4510 | +{ |
| 4511 | + *p = 42; // OK, \tcode{p} is not modified |
| 4512 | +} |
| 4513 | + |
| 4514 | +int h(int x) |
| 4515 | + [[ensures r: r == x]] |
| 4516 | +{ |
| 4517 | + potentially_modify(x); // undefined behavior if \tcode{x} is modified |
| 4518 | + return x; |
| 4519 | +} |
| 4520 | +\end{codeblock} |
| 4521 | +\end{example} |
| 4522 | + |
4427 | 4523 | \pnum
|
4428 | 4524 | If the \grammarterm{contract-level}
|
4429 | 4525 | of a \grammarterm{contract-attribute-specifier} is absent,
|
|
4444 | 4540 | and are not evaluated at run-time.
|
4445 | 4541 | \end{note}
|
4446 | 4542 |
|
| 4543 | +\pnum |
| 4544 | +Multiple contract conditions may be applied to a function type |
| 4545 | +with the same or different \grammarterm{contract-level}{s}. |
| 4546 | +\begin{example} |
| 4547 | +\begin{codeblock} |
| 4548 | +int z; |
| 4549 | + |
| 4550 | +bool is_prime(int k); |
| 4551 | + |
| 4552 | +void f(int x) |
| 4553 | + [[expects: x > 0]] |
| 4554 | + [[expects audit: is_prime(x)]] |
| 4555 | + [[ensures: z > 10]] |
| 4556 | +{ |
| 4557 | + @\commentellip@ |
| 4558 | +} |
| 4559 | +\end{codeblock} |
| 4560 | +\end{example} |
| 4561 | + |
4447 | 4562 | \pnum
|
4448 | 4563 | A translation may be performed
|
4449 | 4564 | with one of the following \defnx{build levels}{build level}:
|
|
4461 | 4576 | There should be no programmatic way of setting, modifying, or querying
|
4462 | 4577 | the build level of a translation unit.
|
4463 | 4578 |
|
4464 |
| -\pnum |
4465 |
| -A precondition is checked by evaluating its predicate |
4466 |
| -immediately before starting evaluation of the function body. |
4467 |
| -\begin{note} |
4468 |
| -The function body includes |
4469 |
| -the \grammarterm{function-try-block}\iref{except} and |
4470 |
| -the \grammarterm{ctor-initializer}\iref{class.base.init}. |
4471 |
| -\end{note} |
4472 |
| -A postcondition is checked by evaluating its predicate |
4473 |
| -immediately before returning control to the caller of the function. |
4474 |
| -\begin{note} |
4475 |
| -The lifetime of local variables and temporaries has ended. |
4476 |
| -Exiting via an exception or via \tcode{longjmp}\iref{csetjmp.syn} |
4477 |
| -is not considered returning control to the caller of the function. |
4478 |
| -\end{note} |
4479 |
| -An evaluation of a predicate that exits via an exception |
4480 |
| -invokes \tcode{std::terminate()}\iref{except.terminate}. |
4481 |
| - |
4482 |
| -\pnum |
4483 |
| -If a function has multiple preconditions, |
4484 |
| -their evaluation (if any) will be performed |
4485 |
| -in the order they appear lexically. |
4486 |
| -If a function has multiple postconditions, |
4487 |
| -their evaluation (if any) will be performed |
4488 |
| -in the order they appear lexically. |
4489 |
| -\begin{example} |
4490 |
| -\begin{codeblock} |
4491 |
| -void f(int * p) |
4492 |
| - [[expects: p != nullptr]] // \#1 |
4493 |
| - [[ensures: *p == 1]] // \#3 |
4494 |
| - [[expects: *p == 0]] // \#2 |
4495 |
| -{ |
4496 |
| - *p = 1; |
4497 |
| -} |
4498 |
| -\end{codeblock} |
4499 |
| -\end{example} |
4500 |
| - |
4501 | 4579 | \pnum
|
4502 | 4580 | It is unspecified whether a contract
|
4503 | 4581 | that would not be checked under the current build level is evaluated.
|
|
4577 | 4655 | \end{codeblock}
|
4578 | 4656 | \end{example}
|
4579 | 4657 |
|
4580 |
| -\rSec3[dcl.attr.contract.iface]{Interface contracts}% |
4581 |
| - |
4582 |
| -\pnum |
4583 |
| -Multiple contract conditions may be applied to a function type |
4584 |
| -with the same or different \grammarterm{contract-level}{s}. |
4585 |
| -\begin{example} |
4586 |
| -\begin{codeblock} |
4587 |
| -int z; |
4588 |
| - |
4589 |
| -bool is_prime(int k); |
4590 |
| - |
4591 |
| -void f(int x) |
4592 |
| - [[expects: x > 0]] |
4593 |
| - [[expects audit: is_prime(x)]] |
4594 |
| - [[ensures: z > 10]] |
4595 |
| -{ |
4596 |
| - @\commentellip@ |
4597 |
| -} |
4598 |
| -\end{codeblock} |
4599 |
| -\end{example} |
4600 |
| - |
4601 |
| -\pnum |
4602 |
| -A postcondition may introduce an identifier to represent |
4603 |
| -the glvalue result or the prvalue result object of the function. |
4604 |
| -\begin{example} |
4605 |
| -\begin{codeblock} |
4606 |
| -int f(char * c) |
4607 |
| - [[ensures res: res > 0 && c != nullptr]]; |
4608 |
| - |
4609 |
| -int g(double * p) |
4610 |
| - [[ensures audit res: res != 0 && p != nullptr && *p <= 0.0]]; |
4611 |
| -\end{codeblock} |
4612 |
| -\end{example} |
4613 |
| - |
4614 |
| -\pnum |
4615 |
| -If a postcondition odr-uses\iref{basic.def.odr} |
4616 |
| -a parameter value in its predicate |
4617 |
| -and the function body makes direct or indirect modifications of that value, |
4618 |
| -the behavior is undefined. |
4619 |
| -\begin{example} |
4620 |
| -\begin{codeblock} |
4621 |
| -int f(int x) |
4622 |
| - [[ensures r: r == x]] |
4623 |
| -{ |
4624 |
| - return ++x; // undefined behavior |
4625 |
| -} |
4626 |
| - |
4627 |
| -int g(int * p) |
4628 |
| - [[ensures r: p != nullptr]] |
4629 |
| -{ |
4630 |
| - *p = 42; // OK, \tcode{p} is not modified |
4631 |
| -} |
4632 |
| - |
4633 |
| -int h(int x) |
4634 |
| - [[ensures r: r == x]] |
4635 |
| -{ |
4636 |
| - potentially_modify(x); // undefined behavior if \tcode{x} is modified |
4637 |
| - return x; |
4638 |
| -} |
4639 |
| -\end{codeblock} |
4640 |
| -\end{example} |
4641 |
| - |
4642 |
| -\pnum |
4643 |
| -\begin{note} |
4644 |
| -A function pointer cannot include contract conditions. |
4645 |
| -\begin{example} |
4646 |
| -\begin{codeblock} |
4647 |
| -typedef int (*fpt)() [[ensures r: r != 0]]; // error: contract condition not on a function declaration |
4648 |
| - |
4649 |
| -int g(int x) |
4650 |
| - [[expects: x >= 0]] |
4651 |
| - [[ensures r: r > x]] |
4652 |
| -{ |
4653 |
| - return x+1; |
4654 |
| -} |
4655 |
| - |
4656 |
| -int (*pf)(int) = g; // OK |
4657 |
| -int x = pf(5); // contract conditions of \tcode{g} are checked |
4658 |
| -\end{codeblock} |
4659 |
| -\end{example} |
4660 |
| -\end{note} |
4661 |
| - |
4662 |
| -\pnum |
4663 |
| -If an overriding function specifies contract conditions, |
4664 |
| -it shall specify the same list of contract conditions as |
4665 |
| -its overridden functions; |
4666 |
| -no diagnostic is required |
4667 |
| -if corresponding conditions will always evaluate to the same value. |
4668 |
| -Otherwise, it is considered to have |
4669 |
| -the list of contract conditions from one of its overridden functions; |
4670 |
| -the names in the contract conditions are bound, |
4671 |
| -and the semantic constraints are checked, |
4672 |
| -at the point where the contract conditions appear. |
4673 |
| -Given a virtual function \tcode{f} |
4674 |
| -with a contract condition that odr-uses \tcode{*this}\iref{basic.def.odr}, |
4675 |
| -the class of which \tcode{f} is a direct member |
4676 |
| -shall be be an unambiguous and accessible base class of any class |
4677 |
| -in which \tcode{f} is overridden. |
4678 |
| -If a function overrides more than one function, |
4679 |
| -all of the overridden functions shall have |
4680 |
| -the same list of contract conditions\iref{dcl.attr.contract}; |
4681 |
| -no diagnostic is required |
4682 |
| -if corresponding conditions will always evaluate to the same value. |
4683 |
| -\begin{example} |
4684 |
| -\begin{codeblock} |
4685 |
| -struct A { |
4686 |
| - virtual void g() [[expects: x == 0]]; |
4687 |
| - int x = 42; |
4688 |
| -}; |
4689 |
| - |
4690 |
| -int x = 42; |
4691 |
| -struct B { |
4692 |
| - virtual void g() [[expects: x == 0]]; |
4693 |
| -} |
4694 |
| - |
4695 |
| -struct C : A, B { |
4696 |
| - virtual void g(); // ill-formed, no diagnostic required |
4697 |
| -}; |
4698 |
| -\end{codeblock} |
4699 |
| -\end{example} |
4700 |
| - |
4701 | 4658 | \indextext{attribute!contracts|)}
|
0 commit comments