diff options
author | Andreas Sandberg <Andreas.Sandberg@arm.com> | 2012-09-25 11:49:40 -0500 |
---|---|---|
committer | Andreas Sandberg <Andreas.Sandberg@arm.com> | 2012-09-25 11:49:40 -0500 |
commit | 4544f3def42ae9b8c528223d8762ae3634c7124a (patch) | |
tree | 21fa1ea3b3e9e6aa57d44110eec07b712650f6fc | |
parent | 6598241f2c188ba6f4ce035d9e1fbdd4619c7e00 (diff) | |
download | gem5-4544f3def42ae9b8c528223d8762ae3634c7124a.tar.xz |
base: Check for static_assert support and provide fallback
C++11 has support for static_asserts to provide compile-time assertion
checking. This is very useful when testing, for example, structure
sizes to make sure that the compiler got the right alignment or vector
sizes.
-rwxr-xr-x | SConstruct | 21 | ||||
-rw-r--r-- | src/base/compiler.hh | 30 |
2 files changed, 49 insertions, 2 deletions
diff --git a/SConstruct b/SConstruct index 515f6047b..842c4fef5 100755 --- a/SConstruct +++ b/SConstruct @@ -684,17 +684,34 @@ def CheckLeading(context): context.Result(ret) return ret +# Test for the presence of C++11 static asserts. If the compiler lacks +# support for static asserts, base/compiler.hh enables a macro that +# removes any static asserts in the code. +def CheckStaticAssert(context): + context.Message("Checking for C++11 static_assert support...") + ret = context.TryCompile(''' + static_assert(1, "This assert is always true"); + ''', extension=".cc") + context.env.Append(HAVE_STATIC_ASSERT=ret) + context.Result(ret) + return ret + # Platform-specific configuration. Note again that we assume that all # builds under a given build root run on the same host platform. conf = Configure(main, conf_dir = joinpath(build_root, '.scons_config'), log_file = joinpath(build_root, 'scons_config.log'), - custom_tests = { 'CheckLeading' : CheckLeading }) + custom_tests = { 'CheckLeading' : CheckLeading, + 'CheckStaticAssert' : CheckStaticAssert, + }) # Check for leading underscores. Don't really need to worry either # way so don't need to check the return code. conf.CheckLeading() +# Check for C++11 features we want to use if they exist +conf.CheckStaticAssert() + # Check if we should compile a 64 bit binary on Mac OS X/Darwin try: import platform @@ -923,7 +940,7 @@ sticky_vars.AddVariables( # These variables get exported to #defines in config/*.hh (see src/SConscript). export_vars += ['USE_FENV', 'SS_COMPATIBLE_FP', 'TARGET_ISA', 'CP_ANNOTATE', 'USE_POSIX_CLOCK', 'PROTOCOL', - ] + 'HAVE_STATIC_ASSERT'] ################################################### # diff --git a/src/base/compiler.hh b/src/base/compiler.hh index a95cb791c..7b1c53d87 100644 --- a/src/base/compiler.hh +++ b/src/base/compiler.hh @@ -31,6 +31,8 @@ #ifndef __BASE_COMPILER_HH__ #define __BASE_COMPILER_HH__ +#include "config/have_static_assert.hh" + //http://msdn2.microsoft.com/en-us/library/ms937669.aspx //http://msdn2.microsoft.com/en-us/library/aa448724.aspx //http://docs.sun.com/source/819-3688/sun.specific.html#marker-998278 @@ -56,4 +58,32 @@ #error "Need to define compiler options in base/compiler.hh" #endif +/* + * Define a compatibility macro that emulates the behavior of + * static_assert using template magic if the compiler doesn't have + * native support. + */ +#if !HAVE_STATIC_ASSERT + +template<bool> +struct static_assert_failure; + +template<> +struct static_assert_failure<false> {}; + +/* The following macro causes the compiler to evaluate the size of the + * static_assert_failure struct. The templates are designed so that + * only static_assert_failure<false> evaluates to a proper size, while + * static_assert_failure<true> generates a compile time error. + */ +#define static_assert(expr, msg) \ + namespace ns_static_assert { \ + enum { \ + static_assert_ ## __LINE__ = \ + sizeof(static_assert_failure<!(expr)>) \ + }; \ + } + +#endif + #endif // __BASE_COMPILER_HH__ |