Preprocessor error

I have the source code

  6 #include <Servo.h> 
  7
  8 void test() { delay(500); }
  9 #if 0
10 class mover {
11   public:
12      int H;
13 [glow=yellow,2,300]     int V;[/glow]
14      mover() { H = 0; V = 0; }
15 }; // class mover
16 #endif

with the error message

sketch_oct09a:13: error: 'mover' was not declared in this scope

Given that this code is preceded by an #if 0 and the terminating #endif has not yet been seen, how is it possible to get an error message on line 13? The reason for line 8 is that subsequently it thinks that delay(), random(), etc. are not defined.

I am using 1.5.6-r2

The reason I temporarily deleted this code was the fact that I was getting another spurious error message

sketch_oct09a:13: error: variable or field 'Move' declared void
sketch_oct09a:13: error: 'mover' was not declared in this scope
sketch_oct09a:13: error: 'M' was not declared in this scope
sketch_oct09a:13: error: expected primary-expression before 'int'
sketch_oct09a:13: error: expected primary-expression before 'int'

from the declaration, on line 116:

116 void Move(mover & M, int H, int V)
117 {
118  if(M.H != H)

Note that there are no references to line 116 in the error messages; they all reference line 13, which is in the middle of the declaration of the class mover.

If I change the name of the function 'Move' to something random, like 'MoveZ', then the same messages occur, except they are complaining about MoveZ (so it is not a case where Move was a name that had some other definition).

Prior to adding the class definition and the Move function, this sketch compiled and ran perfectly. I was "growing it" from the original Servo Sweep example to something relevant to my project, which requires two-axis control. At the moment, the Move function moves the H servo, and then moves the V servo; the plan is to move H and V servos "concurrently", by choosing the steps required to get the two motors to move during each iteration, e.g., at an appropriate iteration of the loop, move servo H by 1, and at another iteration, perhaps the same one in which H was moved, move servo V by 1, continue until each has moved the chosen amount. This requires more sophisticated computations (such as according to some modular counting, so that at the end of the loop, V and H have moved the requisite amount. This was more than I needed to tackle right now, so I abstracted the moving to a separate function so I could rewrite its guts later). So I added the state object 'mover' and the function 'Move' and the world fell apart.

What I don't understand is how code within an #if 0 can possibly be seen by the compiler.

The current Move function traverses H from M.H to H, sets M.H to H, then traverses V from M.V to V, and sets M.V to V. Thus it will always move the platform at two right angles (H and V are the horizontal and vertical axes), whereas what I really want to get is a "smooth" panning motion in both axes. Or more like a DDE computation for a line drawn at an angle on a discrete pixel-based display. There will be quantization of the movement, not pure, smooth approximations, but my application does not require "smooth" motion. Just the illusion of smooth motion. For example, imagine a motion-capturing camera that only captures a frame after each iteration. That's not the problem domain, either, but is intended to convey that I understand the 1-degree quantization issue.

Note also that I have been using C++ for a couple decades, so I have some idea what to expect of a compiler. The behavior I am seeing is not only unexpected, it is nonsensical.
joe

The behavior I am seeing is not only unexpected, it is nonsensical.

Based on the snippets, I'd agree. Not that the compiler is nonsensical, but that your expectation that we can help is.

Perhaps seeing the full code, and being able to look at the cpp file that the compiler actually sees, there is a rational explanation.

I have noticed that when you define a class within your code, then later, misuse one of it's members, the IDE has a tendancy to put the cursor in the wrong place for your error.

Instead of showing you where you misused the class member, it implies that the class definition is wrong. It's definitely a bug. I've seen it lots of times.

Here's an example.

This defines a class someClass. It then attempts to create a function with the return type of someClass.

The error is in the function someClass returnAsomeClass() but the IDE will show the error to be within the class definition.

Remove the function and it compiles OK

class someClass
  {public:
   int number;
   someClass(int v1,int v2){};  
  };
  
void setup()
{
someClass thing(1,2);
}

void loop()
{
}

//delete the following function and it compiles
someClass returnsomeClass()
{ 
}

The error is in the function thing returnAthingClass() but the IDE will show the error to be within the class definition.

thing is an instance. It is not a type. That example makes as much sense as trying to use fredFlinstone as the return type.

PaulS:

The error is in the function thing returnAthingClass() but the IDE will show the error to be within the class definition.

thing is an instance. It is not a type. That example makes as much sense as trying to use fredFlinstone as the return type.

Yep Ironically even that throws the error at the class definition. I've since edited my post to show what I really meant to say.

Try to compile this and it will imply that there's a problem with the class definition

class someClass
  {public:
   int number;
   someClass(int v1,int v2){};  
  };
  
void setup()
{
someClass thing(1,2);
}

void loop()
{
}

//delete the following function and it compiles
someClass* returnAsomeClass()
{ 
}

That is exactly why I would never embed the class definition in the script. Put it in a header file where ti belongs. Put the implementation in a source file, not in the declaration file. Include the header file in the source file and in the sketch, and none of the problems being discussed here would happen.

PaulS:
That is exactly why I would never embed the class definition in the script. Put it in a header file where ti belongs. Put the implementation in a source file, not in the declaration file. Include the header file in the source file and in the sketch, and none of the problems being discussed here would happen.

But it's a bug. There's nothing syntactically wrong with having it in the main sketch. So if the error is found by the compiler, it should report the appropriate line.

flounder:
I have the source code

  6 #include <Servo.h> 

7
 8 void test() { delay(500); }
 9 #if 0
10 class mover {
11   public:
12      int H;
13 [glow=yellow,2,300]     int V;[/glow]
14      mover() { H = 0; V = 0; }
15 }; // class mover
16 #endif




with the error message

sketch_oct09a:13: error: 'mover' was not declared in this scope

I have the sketch:

#include <Servo.h> 
void test() { delay(500); }
#if 0
 class mover {
   public:
      int H;
      int V;
      mover() { H = 0; V = 0; }
 }; // class mover
 #endif
 
 void setup () {}
 void loop () {}

It compiles without errors.

http://snippets-r-us.com/

But it's a bug. There's nothing syntactically wrong with having it in the main sketch. So if the error is found by the compiler, it should report the appropriate line.

Have you looked at the cpp file that the compiler actually sees? Where is the bug? Is it in the dumb stuff the IDE does to create the .cpp file? That would be my guess.

Is it in the preprocessor's handling of the cpp file? Hardly seems likely.

Is it in the compiler? Again, hardly seems likely.

PaulS:

But it's a bug. There's nothing syntactically wrong with having it in the main sketch. So if the error is found by the compiler, it should report the appropriate line.

Have you looked at the cpp file that the compiler actually sees? Where is the bug? Is it in the dumb stuff the IDE does to create the .cpp file? That would be my guess.

Is it in the preprocessor's handling of the cpp file? Hardly seems likely.

Is it in the compiler? Again, hardly seems likely.

Well it's not in the class definition. Somewhere in the IDE. Wether it be the GUI the parser or whatever. The error should not come back to that syntactically correct class definition. IT'S A BUG.

This sort of thing has been reported :

@OP: I suggest you put whatever-it-is that you are doing into a .cpp file inside your project. That is not affected by this preprocessing nonsense.

Or, a .h file.

The Arduino IDE tries to "help" you. It fails from time to time.

Nick
I think this is another issue. If I define a class then it should be quite valid to have a pointer to that class. In the following example you'll find that it is quite OK to have a pointer to the class as a variable type BUT if you attempt to use it as a return type, it causes the problem.

class someClass
  {public:
   int number;
   someClass(int v1,int v2){};  
  };
  
void setup()
{
someClass thing(1,2);
//The compiler allows us to have this pointer to our class
someClass* thingPointer;
}

void loop()
{
}
//The compiler will not, however allow us to return a pointer to our class
someClass* thingFunction()
{
  
}

This is not just erroneously reporting where the error is, it is actually refusing to let us use valid code

I think this is another issue.

Which has very likely also been reported. It has certainly been discussed to death on the forum. And a few times on the developers list.

While you wait, you can either use a header file or add two lines to your sketch...

class someClass;
someClass* thingFunction();

class someClass
  {public:
   int number;
   someClass(int v1,int v2){};  
  };
  
void setup()
{
someClass thing(1,2);
//The compiler allows us to have this pointer to our class
someClass* thingPointer;
}

void loop()
{
}
//The compiler will not, however allow us to return a pointer to our class
someClass* thingFunction()
{
  
}

Or, modify the IDE to do a better job of creating function prototypes and submit a pull request.

Has it? you'll have to excuse us newbies for not having the benefit of that experience.

However, your advice for prototyping the class and function is really useful. So for that you get another Karma point :slight_smile:

KenF:
This is not just erroneously reporting where the error is, it is actually refusing to let us use valid code

The automatic generation of function prototypes, well-intentioned though it may be, can certainly have that effect.

So I suggest you add your voice to those suggesting they stop doing that.

Hmm. The way I see it, the IDE itself is open source. I've paid nothing for it and I've made no contribution towards its development. So to gripe about some of the less finished added features just seems ungrateful. After all, if we all prototype all of our functions (like we should do) this "bug" would never show it's head.

I'd rather offer a solution to a problem than just complain but i don't feel it's a big enough problem for me to go to that effort.

After all, if we all prototype all of our functions (like we should do) this "bug" would never show it's head.

Or if we separate the definition of the class, the implementation of the class, and the use of the class into separate files, like professional programmers...

PaulS:
Or if we separate the definition of the class, the implementation of the class, and the use of the class into separate files, like professional programmers...

Could be overkill to blink an LED though.

Could be overkill to blink an LED though.

But writing a class, creating an instance of the class, and writing functions that return pointers to instances of the class isn't?