0

I have a method

int someMethod(int arg1, int arg2)
{
  //method body
}

and I have a macro defined say _MACRO for the same method so as to execute it based on the condition.

#ifdef _MACRO
int someMethod(int arg1, int agr2)
{
  //method body
}
#endif

I am using this someMethod in say someAnotherMethod(int arg1, int arg2)

int someAnotherMethod(int arg1, int arg2)
{
  //othercode
  #ifdef __MACRO
  someMethod(int arg1, int agr2);
  //othercode
}

I get an error for the same in someAnotherMethod().

error C4100: 'arg1' : unreferenced formal parameter

Can anyone explain this thing and provide an alternative approach?

FedKad
  • 493
  • 4
  • 19
  • 3
    What kind of code is this? C? Where is the closing `#endif` in the last code? And why you put type specifiers (`int`) in the calling code of `someMethod`? – FedKad Jul 17 '19 at 11:38
  • Yes, its a C code – Akshay Kadam Jul 17 '19 at 11:41
  • "unreferenced formal parameter" is a warning, not an error (though you can promote warnings to errors in your settings if you want). It's complaining that you have parameters that you aren't using. You have three options: turn off the warning (either [locally](https://stackoverflow.com/a/26601359/1287251) or in your project settings), stop promoting the warning to an error (again, in your project settings), or use the parameters (i.e. just do `(void)arg1; (void)arg2;` within the function to show the compiler you're using the arguments). – Cornstalks Jul 17 '19 at 12:50
  • 2
    `_MACRO` is a reserved identifier. The [C standard reserves identifiers](https://port70.net/~nsz/c/c11/n1570.html#7.1.3) starting with a single underscore and an uppercase letter along with identifiers starting with two underscores: "All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use." – Andrew Henle Jul 17 '19 at 12:50
  • Possible duplicate of [Avoid warning 'Unreferenced Formal Parameter'](https://stackoverflow.com/questions/3020584/avoid-warning-unreferenced-formal-parameter) – Cornstalks Jul 17 '19 at 12:51
  • @Cornstalks That's a pure C++ question. I'm not sure it's applicable to C. – Andrew Henle Jul 17 '19 at 12:52

4 Answers4

3

The error you’re getting has been elevated from a warning due to some compiler flag. And you’re getting the warning because, when __MACRO is undefined, your someAnotherMethod function has unused parameters.

The conventional way of silencing this warning is to cast the parameter to void, thereby using it.

Something else, your macro name is invalid, you mustn’t use a double underscore, or a leading underscore followed by a capital letter. This notation is reserved for the C implementation.

Instead, use YOUR_LIBRARY_NAME_MACRO as a naming convention.

int someAnotherMethod(int arg1, int arg2) {
# ifdef LIB_MACRO
  someMethod(int arg1, int agr2);
# else
  (void) arg1;
  (void) arg2;
# endif
}

This is sometimes hidden behind a macro:

#define UNUSED(x) (void) (x)

…

int someAnotherMethod(int arg1, int arg2) {
  …
  UNUSED(arg1);
  …
}
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • I used `(void)` as `UNUSED`, but it doesn't avoid `-Wunused-result`, so I came up with a more sophisticated one: `#define UNUSED(e) do { if (e) {} } while (0)` – alx - recommends codidact Jul 17 '19 at 13:25
  • 1
    @CacahueteFrito The `-Wunused-result` warning is unrelated to OP’s question: It corresponds to unused *result* values on functions, but *only* if they have the attribute [`warn_unused_result`](https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html#Function-Attributes). And some versions of GCC indeed ignore `(void) result;` in this context. [That’s a bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82134). – Konrad Rudolph Jul 17 '19 at 13:39
  • Yes, it's unrelated to OP, but related to answer and I thought it might be useful :) – alx - recommends codidact Jul 17 '19 at 13:45
1

I'm hesitant to present you with this solution as it's the ugliest hack ever.

Context : I'm working with a very old C compiler that has a lot of quirks, one of which is that the warnings about unused parameters or variables can happen at any given steps of the optimization process. So, for example, sometimes you get a warning that a certain variable is unused, but truly, it has just been optimized away.

The old codebase is also littered by #ifdef, so I've encountered your problem more than once.

The hack

suppresswarning.h

extern long SuppressWarning;
#define SUPPRESS_WARNING(p) (SuppressWarning += (uintptr_t)&(p))

suppresswarning.c

long SupressWarning;

YourFile.c

#include "suppresswarning.h"

int someAnotherMethod(int arg1, int arg2)
{
  //othercode
#ifdef __MACRO
  someMethod(arg1, agr2);
  //othercode
#else
  SUPPRESS_WARNING(arg1);
  SUPPRESS_WARNING(arg2);
#endif
}

The SUPPRESS_WARNING macro, essentially, prevents the compiler from optimizing the variable away. This has the added value to be clear for any new programmer reading the code ; SUPPRESS_WARNING suppresses a warning.

This hack doesn't necessarly require to add a translation unit. Most projects have miscellaneous units for debugging or for utility functions ; this can be put there instead.

MartinVeronneau
  • 1,296
  • 7
  • 24
  • @EdwardKarak Because that completely changes the semantics. That said, the macro suggested also unnecessarily generates dead code (the optimised will probably remove that but why bother?). – Konrad Rudolph Jul 17 '19 at 13:15
  • @EdwardKarak That would impede optimizations – alx - recommends codidact Jul 17 '19 at 13:20
  • 1
    @KonradRudolph That's what common sense seems to indicates, but for our old compiler, that does it. And yes, that creates dead code, but the slight loss in performance is offfset by the fact that we can build this multi-millions lines of a behemoth without getting thousands of false positive warnings. – MartinVeronneau Jul 17 '19 at 13:29
  • @MartinVéronneau I don’t doubt that this “does it”. But it’s unnecessary: The method in my answer is the conventional way of suppressing this warning, and generates no dead code and requires no extra files/translation units/build steps. – Konrad Rudolph Jul 17 '19 at 13:41
  • 1
    @KonradRudolph I see absolutely no problem with your method (and in fact, I'll upvote it), but with the old compiler we're using it doesn work all the time (I just tested that). That's really an old compiler for an embedded platform, and we're stuck with it. Anyway, the warning posted by the OP clearly comes from MSVC, so I agree that your method is better. – MartinVeronneau Jul 17 '19 at 14:47
0

Alternative:

#define FOO (FOO1)

enum Foo {
        FOO1,
        FOO2,
        FOO3
};

int foo1(void);
int foo2(void);
int foo3(void);

int foo(void)
{

        switch (FOO) {
        case FOO1:
                return foo1();
        case FOO2:
                return foo2();
        case FOO3:
                return foo3();
        default:
                return -1;
        }
}

int foo1(void)
{
        return 1;
}

int foo2(void)
{
        return 2;
}

int foo3(void)
{
        return 3;
}

The benefit of this is that the compiler compiles all the code, so you can check if there are any errors in the code, which with the preprocessor you don't get.

Basically the preprocessor #if and company are useful only for using features that may not be available, but if a feature is available, then prefer if or switch.

0
int someAnotherMethod(
#ifdef __XYZ
int arg1,
 #else
int,
#endif
int arg2)
{
//othercode
#ifdef __XYZ
someMethod(int arg1, int agr2);
#endif
//othercode
}

This worked fine for both the arguments.

  • This does not "work fine". There are multiple problems with this answer. First and foremost, C does not support arguments without a name. See https://stackoverflow.com/questions/8776810/parameter-name-omitted-c-vs-c. Second, `__XYZ` is a reserved identifier and should not be used. – Andrew Henle Jul 22 '19 at 13:58