compiler error that depends upon the location of a typedef...

Greetings,

And thanks in advance!

I'm running into an compiler error that appears to be caused by the location of a typedef within a sketch file. The compiler error is reported as "was not declared in this scope". I've created a repository on github at arduino-odd-behavior-demo-01 with details, but here is a quick overview -

void setup() {
}

void loop() {
}

typedef struct {
   const char* name;
   int time;
   float value;
} SensorData;

/* no error on the next line, why? */
SensorData sdata;

/* the "SensorData was not declared in this scope" error occurs here */
bool testfunc(SensorData &_data) {

}

I'd like to understand why it's occurring, and if it is actually an issue within the compiler.

Thanks!
jim

Move the typedef to the top of the file,
the effect is caused by the automatic prototype generation of the IDE. IMHO

I do realize that “fixes” it, but it’s not conducive to how I want to organize the original project file. If that’s expected behavior of this compiler are there any alternatives to it? Because IMHO this seems to be more of an error in how the preprocessor is working.

It is expected behaviour of the IDE to include prototypes not specified by the user,
it is designed to be used by unexperienced persons.

Add your own prototypes and the you will see the need to have the typedef
(or at least a forward declaration of it) above that point.

Put the typedef in an include file.

What is your problem really?

are there any alternatives to it?

Move all the typedefs to a separate .h file…
Or you can move most of your code, including the typedefs, to a .cpp file instead of a .ino file (and use your own function prototypes, where needed.)

IMHO this seems to be more of an error in how the preprocessor is working.

Yeah, probably. The automatic prototype generation is hard to get right. If moving the typdef to the start of the file helps, then it’s gotten a lot better than it used to be. (The extra .h file pretty much used to be the only solution.)

If you turn on verbose compilation in Preferences and then examine the output in the black console window at the bottom of the Arduino IDE window after compilation, you will find the location of the temporary build folder. The sketch subfolder of the temporary build folder contains the .cpp file that was generated from your sketch after the preprocessor had its way with it:

#include <Arduino.h>
#line 1 "C:\\Users\\per\\Desktop\\arduino-odd-behavior-demo-01-master\\typedefstruct_fail\\typedefstruct_fail.ino"
#line 1 "C:\\Users\\per\\Desktop\\arduino-odd-behavior-demo-01-master\\typedefstruct_fail\\typedefstruct_fail.ino"

#line 2 "C:\\Users\\per\\Desktop\\arduino-odd-behavior-demo-01-master\\typedefstruct_fail\\typedefstruct_fail.ino"
void setup();
#line 5 "C:\\Users\\per\\Desktop\\arduino-odd-behavior-demo-01-master\\typedefstruct_fail\\typedefstruct_fail.ino"
void loop();
#line 17 "C:\\Users\\per\\Desktop\\arduino-odd-behavior-demo-01-master\\typedefstruct_fail\\typedefstruct_fail.ino"
bool testfunc(SensorData &_data);
#line 2 "C:\\Users\\per\\Desktop\\arduino-odd-behavior-demo-01-master\\typedefstruct_fail\\typedefstruct_fail.ino"
void setup() {
}

void loop() {
}

typedef struct {
   const char* name;
   int time;
   float value;
} SensorData;

/* no error on the next line, why? */
SensorData sdata;

bool testfunc(SensorData &_data) {

}

You can see the cause of the error and also that the #line directive causes the error message to reference line 17.

As you suspected, this is not a problem with the compiler, it’s the sketch preprocessor. They did a big rewrite of it when they moved preprocessing to a tool separate from the IDE named arduino-builder that was released with Arduino IDE 1.6.6 and then slowly improved over time to where it’s now better than the old system but still fails in some cases. The word is they are now going to rework it again (Google Groups) but from what I can see it’s been slow going:
https://github.com/arduino/arduino-preprocessor
So I don’t know what this means for arduino-builder. I’m not sure if it’s worth reporting issues such as this since it’s possible they are already fixed in arduino-preprocessor. I also think it’s likely that the preprocessor will never be smart enough to always get prototype generation right and there’s a certain point where you have to say “good enough”. Where that point is, only the Arduino developers or management can say. If you like, you could submit an error report to the arduino-builder repository but please spend some time searching through the issues and pull requests first to make sure it hasn’t already been reported:
https://github.com/arduino/arduino-builder/issues?q=

An alternative fix: Put in your own function prototype, after the type declaration and before the function declaration. That will prevent the IDE from generating a prototype for you.

bool testfunc(SensorData &_data);
bool testfunc(SensorData &_data) {

}

It's not beautiful but it allows you to keep the typedef and function declaration where they are.

@pert Thank you for the excellent explanation of what's going on and how to see it. That has given me a much better understanding of what's going on. In fact, that knowledge will most likely help me track down the cause and a subsequent fix a different problem I was having with some classes I was working on in another project. After reading your explanation of the preprocessor I think it's related.

I will certainly search the issues and pulls before creating a new one. But I don't think that it will be necessary to post a new one even if not found in either place. From what I've learned here I've got a much better understanding of how to avoid this in the future, and to recognize similar issues.

And a big thanks to everyone else who replied in this thread, you've been helpful! I'll update my repo with a link to this thread and quick description of the cause and fix.

regards,
j

jxmot:
I do realize that "fixes" it, but it's not conducive to how I want to organize the original project file. If that's expected behavior of this compiler are there any alternatives to it? Because IMHO this seems to be more of an error in how the preprocessor is working.

How you want to lay out your file and how the compiler wants the code to be laid out are two different things. And the compiler is the boss :slight_smile:

Try to compile your code for a PC (e.g. using Visual Studio or gcc/g++) and call your testFunc from e.g. setup() or main(). It will give you a very hard time 8)

By the way, it's Arduino's (incomplete) attempt to make it beginner friendly that causes the error (as explained by pert); it's not the compiler.