Nvc++ 22.1 - nonsensical warning about missing return statement

Consider the following code:

template<int D>
int f(){
  if constexpr(D==0) {
    return 42;
  } else {
    return 0;
  }
}

int main() {
  f<1>();
}

nvc++ 22.1 apparently fails to analyze this trivial branching and warns:

$ nvc++ -std=c++17 nvcxx-test.cpp
"nvcxx-test.cpp", line 9: warning: missing return statement at end of non-void function "f<D>() [with D=1]"
  }
  ^
          detected during instantiation of "int f<D>() [with D=1]" at line 12

Which is clearly an incorrect warning.

But hilariously, when I try to do what it wants and add a (unnecessary) return at the end:

template<int D>
int f(){
  if constexpr(D==0) {
    return 42;
  } else {
    return 0;
  }
  return 0; //nvc++ warns without return statement at end
}

int main() {
  f<1>();
}

All of a sudden it correctly warns:

$ nvc++ -std=c++17 nvcxx-test.cpp
"nvcxx-test.cpp", line 9: warning: statement is unreachable
    return 0; //nvc++ warns without return statement at end
    ^

Which I think is hilarious, and makes me feel trolled by nvc++ ;-)

On a more serious note, this pattern appears massively in my code base, causing the console output to be cluttered with nonsensical nvc++ warnings - and no clear workaround to get rid of this warning in the code (apart from disabling warnings altogether). So, this is a major nuisance.

Oh man - don’t know if to laugh or cry - thanks for raising this.
I shall be sure to send this to the compiler team - I am sure there will be some serious discussions about our test suite.

If you find anything else - keep it coming, its posts like this which help make our products better.
Thanks !!

Thanks for feeling with me and passing it along! I indeed have more, but it’s not always easy to find a minimal reproducer that triggers the issue. I will surely keep posting as I manage to boil things down to such reproducers :-)

Hi illuhad,

The second warning is correct in that the final return statement is unreachable. However the first warning does appear to be extraneous. I’ve filed a problem report, TPR #31319, and sent it to engineering for investigation.

-Mat

Thanks Mat. I agree that the second warning is correct. I just pointed it out because it leaves the impression that nvc++ can both not analyze the branching (first warning) and simultaneously can analyze the branching (second warning).

I suspect this issue is caused by instantiation of if constexpr statements, and there might be some more sore points in this area. For example,


template<int D>
int f(){
  if constexpr(D==0) {
    return 42;
  }
  return 0;
}

int main() {
  f<1>(); // no warning
  f<0>(); // warning: unreachable "return 0"
}

Here, f<1>() by itself does not generate warnings.
However if f<0>() is instantiated, a warning is emitted because the return is unreachable.

Now it’s not strictly wrong that the f<0>() instantiation has an unreachable return. However, the warning is not very helpful because there are branches (depending on the template parameter) where the return is not unreachable. And I think there is a lot of code in the wild that uses such patterns and I would consider it legitimate. E.g. neither clang 13 nor gcc 10.3 warn in this case.

I noticed as well that the warning is not emitted when the constexpr is true and put it in my report. Though will let engineering review and determine how best to fix.

I’m assuming that, while the warning is not helpful, the code compiles and runs correctly otherwise?

Yes, it seems like the generated code for this example is correct.

The only other thing I noticed that might be related (and which prompted this investigation in the first place) is that compilation of my production code base eventually crashes with this ICE:

"/usr/include/c++/10/array", line 50: internal error: assertion failed: process_fill_in: specified fill-in not found (edg_error.cpp, line 3593 in process_fill_in)

        typedef _Tp _Type[_Nm];

The ICE disappears and the code compiles (and runs) correctly if I suppress warnings with -w. As I had mentioned, I get these warnings a lot in my production code.Is it possible that this ICE is somehow triggered by a warning overflow or something like that?

Unfortunately, so far I could not succeed in creating a minimal reproducer for this ICE.

That is odd, The ICE is coming from the EDG front-end C++ compiler so not something we directly control. But let me ask our compiler engineering manager to contact them for any clues as to what may trigger the error or if they’ve had other similar reports.

Obviously our fix for the nested lamba issue you previously reported didn’t effect this so most likely was unrelated.

Thanks Mat, really appreciate your efforts! I’m also scratching my head as to how the warning level can influence EDG frontend ICEs - I’m assuming you are relying on your own logic for generating warnings, based on the discussion here.

Yes, the nested lambda issue is unrelated. Thanks for the fix. I’m fighting multiple issues here ;-)

I’m also scratching my head as to how the warning level can influence EDG frontend ICEs

Talking with one our compiler engineers, we think it’s likely to be the result of a misconfigured compiler diagnostic . For example, the code being compiled triggers a warning or error that is supposed to have an argument, but the code in the compiler that reports the warning or error doesn’t supply any argument.

Though unfortunately without a reproducer, we can’t tell for sure. I know you’ve tried, but if there is a way to get us an example of the code that triggers the problem, that would be appreciated.

Thanks,
Mat

Thanks for the feedback! So far I could not create a minimal reproducer, however if it helps I can provide you with the full preprocessed version of my code in a single file. It’s around 5MB in size, and reproduces the issue (alongside with many more additional warnings because it seems nvc++ warns differently for system headers, and this distinction doesn’t work anymore when everything is in one file). If this is not not too unwieldy for your engineers, should I attach it here, or is there a better way to share?

In the end it’s open source code, so I’m not concerned about disclosing it.

The post-processed file would be fine. While I’m not sure what the file size limit is for attachments to the forums, please do give it a try. If it doesn’t like the size, then direct message me and we can find an alternative method.

If the code is available on the web, such as on GitHub, I can grab the full source as well. Yes a minimal reproducing example is ideal and appreciated, but the “minimal” part is optional.

nvcxx-test.i (4.9 MB)
Alright, here it is. Thanks for having a look!

Note that you won’t be able to run it in any case due to missing libraries that you have to link against; so linker errors would be the expected outcome. However it crashes before this.

Compile with: nvc++ -cuda -std=c++17 nvcxx-test.i

This is part of a multi-backend parallel programming model framework, where one of the backends is CUDA as supported by nvc++. As such, you might find identifiers from other backends referring to other models that NVIDIA might not directly support - but as can be seen from the compiler invocation the code in question is just regular CUDA C++.
(With the addition that it relies on nvc++'s capabilities to automatically infer device/host attributes).

I was able to reproduce the error and have filed TPR #31331.

Like you, any attempts to reduce the problem resulted in the error going away.

2 Likes

Engineering let me know that TPR #31319 and 31331 were fixed in our 22.3 release.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.