Skip to content

Commit 5cd7ca3

Browse files
committed
Implementation base of N3006 Underspecified object declarations
1 parent 902fb1b commit 5cd7ca3

File tree

6 files changed

+73
-2
lines changed

6 files changed

+73
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ ABI Changes in This Version
9999
ifuncs. Its purpose was to preserve backwards compatibility when the ".ifunc"
100100
suffix got removed from the name mangling. The alias interacts badly with
101101
GlobalOpt (see the issue #96197).
102-
102+
103103
- Fixed Microsoft name mangling for auto non-type template arguments of pointer
104104
type for MSVC 1920+. This change resolves incompatibilities with code compiled
105105
by MSVC 1920+ but will introduce incompatibilities with code compiled by
@@ -348,6 +348,9 @@ C23 Feature Support
348348
but C23 added them to ``<float.h>`` in
349349
`WG14 N2848 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2848.pdf>`_.
350350

351+
- Clang now diagnoses `N3006 Underspecified object declarations
352+
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3006.htm>`_.
353+
351354
Non-comprehensive list of changes in this release
352355
-------------------------------------------------
353356

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7779,6 +7779,8 @@ def err_attribute_arm_mve_polymorphism : Error<
77797779
"'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an MVE/NEON vector type">;
77807780
def err_attribute_webassembly_funcref : Error<
77817781
"'__funcref' attribute can only be applied to a function pointer type">;
7782+
def err_c23_underspecified_object_declaration: Error<
7783+
"'%select{struct|<ERROR>|union|<ERROR>|enum}0 %1' is defined as an underspecified object initializer">;
77827784

77837785
def warn_setter_getter_impl_required : Warning<
77847786
"property %0 requires method %1 to be defined - "

clang/lib/Sema/SemaExpr.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6978,6 +6978,33 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
69786978
diagID))
69796979
return ExprError();
69806980
}
6981+
} else if (LangOpts.C23 &&
6982+
(literalType->isRecordType() || literalType->isEnumeralType())) {
6983+
// C23 6.2.1p7: Structure, union, and enumeration tags have scope that
6984+
// begins just after the appearance of the tag in a type specifier that
6985+
// declares the tag.
6986+
// [...]
6987+
// An ordinary identifier that has an underspecified definition has scope
6988+
// that starts when the definition is completed; if the same ordinary
6989+
// identifier declares another entity with a scope that encloses the current
6990+
// block, that declaration is hidden as soon as the inner declarator is
6991+
// completed*.)
6992+
// [...]
6993+
// *) That means, that the outer declaration is not visible for the
6994+
// initializer.
6995+
auto Range = SourceRange(LParenLoc, RParenLoc);
6996+
const auto *Tag = literalType->castAs<TagType>();
6997+
const auto &TagRange = Tag->getDecl()->getSourceRange();
6998+
6999+
// We should diagnose underspecified declaration, unless the identifier has
7000+
// been diagnosed as being a redefinition, since the tag is made anonymous.
7001+
if (Range.fullyContains(TagRange) && Tag->getDecl()->getIdentifier()) {
7002+
Diag(TagRange.getBegin(),
7003+
diag::err_c23_underspecified_object_declaration)
7004+
<< (unsigned)Tag->getDecl()->getTagKind()
7005+
<< Tag->getDecl()->getName() << TagRange;
7006+
return ExprError();
7007+
}
69817008
} else if (!literalType->isDependentType() &&
69827009
RequireCompleteType(LParenLoc, literalType,
69837010
diag::err_typecheck_decl_incomplete_type,

clang/test/C/C23/n3006.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %clang_cc1 -std=c2x -verify %s
2+
3+
/* WG14 N3006: Full
4+
* Underspecified object declarations
5+
*/
6+
7+
struct S1 { int x, y; }; // expected-note {{previous definition is here}}
8+
union U1 { int a; double b; }; // expected-note {{previous definition is here}}
9+
enum E1 { FOO, BAR }; // expected-note {{previous definition is here}}
10+
11+
auto normal_struct = (struct S1){ 1, 2 };
12+
auto underspecified_struct = (struct S2 { int x, y; }){ 1, 2 }; // expected-error {{'struct S2' is defined as an underspecified object initializer}}
13+
auto underspecified_struct_redef = (struct S1 { char x, y; }){ 'A', 'B'}; // expected-error {{redefinition of 'S1'}}
14+
auto underspecified_empty_struct = (struct S3 { }){ }; // expected-error {{'struct S3' is defined as an underspecified object initializer}}
15+
16+
auto normal_union_int = (union U1){ .a = 12 };
17+
auto normal_union_double = (union U1){ .b = 2.4 };
18+
auto underspecified_union = (union U2 { int a; double b; }){ .a = 34 }; // expected-error {{'union U2' is defined as an underspecified object initializer}}
19+
auto underspecified_union_redef = (union U1 { char a; double b; }){ .a = 'A' }; // expected-error {{redefinition of 'U1'}}
20+
auto underspecified_empty_union = (union U3 { }){ }; // expected-error {{'union U3' is defined as an underspecified object initializer}}
21+
22+
auto normal_enum_foo = (enum E1){ FOO };
23+
auto normal_enum_bar = (enum E1){ BAR };
24+
auto underspecified_enum = (enum E2 { BAZ, QUX }){ BAZ }; // expected-error {{'enum E2' is defined as an underspecified object initializer}}
25+
auto underspecified_enum_redef = (enum E1 { ONE, TWO }){ ONE }; // expected-error {{redefinition of 'E1'}}
26+
auto underspecified_empty_enum = (enum E3 { }){ }; // expected-error {{'enum E3' is defined as an underspecified object initializer}} \
27+
expected-error {{use of empty enum}}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,c23 -std=c23 %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,c17 -std=c17 %s
3+
4+
auto underspecified_struct = (struct S1 { int x, y; }){ 1, 2 }; // c23-error {{'struct S1' is defined as an underspecified object initializer}} \
5+
c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \
6+
c17-error {{illegal storage class on file-scoped variable}}
7+
auto underspecified_union = (union U1 { int a; double b; }){ .a = 34 }; // c23-error {{'union U1' is defined as an underspecified object initializer}} \
8+
c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \
9+
c17-error {{illegal storage class on file-scoped variable}}
10+
auto underspecified_enum = (enum E1 { FOO, BAR }){ BAR }; // c23-error {{'enum E1' is defined as an underspecified object initializer}} \
11+
c17-error {{type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int}} \
12+
c17-error {{illegal storage class on file-scoped variable}}

clang/www/c_status.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ <h2 id="c2x">C23 implementation status</h2>
11801180
<tr>
11811181
<td>Underspecified object definitions</td>
11821182
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3006.htm">N3006</a></td>
1183-
<td class="none" align="center">No</td>
1183+
<td class="unreleased" align="center">Clang 19</td>
11841184
</tr>
11851185
<tr>
11861186
<td>Type inference for object declarations</td>

0 commit comments

Comments
 (0)