Sonar Scanner fails with 9.9 if operator== is implemented in cpp file

  • SonarQube 9.9 LTS
  • SonarScanner 4.6.x and also latest 4.8.x

The scanner runs fail with the attached error output.

scanner_log.txt (6.9 KB)

Moving the operator implementation from the .cpp file to the header file solved it.

.cpp causing the crash before removing the operator:

namespace somens
{
...
  bool TxPhases::operator==(const TxPhases& other) const = default;

...

.h before:

  bool operator==(const TxPhases& other) const;

.h after:

  bool operator==(const TxPhases& other) const = default;

Hi @petermbauer!
Please attach the sonar-cfamily-reproducer.zip file that the log mentions.

Thanks for sharing the reproducer on a private channel.

The crash happens during parsing, where we recognize that there is no viable overload candidate for the call within the synthesized operator==() for your class because the default version will use std::equal(). The crash happens because if you user-provide the defaulted equality operator, then the declaration of the equality operator will be mentioned in the “no viable overloads found” diagnostics and that is where it crashes.

I created CPP-4149 for tracking this crash.

To unblock you I would recommend to check your code if the “no viable overloads found” diagnostic is valid and try to fix that, so that we wouldn’t diagnose it and try to construct a message for it and crashing.

Alternatively, or if that is not a valid error, you can always exclude the given file from the analysis using the sonar.exclusions option until we fix this crash.

Thanks for taking care of this so quickly, we already moved the operator definition to the header file to unblock us.

Mind that leads to a slight semantic difference, on which you probably not depend on but I’m mention it anyway.
It’s that if you in the class define the function with = default; it means that it’s NOT “user-provided” but “auto synthesized”. It means that the rest of the special member functions will be generated by the compiler automatically.

On the other hand, if you only declare it and later specify it’s body as MyClass::specialmemberfn() = default; it means that it’s “user-provided” but we use the default version what the compiler would have generated. This means that the rest of the special member functions WON’T be “auto synthesized”.

It could be important if you expose the given class in some public APIs that ends up consumed by some user-code, and start depending on the fact that the rest of the special member functions exist/ doesn’t exist. So, making such changes is an ABI-breaking change.

To learn more about the meaning of “user-provided” and “defaulted” check out this StackOverflow post:

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