How to set -fpermissive when using Teensy board

The sketch fragments below compile without error or warning with UNO, but generates the following warning with the Teensy 4.0:

C:\Users\Mike\AppData\Local\Temp\arduino_build_810777\sketch\pages.h:110:71: warning: invalid conversion from 'void ()()' to 'int16_t ()() {aka short int (*)()}' [-fpermissive]

CreateButton("ONOFF", 2, 340, 65, "ON", BUTTON, RED, *SystemSwitch);

It seems the -fpermissive feature is not set by default when the Teensy board is selected but it is with the arduino UNO.

How can -fpermissive be set when using the arduino IDE and a Teensy board?
Alternatively, how can the code be changed to work in both environments?

This code snippet has comments pointing out the relevant parts. The last line causes the warning.

// this is the structure where the function pointer will be stored
struct Button
{
  public:
    String buttonKey;
    int x;
    int y;
    int height;
    int length;
    int16_t (*funct)();      // this is where the function pointer will be stored
};

Button myArray[20];
Button item;

// this is the function prototype with an optional last argument
void CreateButton(String buttonKey, int txSize, int x, int y, String txt, int bgClr, int txClr, int16_t (*funct)() = NULL);  	

// this is the actual function
{void CreateButton(String buttonKey, int txSize, int x, int y, String txt, int bgClr, int txClr, int16_t (*funct)())  		
  float charWidth[6]  = {6, 6, 12, 18, 24, 28};
  float charHeight[6] = {7, 7, 14, 22, 30, 36};
  float rectWidth, rectHeight;

  rectWidth = (txt.length() + 1) * charWidth[txSize];
  rectHeight = charHeight[txSize] + 20;

  tft.drawRect(x, y, rectWidth, rectHeight,  TEXT);
  tft.fillRect(x + 1, y + 1, rectWidth - 2, rectHeight - 2, bgClr);

  int txtStartX = x + (charWidth[txSize] / 2) + 1;                       
  int txtStartY = y + 10;                                                  

  tft.setCursor(txtStartX, txtStartY);
  tft.setTextColor(txClr);
  tft.setTextSize(txSize);
  tft.print(txt);

  if (funct != NULL)
  {
    // See if this button is already in the list

    for (int i = 0; i < itemCount; i++ )
    {
      if (buttonKey == myArray[i].buttonKey)             
        return;
    }

    // Store the button coordinates for this button press
    item.buttonKey = buttonKey;
    item.x = x;
    item.y = y;
    item.length =  rectWidth;
    item.height = rectHeight;
    item.funct = funct;
    myArray[itemCount++] = item;
  }
}

// this is the actual function call
CreateButton("ONOFF", 2, 340, 65, "ON", BUTTON, RED, *SystemSwitch);

Since the compiler apparently has a problem with the variable 'SystemSwitch' in that function call, don't you think it would have been helpful to post at least enough code so that the definition of that variable was included?

Better yet, post the full code. UNLESS the full code is large, ugly, or full of unrelated clutter. In that case, post an MRE.

EDIT:

PickyBiker:
Alternatively, how can the code be changed to work in both environments?

BTW, this IS the right approach. Don't dumb-down the compiler, fix your code.

SystemSwitch is a function.

void SystemSwitch()
{
  systemOn = !systemOn;
  GoHome();
}

I agree fixing the code is better.

OK, then the compiler is correct (as usual). The prototype for the CreateButton() function says the (optional) last argument is a pointer to a function which takes no arguments and returns an int16_t.

You're (incorrectly) trying to pass it a pointer to a function which takes no arguments and returns no value (aka 'void').

another way to approach this...

instead of..

struct Button
{
  public:
    String buttonKey;
    int x;
    int y;
    int height;
    int length;
    int16_t (*funct)();      // this is where the function pointer will be stored
};

Make it a class Button with a virutal method :
virtual void Button::Action(void);Then you just use that as your base class and derive different Button classes that do different things when actuvated. By filling in your action() method's differently.

..Or not..

-jim lee

Just to emphasize - -fpermissive is a horrible, horrible thing. It is truly unfortunate that it is set by default, because it will actively hide bugs in your code.

Case in point - this right here. There's also the "Why are some of my 'case' statements missing" problem that keeps cropping up.

From the GCC docs (emphasis added)

-fpermissive

Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive allows some nonconforming code to compile.

Backwards compatibility probably means the Arduino IDE is stuck with it, bit I sure do wish there was a way to turn it off without having to edit parts of the Arduino installation.

Thanks for the help gfvalvo. I took your advice and created a working minimal example. This is now compiling without error or warning using either board and it calls one function explicitly and one by default.

struct Button
{
  public:
    String buttonKey;
    int x;
    int y;
    int height;
    int length;
    void (*funct)();
};

void Hello()
{  
  Serial.println("Hello");
}

void Goodbye()
{
 Serial.println("Goodbye");
}

void CreateButton(String buttonKey, int txSize, int x, int y, String txt, int bgClr, int txClr, void (*funct)() = *Goodbye);

int itemCount;
Button myArray[20];
Button item;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  CreateButton("key1", 2, 40, 120, "Hello", 0xffff, 0x0000, *Hello);    // call Hello
  CreateButton("key2", 2, 40, 120, "Goodbye", 0xffff, 0x0000);          // call Goodbye using default arg
  myArray[0].funct();       // call the Hello button's function
  myArray[1].funct();       // call the Goodbye button's function
  delay(1000);
}


/**********************************************************************************/
void CreateButton(String buttonKey, int txSize, int x, int y, String txt, int bgClr, int txClr, void (*funct)())
{

  if (funct != NULL)
  {
    // See if this button is already in the list

    for (int i = 0; i < itemCount; i++ )
    {
      if (buttonKey == myArray[i].buttonKey)                // Already in the list?
        return;
    }

    // Store the button coordinates for this button press
    item.buttonKey = buttonKey;
    item.x = x;
    item.y = y;
    item.length =  25;
    item.height = 20;
    item.funct = *funct;
    myArray[itemCount++] = item;
  }
}

MHotchin:
Backwards compatibility probably means the Arduino IDE is stuck with it, bit I sure do wish there was a way to turn it off without having to edit parts of the Arduino installation.

Having just gone through this learning curve, I agree.
It seems to me there could be a default setting in the Arduino with -fpermissive set by default and if the user chooses, he could change the setting to off by default. That would maintain backward compatibility and give people a choice.

Make it a class Button with a virtual method

jimLee, the way I am storing and calling the function for the buttons seems overly complicated to me. Does it work? Yes, but there should be an easier way. I am a self taught C programmer (zero formal training) and I do not yet understand virtual functions.

I like your alternative and will research it.

Thanks!

PickyBiker:
Thanks for the help gfvalvo. I took your advice and created a working minimal example. This is now compiling without error or warning using either board and it calls one function explicitly and one by default.

It does compile, but the syntax in these two lines is incorrect:

void CreateButton(String buttonKey, int txSize, int x, int y, String txt, int bgClr, int txClr, void (funct)() = ____Goodbye);

CreateButton("key1", 2, 40, 120, "Hello", 0xffff, 0x0000, __*__Hello);

The "" in front of the function names implies that you're dereferencing pointers. You're not. Even though the compiler luckily figured out what you wanted to do, putting the ""s there is confusing.

Some discussion on removing -fpermissive here:

MHotchin:
I sure do wish there was a way to turn it off without having to edit parts of the Arduino installation.

There is a proposal for this in the issue linked above. I not really into adding some -fpermissive specific option, but a general purpose system for customizing compilation flags might be reasonable.

It is possible to do this from the command line by overriding the compiler.cpp.flags property:

so you would duplicate the current value, except without the -fpermissive.

So if you are using Arduino CLI this is done with the --build-properties option. For use with an AVR board:

arduino-cli compile --build-properties "compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto"

If using the Arduino IDE's command line interface, you can do the same with the --pref option

Better would be if we could leave the compiler.cpp.flags property alone and instead use the compiler.cpp.extra_flags property to nullify the -fpermissive flag that's added earlier in the compilation command. However, this would require something like -fno-permissive and it seems there is no such thing. While researching that, I found a stack overflow answer that suggested using -pedantic for this purpose, but that's just silly because -pedantic is only about warnings, but we're already getting a warning. This is about errors being downgraded to warnings. -pedantic-errors makes more sense, but -fpermissive -pedantic-errors leaves the permissive stuff as warnings, while adding errors for things that would compile fine even without -fpermissive, so that's also worthless.

gfvalvo, yes, I see that. Removed the asterisks indicating pointers and it still compiles without error or warning in both environments.

Learned a few things today.

Thanks again.