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.

3
  • Please make a small sketch that shows the problem. It compiles when I try to make a small sketch.
    – Jot
    Commented Aug 16, 2018 at 3:35
  • Check the syntax of whatever precedes your function definition. This sounds like the compiler lost sync and isn't expecting a function definition to start here. As a test, can you define a different function here instead?
    – JRobert
    Commented Aug 16, 2018 at 12:37
  • Well I actually had a really complex function before it, and the project was already pretty huge. Thats why I created such a small sketch to isolate the problem, with the simplest function I could think of. there's nothing really before it. It was easy enough to eliminate all functions before my structure, but it does seem like a compiler bug at this point.
    – Randy
    Commented Aug 18, 2018 at 21:50

3 Answers 3

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.

8
  • Hmm.. well all I've ever used was the official Arduino 1.8.3 (though I've been dying to try that Eclipse plugin!). Well thanks! I'll try that .H file approach. But the fact it compiles for YOU at least tells me I'm not crazy, and that the code SHOULD be compiling. For now, I've found a work-around... I can just make my function take a void * , and then within the function body make a new pointer to that struct type, and finally cast the passed void pointer to initialize it. That seems to work.
    – Randy
    Commented Aug 16, 2018 at 6:09
  • I'm accepting this answer, even though I haven't upgraded my IDE yet, because putting the structure and typedef near the top of the file ( before any functions are declared, but after all other header files) solves the issue. Still, I've updated my post with a short sketch that illustrates the problem reliably, and I'd be interested in a confirmation that your 1.8.5 does compile it without error. Not that I don't trust compiler improvements, but my current project is complex enough that regressive testing is very time consuming, So I'd rather save that upgrade for a "rainy day" :-)
    – Randy
    Commented Aug 16, 2018 at 17:39
  • the attached sketch fails in IDE 1.8.5 too
    – Juraj
    Commented Aug 16, 2018 at 17:43
  • 1
    it is ino to cpp conversion problem. the coversion does, if I am not mistaken, the arduino-builder github.com/arduino/arduino-builder
    – Juraj
    Commented Aug 16, 2018 at 19:58
  • 2
    one of the things done by the builder is creating forward declaration of functions. my hypothesis is that your order of function, variable and typedef leads to wrong order of forward declarations
    – Juraj
    Commented Aug 16, 2018 at 20:17
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.

1
  • The dreaded automatic function prototype generator strikes again!
    – 6v6gt
    Commented Nov 16, 2023 at 6:34
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.

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.