| Issue |
164921
|
| Summary |
C23 underspecified declarations are not checked enough with -pedantic
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
Halalaluyafail3
|
Here are some examples which demonstrate Clang accepts invalid underspecified declarations (constexpr and type inference):
```c
int main(){
// Example 1
constexpr int a=1,b=2;
auto c=1,d=2;
//Example 2
constexpr struct{int h;}e={};
auto f=(struct{int h;}){};
//Example 3
typedef int g;
{
auto g=0;
}
}
```
Examples 1 and 2 violate:
> A declaration such that the declaration specifiers contain no type specifier or that is declared with
constexpr is said to be underspecified. If such a declaration is not a definition, if it declares no or more
than one ordinary identifier, if the declared identifier already has a declaration in the same scope,
if the declared entity is not an object, or if anywhere within the sequence of tokens making up the
declaration identifiers that are not ordinary are declared, the behavior is implementation-defined.
Section 6.7.1 Paragraph 12 ISO/IEC 9899:2024
Example 3 violates:
> A typedef name shares the same name space
as other identifiers declared in ordinary declarators. If the identifier is redeclared in an enclosed
block, the type of the inner declaration shall not be inferred (6.7.10).
Section 6.7.9 "Type definitions" Paragraph 3 ISO/IEC 9899:2024
In the case of example 3, the behavior is undefined because it violates a 'shall' outside of a constraints clause. For the other examples, their behavior is described as implementation-defined, but without any other restrictions on the possible behaviors.
> implementation-defined behavior
>
> unspecified behavior where each implementation documents how the choice is made
Section 3.5.1 Paragraph 1 ISO/IEC 9899:2024
> undefined behavior
>
> behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which
this document imposes no requirements
Section 3.5.3 Paragraph 1 ISO/IEC 9899:2024
> unspecified behavior
>
> behavior, that results from the use of an unspecified value, or other behavior upon which this
document provides two or more possibilities and imposes no further requirements on which is
chosen in any instance
Section 3.5.4 Paragraph 1 ISO/IEC 9899:2024
Because there is no constraint on what the possible behaviors are, any possible behavior is valid and does not violate the standard. That is, the standard imposes no requirements on their behavior. Examples 1 and 2 are also obviously nonportable given that anything can happen. Given these facts, examples 1 and 2 can be classified as having undefined behavior because they meet the definition of undefined behavior. Effectively, by describing the behavior as implementation-defined and without any further constraints it is 'undefined behavior, but documented'.
Strictly, the behavior is undefined so these invalid declarations don't need to be diagnosed. However, I still think it would be useful to diagnose them with -pedantic. This would also be consistent with how Clang currently diagnoses declarator operators combined with type inference:
```c
int main(){
auto*p=(void*)0;//warning with -pedantic
}
```
It may be worth making example 3 invalid by default, given that it is quite weird. GCC also rejects all 3 examples, even without -pedantic.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs