Compiler warning with structs

Please find below two samples of code which show a problem I am having in my project. Please can someone advise what is wrong with the 'bad' one.

Cheers Alan

One version compiles without issues and the other returns an error. The change I have made is the order of function and struct.

Here is the good code:

struct Y {};
struct X {};

void vY(Y * py) {}
void vX(X * px) {}

void setup() {}
void loop() {}

And here is the other one.

struct Y {};
void vY(Y * py) {}

struct X {};
void vX(X * px) {}

void setup() {}
void loop() {}

And here is the error report from the IDE

sketch_jun18a:3:9: error: variable or field 'vX' declared void

 void vX(X * px) {}

         ^

sketch_jun18a:3:9: error: 'X' was not declared in this scope

sketch_jun18a:3:13: error: 'px' was not declared in this scope

 void vX(X * px) {}

             ^~

sketch_jun18a:3:9: error: variable or field 'vX' declared void

 void vX(X * px) {}

         ^

sketch_jun18a:3:9: error: 'X' was not declared in this scope

sketch_jun18a:3:13: error: 'px' was not declared in this scope

 void vX(X * px) {}

             ^~

exit status 1
variable or field 'vX' declared void

if I add a main() to it it compiles w/o error using gcc on may laptop.

wonder if it's due to the translation of the .ino to a .cpp file

The Arduino IDE automatically adds function prototypes. The code that gets passed to the compiler is:

#include <Arduino.h>
#line 1 "/home/pieter/Arduino/sketch_jun18a/sketch_jun18a.ino"
#line 1 "/home/pieter/Arduino/sketch_jun18a/sketch_jun18a.ino"

struct Y {};
#line 3 "/home/pieter/Arduino/sketch_jun18a/sketch_jun18a.ino"
void vY(Y * py);
#line 6 "/home/pieter/Arduino/sketch_jun18a/sketch_jun18a.ino"
void vX(X * px);
#line 8 "/home/pieter/Arduino/sketch_jun18a/sketch_jun18a.ino"
void setup();
#line 9 "/home/pieter/Arduino/sketch_jun18a/sketch_jun18a.ino"
void loop();
#line 3 "/home/pieter/Arduino/sketch_jun18a/sketch_jun18a.ino"
void vY(Y * py) {}

struct X {};
void vX(X * px) {}

void setup() {}
void loop() {}

As you can see, it moved the prototype for the vX function before the definition of the struct X. You can add your own prototypes for the function to prevent the Arduino preprocessor from messing it up, or you can move your structs and/or functions to a separate pair of .hpp/.cpp files, since the Arduino builder only adds prototypes in .ino files.

Pieter

Well that explains why we have an error message but...

... it doesn't explain why struct Y gets put/left at the top, where it's good but then leaves struct X hanging about further down the code where it causes a problem.

I added a struct Z below structs Y and X and it also generates the same error. So why is the first struct okay?

Is this a bug in the IDE tool chain?

I don't think it's moving the structs. So they aren't getting "left hanging about" anywhere.

Prior to the first function it's auto inserting all the function protoypes for all the other functions in the sketch.

Problem comes when those prototypes reference structs which haven't been declared yet.

I guess it is a bug. The IDE assumes either...
a) You define all your structs before your functions (not required, but quite a common coding pattern).
b) You supply your own function prototypes. Which by definition must come after any struct definitions they reference.

Another way to work around it:

struct Y {};
void vY(Y * py) {}


struct X {};
void vX(struct X * px) {} ////// ADDED THE 'struct' KEYWORD


void setup() {}
void loop() {}

The automatically generated prototype doesn't need the declaration of 'X' if it knows that 'X' is a 'struct'.

johnwasser:
Another way to work around it:

struct Y {};

void vY(Y * py) {}

struct X {};
void vX(struct X * px) {} ////// ADDED THE 'struct' KEYWORD

void setup() {}
void loop() {}



The automatically generated prototype doesn't need the declaration of 'X' if it knows that 'X' is a 'struct'.

Gosh! What a game. I assume they modified the way pre-processing happens, compared with a traditional tool chain, to make it easy for the majority to do the majority of things but hey ho, I've been caught out a couple of times by things like this... not to worry its all fun.

Just work like you're in a regular C++ environment rather than the Arduino IDE. ALWAYS add your own prototypes and you'll ALWAYS know what you have.

I work mostly in Eclipse / Sloeber where it's required to do exactly that.

acboother:
Gosh! What a game. I assume they modified the way pre-processing happens, compared with a traditional tool chain, to make it easy for the majority to do the majority of things but hey ho, I've been caught out a couple of times by things like this... not to worry its all fun.

Yes, it's intended to make C++ programming easier for non-programmers. They try to make it so you don't have to declare functions before you use them (by inserting prototypes at the top) and so you don't have to list all of the libraries you want the linker to link with (by recognizing "#include" lines as probable references to libraries) and so you don't have to learn how to do external references (by merging all your .ino files into a single file).