我一直在尝试更改一些语法,强制用户在访问之前在我编写的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
答案 0 :(得分:1)
不是真正的答案&#34;,但写入评论的文字太多了。我在g ++ 4.8.2 for x86-64中看到了同样的问题(从源代码开始,在结束时或3月初/ 4月初)。
似乎编译器正在拾取您的通用模板,而不是专用模板。
template<uint8_t nPin, PinMode mode>
class Pin
{
};
确实没有set
成员。如果我在该类中添加set
成员,则代码将编译。我不确定为什么编译器认为使用它比专门的类更好。我怀疑它是4.8.2中的一个错误。
(我注意到你的g ++ 4.8.2 for x86-64是&#34;预发布&#34;,这可以解释为什么它在两种体系结构上有所不同)。
它在clang ++ 3.5(截至昨天的不稳定分支)和g ++ 4.6.3中编译。它不能用clang ++ 2.9编译。
答案 1 :(得分:1)
您的代码中存在两个问题。
不确定原因,但在模板中使用枚举类不能正常工作。由于它是模板和新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();
}