Skip to content

Commit d99267d

Browse files
report an incomplete type when plain auto is deduced from void. [GH #27]
1 parent 9c4aeac commit d99267d

17 files changed

Lines changed: 99 additions & 145 deletions

File tree

‎src/Changes‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@ example, with --clang_version 230100:
1313
was previously recorded as "clangdiagnostic push". That is now fixed.
1414
10/4/26 [GH #27]
1515
Clearer diagnostic when auto is deduced from void
16+
10/6/26 [GH #27]
17+
Clearer diagnostic when auto is deduced from an incomplete type
1618

17-
Deducing "auto" from a void expression failed with the generic message
18-
"cannot deduce \"auto\" type". The diagnostic now says that the type is
19-
void. For example:
19+
Deducing a plain "auto" (including cv-qualified "auto") from void or another
20+
incomplete type used to fail with "cannot deduce \"auto\" type". The type
21+
is now deduced, and the usual incomplete-type diagnostic is issued, as it
22+
already is for decltype(auto). For example:
2023

2124
void g();
22-
auto x = g();
25+
auto x = g(); // incomplete type "void" is not allowed
26+
auto *p = g(); // cannot deduce "auto" type
2327

24-
decltype(auto) is unchanged: deduction succeeds and the incomplete-type
25-
diagnostic is issued.
28+
Forms that are not a plain "auto", such as "auto *", still fail deduction.
2629

2730

2831
10/1/26 [GH #197]

‎src/error_msg.txt‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3679,6 +3679,5 @@ ec_exp_interpolator;;"expected an interpolator (\"\\[\", \"\\[:\", \"\\{\", \"\\
36793679
ec_interpolated_id_is_not_identifier;;"%sq does not spell an identifier"
36803680
ec_interpolated_operand_is_not_token_sequence;;"the operand of a \"\\{...}\" interpolator is not a token sequence"
36813681
ec_tag_redefined_differently;;"this declaration of %n does not declare the same type as the declaration %p"
3682-
ec_cannot_deduce_auto_from_void;;"cannot deduce \"auto\" type from type \"void\""
36833682
###############################################################################
36843683

‎src/expr.c‎

Lines changed: 12 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -937,31 +937,6 @@ initializer lists can have their braces ignored.
937937
} /* ignore_braces_for_placeholder_deduction */
938938

939939

940-
static an_error_code error_for_failed_auto_deduction(
941-
a_boolean is_decltype_auto,
942-
a_type_ptr initializer_type)
943-
/*
944-
Return the diagnostic for a failed placeholder-type deduction.
945-
is_decltype_auto is TRUE when the placeholder is decltype(auto).
946-
initializer_type is the type of the initializer, or NULL when that type is
947-
not available (for example, a braced-init-list).
948-
*/
949-
{
950-
an_error_code result;
951-
952-
if (is_decltype_auto) {
953-
result = ec_cannot_deduce_decltype_auto_type;
954-
} else if (initializer_type != NULL && is_void_type(initializer_type)) {
955-
/* void is not an object type, so deduction cannot succeed. Name that
956-
type instead of using the generic message. */
957-
result = ec_cannot_deduce_auto_from_void;
958-
} else {
959-
result = ec_cannot_deduce_auto_type;
960-
} /* if */
961-
return result;
962-
} /* error_for_failed_auto_deduction */
963-
964-
965940
void prescan_initializer_for_auto_type_deduction(
966941
a_decl_parse_state *dps,
967942
a_boolean parenthesized_init)
@@ -1203,20 +1178,12 @@ swallowed); otherwise, it's "="-form or "{...}" form.
12031178
dps->deduced_auto_type = unknown_type();
12041179
} else {
12051180
/* Deduction failed. */
1206-
{ an_error_code err_code;
1207-
a_type_ptr init_type = NULL;
1208-
1209-
if (dps->has_deducible_class_templ_args) {
1210-
err_code = ec_cannot_deduce_class_template_arguments;
1211-
} else {
1212-
if (icp != NULL && is_expression_component(icp)) {
1213-
init_type = operand_of_arg_list_elem(icp)->type;
1214-
} /* if */
1215-
err_code = error_for_failed_auto_deduction(
1216-
dps->decltype_auto_specifier_seen, init_type);
1217-
} /* if */
1218-
expr_pos_error(err_code, &dps->auto_pos);
1219-
}
1181+
expr_pos_error(dps->has_deducible_class_templ_args ?
1182+
ec_cannot_deduce_class_template_arguments :
1183+
(an_error_code)(dps->decltype_auto_specifier_seen ?
1184+
ec_cannot_deduce_decltype_auto_type :
1185+
ec_cannot_deduce_auto_type),
1186+
&dps->auto_pos);
12201187
dps->specifiers_type = dps->deduced_auto_type = dps->type =
12211188
error_type();
12221189
dps->has_deduced_type = FALSE;
@@ -48785,9 +48752,9 @@ the type of element_operand and sets the variable type to the deduced type.
4878548752
type as it is. */
4878648753
} else {
4878748754
/* Deduction failed. */
48788-
pos_error(error_for_failed_auto_deduction(
48789-
iterator->declared_with_decltype_auto,
48790-
element_operand->type),
48755+
pos_error(iterator->declared_with_decltype_auto ?
48756+
ec_cannot_deduce_decltype_auto_type :
48757+
ec_cannot_deduce_auto_type,
4879148758
&iterator->source_corresp.decl_position);
4879248759
iterator->type = error_type();
4879348760
} /* if */
@@ -52422,9 +52389,7 @@ are left unaffected).
5242252389
is_decltype_auto_case = TRUE;
5242352390
} /* if */
5242452391
} else {
52425-
/* The declared type is not a plain "auto" (for example, "auto *").
52426-
void still cannot be used to deduce it. */
52427-
pos_error(ec_cannot_deduce_auto_from_void, diag_pos);
52392+
pos_error(ec_cannot_deduce_auto_type, diag_pos);
5242852393
deduced_return_type = error_type();
5242952394
} /* if */
5243052395
if (keep_placeholder) {
@@ -52524,8 +52489,8 @@ type with the type of return_op.
5252452489
/* The type is still dependent, so leave the return type as it is. */
5252552490
} else {
5252652491
/* Deduction failed. */
52527-
pos_error(error_for_failed_auto_deduction(is_decltype_auto,
52528-
return_op->type),
52492+
pos_error(is_decltype_auto ? ec_cannot_deduce_decltype_auto_type
52493+
: ec_cannot_deduce_auto_type,
5252952494
&return_op->position);
5253052495
*return_type = error_type();
5253152496
rout_type->variant.routine.return_type = *return_type;

‎src/overload.c‎

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ static a_boolean adjust_deduction_pair(
6565
a_template_arg_ptr template_arg_list,
6666
a_type_ptr *qc_param_type,
6767
a_type_ptr *qc_arg_type,
68-
a_boolean *consider_nondeduced);
68+
a_boolean *consider_nondeduced,
69+
a_boolean allow_incomplete_arg);
6970
static a_boolean check_narrowing_conversion(an_operand *source_operand,
7071
a_type_ptr dest_type,
7172
a_boolean check_enum_target,
@@ -1485,7 +1486,8 @@ from previous arguments; in the standard case, it is always NULL.
14851486
(an_operand *)NULL, templ_params,
14861487
(a_template_arg *)NULL,
14871488
(a_type_ptr*)NULL, (a_type_ptr*)NULL,
1488-
(a_boolean *)NULL) &&
1489+
(a_boolean *)NULL,
1490+
/*allow_incomplete_arg=*/FALSE) &&
14891491
tentatively_matches_template_type(local_arg_type,
14901492
local_param_type,
14911493
templ_params,
@@ -4272,7 +4274,8 @@ static a_boolean adjust_deduction_pair(
42724274
a_template_arg_ptr template_arg_list,
42734275
a_type_ptr *qc_param_type,
42744276
a_type_ptr *qc_arg_type,
4275-
a_boolean *consider_nondeduced)
4277+
a_boolean *consider_nondeduced,
4278+
a_boolean allow_incomplete_arg)
42764279
/*
42774280
Adjust the types *p_param_type (a parameter type of a function template or a
42784281
type involving the "auto" type specifier) and *p_arg_type (the type of the
@@ -4295,7 +4298,10 @@ are not removed. If consider_nondeduced is non-NULL and the reason for
42954298
failure is that an indefinite function matches several ways, return
42964299
*consider_nondeduced TRUE. template_arg_list is used in some nonstandard
42974300
modes to introduce knowledge from previous arguments; in the standard case,
4298-
it is always NULL.
4301+
it is always NULL. allow_incomplete_arg is TRUE when deducing a plain
4302+
"auto" (not, for example, "auto *"). In that case an incomplete argument
4303+
type, including void, is left for deduction so the caller can diagnose the
4304+
incomplete type instead of reporting a deduction failure.
42994305
*/
43004306
{
43014307
a_boolean adjustment_okay = FALSE, indefinite_function_designator = FALSE;
@@ -4402,8 +4408,13 @@ it is always NULL.
44024408
if (is_incomplete_type(arg_type) && !is_managed_nullptr_type(arg_type)) {
44034409
/* Although the managed (C++/CLI) nullptr type is incomplete and
44044410
cannot be used as the type of an object, for example, the Microsoft
4405-
compiler allows it as a template argument. */
4406-
goto done;
4411+
compiler allows it as a template argument. A plain "auto" variable
4412+
is also allowed through: the type is deduced, and the incomplete-type
4413+
diagnostic is issued for the variable (the same diagnostic as for
4414+
decltype(auto)). "auto *" and similar forms still fail deduction. */
4415+
if (!(allow_incomplete_arg && is_template_param_type(param_type))) {
4416+
goto done;
4417+
} /* if */
44074418
} /* if */
44084419
} /* if */
44094420
/* Return the adjusted types at this point as the types that can be used to
@@ -4621,7 +4632,8 @@ deduction was successful: some cases are treated as "nondeduced contexts").
46214632
elem_operand,
46224633
templ_params, *template_arg_list,
46234634
&qc_param_type, &qc_arg_type,
4624-
&consider_nondeduced)) {
4635+
&consider_nondeduced,
4636+
/*allow_incomplete_arg=*/FALSE)) {
46254637
if (consider_nondeduced) continue;
46264638
deduction_okay = FALSE;
46274639
break;
@@ -4775,7 +4787,8 @@ deduction succeeds, FALSE if it fails.
47754787
if (!adjust_deduction_pair(&param_type, &arg_type, operand,
47764788
templ_params, *template_arg_list,
47774789
&qc_param_type, &qc_arg_type,
4778-
&consider_nondeduced)) {
4790+
&consider_nondeduced,
4791+
/*allow_incomplete_arg=*/FALSE)) {
47794792
if (consider_nondeduced) {
47804793
/* The argument is an indefinite function that can match in more than
47814794
one way. Keep going without adding anything to the template
@@ -31238,7 +31251,8 @@ TRUE and FALSE is returned.
3123831251
if (!adjust_deduction_pair(&type, &arg_type, initializer_operand,
3123931252
templ_param, (a_template_arg *)NULL,
3124031253
&qc_param_type, &qc_arg_type,
31241-
(a_boolean *)NULL)) {
31254+
(a_boolean *)NULL,
31255+
/*allow_incomplete_arg=*/TRUE)) {
3124231256
okay = FALSE;
3124331257
} else if (!deduce_from_one_pair(type, arg_type,
3124431258
qc_param_type, qc_arg_type,
Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,30 @@
11
fe_only -DTEST_NUMBER=1 --c++23 Test_name.c
2-
"Test_name.c", line 22: error: cannot deduce "auto" type from type "void"
3-
auto opts = Args{}.parse();
4-
^
2+
"Test_name.c", line 27: error: incomplete type "void" is not allowed
3+
auto v1 = void();
4+
^
55

6-
"Test_name.c", line 23: error: cannot deduce "auto" type from type "void"
7-
auto x = g();
8-
^
6+
"Test_name.c", line 28: error: incomplete type "void" is not allowed
7+
decltype(auto) v2 = void();
8+
^
99

10-
"Test_name.c", line 24: error: cannot deduce "auto" type from type "void"
11-
auto &&r = g();
12-
^
10+
"Test_name.c", line 29: error: incomplete type "Incomplete" is not allowed
11+
auto v3 = getIncomplete();
12+
^
1313

14-
"Test_name.c", line 25: error: cannot deduce "auto" type from type "void"
15-
const auto c = g();
16-
^
14+
"Test_name.c", line 30: error: incomplete type "void" is not allowed
15+
auto opts = Args{}.parse();
16+
^
1717

18-
"Test_name.c", line 26: error: cannot deduce "auto" type from type "void"
19-
auto *p = g();
18+
"Test_name.c", line 32: error: cannot deduce "auto" type
19+
auto *v4 = void();
2020
^
2121

22-
"Test_name.c", line 27: error: cannot deduce "auto" type from type "void"
23-
auto *q = new auto(g());
24-
^
25-
26-
"Test_name.c", line 27: error: cannot deduce "auto" type
27-
auto *q = new auto(g());
22+
"Test_name.c", line 33: error: cannot deduce "auto" type
23+
auto *v5 = 1;
2824
^
2925

30-
"Test_name.c", line 28: error: incomplete type "void" is not allowed
31-
decltype(auto) d = g();
32-
^
33-
34-
"Test_name.c", line 33: error: cannot deduce "auto" type from type "void"
35-
return g();
36-
^
26+
"Test_name.c", line 34: error: cannot deduce "auto" type
27+
auto *p = g();
28+
^
3729

38-
9 errors detected in the compilation of "Test_name.c".
30+
7 errors detected in the compilation of "Test_name.c".

‎tests/tests/changes/GH27.sft.cpp‎

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
//type:fn
22
//options_all:--c++23
33
//remark:[GH #27] Clearer diagnostic when auto deduces to void
4-
// 10/4/26 [GH #27]
4+
// 10/6/26 [GH #27]
55
//
6-
// Deducing auto from a void initializer used to say only
7-
// "cannot deduce \"auto\" type".
6+
// A plain auto deduced from void or another incomplete type gets the
7+
// incomplete-type diagnostic, matching decltype(auto). auto * still
8+
// fails deduction.
9+
10+
struct Incomplete;
11+
12+
struct Incomplete &getIncomplete();
813

914
struct Clap {
1015
template <typename Spec>
@@ -19,16 +24,12 @@ void g();
1924

2025
void f()
2126
{
27+
auto v1 = void();
28+
decltype(auto) v2 = void();
29+
auto v3 = getIncomplete();
2230
auto opts = Args{}.parse();
23-
auto x = g();
24-
auto &&r = g();
25-
const auto c = g();
26-
auto *p = g();
27-
auto *q = new auto(g());
28-
decltype(auto) d = g();
29-
}
3031

31-
auto *h()
32-
{
33-
return g();
32+
auto *v4 = void();
33+
auto *v5 = 1;
34+
auto *p = g();
3435
}

‎tests/tests/imported/clang/cpp/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/.p2-1z.rto/default.1.1.txt‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
1212
^
1313
detected during instantiation of "auto d<k>() [with k=0]" at line 41
1414

15-
"Test_name.c", line 46: error: cannot deduce "auto" type
15+
"Test_name.c", line 46: error: incomplete type "void" is not allowed
1616
auto e = []{ if constexpr (false) return 0; }(); // expected-error {{variable has incomplete type 'void'}}
17-
^
17+
^
1818

1919
2 errors detected in the compilation of "Test_name.c".

‎tests/tests/imported/clang/cpp/CXX/expr/expr.prim/expr.prim.lambda/.p11-1y.rto/default.1.1.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
3131
auto bad_init_3 = [&a(void_fn())] {}; // expected-error {{cannot form a reference to 'void'}}
3232
^
3333

34-
"Test_name.c", line 51: error: cannot deduce "auto" type
34+
"Test_name.c", line 51: error: incomplete type "void" is not allowed
3535
auto bad_init_4 = [a(void_fn())] {}; // expected-error {{has incomplete type 'void'}}
3636
^
3737

‎tests/tests/imported/clang/cpp/CXX/stmt.stmt/stmt.iter/stmt.ranged/.p1.rto/default.1.1.txt‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,6 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
127127
for (auto u : NoEnd()) { // expected-error {{no viable 'end' function available}}
128128
^
129129

130-
"Test_name.c", line 180: error: cannot deduce "auto" type
131-
for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void}}\
132-
^
133-
134130
"Test_name.c", line 180: error: incomplete type "void" is not allowed
135131
for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void}}\
136132
^
@@ -305,4 +301,4 @@ fe_only -DTEST_NUMBER=1 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
305301
^
306302
detected during instantiation of "void rdar13712739::foo(const T &) [with T=int]" at line 290
307303

308-
55 errors detected in the compilation of "Test_name.c".
304+
54 errors detected in the compilation of "Test_name.c".

‎tests/tests/imported/clang/cpp/CXX/stmt.stmt/stmt.iter/stmt.ranged/.p1.rto/default.2.1.txt‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
127127
for (auto u : NoEnd()) { // expected-error {{no viable 'end' function available}}
128128
^
129129

130-
"Test_name.c", line 180: error: cannot deduce "auto" type
131-
for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void}}\
132-
^
133-
134130
"Test_name.c", line 180: error: incomplete type "void" is not allowed
135131
for (auto u : NoIncr()) { // expected-error {{arithmetic on a pointer to void}}\
136132
^
@@ -305,4 +301,4 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers
305301
^
306302
detected during instantiation of "void rdar13712739::foo(const T &) [with T=int]" at line 290
307303

308-
55 errors detected in the compilation of "Test_name.c".
304+
54 errors detected in the compilation of "Test_name.c".

0 commit comments

Comments
 (0)