代码使用g++编译,但不使用arm-none-eabi-g++

Code compiles with g++ but not with arm-none-eabi-g++

本文关键字:arm-none-eabi-g++ 编译 g++ 代码      更新时间:2023-10-16

我一直在尝试更改一些语法,以强制用户在访问我编写的STM32F4 Cortex-M4 CPU的简单库之前启用外围时钟。

在与以下代码斗争了几个小时后,我找不到我做错了什么,并试图用linux g++编译它,它成功了。

这是关于ARM g++的编译器错误吗?还是我一直在使用linux g++以前允许我使用的一些非标准行为?

下面是一个简化的代码示例:

#include <cstdint>
template<std::size_t port>
class Port
{
public: //Declarations
  enum class PinMode
  {
    Input = 0x0,
    Output = 0x1,
    Alternate = 0x2,
    Analog = 0x3
  };
  template<uint8_t nPin, PinMode mode>
  class Pin
  {
  };
  template<uint8_t nPin>
  class Pin<nPin, PinMode::Output>
  {
  public: //Declarations
    enum class OutputSpeed : uint32_t
    {
      Low,
      Medium,
      Fast,
      High
    };
    enum class PullMode : uint32_t
    {
      None = 0x0,
      PullUp = 0x1,
      PullDown = 0x2
    };
  public: //Methods
    void setOutputSpeed(OutputSpeed const ospeed) volatile;
    void setPullMode(PullMode const ppm) volatile;
    void set() volatile
    {
      reinterpret_cast<Port<port> volatile*>(port)->m_BSRR |= static_cast<uint16_t>(0x1) <<nPin;
    }
    void reset() volatile;
    bool getOutputState() volatile;
  }; //END OutputPin
public: //Registers
  uint32_t m_BSRR;
}; //END Port
int main()
{
  auto pin = Port<0>::Pin<5, Port<0>::PinMode::Output>();
  pin.set();
}

ARM g++输出。

Using built-in specs.
COLLECT_GCC=arm-none-eabi-g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-none-eabi/4.8.2/lto-wrapper
Target: arm-none-eabi
Configured with: ../configure --target=arm-none-eabi --prefix=/usr --libexecdir=/usr/lib --with-pkgversion='Arch Repository' --with-bugurl=https://bugs.archlinux.org/ --enable-multilib --enable-interwork --enable-languages=c,c++ --with-newlib --with-gnu-as --with-gnu-ld --disable-nls --disable-shared --disable-threads --with-headers=newlib/libc/include --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-libgomp --with-system-zlib --disable-newlib-supplied-syscalls
Thread model: single
gcc version 4.8.2 (Arch Repository) 
COLLECT_GCC_OPTIONS='-std=c++11' '-v'
 /usr/lib/gcc/arm-none-eabi/4.8.2/cc1plus -quiet -v -D__USES_INITFINI__ test.cpp -quiet -dumpbase test.cpp -auxbase test -std=c++11 -version -o /tmp/cc6TlpeV.s
GNU C++ (Arch Repository) version 4.8.2 (arm-none-eabi)
    compiled by GNU C version 4.8.2 20140206 (prerelease), GMP version 5.1.3, MPFR version 3.1.2-p5, MPC version 1.0.2
warning: GMP header version 5.1.3 differs from library version 6.0.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/lib/gcc/arm-none-eabi/4.8.2/../../../../arm-none-eabi/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/arm-none-eabi/4.8.2/../../../../arm-none-eabi/include/c++/4.8.2
 /usr/lib/gcc/arm-none-eabi/4.8.2/../../../../arm-none-eabi/include/c++/4.8.2/arm-none-eabi
 /usr/lib/gcc/arm-none-eabi/4.8.2/../../../../arm-none-eabi/include/c++/4.8.2/backward
 /usr/lib/gcc/arm-none-eabi/4.8.2/include
 /usr/lib/gcc/arm-none-eabi/4.8.2/include-fixed
 /usr/lib/gcc/arm-none-eabi/4.8.2/../../../../arm-none-eabi/include
End of search list.
GNU C++ (Arch Repository) version 4.8.2 (arm-none-eabi)
    compiled by GNU C version 4.8.2 20140206 (prerelease), GMP version 5.1.3, MPFR version 3.1.2-p5, MPC version 1.0.2
warning: GMP header version 5.1.3 differs from library version 6.0.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 8ead046d6b54a8fe43e9a23d5562e5d4
test.cpp: In function 'int main()':
test.cpp:60:7: error: 'class Port<0u>::Pin<5u, (Port<0u>::PinMode)1>' has no member named 'set'
   pin.set();
       ^

G++输出:

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /build/gcc/src/gcc-4.8-20140206/configure --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared --enable-threads=posix --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object --enable-linker-build-id --enable-cloog-backend=isl --disable-cloog-version-check --enable-lto --enable-plugin --enable-install-libiberty --with-linker-hash-style=gnu --disable-multilib --disable-werror --enable-checking=release
Thread model: posix
gcc version 4.8.2 20140206 (prerelease) (GCC) 
COLLECT_GCC_OPTIONS='-std=c++11' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/cc1plus -quiet -v -D_GNU_SOURCE test.cpp -quiet -dumpbase test.cpp -mtune=generic -march=x86-64 -auxbase test -std=c++11 -version -o /tmp/ccgCeLLA.s
GNU C++ (GCC) version 4.8.2 20140206 (prerelease) (x86_64-unknown-linux-gnu)
    compiled by GNU C version 4.8.2 20140206 (prerelease), GMP version 5.1.3, MPFR version 3.1.2-p5, MPC version 1.0.2
warning: GMP header version 5.1.3 differs from library version 6.0.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../x86_64-unknown-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../include/c++/4.8.2
 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../include/c++/4.8.2/x86_64-unknown-linux-gnu
 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../include/c++/4.8.2/backward
 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/include
 /usr/local/include
 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/include-fixed
 /usr/include
End of search list.
GNU C++ (GCC) version 4.8.2 20140206 (prerelease) (x86_64-unknown-linux-gnu)
    compiled by GNU C version 4.8.2 20140206 (prerelease), GMP version 5.1.3, MPFR version 3.1.2-p5, MPC version 1.0.2
warning: GMP header version 5.1.3 differs from library version 6.0.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 51ac5eb9b6c30af2da1950e6dfed6398
COLLECT_GCC_OPTIONS='-std=c++11' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 as -v --64 -o /tmp/ccWIQqrr.o /tmp/ccgCeLLA.s
GNU assembler version 2.24 (x86_64-unknown-linux-gnu) using BFD version (GNU Binutils) 2.24
COMPILER_PATH=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/:/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/:/usr/lib/gcc/x86_64-unknown-linux-gnu/:/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/:/usr/lib/gcc/x86_64-unknown-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/:/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-std=c++11' '-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/collect2 --build-id --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crt1.o /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crti.o /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/crtbegin.o -L/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2 -L/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../.. /tmp/ccWIQqrr.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/crtend.o /usr/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/../../../../lib/crtn.o

您的代码中有两个问题。

不知道为什么,但是在模板中有enum类不能正常工作。由于这是模板和新的c++功能的一个角落,很难在标准中找到禁止它的确切位置。甚至可能是编译器错误。

所以,固定代码看起来像:

#include <cstdint>
  enum class PinMode
  {
    Input = 0x0,
    Output = 0x1,
    Alternate = 0x2,
    Analog = 0x3
  };
    enum class OutputSpeed : uint32_t
    {
      Low,
      Medium,
      Fast,
      High
    };
    enum class PullMode : uint32_t
    {
      None = 0x0,
      PullUp = 0x1,
      PullDown = 0x2
    };
template<std::size_t port>
class Port
{
public: //Declarations

  template<uint8_t nPin, PinMode mode>
  class Pin;
  template<uint8_t nPin>
  class Pin<nPin, PinMode::Output>
  {
  public: //Methods
    void setOutputSpeed(OutputSpeed const ospeed) volatile;
    void setPullMode(PullMode const ppm) volatile;
    void set() volatile
    {
      reinterpret_cast<Port<port> volatile*>(port)->m_BSRR |= static_cast<uint16_t>(0x1) <<nPin;
    }
    void reset() volatile;
    bool getOutputState() volatile;
  }; //END OutputPin
public: //Registers
  uint32_t m_BSRR;
}; //END Port
int main()
{
    auto pin = Port<0>::Pin< 5, PinMode::Output >();
  pin.set();
}

不是真正的"答案",而是太多的文本无法写入评论。我在x86-64的g++4.8.2中看到了同样的问题(大约在3月底或4月初从源代码构建的住宅)。

编译器似乎是在使用通用模板,而不是专用模板。

  template<uint8_t nPin, PinMode mode>
  class Pin
  {
  };

其实际上没有CCD_ 1成员。如果我在该类中添加一个set成员,代码就会编译。我不知道为什么编译器认为使用这个类比使用专用类更好。我怀疑这是4.8.2中的一个错误。

(我确实注意到x86-64的g++4.8.2是一个"预发行版",这可以解释为什么它在两种体系结构上不同)。

它在clang++3.5(截至昨天的不稳定分支)和g++4.6.3中编译。它不使用clang++2.9进行编译。