Eager/Non-uniform suggestions to use const (c:S995 )

Eclipse 2025-09 (and at least a few earlier ones), SonarQube 11.15 (no cloud, no modifications), macOS 15.6.1, C

I’ve read through several of the S995 related threads. Those tend to be more obvious examples, but not exactly what I’m seeing.

I have several cases where a parameter (usually an opaque struct) is flagged to add const. Indeed, the immediate function does not modify the struct, but farther down the call chain it will be modified.

Additionally, the suggestion is not flagged uniformly for all cases which would seem to be the same. I could have several adjacent functions in a file, all the same style. Some will have the suggestion to use const for a parameter, and some will not.

A) Is this a genuine false positive? Should SQ be digging deep enough to discover the eventual modification of the flagged parameter?

B) If yes – how can I help you discover the root of the where the logic breakdown is?

C) If no — is there some C convention I could be using to inform SQ to ignore those cases it flags (though I hesitate to do something for some cases but not others that don’t get flagged).

Thanks for your time.

— greg

// For example, this first fn gets flagged to add const for restCmd.
// But, the second fn does not get flagged (it's actually a longer, 
// but only repeats the same type of 3-line clusters a few more times).
// Every one of the mRestJson functions modifies `pb_string* replyWip`
// which is a field in `m_restCommand* restCmd`. So, const cannot be
// used and then passed/enforced downstream.

void mRestPower_renderRatingsGroup (m_restCommand* restCmd, const m_powerDevice* theDevice)
{
    pb_string* replyWip = mRestCmd_replyWip(restCmd);

    mRestJson_addFieldName(replyWip, "phase");
    mRestPower_renderPhase(restCmd, theDevice);
    mRestJson_addFieldDelimiter(replyWip);

    mRestJson_addFieldName(replyWip, "rated_volts");
    mRestPower_renderRatedVolts(restCmd, theDevice);
    mRestJson_addFieldDelimiter(replyWip);

    mRestJson_addFieldName(replyWip, "rated_amps");
    mRestPower_renderRatedAmps(restCmd, theDevice);
}


void mRestPower_renderPowerGroup (m_restCommand* restCmd, const m_powerDevice* theDevice)
{
    pb_string* replyWip = mRestCmd_replyWip(restCmd);

    mRestJson_addFieldName(replyWip, "amps");
    mRestPower_renderAmps(restCmd, theDevice);
    mRestJson_addFieldDelimiter(replyWip);

    mRestJson_addFieldName(replyWip, "consumed_amps");
    mRestPower_renderConsumedAmps(restCmd, theDevice);
    mRestJson_addFieldDelimiter(replyWip);
}

Hi @gw48 ,

This looks like a false positive indeed, but it is not one I manage to reproduce.

Could you please generate a reproducer file for this case?

To generate the reproducer file:

  • Search in the analysis log for the full path of the source file for which you want to create a reproducer (for instance, a file that contains a false-positive). You will have to use exactly this name (same case, / or \…)

  • Add the reproducer option to the scanner configuration:
    sonar.cfamily.reproducer=“Full path to the .source file”

  • Re-run the scanner to generate a file named sonar-cfamily-reproducer.zip in the project folder.

  • I’ll send you a direct message so that you can share this file with us privately.

Thanks