Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: memcpy not memcpying? Date: Tue, 05 Nov 2019 10:04:53 -0800 Organization: None to speak of Lines: 78 Message-ID: References: <2LVuF.7$BF1.0@fx26.iad> <6KfvF.57888$rJ1.57717@fx01.am4> <0DivF.23103$Q26.16540@fx34.am4> <1BAvF.13970$mB7.12243@fx32.am4> <%%DvF.115593$Yl3.480@fx24.am4> <87eeynlwc7.fsf@bsb.me.uk> <87r22njuxc.fsf@bsb.me.uk> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="697166bd5d21c4208f0d1c605eecfc39"; logging-data="21653"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Rz9BBrZgMNGjeC/5j1LhD" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:F+K0s+tlhxAN0RDLgwyCQ7iqPKI= sha1:aPQ0xWOOkhPK6Q3jP/hsDY6k/4s= Xref: csiph.com comp.lang.c:147630 Ben Bacarisse writes: > Keith Thompson writes: >> Ben Bacarisse writes: >> [...] >>> I think I might use _Generic here because checking the size is not >>> always going to be enough: >>> >>> _Static_assert( >>> _Generic(i, int: 1, default: 0), >>> "Check this because symbolcount_t is not compatible with int." >>> ); >>> >>> This works (in both clang and gcc) with -std=c11 -pedantic, but I am not >>> sure that _Generic /must/ be allowed here. It would be a shame if >>> generic selections were not considered to be standard constant >>> expressions. Have I missed something in the standard? >> >> I think it's covered in 6.6, which has this contraint in p2: >> >> Constant expressions shall not contain assignment, increment, >> decrement, function-call, or comma operators, except when they >> are contained within a subexpression that is not evaluated. >> >> Which implies, I think, that a generic selection is a constant >> expression if the result expression is a constant expression, >> even if the other subexpressions are not. > > I'm sure that's right, but I skipped over that because it's saying what > must /not/ be in a constant expression. Presumably it's a case of > everything else is OK. I believe so, yes -- and admittedly what I wrote above was not as rigorous as it should have been. 6.6 defines a *constant-expression* syntactically: constant-expression: conditional-expression Some constructs require a constant expression, for example enumerator: enumeration-constant enumeration-constant = constant-expression Which means that the expression on the right of the = in an enumerator (a) has to be a conditional-expression and (b) has to satisify the constraints of a constant-expression. (And it also has to satisfy the constraint in 6.7.2.2, that it's an integer constant expression at has a value representable as an int.) A generic selection in a static assert doesn't violate any of the constraints of a constant-expression -- but it's required to be an integer constant expression, and it doesn't meet those requirements (6.6p6). (Constant expressions have a blacklist of things that aren't allowed. Integer constant expressions have a whitelist of things that are allowed. But the requirement for an integer constant expression in a _Static_assert is a "shall" outside a constraint, so violating it has undefined behavior. >> gcc and clang seem to agree. gcc and clang seem to be permitting _Generic in integer constant expressions (or at least not rejecting it). I believe they are not required to do so. I find it odd that having a _Static_assert with something that is a constant expression but is not an integer constant expression was left as undefined behavior. If compilers don't behave reasonably (doing more than what the standard requires), that could be a source of bugs that are difficult to detect. -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for Philips Healthcare void Void(void) { Void(); } /* The recursive call of the void */