Skip to content

diagnose auto deduction from void more specifically, fix for [GH #27] - #206

Merged
nv-cmeerw merged 10 commits into
edgcpp:mainfrom
mohitmishra786:gh-27-auto-void-diagnostic
Oct 9, 2026
Merged

nv-cmeerw merged 10 commits into
edgcpp:mainfrom
mohitmishra786:gh-27-auto-void-diagnostic

Conversation

@mohitmishra786

Copy link
Copy Markdown
Contributor

Fixes #27
deducing auto from a void expression used to say only cannot deduce "auto" type, because void is incomplete and deduction stopped before it could name the type. Those cases now say cannot deduce "auto" type from type "void". That covers the reported example, auto x = g(), auto &&, const auto, auto *, new auto(...), and auto * return types. decltype(auto) is unchanged: deduction still succeeds, and the existing incomplete type "void" is not allowed diagnostic is issued.

one leftover generic message remains on auto *q = new auto(g()). The new auto part uses the new wording. The pointer variable then sees a failed new-expression, not a void expression, so it keeps the generic message.

testing is done like below
edg-docker-test --non-interactive --posture=quick-c-fe changes/GH27 on the linux-gcc-debug Docker build. The test is tests/tests/changes/GH27.sft.cpp (//type:fn, --c++23). The first run passed with no previous output. -W wrote tests/tests/changes/.GH27.rto/default.1.1.txt, and a second run matched that recording.

@mohitmishra786

mohitmishra786 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor Author

@wchilders-nvidia @daveedvdv could you please review this PR too?
thanks for your time ;-)

@nv-cmeerw

Copy link
Copy Markdown
Contributor

I'd prefer auto and decltype(auto) to behave the same way here (and the deduction failure error seems somewhat misleading).

Maybe some (related) cases to think about (with the kind of error I'd expect here):

struct Incomplete &getIncomplete();

void f()
{
  auto v1 = void(); // error: incomplete type
  decltype(auto) v2 = void(); // error: incomplete type
  auto v3 = getIncomplete(); // error: incomplete type

  auto *v4 = void(); // error: cannot deduce
  auto *v5 = 1;   // error: cannot deduce
}

I wouldn't actually mind putting more information about the types for deduction failures in the diagnostics (for both v4 and v5 above)

@mohitmishra786

Copy link
Copy Markdown
Contributor Author

I'd prefer auto and decltype(auto) to behave the same way here (and the deduction failure error seems somewhat misleading).

Maybe some (related) cases to think about (with the kind of error I'd expect here):

struct Incomplete &getIncomplete();

void f()
{
  auto v1 = void(); // error: incomplete type
  decltype(auto) v2 = void(); // error: incomplete type
  auto v3 = getIncomplete(); // error: incomplete type

  auto *v4 = void(); // error: cannot deduce
  auto *v5 = 1;   // error: cannot deduce
}

I wouldn't actually mind putting more information about the types for deduction failures in the diagnostics (for both v4 and v5 above)

indeed true, yeah, calling that a deduction failure was the wrong diagnosis. For auto v = void() the type really is void, and the problem is that a variable can't have it. decltype(auto) already said "incomplete type", so plain auto now does the same.

auto v1 = void(), decltype(auto) v2 = void(), and auto v3 = getIncomplete() all report an incomplete type. auto *v4 = void() and auto *v5 = 1 still fail deduction, with the existing "cannot deduce "auto" type" message. I didn't add the declared type and the initializer type onto every deduction failure. That string is recorded in a lot of tests, and the two cases above already match what you wrote. I can do the richer message separately if you still want it.

The CI mismatches were from the old wording. Recordings that now say incomplete type are updated, and the auto * return tests are back to "cannot deduce".

@mohitmishra786
mohitmishra786 force-pushed the gh-27-auto-void-diagnostic branch from 674c07f to ea9361c Compare October 5, 2026 20:07
@mohitmishra786

Copy link
Copy Markdown
Contributor Author

@wchilders-nvidia @daveedvdv @nv-cmeerw updated the PR as due to conflict of last changes, please check once more in you free time

@daveedvdv-nvidia

Copy link
Copy Markdown

Hi @mohitmishra786,

Thanks for working on this improvement!

Can you add changes for the output differences in existing tests. See e.g. https://github.com/edgcpp/compiler/actions/runs/37155984995/job/111792273841

@mohitmishra786
mohitmishra786 force-pushed the gh-27-auto-void-diagnostic branch from ea9361c to ae2716c Compare October 6, 2026 04:28
@mohitmishra786

Copy link
Copy Markdown
Contributor Author

Hi @mohitmishra786,

Thanks for working on this improvement!

Can you add changes for the output differences in existing tests. See e.g. https://github.com/edgcpp/compiler/actions/runs/37155984995/job/111792273841

That job is the earlier run, from before the recording updates. The tests whose output changed from "cannot deduce "auto" type" to the incomplete-type diagnostic now have updated default recordings: dcl.spec.auto/p2-1z, expr.prim.lambda/p11-1y, stmt.ranged/p1, auto-subst-failure, lambda-unevaluated, matrix-type-builtins-disabled, typeid-requires-typeinfo, and the new GH27 test. I rebased onto main again so the Changes file includes the 7.1 notes.

Maybe we can trigger fresh run of CI and see everything again.

@mohitmishra786

Copy link
Copy Markdown
Contributor Author
Screenshot 2026-10-06 at 9 59 02 AM Seems awaiting maintainers approval for the run

Comment thread src/overload.c Outdated
Comment thread src/overload.c Outdated
is also allowed through: the type is deduced, and the incomplete-type
diagnostic is issued for the variable (the same diagnostic as for
decltype(auto)). "auto *" and similar forms still fail deduction. */
if (!(allow_incomplete_arg && is_template_param_type(param_type))) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if should just be folded into the enclosing if. The comment mentions "auto", but the condition tests for template parameter type (should probably use is_auto_type then). But I think this should just test for allow_incomplete_arg (and not test for "auto" at all here), as we only set allow_incomplete_arg for the placeholder type deduction case.

I am actually wondering if that whole is_incomplete_type check should go away completely. There is a deeper issue here, consider:

struct Incomplete &getIncomplete();

template<typename T>
void g(T, int) // 1
{ }

template<typename T>
void g(T &, long) // 2
{ }

void f()
{
  g(getIncomplete(), 0);
}

Currently, we accept this, because we fail deduction for 1 and just call 2 instead. But we should succeed deduction for 1 and then diagnose the incomplete type error there.

We don't need to fix that with this change, but would be a good follow-up issue then.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if should just be folded into the enclosing if. The comment mentions "auto", but the condition tests for template parameter type (should probably use is_auto_type then). But I think this should just test for allow_incomplete_arg (and not test for "auto" at all here), as we only set allow_incomplete_arg for the placeholder type deduction case.

I am actually wondering if that whole is_incomplete_type check should go away completely. There is a deeper issue here, consider:

struct Incomplete &getIncomplete();

template<typename T>
void g(T, int) // 1
{ }

template<typename T>
void g(T &, long) // 2
{ }

void f()
{
  g(getIncomplete(), 0);
}

Currently, we accept this, because we fail deduction for 1 and just call 2 instead. But we should succeed deduction for 1 and then diagnose the incomplete type error there.

We don't need to fix that with this change, but would be a good follow-up issue then.

Updated the comment to talk about placeholder type deduction, and folded the check so it only looks at allow_incomplete_arg. The Changes entry no longer quotes the old diagnostic, and the examples use "// Error:".

I left the template case (g(getIncomplete(), 0) succeeding deduction and then diagnosing the incomplete type) for a follow-up. changes/GH27 still matches.

Comment thread src/Changes Outdated
Comment thread src/Changes Outdated
@mohitmishra786

mohitmishra786 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

@nv-cmeerw update the pr as per the comments, workflows are yet to run after one of the maintainers approval
please review and let me know if any more changes or its good now

@mohitmishra786

Copy link
Copy Markdown
Contributor Author

@nv-cmeerw I see ci good now, once back please review, thanks

Comment thread src/overload.c
/* In a prototype instantiation a deduction failure is often
suppressed. Keep that behavior for an incomplete initializer:
the incomplete-type diagnostic is issued at instantiation. */
a_boolean allow_incomplete_arg =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The need for this change isn't entirely obvious. Was there any test case that would show undesirable results without this change? If so, it might be worth adding one example to your GH27.sft.cpp test to demonstrate the need for this change.

Thanks for your continued work on this issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. Without that check, a template definition is diagnosed even when the type is completed before instantiation:

struct Later;
extern Later later_obj;
template<int> void use_later() { auto x = later_obj; }
struct Later { int n; };
void call_later() { use_later<0>(); }

A deduction failure in the template definition is already suppressed in GNU and Microsoft modes. Diagnosing an incomplete type there instead turned decomp44 and decomp45 into errors. The check keeps that suppression. GH27 now has a --gnu_version run with this template, and it produces no diagnostic for use_later. The errors outside the template are unchanged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation.

Unfortunately, it's a bit more complicated. So GCC and MSVC don't diagnose substitution failures and incomplete-type errors in template definition. We are only emulating the substitution failure part, but because we treated an incomplete type deduction as a substitution failure we kind of emulated that part as well.

Your change would mean that for auto var = void() inside a template definition we wouldn't get the "incomplete type" error in standard or Clang modes any more (but instead get the old deduction failure error).

I think for now we'll have to duplicate the condition here:

      /* GCC and Microsoft don't diagnose incomplete-type errors in template
         definitions, but for now the only way for us to emulate that is by
         failing deduction in these cases (which we then allow, see
         prescan_initializer_for_auto_type_deduction). */
      a_boolean  allow_incomplete_arg =
               !((gpp_version_is(any_version) || ms_version_is(any_version)) &&
                 scope_stack_top().in_prototype_instantiation &&
                 innermost_function_scope != NULL);

and run the template definition test not just in GCC mode, but all possible modes, i.e. --c++11 -A:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--ms_c++20 --microsoft_version 1951

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, that makes sense. I had folded the incomplete-type case into the GNU/Microsoft suppression, so standard and Clang modes went back to the deduction failure error for auto var = void() in a template definition.

I've used your condition and comment as is, so incomplete-type deduction is only failed in a template definition in GNU and Microsoft modes, where prescan_initializer_for_auto_type_deduction then allows it.

The template definition test is now a separate test, changes/GH27_a, because GH27 needs --c++23 for the explicit object parameter. GH27_a runs with --c++11 -A:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--ms_c++20 --microsoft_version 1951. It also has a non-template auto v = void() so that every mode has an error, as the test type requires. Results:

  • strict mode: "incomplete type" errors in the template definitions
  • GNU and Microsoft modes: no diagnostic in the template definitions
  • Clang mode: "incomplete type" errors in the template definitions with the C++-generating back end config (recorded as edg_x86_64_cp.3.1.txt). In the default config, Clang mode reports nothing inside an uninstantiated template body. That isn't specific to this change: a template body with no auto and int x = "s"; isn't diagnosed there either.

@mohitmishra786
mohitmishra786 force-pushed the gh-27-auto-void-diagnostic branch from c572536 to a629bee Compare October 8, 2026 05:00
@mohitmishra786

Copy link
Copy Markdown
Contributor Author

@nv-cmeerw updated the PR with above comments and rebased to the latest changes

Comment thread src/Changes Outdated
auto *p = g(); // Error: cannot deduce "auto" type

Forms that are not a plain "auto", such as "auto *", still fail deduction.
The diagnostic is not issued while scanning a template definition, because

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need to mention the template definition part here, as it's just keeping the existing behaviour.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, removed.

@mohitmishra786

Copy link
Copy Markdown
Contributor Author

@nv-cmeerw updated the PR as per the comments and the reasoning, up for review

Comment thread src/Changes


10/5/26 [GH #195]
C++-generating back end: dependent multi-dimensional subscripts

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am somehow seeing unrelated changes here (and the new Changes entry should be added to the top with the new date). Is this just something specific to this particular PR, or is there a deeper issue with the shared Changes file when iterating on a PR? @wchilders-nvidia any thoughts here?

Otherwise, I think it's good to go now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was specific to this PR. While resolving the src/Changes conflicts in earlier rebases, I moved the GH #195 and GH #191 entries below GH #203, so the diff showed them as removed and re-added. I've now taken src/Changes from main as is and only added the GH #27 entry at the top of 7.1 with today's date (10/9/26), so the diff is just that one entry.

The last CI run also failed edg_x86_32_cp on changes/GH27_a: in that config, Clang mode reports the template-definition errors just as edg_x86_64_cp does, so I've added the matching edg_x86_32_cp.3.1.txt recording.

@mohitmishra786

Copy link
Copy Markdown
Contributor Author

@nv-cmeerw now ci passes and everything aligned, let me know if anything more you see not aligning, I updated the order fix too

@nv-cmeerw nv-cmeerw left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me now.

@nv-cmeerw
nv-cmeerw merged commit cd4cea1 into edgcpp:main Oct 9, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[GNATS 26877] Provide friendlier diagnostic for auto-void deduction

3 participants