2

I know I'm in a C++ compiler, but I typically create a typedef from structures, probably a holdover from earlier C programming. So this has my head spinning. I create a Typedef from a structure. After that, I have no trouble declaring a global or local version of that structure anywhere in a function, or outside of all functions (global). But when I try to create a function with this typedef as an arg, or even a function arg with a pointer the such a typedef, the compiler complains (and the complaint doesn't seem to make sense). Example...

typedef struct ss_tag {
  uint16_t settingsSavedCount;
  uint16_t codeID;

// a few more vars

uint8_t powerDownSaveFlag; // lets me know why we're being reset. uint8_t future[10]; } Sunstates;

So now, this typedef seems as good as any other. Either of these statements compile fine...

Sunstates sunStates; 
Sunstates * pSS = &sunStates;

But if I now try to create a function, with either an instance of this data type or a pointer to it, like so...

void systemDataVerify(Sunstates *pST) {  }

The Arduino compiler offers this confusing error message...

Arduino: 1.8.3 (Windows XP), Board: "Arduino Nano, ATmega328"

SolarControler_21a:393: error: variable or field 'systemDataVerify' declared void

void systemDataVerify(Sunstates *pSS) { }

                   ^

SolarControler_21a:393: error: 'Sunstates' was not declared in this scope

SolarControler_21a:393: error: 'pSS' was not declared in this scope

void systemDataVerify(Sunstates *pSS) { }

exit status 1 variable or field 'systemDataVerify' declared void

The fact that it doesn't like me declaring a function void is odd, but not as troubling as it calling my function a 'variable or field' and definitely not as strange as it saying my datatype (Sunstates) was NOT "declared in this scope." The data type was defined immediately before the function... and the fact I could declare both instances of the type AND pointers to it kind of proves it exists within the scope. Can someone help me understand why the compiler is complaining?

Edit... I was asked to include a short sketch that shows the problem...

uint8_t somefunction() {
  return;
}

// define structure to hold/save setup and mode info

typedef struct ss_tag { uint16_t settingsSavedCount; uint8_t powerDownSaveFlag; // lets me know why we're being reset. } Sunstates;

Sunstates sunStates; // create an instance

// create a function to accept a pointer to // type Sunstates as an arg

void systemDataVerify(Sunstates *p) { return; }

void setup() { // put your setup code here, to run once: }

void loop() { // put your main code here, to run repeatedly: }

Now... I have discovered that if I remove the 'somefunction()' definition before the Structure definition, the problem goes away. And I'm using Arduino 1.8.3 to compile this.

dda
  • 1,595
  • 1
  • 12
  • 17
Randy
  • 407
  • 3
  • 13

3 Answers3

5

I do not get this error in Arduino IDE 1.8.5 with snippet you provided, but I get it in Sloeber Eclipse plugin. The later attached sketch fails to compile in Arduino IDE 1.8.5 too.

The error is in Arduino build chain ino to cpp conversion for the C++ compilation. Put the typedef declaration into .h file and include it in ino.

EDIT: Details are in my newer answer to a similar problem.

Juraj
  • 18,264
  • 4
  • 31
  • 49
2

It's not a compiler bug, @alm.

If I take the Minimal, Reproducible Example provided by the OP, and compile it, and then look at the intermediate file produced by the IDE (not the compiler) you can see what is happening:

#include <Arduino.h>
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
uint8_t somefunction();
#line 18 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
void systemDataVerify(Sunstates *p);
#line 22 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
void setup();
#line 26 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
void loop();
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
uint8_t somefunction() {
  return;
}

// define structure to hold/save setup and mode info

typedef struct ss_tag { uint16_t settingsSavedCount; uint8_t powerDownSaveFlag; // lets me know why we're being reset. } Sunstates;

Sunstates sunStates; // create an instance

// create a function to accept a pointer to // type Sunstates as an arg

void systemDataVerify(Sunstates *p) { return; }

void setup() { // put your setup code here, to run once: }

void loop() { // put your main code here, to run repeatedly: }

You will notice that the IDE "helpfully" produces function prototypes for your functions, and that the order in which it does that means that it puts the prototype for void systemDataVerify(Sunstates *p); before the typedef for the structure, leading to the error message.

The solution is simple. Put your own function prototype into your source, thus telling the IDE to not bother, like this:

uint8_t somefunction() {
  return;
}

// define structure to hold/save setup and mode info

typedef struct ss_tag { uint16_t settingsSavedCount; uint8_t powerDownSaveFlag; // lets me know why we're being reset. } Sunstates;

void systemDataVerify(Sunstates *p); // <<<<<< ---- function prototype

Sunstates sunStates; // create an instance

// create a function to accept a pointer to // type Sunstates as an arg

void systemDataVerify(Sunstates *p) { return; }

void setup() { // put your setup code here, to run once: }

void loop() { // put your main code here, to run repeatedly: }


Looks like a compiler bug to me. Perhaps that should be passed along to the compiler people.

It's not a bug in the compiler, arguably it is an idiosyncrasy of how the IDE works. No point in submitting bug reports to the compiler-writers. You could conceivably raise an issue on Github for the IDE complaining about the way they generate function prototypes.


For more information see my answer here. In it I mention:

The function prototype generation however can lead to obscure error messages if you are not careful.

Nick Gammon
  • 38,901
  • 13
  • 69
  • 125
0

Here I am 5 years after the OP with the same issue. I'm on Arduino IDE Version: 2.2.1 Date: 2023-08-31T14:35:44.802Z. And I'm using the Adafruit ATSAMD21 M0.

Note that my offending typedef is already in a .h file placing it after everything it needs and before any use so that fix doesn't work for me.

I've discovered what does work around this issue:

Changing this:
int storeXXX( framBlock *fb ) {

To this:
int storeXXX( struct _framBlock *fb ) {

That is, use the 'real' type for function arguments. The typedef appears to be Ok everywhere else, locals, globals, before and after the point of the error report, etc. Just not as a function argument.

Note that the OP found a similar solution in using void * as the type of his typedef'd pointer. I saw no mention of using the 'real' type which is a more straight forward fix.

Looks like a compiler bug to me. Perhaps that should be passed along to the compiler people.

alm
  • 9
  • 2