Skip to content

Commit 9c4aeac

Browse files
diagnose auto deduction from void more specifically. [GH #27]
1 parent d6518a9 commit 9c4aeac

5 files changed

Lines changed: 132 additions & 12 deletions

File tree

‎src/Changes‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ example, with --clang_version 230100:
1111
#pragma clang diagnostic push
1212

1313
was previously recorded as "clangdiagnostic push". That is now fixed.
14+
10/4/26 [GH #27]
15+
Clearer diagnostic when auto is deduced from void
16+
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:
20+
21+
void g();
22+
auto x = g();
23+
24+
decltype(auto) is unchanged: deduction succeeds and the incomplete-type
25+
diagnostic is issued.
1426

1527

1628
10/1/26 [GH #197]

‎src/error_msg.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3679,5 +3679,6 @@ 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\""
36823683
###############################################################################
36833684

‎src/expr.c‎

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,31 @@ 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+
940965
void prescan_initializer_for_auto_type_deduction(
941966
a_decl_parse_state *dps,
942967
a_boolean parenthesized_init)
@@ -1178,12 +1203,20 @@ swallowed); otherwise, it's "="-form or "{...}" form.
11781203
dps->deduced_auto_type = unknown_type();
11791204
} else {
11801205
/* Deduction failed. */
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);
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+
}
11871220
dps->specifiers_type = dps->deduced_auto_type = dps->type =
11881221
error_type();
11891222
dps->has_deduced_type = FALSE;
@@ -48752,9 +48785,9 @@ the type of element_operand and sets the variable type to the deduced type.
4875248785
type as it is. */
4875348786
} else {
4875448787
/* Deduction failed. */
48755-
pos_error(iterator->declared_with_decltype_auto ?
48756-
ec_cannot_deduce_decltype_auto_type :
48757-
ec_cannot_deduce_auto_type,
48788+
pos_error(error_for_failed_auto_deduction(
48789+
iterator->declared_with_decltype_auto,
48790+
element_operand->type),
4875848791
&iterator->source_corresp.decl_position);
4875948792
iterator->type = error_type();
4876048793
} /* if */
@@ -52389,7 +52422,9 @@ are left unaffected).
5238952422
is_decltype_auto_case = TRUE;
5239052423
} /* if */
5239152424
} else {
52392-
pos_error(ec_cannot_deduce_auto_type, diag_pos);
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);
5239352428
deduced_return_type = error_type();
5239452429
} /* if */
5239552430
if (keep_placeholder) {
@@ -52489,8 +52524,8 @@ type with the type of return_op.
5248952524
/* The type is still dependent, so leave the return type as it is. */
5249052525
} else {
5249152526
/* Deduction failed. */
52492-
pos_error(is_decltype_auto ? ec_cannot_deduce_decltype_auto_type
52493-
: ec_cannot_deduce_auto_type,
52527+
pos_error(error_for_failed_auto_deduction(is_decltype_auto,
52528+
return_op->type),
5249452529
&return_op->position);
5249552530
*return_type = error_type();
5249652531
rout_type->variant.routine.return_type = *return_type;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
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+
^
5+
6+
"Test_name.c", line 23: error: cannot deduce "auto" type from type "void"
7+
auto x = g();
8+
^
9+
10+
"Test_name.c", line 24: error: cannot deduce "auto" type from type "void"
11+
auto &&r = g();
12+
^
13+
14+
"Test_name.c", line 25: error: cannot deduce "auto" type from type "void"
15+
const auto c = g();
16+
^
17+
18+
"Test_name.c", line 26: error: cannot deduce "auto" type from type "void"
19+
auto *p = g();
20+
^
21+
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());
28+
^
29+
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+
^
37+
38+
9 errors detected in the compilation of "Test_name.c".

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//type:fn
2+
//options_all:--c++23
3+
//remark:[GH #27] Clearer diagnostic when auto deduces to void
4+
// 10/4/26 [GH #27]
5+
//
6+
// Deducing auto from a void initializer used to say only
7+
// "cannot deduce \"auto\" type".
8+
9+
struct Clap {
10+
template <typename Spec>
11+
auto parse(this Spec const& spec) {
12+
}
13+
};
14+
15+
struct Args : Clap {
16+
};
17+
18+
void g();
19+
20+
void f()
21+
{
22+
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+
}
30+
31+
auto *h()
32+
{
33+
return g();
34+
}

0 commit comments

Comments
 (0)