Arduino: ERROR: expected unqualified-id before '(' token

Created on 19 Feb 2019  路  17Comments  路  Source: esp8266/Arduino

Basic Infos

  • [ ] This issue complies with the issue POLICY doc.
  • [ ] I have read the documentation at readthedocs and the issue is not addressed there.
  • [ ] I have tested that the issue is present in current master branch (aka latest git).
  • [ ] I have searched the issue tracker for a similar issue.
  • [ ] If there is a stack dump, I have decoded it.
  • [ ] I have filled out all fields below.

Platform

  • Hardware: Sparkfun ESP8266 Thing Dev
  • Core Version: 2.5.0
  • Development Env: Arduino IDE
  • Operating System: Windows

Settings in IDE

  • Module: Generic ESP8266 Module
  • Flash Mode: N/A
  • Flash Size: N/A
  • lwip Variant: N/A
  • Reset Method: N/A
  • Flash Frequency: N/A
  • CPU Frequency: N/A
  • Upload Using: N/A
  • Upload Speed: N/A

Problem Description

On building a sample piece of code for an ESP8266 Module I am unable to compile. The error I am seeing when running Verify in the Arduino IDE is:

Debug Messages

Arduino: 1.8.8 (Windows 10), Board: "Generic ESP8266 Module, 80 MHz, Flash, Disabled, ck, 26 MHz, 40MHz, DOUT (compatible), 512K (no SPIFFS), 2, v2 Lower Memory, Disabled, None, Only Sketch, 115200"

Build options changed, rebuilding all
In file included from C:\Users\yomaguir\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\ESP8266WiFi\src/WiFiClient.h:25:0,

                 from C:\Users\yomaguir\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\ESP8266WiFi\src/ESP8266WiFi.h:39,

                 from C:\Users\yomaguir\Documents\Arduino\libraries\AzureIoTUtility\src\adapters\sslClient_arduino.cpp:9:

c:\users\yomaguir\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\2.5.0-3-20ed2b9\xtensa-lx106-elf\include\c++\4.8.2\bits\random.tcc: In member function 'void std::poisson_distribution<_IntType>::param_type::_M_initialize()':

C:\Users\yomaguir\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\cores\esp8266/Arduino.h:137:22: error: expected unqualified-id before '(' token

 #define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

                      ^

c:\users\yomaguir\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\2.5.0-3-20ed2b9\xtensa-lx106-elf\include\c++\4.8.2\bits\random.tcc: In member function 'void std::binomial_distribution<_IntType>::param_type::_M_initialize()':

C:\Users\yomaguir\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\cores\esp8266/Arduino.h:137:22: error: expected unqualified-id before '(' token

 #define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

                      ^

C:\Users\yomaguir\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\cores\esp8266/Arduino.h:137:22: error: expected unqualified-id before '(' token

 #define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

                      ^

exit status 1
Error compiling for board Generic ESP8266 Module.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
waiting for feedback

Most helpful comment

I am curious why this macro error just started ocurring in v2.5.0. Did something in the Arduino.h library change from the previous version?

All 17 comments

The issue template requires a MCVE sketch to reproduce. Without that, it's unlikely this will be looked at.
Please provide a minimal sketch to reproduce the issue.

I encountered the same error after updating to 2.5.0

MCVE

Arduino IDE Version: 1.8.8
Board Manager: Adafruit Feather HUZZAH ESP8266 Version 2.5.0
Library: AzureIoTHub Version 1.0.45

#include <AzureIoTHub.h>

void setup()
{

}
void loop()
{
    delay(10);
}

It is a compilation issue.

MCVE

PlatformIO 3.6.4 | VSCode 1.31.1
Board: Wemos D1 Mini
Library: esp8266/Arduino 2.5.0

#include "Arduino.h"

void setup() {}

void loop() {}

Ok, so I found the underlying error in random.tcc (the file from our compilation errors).

This is the function that is responsible for the compilation error:

template<typename _IntType>
    void
    poisson_distribution<_IntType>::param_type::
    _M_initialize()
    {
#if _GLIBCXX_USE_C99_MATH_TR1
      if (_M_mean >= 12)
    {
      const double __m = std::floor(_M_mean);
      _M_lm_thr = std::log(_M_mean);
      _M_lfm = std::lgamma(__m + 1);
      _M_sm = std::sqrt(__m);

      const double __pi_4 = 0.7853981633974483096156608458198757L;
      const double __dx = std::sqrt(2 * __m * std::log(32 * __m
                                  / __pi_4));
      _M_d = std::round(std::max(6.0, std::min(__m, __dx)));
      const double __cx = 2 * __m + _M_d;
      _M_scx = std::sqrt(__cx / 2);
      _M_1cx = 1 / __cx;

      _M_c2b = std::sqrt(__pi_4 * __cx) * std::exp(_M_1cx);
      _M_cb = 2 * __cx * std::exp(-_M_d * _M_1cx * (1 + _M_d / 2))
        / _M_d;
    }
      else
#endif
    _M_lm_thr = std::exp(-_M_mean);
      }

"round" in std::round() gets replaced by the round macro in Arduino.h, thus rendering the syntax faulty and not compilable.

Temporary fix

Commenting out line 137 in Arduino.h fixes the problem and the code compiles as usual.

Yep. Seems like ESP8266 is trying to redefine round, but it's literally the same? Can the ESP8266 folks explain this block of code in the ESP8266 Arduino.h?

Vanilla Arduino.h:

#ifdef abs
#undef abs
#endif

#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))

ESP8266 Arduino.h:

#ifdef abs
#undef abs
#endif

#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
// #define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) // comment line added by me
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x)

ESP Arduino.h was just a forked copy of arduino.cc's Arduino.h as far as I understand it.

I personally think these macros are an awful construct, but it's a compatibility thing having those macros (esp. since ...round returns a float/double on most every system out there while this macro returns a long.

That said, it looks like both AVR arduino and esp8266 arduino match here. Do you have some other Arduino chip where this #define round(x) is not present in the header (i.e. one where you could build your sample successfully)?

Then we could say we're still Arduino compatible and remove these ugly bits.

Yep. Seems like ESP8266 is trying to redefine round, but it's literally the same?

This question would be asked to "vanilla" arduino folks.
We would like (at least I) to remove it but we can't (can we?), side effects are supposed to be unpredictable when it comes to compatibility with arduino.

There are three versions of round, the one in math.h, the one in libstdc++ (std::round()) and this define which breaks standard c++ code using std::round, this issue. If possible, one can put #undef round where std::round is needed (or libc's). That way core sources don't need to be modified.

The least we could do is

#define round(x)     ({ __typeof__(x) _x = (x); _x>=0?(long)(_x+0.5):(long)(_x-0.5); })

which is saner (same goes with the other macros) (because of only one evaluation of (x)).

The other way to avoid the issue in your code is to just add #undef round immediately before the offending include/source files.

I am curious why this macro error just started ocurring in v2.5.0. Did something in the Arduino.h library change from the previous version?

That said, it looks like both AVR arduino and esp8266 arduino match here. Do you have some other Arduino chip where this #define round(x) is not present in the header (i.e. one where you could build your sample successfully)?

it looks like in ESP32 they're overriding "vanilla" Arduino.h macros with those from std.

https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/Arduino.h

Also as someone with no knowledge really of the arduino board manager design, is there a reason for the fork of Arduino.h for ESP8266 except for when you want to redefine certain definitions?

I also have @KarateBrot's question. It looks like espressif had a PR for ESP32 recently to redefine their round and abs values, so perhaps there was a breaking change somewhere else that affected everyone.

The other way to avoid the issue in your code is to just add #undef round immediately before the offending include/source files.

I added #undef round in my ino file at start but still receiving this error. Commenting corresponding line in Arduino.h fixes problem.

To get past this i deleted the #define line in the ESP8266 library manually.

To get past this i deleted the #define line in the ESP8266 library manually.

I did delete #define round(x). My arduino works fine. but it does not connect iothub.

After reading through, it seems like this can be closed. The workaround breaks Arduino compatibility (which, in this case, I think is perfectly fine because the Arduino macro is a brain dead leftover from a time when they didn't have any FP in the AVR), so it can't be part of our core.

Actually, the code snippet shown requires the real double round(double) method to function properly. So, your change (or just adding #undef round after including Arduino.h is needed to make the Azure code work.

De-crufting Arduino.h is a bigger discussion and probably needs to be held in arduino.cc's repos so that every Arduino plug-in will follow through...

After reading through, it seems like this can be closed. The workaround breaks Arduino compatibility (which, in this case, I think is perfectly fine because the Arduino macro is a brain dead leftover from a time when they didn't have any FP in the AVR), so it can't be part of our core.

Actually, the code snippet shown _requires_ the real double round(double) method to function properly. So, your change (or just adding #undef round after including Arduino.h is needed to make the Azure code work.

De-crufting Arduino.h is a bigger discussion and probably needs to be held in arduino.cc's repos so that every Arduino plug-in will follow through...

What change? Trying/failing to compile adafruit ESP8266 azure sample code brought me here. What exactly is the necessary change? If commenting out the def breaks iothub, then how to not break it? Thanks.

What change? Trying/failing to compile adafruit ESP8266 azure sample code brought me here. What exactly is the necessary change? If commenting out the def breaks iothub, then how to not break it? Thanks.

A workaround for me was to comment (or delete) the round macro in arduino.h (#define round(x) ...) because it clashes with std::round of c++. Maybe you need to comment other macros but at least for me it was a problem with round.

Was this page helpful?
0 / 5 - 0 ratings