From 97d687c8cbca9f3f6aa4632a9a3ab4f3b54f0b53 Mon Sep 17 00:00:00 2001 From: Andre Maroneze <andre.maroneze@cea.fr> Date: Mon, 3 Jan 2022 18:45:08 +0100 Subject: [PATCH] [Libc] add stdnoreturn.h and add/improve some specs --- headers/header_spec.txt | 1 + share/compliance/glibc_functions.json | 1 + share/libc/__fc_libc.h | 1 + share/libc/stdlib.h | 14 ++ share/libc/stdnoreturn.h | 31 +++ share/libc/time.h | 11 + .../tests/sarif/oracle/std_string.sarif | 232 +++++++++++++++++- tests/libc/fc_libc.c | 1 + tests/libc/oracle/coverage.res.oracle | 2 +- tests/libc/oracle/fc_libc.0.res.oracle | 27 +- tests/libc/oracle/fc_libc.1.res.oracle | 30 +++ tests/libc/oracle/fc_libc.2.res.oracle | 1 + tests/libc/oracle/stdlib_h.res.oracle | 2 + tests/libc/oracle/stdnoreturn_h.res.oracle | 23 ++ tests/libc/oracle/time_h.res.oracle | 21 ++ tests/libc/stdnoreturn_h.c | 20 ++ tests/libc/time_h.c | 5 + 17 files changed, 399 insertions(+), 24 deletions(-) create mode 100644 share/libc/stdnoreturn.h create mode 100644 tests/libc/oracle/stdnoreturn_h.res.oracle create mode 100644 tests/libc/stdnoreturn_h.c diff --git a/headers/header_spec.txt b/headers/header_spec.txt index 4e8f0d8ddef..31a54d668dd 100644 --- a/headers/header_spec.txt +++ b/headers/header_spec.txt @@ -294,6 +294,7 @@ share/libc/stdio.c: CEA_LGPL share/libc/stdio.h: CEA_LGPL share/libc/stdlib.c: CEA_LGPL share/libc/stdlib.h: CEA_LGPL +share/libc/stdnoreturn.h: CEA_LGPL share/libc/string.c: CEA_LGPL share/libc/string.h: CEA_LGPL share/libc/strings.h: CEA_LGPL diff --git a/share/compliance/glibc_functions.json b/share/compliance/glibc_functions.json index 90906ec100e..78d75c93756 100644 --- a/share/compliance/glibc_functions.json +++ b/share/compliance/glibc_functions.json @@ -929,6 +929,7 @@ "mkfifo", "mknod", "mkstemp", + "mkstemps", "mktemp", "mktime", "mlock", diff --git a/share/libc/__fc_libc.h b/share/libc/__fc_libc.h index 3e710e9cec5..2f78bbc8bb1 100644 --- a/share/libc/__fc_libc.h +++ b/share/libc/__fc_libc.h @@ -80,6 +80,7 @@ #include "stdint.h" #include "stdio.h" #include "stdlib.h" +#include "stdnoreturn.h" #include "string.h" #include "strings.h" #include "stropts.h" diff --git a/share/libc/stdlib.h b/share/libc/stdlib.h index dcb1f408493..c40adfa3b82 100644 --- a/share/libc/stdlib.h +++ b/share/libc/stdlib.h @@ -692,6 +692,7 @@ extern int posix_memalign(void **memptr, size_t alignment, size_t size); // missing: requires 'last 6 characters of template must be XXXXXX' // missing: assigns \result, templat[0..] \from 'filesystem', 'RNG'; requires valid_template: valid_string(templat); + requires template_len: strlen(templat) >= 6; assigns templat[0..] \from \nothing; assigns \result \from \nothing; ensures result_error_or_valid_fd: \result == -1 || @@ -699,6 +700,19 @@ extern int posix_memalign(void **memptr, size_t alignment, size_t size); */ extern int mkstemp(char *templat); +/*@ + // missing: requires 'last (6+suffixlen) characters of template must be X's' + // missing: assigns \result, templat[0..] \from 'filesystem', 'RNG'; + requires valid_template: valid_string(templat); + requires template_len: strlen(templat) >= 6 + suffixlen; + requires non_negative_suffixlen: suffixlen >= 0; + assigns templat[0..] \from \nothing; + assigns \result \from \nothing; + ensures result_error_or_valid_fd: \result == -1 || + 0 <= \result < __FC_FOPEN_MAX; + */ +extern int mkstemps(char *templat, int suffixlen); + // This function may allocate memory for the result, which is not supported by // some plugins such as Eva. In such cases, it is preferable to use the stub // provided in stdlib.c. diff --git a/share/libc/stdnoreturn.h b/share/libc/stdnoreturn.h new file mode 100644 index 00000000000..866c6b74aea --- /dev/null +++ b/share/libc/stdnoreturn.h @@ -0,0 +1,31 @@ +/**************************************************************************/ +/* */ +/* This file is part of Frama-C. */ +/* */ +/* Copyright (C) 2007-2021 */ +/* CEA (Commissariat à l'énergie atomique et aux énergies */ +/* alternatives) */ +/* */ +/* you can redistribute it and/or modify it under the terms of the GNU */ +/* Lesser General Public License as published by the Free Software */ +/* Foundation, version 2.1. */ +/* */ +/* It is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* See the GNU Lesser General Public License version 2.1 */ +/* for more details (enclosed in the file licenses/LGPLv2.1). */ +/* */ +/**************************************************************************/ + +// This file is not in the C standard; it exists for compatibility purposes + +// 'noreturn' is an attribute in C++ +#ifndef __cpluscplus +// Note that Frama-C still requires the '-c11' command-line option to parse +// the _Noreturn keyword. Mere inclusion of this header without the option +// will not work. +#define noreturn _Noreturn +#endif diff --git a/share/libc/time.h b/share/libc/time.h index fe6304ce88d..1ac6af43c3f 100644 --- a/share/libc/time.h +++ b/share/libc/time.h @@ -148,6 +148,7 @@ extern struct tm *gmtime(const time_t *timer); assigns __fc_time_tm \from *timer; ensures result_null_or_internal_tm: \result == &__fc_time_tm || \result == \null; + ensures maybe_error: errno == \old(errno) || errno == EOVERFLOW; */ extern struct tm *localtime(const time_t *timer); @@ -277,6 +278,16 @@ extern struct tm *getdate(const char *string); extern struct tm *gmtime_r(const time_t *restrict timer, struct tm *restrict result); +/*@ + requires valid_timer: \valid_read(timep); + requires valid_result: \valid(result); + assigns \result \from indirect:*timep, result; + assigns *result \from indirect:*timep; + assigns errno \from indirect:*timep; + ensures result_null_or_initialized:initialization: + (\result == result && \initialized(result)) || \result == \null; + ensures maybe_error: errno == \old(errno) || errno == EOVERFLOW; +*/ extern struct tm *localtime_r(const time_t *restrict timep, struct tm *restrict result); diff --git a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif index 368f8a6a14c..082afbda187 100644 --- a/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif +++ b/src/plugins/markdown-report/tests/sarif/oracle/std_string.sarif @@ -11276,9 +11276,9 @@ "uriBaseId": "FRAMAC_SHARE" }, "region": { - "startLine": 700, + "startLine": 701, "startColumn": 11, - "endLine": 700, + "endLine": 701, "endColumn": 18, "byteLength": 7 } @@ -11309,6 +11309,29 @@ } ] }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "template_len." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 695, + "startColumn": 25, + "endLine": 695, + "endColumn": 45, + "byteLength": 20 + } + } + } + ] + }, { "ruleId": "user-spec", "kind": "pass", @@ -11322,9 +11345,9 @@ "uriBaseId": "FRAMAC_SHARE" }, "region": { - "startLine": 697, + "startLine": 698, "startColumn": 36, - "endLine": 698, + "endLine": 699, "endColumn": 53, "byteLength": 70 } @@ -11345,9 +11368,9 @@ "uriBaseId": "FRAMAC_SHARE" }, "region": { - "startLine": 695, + "startLine": 696, "startColumn": 10, - "endLine": 695, + "endLine": 696, "endColumn": 22, "byteLength": 12 } @@ -11371,9 +11394,9 @@ "uriBaseId": "FRAMAC_SHARE" }, "region": { - "startLine": 695, + "startLine": 696, "startColumn": 10, - "endLine": 695, + "endLine": 696, "endColumn": 22, "byteLength": 12 } @@ -11396,9 +11419,198 @@ "uriBaseId": "FRAMAC_SHARE" }, "region": { - "startLine": 696, + "startLine": 697, "startColumn": 10, - "endLine": 696, + "endLine": 697, + "endColumn": 17, + "byteLength": 7 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "behavior default! in function mkstemps." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 714, + "startColumn": 11, + "endLine": 714, + "endColumn": 19, + "byteLength": 8 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "valid_template." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 706, + "startColumn": 27, + "endLine": 706, + "endColumn": 48, + "byteLength": 21 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "template_len." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 707, + "startColumn": 25, + "endLine": 707, + "endColumn": 57, + "byteLength": 32 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "non_negative_suffixlen." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 708, + "startColumn": 35, + "endLine": 708, + "endColumn": 49, + "byteLength": 14 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "result_error_or_valid_fd." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 711, + "startColumn": 36, + "endLine": 712, + "endColumn": 53, + "byteLength": 70 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { "text": "assigns clause in function mkstemps." }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 709, + "startColumn": 10, + "endLine": 709, + "endColumn": 22, + "byteLength": 12 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": + "from clause of term *(templat + (0 ..)) in function mkstemps." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 709, + "startColumn": 10, + "endLine": 709, + "endColumn": 22, + "byteLength": 12 + } + } + } + ] + }, + { + "ruleId": "user-spec", + "kind": "pass", + "level": "none", + "message": { + "text": "from clause of term \\result in function mkstemps." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "libc/stdlib.h", + "uriBaseId": "FRAMAC_SHARE" + }, + "region": { + "startLine": 710, + "startColumn": 10, + "endLine": 710, "endColumn": 17, "byteLength": 7 } diff --git a/tests/libc/fc_libc.c b/tests/libc/fc_libc.c index 89e599df66e..7c5a799d86a 100644 --- a/tests/libc/fc_libc.c +++ b/tests/libc/fc_libc.c @@ -127,6 +127,7 @@ #include "stdint.h" #include "stdio.h" #include "stdlib.h" +#include "stdnoreturn.h" #include "string.h" #include "strings.h" #include "stropts.h" diff --git a/tests/libc/oracle/coverage.res.oracle b/tests/libc/oracle/coverage.res.oracle index 65435f28136..8f5441c585c 100644 --- a/tests/libc/oracle/coverage.res.oracle +++ b/tests/libc/oracle/coverage.res.oracle @@ -28,7 +28,7 @@ main: 4 stmts out of 4 (100.0%) [metrics] Eva coverage statistics ======================= - Syntactically reachable functions = 2 (out of 114) + Syntactically reachable functions = 2 (out of 115) Semantically reached functions = 2 Coverage estimation = 100.0% [metrics] Statements analyzed by Eva diff --git a/tests/libc/oracle/fc_libc.0.res.oracle b/tests/libc/oracle/fc_libc.0.res.oracle index 3e6a3b4a237..47563bc9e75 100644 --- a/tests/libc/oracle/fc_libc.0.res.oracle +++ b/tests/libc/oracle/fc_libc.0.res.oracle @@ -4,10 +4,10 @@ [eva] Initial state computed [eva:initial-state] Values of globals at initialization -[eva] fc_libc.c:169: assertion got status valid. [eva] fc_libc.c:170: assertion got status valid. [eva] fc_libc.c:171: assertion got status valid. [eva] fc_libc.c:172: assertion got status valid. +[eva] fc_libc.c:173: assertion got status valid. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== @@ -64,7 +64,7 @@ wcslen (3 calls); wcsncat (0 call); wcsncpy (0 call); wmemcpy (1 call); wmemset (0 call); - Specified-only functions (427) + Specified-only functions (429) ============================== FD_CLR (0 call); FD_ISSET (0 call); FD_SET (0 call); FD_ZERO (0 call); Frama_C_int_interval (0 call); Frama_C_long_interval (0 call); @@ -138,16 +138,17 @@ jrand48 (0 call); kill (0 call); killpg (0 call); labs (0 call); lcong48 (0 call); ldexp (0 call); ldexpf (0 call); ldiv (0 call); listen (0 call); llabs (0 call); lldiv (0 call); localtime (0 call); - log (0 call); log10 (0 call); log10f (0 call); log10l (0 call); - log2 (0 call); log2f (0 call); log2l (0 call); logf (0 call); logl (0 call); - longjmp (0 call); lrand48 (0 call); lseek (0 call); lstat (0 call); - malloc (13 calls); mblen (0 call); mbstowcs (0 call); mbtowc (0 call); - mkdir (0 call); mkfifo (0 call); mknod (0 call); mkstemp (0 call); - mktime (0 call); mrand48 (0 call); nan (0 call); nanf (0 call); - nanl (0 call); nanosleep (0 call); nrand48 (0 call); ntohl (0 call); - ntohs (0 call); open (0 call); openat (0 call); opendir (0 call); - openlog (0 call); pathconf (0 call); pclose (0 call); perror (0 call); - pipe (0 call); poll (0 call); popen (0 call); pow (0 call); powf (0 call); + localtime_r (0 call); log (0 call); log10 (0 call); log10f (0 call); + log10l (0 call); log2 (0 call); log2f (0 call); log2l (0 call); + logf (0 call); logl (0 call); longjmp (0 call); lrand48 (0 call); + lseek (0 call); lstat (0 call); malloc (13 calls); mblen (0 call); + mbstowcs (0 call); mbtowc (0 call); mkdir (0 call); mkfifo (0 call); + mknod (0 call); mkstemp (0 call); mkstemps (0 call); mktime (0 call); + mrand48 (0 call); nan (0 call); nanf (0 call); nanl (0 call); + nanosleep (0 call); nrand48 (0 call); ntohl (0 call); ntohs (0 call); + open (0 call); openat (0 call); opendir (0 call); openlog (0 call); + pathconf (0 call); pclose (0 call); perror (0 call); pipe (0 call); + poll (0 call); popen (0 call); pow (0 call); powf (0 call); pthread_cond_broadcast (0 call); pthread_cond_destroy (0 call); pthread_cond_init (0 call); pthread_cond_wait (0 call); pthread_create (0 call); pthread_getname_np (0 call); pthread_join (0 call); @@ -221,7 +222,7 @@ Goto = 118 Assignment = 718 Exit point = 129 - Function = 557 + Function = 559 Function call = 166 Pointer dereferencing = 350 Cyclomatic complexity = 436 diff --git a/tests/libc/oracle/fc_libc.1.res.oracle b/tests/libc/oracle/fc_libc.1.res.oracle index 880d36bf6a6..566c5af75a0 100644 --- a/tests/libc/oracle/fc_libc.1.res.oracle +++ b/tests/libc/oracle/fc_libc.1.res.oracle @@ -1620,6 +1620,7 @@ extern size_t wcstombs(char * restrict s, wchar_t const * restrict pwcs, int posix_memalign(void **memptr, size_t alignment, size_t size); /*@ requires valid_template: valid_string(templat); + requires template_len: strlen(templat) ≥ 6; ensures result_error_or_valid_fd: \result ≡ -1 ∨ (0 ≤ \result < 16); assigns *(templat + (0 ..)), \result; @@ -1628,6 +1629,17 @@ int posix_memalign(void **memptr, size_t alignment, size_t size); */ extern int mkstemp(char *templat); +/*@ requires valid_template: valid_string(templat); + requires template_len: strlen(templat) ≥ 6 + suffixlen; + requires non_negative_suffixlen: suffixlen ≥ 0; + ensures + result_error_or_valid_fd: \result ≡ -1 ∨ (0 ≤ \result < 16); + assigns *(templat + (0 ..)), \result; + assigns *(templat + (0 ..)) \from \nothing; + assigns \result \from \nothing; + */ +extern int mkstemps(char *templat, int suffixlen); + char *realpath(char const * restrict file_name, char * restrict resolved_name); char *canonicalize_file_name(char const *path); @@ -5286,6 +5298,8 @@ extern struct tm *gmtime(time_t const *timer); ensures result_null_or_internal_tm: \result ≡ &__fc_time_tm ∨ \result ≡ \null; + ensures + maybe_error: __fc_errno ≡ \old(__fc_errno) ∨ __fc_errno ≡ 75; assigns \result, __fc_time_tm; assigns \result \from __fc_p_time_tm; assigns __fc_time_tm \from *timer; @@ -5440,6 +5454,22 @@ extern int clock_nanosleep(clockid_t clock_id, int flags, extern struct tm *gmtime_r(time_t const * restrict timer, struct tm * restrict result); +/*@ requires valid_timer: \valid_read(timep); + requires valid_result: \valid(result); + ensures + result_null_or_initialized: initialization: + (\result ≡ \old(result) ∧ \initialized(\old(result))) ∨ + \result ≡ \null; + ensures + maybe_error: __fc_errno ≡ \old(__fc_errno) ∨ __fc_errno ≡ 75; + assigns \result, *result, __fc_errno; + assigns \result \from (indirect: *timep), result; + assigns *result \from (indirect: *timep); + assigns __fc_errno \from (indirect: *timep); + */ +extern struct tm *localtime_r(time_t const * restrict timep, + struct tm * restrict result); + /*@ requires valid_request: \valid_read(rqtp); requires initialization: initialized_request: diff --git a/tests/libc/oracle/fc_libc.2.res.oracle b/tests/libc/oracle/fc_libc.2.res.oracle index 19a092a2d83..9e97d67741a 100644 --- a/tests/libc/oracle/fc_libc.2.res.oracle +++ b/tests/libc/oracle/fc_libc.2.res.oracle @@ -100,6 +100,7 @@ skipping FRAMAC_SHARE/libc/complex.h [kernel] Parsing FRAMAC_SHARE/libc/stdint.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/stdio.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/stdlib.h (with preprocessing) +[kernel] Parsing FRAMAC_SHARE/libc/stdnoreturn.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/string.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/strings.h (with preprocessing) [kernel] Parsing FRAMAC_SHARE/libc/stropts.h (with preprocessing) diff --git a/tests/libc/oracle/stdlib_h.res.oracle b/tests/libc/oracle/stdlib_h.res.oracle index 76a413c1aad..158e8ba4bdc 100644 --- a/tests/libc/oracle/stdlib_h.res.oracle +++ b/tests/libc/oracle/stdlib_h.res.oracle @@ -237,6 +237,8 @@ [eva] using specification for function mkstemp [eva] stdlib_h.c:82: function mkstemp: precondition 'valid_template' got status valid. +[eva] stdlib_h.c:82: + function mkstemp: precondition 'template_len' got status valid. [eva] Done for function mkstemp [eva] computing for function drand48 <- main. Called from stdlib_h.c:86. diff --git a/tests/libc/oracle/stdnoreturn_h.res.oracle b/tests/libc/oracle/stdnoreturn_h.res.oracle new file mode 100644 index 00000000000..f5fbba713d5 --- /dev/null +++ b/tests/libc/oracle/stdnoreturn_h.res.oracle @@ -0,0 +1,23 @@ +[kernel] Parsing stdnoreturn_h.c (with preprocessing) +[eva] Analyzing a complete application starting at main +[eva] Computing initial state +[eva] Initial state computed +[eva:initial-state] Values of globals at initialization + v ∈ [--..--] +[eva] computing for function f <- main. + Called from stdnoreturn_h.c:18. +[eva] Recording results for f +[eva] Done for function f +[eva] computing for function g <- main. + Called from stdnoreturn_h.c:19. +[eva] Recording results for g +[eva] Done for function g +[eva] Recording results for main +[eva] done for function main +[eva] ====== VALUES COMPUTED ====== +[eva:final-states] Values at end of function f: + NON TERMINATING FUNCTION +[eva:final-states] Values at end of function g: + NON TERMINATING FUNCTION +[eva:final-states] Values at end of function main: + __retres ∈ {0} diff --git a/tests/libc/oracle/time_h.res.oracle b/tests/libc/oracle/time_h.res.oracle index 8ca10a9c75b..1700a2d16a4 100644 --- a/tests/libc/oracle/time_h.res.oracle +++ b/tests/libc/oracle/time_h.res.oracle @@ -233,10 +233,29 @@ function asctime: precondition 'initialization,init_timeptr' got status valid. [eva] Done for function asctime [eva:alarm] time_h.c:65: Warning: assertion got status unknown. +[eva] computing for function localtime <- main. + Called from time_h.c:67. +[eva] using specification for function localtime +[eva] time_h.c:67: + function localtime: precondition 'valid_timer' got status valid. +[eva] Done for function localtime +[eva] computing for function localtime_r <- main. + Called from time_h.c:69. +[eva] using specification for function localtime_r +[eva] time_h.c:69: + function localtime_r: precondition 'valid_timer' got status valid. +[eva] time_h.c:69: + function localtime_r: precondition 'valid_result' got status valid. +[eva] Done for function localtime_r +[eva] computing for function localtime_r <- main. + Called from time_h.c:69. +[eva] Done for function localtime_r +[eva] time_h.c:70: assertion got status valid. [eva] Recording results for main [eva] done for function main [eva] ====== VALUES COMPUTED ====== [eva:final-states] Values at end of function main: + __fc_errno ∈ [--..--] __fc_ctime[0..25] ∈ [--..--] __fc_time_tm ∈ [--..--] Frama_C_entropy_source ∈ [--..--] @@ -252,4 +271,6 @@ t ∈ [--..--] res_time ∈ {{ NULL ; &mytime2 }} or UNINITIALIZED mytime2 ∈ [--..--] or UNINITIALIZED + localp ∈ {{ NULL ; &localr }} + localr ∈ [--..--] or UNINITIALIZED __retres ∈ {0; 1; 2} diff --git a/tests/libc/stdnoreturn_h.c b/tests/libc/stdnoreturn_h.c new file mode 100644 index 00000000000..8b234faea6a --- /dev/null +++ b/tests/libc/stdnoreturn_h.c @@ -0,0 +1,20 @@ +/*run.config + STDOPT: #"-c11" +*/ + +#include <stdnoreturn.h> + +noreturn void f(void) { + while (1); +} + +_Noreturn void g(void) { + while (2); +} + +volatile int v; + +int main() { + if (v) f(); + if (v) g(); +} diff --git a/tests/libc/time_h.c b/tests/libc/time_h.c index 52a14290535..28d599ddb65 100644 --- a/tests/libc/time_h.c +++ b/tests/libc/time_h.c @@ -64,5 +64,10 @@ int main() { time_str = asctime(&mytime); //@ assert valid_string(time_str); + struct tm *localp = localtime(&t); + struct tm localr; + localp = localtime_r(&t, &localr); + //@ assert localp == \null || localp == &localr; + return 0; } -- GitLab