1

I'm looking for a creative solution for making sure that variables delivered to a specific macro are declared with type volatile in C language, with TMS470 compiler. meaning:

good method:

volatile int   *_p_reg;
VOLATILE_MACRO(_p_reg);

compilation failure:

int   *_p_reg;
VOLATILE_MACRO(_p_reg);

I wish to perform the verification after the compilation, meaning going over the disassembly or the debug information and identify those calls. I can't seem to find any evidence for the volatile in the debug info.

any ideas?

thanks!

gilboash
  • 135
  • 1
  • 10
  • I suspect that the only way you might achieve this is by generating an error at compile-time. Once the code is generated you've probably lost any information that might otherwise help you. – Paul R Jun 17 '14 at 14:13
  • 1. how can I fail compilation in compile-time? (as it is not cpp...). 2. isnt there a way to determine volatiles from debug info somehow? – gilboash Jun 17 '14 at 14:15
  • I suppose the fashionable `_Generic` keyword of C11 could be used for exactly this purpose. Although a more... generic solution would be to get a static analyser that has stricter type checks than a C compiler. – Lundin Jun 17 '14 at 14:21
  • You can also gcc extensions for this - I have both a compile-time and a run-time solution which I've just tested and they seem to work - let me know if this is potentially useful (i.e. if you can safely assume gcc or a gcc-compatible compiler) and I'll post details as an answer. – Paul R Jun 17 '14 at 14:42
  • Lundin - _Generic can be great solution for me, I just need to make sure if TMS470 supports this option is it is not trivial. Does it count as gcc extenstion as well? – gilboash Jun 17 '14 at 14:46
  • Paul R - it is definitly potentially useful, would appreciate your answer. thanks. – gilboash Jun 17 '14 at 14:56
  • @gilboash: no problem - I've posted an answer below now. – Paul R Jun 17 '14 at 15:28

2 Answers2

1

I wouldn't expect there to be any, but of course it's totally up to the compiler.

You could of course re-architect it so that the macro does the whole definition, i.e.

#define VOLATILE_MACRO(t, p) volatile t p

and use it like:

VOLATILE_MACRO(int, _p_reg);

but of course that might not work for you.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • thanks! but the macro is quite general, suppose to serve several modules, the declaration is not a part of the macro as it is doing bit manipulations. I'm looking for a creative way to "force" the developer to use this macro on volatiles only – gilboash Jun 17 '14 at 14:23
0

Two possible solutions using gcc extensions. The run-time version uses __builtin_types_compatible_p and an assert. The compile-time version is similar but uses a hack to get a static assert which fires at compile-time (albeit with a rather cryptic error message):

Run-time

#include <stdio.h>
#include <assert.h>

#define VOLATILE_MACRO(p) \
    assert (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)))

int main()
{
    volatile int * x;
    int * y;

    VOLATILE_MACRO(x);  // <<< OK
    VOLATILE_MACRO(y);  // <<< run-time error

    return 0;
}

Compile-time

#include <stdio.h>
#include <assert.h>

#define A                      BUILD_NAME(__LINE__)
#define BUILD_NAME(line)       BUILD_NAME2(line)
#define BUILD_NAME2(line)      assert_ ## line
#define STATIC_ASSERT(test)    typedef char A[(test) ? 1 : -1]

#define VOLATILE_MACRO(p) \
    STATIC_ASSERT (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)))

int main()
{
    volatile int * x;
    int * y;

    VOLATILE_MACRO(x);  // <<< OK
    VOLATILE_MACRO(y);  // <<< compile error

    return 0;
}

Note that if you need to support other volatile types then the macro can simply be extended with multiple chained __builtin_types_compatible_p tests, e.g.

#define VOLATILE_MACRO(p) \
    assert (__builtin_types_compatible_p(typeof(p), typeof(volatile int *)) ||
            __builtin_types_compatible_p(typeof(p), typeof(volatile short *)))
Paul R
  • 208,748
  • 37
  • 389
  • 560