From 018e2571e6ee53b67e51f27435ead91decefd394 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 16 May 2016 18:39:17 -0500 Subject: [PATCH] Added other attributes on supported compilers tested on GCC, Clang, online compiler, and IAR attributes - PACK - ALIGN - UNUSED - WEAK - PURE - FORCEINLINE - NORETURN - UNREACHABLE - DEPRECATED --- hal/TESTS/api/toolchain/attributes.c | 109 ++++++++++++++++++++----- hal/TESTS/api/toolchain/main.cpp | 20 +++-- hal/api/toolchain.h | 117 +++++++++++++++++++++++++-- 3 files changed, 218 insertions(+), 28 deletions(-) diff --git a/hal/TESTS/api/toolchain/attributes.c b/hal/TESTS/api/toolchain/attributes.c index e235477744..196d968c1c 100644 --- a/hal/TESTS/api/toolchain/attributes.c +++ b/hal/TESTS/api/toolchain/attributes.c @@ -4,15 +4,44 @@ #include -struct TestAttrPackedStruct { +typedef struct { char a; int x; -} PACKED; +} PACKED TestAttrPackedStruct; int testPacked() { int failed = 0; - if (sizeof(struct TestAttrPackedStruct) != sizeof(int) + sizeof(char)) { + 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++; } @@ -29,21 +58,6 @@ int testUnused() { } -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(); -} - - int testWeak1(); int testWeak2(); @@ -59,3 +73,62 @@ 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(); +} + diff --git a/hal/TESTS/api/toolchain/main.cpp b/hal/TESTS/api/toolchain/main.cpp index 40ccacb3cd..4d64b2b2d4 100644 --- a/hal/TESTS/api/toolchain/main.cpp +++ b/hal/TESTS/api/toolchain/main.cpp @@ -12,9 +12,14 @@ 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 testDeprecated(); int testWeak(); + int testPure(); + int testForceInline(); + int testNoReturn(); + int testUnreachable(); + int testDeprecated(); } @@ -30,10 +35,15 @@ status_t test_setup(const size_t number_of_cases) { } Case cases[] = { - Case("Testing PACKED attribute", test_wrapper), - Case("Testing UNUSED attribute", test_wrapper), - Case("Testing DEPRECATED attribute", test_wrapper), - Case("Testing WEAK attribute", test_wrapper), + Case("Testing PACKED attribute", test_wrapper), + Case("Testing ALIGN attribute", test_wrapper), + Case("Testing UNUSED attribute", test_wrapper), + Case("Testing WEAK attribute", test_wrapper), + Case("Testing PURE attribute", test_wrapper), + Case("Testing FORCEINLINE attribute", test_wrapper), + Case("Testing NORETURN attribute", test_wrapper), + Case("Testing UNREACHABLE attribute", test_wrapper), + Case("Testing DEPRECATED attribute", test_wrapper), }; Specification specification(test_setup, cases); diff --git a/hal/api/toolchain.h b/hal/api/toolchain.h index b448fca102..b8756d206c 100644 --- a/hal/api/toolchain.h +++ b/hal/api/toolchain.h @@ -28,16 +28,16 @@ // Attributes -/** PACK +/** PACKED * Pack a structure, preventing any padding from being added between fields. * * @code * #include "toolchain.h" * - * struct foo { + * typedef struct { * char x; * int y; - * } PACKED; + * } PACKED foo; * @endcode */ #ifndef PACKED @@ -48,19 +48,37 @@ #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){ + * void foo(UNUSED int arg) { * * } * @endcode */ #ifndef UNUSED -#if defined(__GNUC__) || defined(__CC_ARM) || defined(__clang__) +#if defined(__GNUC__) || defined(__clang__) || defined(__CC_ARM) #define UNUSED __attribute__((__unused__)) #else #define UNUSED @@ -93,6 +111,95 @@ #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