mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #97 from geky/compiler-polyfill
Add useful attributes supported by supported compilers
commit
23d77e4423
|
@ -0,0 +1,134 @@
|
||||||
|
#include "toolchain.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char a;
|
||||||
|
int x;
|
||||||
|
} PACKED TestAttrPackedStruct;
|
||||||
|
|
||||||
|
int testPacked() {
|
||||||
|
int failed = 0;
|
||||||
|
|
||||||
|
if (sizeof(TestAttrPackedStruct) != sizeof(int) + sizeof(char)) {
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int testAlign() {
|
||||||
|
int failed = 0;
|
||||||
|
|
||||||
|
ALIGN(8) char a;
|
||||||
|
ALIGN(8) char b;
|
||||||
|
ALIGN(16) char c;
|
||||||
|
ALIGN(8) char d;
|
||||||
|
ALIGN(16) char e;
|
||||||
|
|
||||||
|
if(((uintptr_t)&a) & 0x7){
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if(((uintptr_t)&b) & 0x7){
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if(((uintptr_t)&c) & 0xf){
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if(((uintptr_t)&d) & 0x7){
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
if(((uintptr_t)&e) & 0xf){
|
||||||
|
failed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int testUnused1(UNUSED int arg) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testUnused() {
|
||||||
|
return testUnused1(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int testWeak1();
|
||||||
|
int testWeak2();
|
||||||
|
|
||||||
|
WEAK int testWeak1() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testWeak2() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testWeak() {
|
||||||
|
return testWeak1() | testWeak2();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PURE int testPure1() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testPure() {
|
||||||
|
return testPure1();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FORCEINLINE int testForceInline1() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testForceInline() {
|
||||||
|
return testForceInline1();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NORETURN int testNoReturn1() {
|
||||||
|
while (1) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
int testNoReturn() {
|
||||||
|
if (0) {
|
||||||
|
testNoReturn1();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int testUnreachable1(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNREACHABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testUnreachable() {
|
||||||
|
return testUnreachable1(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DEPRECATED("this message should not be displayed")
|
||||||
|
void testDeprecatedUnused();
|
||||||
|
void testDeprecatedUnused() { }
|
||||||
|
|
||||||
|
DEPRECATED("this message should be displayed")
|
||||||
|
int testDeprecatedUsed();
|
||||||
|
int testDeprecatedUsed() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int testDeprecated() {
|
||||||
|
return testDeprecatedUsed();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "toolchain.h"
|
||||||
|
#include "test_env.h"
|
||||||
|
#include "unity.h"
|
||||||
|
#include "utest.h"
|
||||||
|
|
||||||
|
using namespace utest::v1;
|
||||||
|
|
||||||
|
|
||||||
|
// Test functions declared as C functions to avoid issues with name mangling
|
||||||
|
extern "C" {
|
||||||
|
int testPacked();
|
||||||
|
int testAlign();
|
||||||
|
int testUnused();
|
||||||
|
int testWeak();
|
||||||
|
int testPure();
|
||||||
|
int testForceInline();
|
||||||
|
int testNoReturn();
|
||||||
|
int testUnreachable();
|
||||||
|
int testDeprecated();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Test wrapper and test cases for utest
|
||||||
|
template <int (*F)()>
|
||||||
|
void test_wrapper() {
|
||||||
|
TEST_ASSERT_UNLESS(F());
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t test_setup(const size_t number_of_cases) {
|
||||||
|
GREENTEA_SETUP(40, "default_auto");
|
||||||
|
return verbose_test_setup_handler(number_of_cases);
|
||||||
|
}
|
||||||
|
|
||||||
|
Case cases[] = {
|
||||||
|
Case("Testing PACKED attribute", test_wrapper<testPacked>),
|
||||||
|
Case("Testing ALIGN attribute", test_wrapper<testAlign>),
|
||||||
|
Case("Testing UNUSED attribute", test_wrapper<testUnused>),
|
||||||
|
Case("Testing WEAK attribute", test_wrapper<testWeak>),
|
||||||
|
Case("Testing PURE attribute", test_wrapper<testPure>),
|
||||||
|
Case("Testing FORCEINLINE attribute", test_wrapper<testForceInline>),
|
||||||
|
Case("Testing NORETURN attribute", test_wrapper<testNoReturn>),
|
||||||
|
Case("Testing UNREACHABLE attribute", test_wrapper<testUnreachable>),
|
||||||
|
Case("Testing DEPRECATED attribute", test_wrapper<testDeprecated>),
|
||||||
|
};
|
||||||
|
|
||||||
|
Specification specification(test_setup, cases);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return !Harness::run(specification);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "toolchain.h"
|
||||||
|
|
||||||
|
int testWeak1() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WEAK int testWeak2() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,214 @@
|
||||||
#ifndef MBED_TOOLCHAIN_H
|
#ifndef MBED_TOOLCHAIN_H
|
||||||
#define MBED_TOOLCHAIN_H
|
#define MBED_TOOLCHAIN_H
|
||||||
|
|
||||||
|
|
||||||
|
// Warning for unsupported compilers
|
||||||
|
#if !defined(__GNUC__) /* GCC */ \
|
||||||
|
&& !defined(__CC_ARM) /* ARMCC */ \
|
||||||
|
&& !defined(__clang__) /* LLVM/Clang */ \
|
||||||
|
&& !defined(__ICCARM__) /* IAR */
|
||||||
|
#warning "This compiler is not yet supported."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
|
||||||
|
/** PACKED
|
||||||
|
* Pack a structure, preventing any padding from being added between fields.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* typedef struct {
|
||||||
|
* char x;
|
||||||
|
* int y;
|
||||||
|
* } PACKED foo;
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef PACKED
|
||||||
|
#if defined(__ICCARM__)
|
||||||
|
#define PACKED __packed
|
||||||
|
#else
|
||||||
|
#define PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** ALIGN(N)
|
||||||
|
* Declare a variable to be aligned on an N-byte boundary.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* ALIGN(16) char a;
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef ALIGN
|
||||||
|
#if defined(__ICCARM__)
|
||||||
|
#define _ALIGN(N) _Pragma(#N)
|
||||||
|
#define ALIGN(N) _ALIGN(data_alignment=N)
|
||||||
|
#else
|
||||||
|
#define ALIGN(N) __attribute__((aligned(N)))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** UNUSED
|
||||||
|
* Declare a function argument to be unused, suppressing compiler warnings
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* void foo(UNUSED int arg) {
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef UNUSED
|
||||||
|
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||||
|
#define UNUSED __attribute__((__unused__))
|
||||||
|
#else
|
||||||
|
#define UNUSED
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** WEAK
|
||||||
|
* Mark a function as being weak.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* weak functions are not friendly to making code re-usable, as they can only
|
||||||
|
* be overridden once (and if they are multiply overridden the linker will emit
|
||||||
|
* no warning). You should not normally use weak symbols as part of the API to
|
||||||
|
* re-usable modules.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* WEAK void foo() {
|
||||||
|
* // a weak implementation of foo that can be overriden by a definition
|
||||||
|
* // without __weak
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef WEAK
|
||||||
|
#if defined(__ICCARM__)
|
||||||
|
#define WEAK __weak
|
||||||
|
#else
|
||||||
|
#define WEAK __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** PURE
|
||||||
|
* Hint to the compiler that a function depends only on parameters
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* PURE int foo(int arg){
|
||||||
|
* // no access to global variables
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef PURE
|
||||||
|
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||||
|
#define PURE __attribute__((const))
|
||||||
|
#else
|
||||||
|
#define PURE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** FORCEINLINE
|
||||||
|
* Declare a function that must always be inlined. Failure to inline
|
||||||
|
* such a function will result in an error.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* FORCEINLINE void foo() {
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef FORCEINLINE
|
||||||
|
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||||
|
#define FORCEINLINE static inline __attribute__((always_inline))
|
||||||
|
#elif defined(__ICCARM__)
|
||||||
|
#define FORCEINLINE _Pragma("inline=force") static
|
||||||
|
#else
|
||||||
|
#define FORCEINLINE static inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** NORETURN
|
||||||
|
* Declare a function that will never return.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* NORETURN void foo() {
|
||||||
|
* // must never return
|
||||||
|
* while (1) {}
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef NORETURN
|
||||||
|
#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM)
|
||||||
|
#define NORETURN __attribute__((noreturn))
|
||||||
|
#elif defined(__ICCARM__)
|
||||||
|
#define NORETURN __noreturn
|
||||||
|
#else
|
||||||
|
#define NORETURN
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** UNREACHABLE
|
||||||
|
* An unreachable statement. If the statement is reached,
|
||||||
|
* behaviour is undefined. Useful in situations where the compiler
|
||||||
|
* cannot deduce the unreachability of code.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* void foo(int arg) {
|
||||||
|
* switch (arg) {
|
||||||
|
* case 1: return 1;
|
||||||
|
* case 2: return 2;
|
||||||
|
* ...
|
||||||
|
* }
|
||||||
|
* UNREACHABLE;
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef UNREACHABLE
|
||||||
|
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__CC_ARM)
|
||||||
|
#define UNREACHABLE __builtin_unreachable()
|
||||||
|
#else
|
||||||
|
#define UNREACHABLE while (1)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** DEPRECATED("message string")
|
||||||
|
* Mark a function declaration as deprecated, if it used then a warning will be
|
||||||
|
* issued by the compiler possibly including the provided message. Note that not
|
||||||
|
* all compilers are able to display the message.
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* #include "toolchain.h"
|
||||||
|
*
|
||||||
|
* DEPRECATED("don't foo any more, bar instead")
|
||||||
|
* void foo(int arg);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
#ifndef DEPRECATED
|
||||||
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define DEPRECATED(M) __attribute__((deprecated(M)))
|
||||||
|
#elif defined(__CC_ARM)
|
||||||
|
#define DEPRECATED(M) __attribute__((deprecated))
|
||||||
|
#else
|
||||||
|
#define DEPRECATED(M)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// FILEHANDLE declaration
|
||||||
#if defined(TOOLCHAIN_ARM)
|
#if defined(TOOLCHAIN_ARM)
|
||||||
#include <rt_sys.h>
|
#include <rt_sys.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,16 +232,10 @@
|
||||||
typedef int FILEHANDLE;
|
typedef int FILEHANDLE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Backwards compatibility
|
||||||
#ifndef EXTERN
|
#ifndef EXTERN
|
||||||
#define EXTERN extern
|
#define EXTERN extern
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (__ICCARM__)
|
|
||||||
# define WEAK __weak
|
|
||||||
# define PACKED __packed
|
|
||||||
#else
|
|
||||||
# define WEAK __attribute__((weak))
|
|
||||||
# define PACKED __attribute__((packed))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue