From 760bc01f246e069bb05904b85220a4802112523e Mon Sep 17 00:00:00 2001 From: Colin Patrick McCabe Date: Thu, 31 Mar 2011 18:17:51 -0700 Subject: [PATCH] config: typecheck initialization macros When initializing the config_options array, complain if the size of the option field we're trying to initialize doesn't match the size of our type. This will prevent careless type annotations from overwriting neighboring option fields. Also create a header called "static assert" which implements a compile-time assert. Signed-off-by: Colin McCabe --- src/Makefile.am | 1 + src/common/config.cc | 63 ++++++++++++++++++++++++++------------ src/common/static_assert.h | 24 +++++++++++++++ 3 files changed, 68 insertions(+), 20 deletions(-) create mode 100644 src/common/static_assert.h diff --git a/src/Makefile.am b/src/Makefile.am index 65ba205a8a3db..2939ac1b8aeed 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -776,6 +776,7 @@ noinst_HEADERS = \ common/ceph_crypto.h\ common/utf8.h\ common/strtol.h\ + common/static_assert.h\ crush/CrushWrapper.h\ crush/CrushWrapper.i\ crush/builder.h\ diff --git a/src/common/config.cc b/src/common/config.cc index b7d327ffa0263..9a3a5015c85d2 100644 --- a/src/common/config.cc +++ b/src/common/config.cc @@ -14,15 +14,16 @@ #include "auth/Auth.h" #include "common/BackTrace.h" -#include "common/ceph_argparse.h" #include "common/Clock.h" #include "common/ConfUtils.h" #include "common/ProfLogger.h" +#include "common/ceph_argparse.h" #include "common/common_init.h" -#include "common/dyn_snprintf.h" -#include "common/version.h" #include "common/config.h" +#include "common/dyn_snprintf.h" +#include "common/static_assert.h" #include "common/strtol.h" +#include "common/version.h" #include "include/atomic.h" #include "include/str_list.h" #include "include/types.h" @@ -67,32 +68,54 @@ struct ceph_file_layout g_default_file_layout = { #define _STR(x) #x #define STRINGIFY(x) _STR(x) +#define TYCHECK(x, ty) STATIC_ASSERT(sizeof(x) == sizeof(ty)) + #define OPTION_OPT_STR(section, name, type, def_val) \ - { STRINGIFY(section), NULL, STRINGIFY(name), \ - &g_conf.name, def_val, 0, 0, type } + { STRINGIFY(section) + TYCHECK(g_conf.name, std::string), \ + NULL, STRINGIFY(name), \ + &g_conf.name, def_val, 0, 0, type } #define OPTION_OPT_ADDR(section, name, type, def_val) \ - { STRINGIFY(section), NULL, STRINGIFY(name), \ - &g_conf.name, def_val, 0, 0, type } + { STRINGIFY(section) + TYCHECK(g_conf.name, entity_addr_t), \ + NULL, STRINGIFY(name), \ + &g_conf.name, def_val, 0, 0, type } #define OPTION_OPT_LONGLONG(section, name, type, def_val) \ - { STRINGIFY(section), NULL, STRINGIFY(name), \ - &g_conf.name, 0, def_val, 0, type } -#define OPTION_OPT_U64 OPTION_OPT_LONGLONG -#define OPTION_OPT_U32 OPTION_OPT_LONGLONG -#define OPTION_OPT_INT OPTION_OPT_LONGLONG -#define OPTION_OPT_BOOL OPTION_OPT_INT + { STRINGIFY(section) + TYCHECK(g_conf.name, long long), \ + NULL, STRINGIFY(name), \ + &g_conf.name, 0, def_val, 0, type } + +#define OPTION_OPT_INT(section, name, type, def_val) \ + { STRINGIFY(section) + TYCHECK(g_conf.name, int), \ + NULL, STRINGIFY(name), \ + &g_conf.name, 0, def_val, 0, type } + +#define OPTION_OPT_BOOL(section, name, type, def_val) \ + { STRINGIFY(section) + TYCHECK(g_conf.name, bool), \ + NULL, STRINGIFY(name), \ + &g_conf.name, 0, def_val, 0, type } + +#define OPTION_OPT_U32(section, name, type, def_val) \ + { STRINGIFY(section) + TYCHECK(g_conf.name, uint32_t), \ + NULL, STRINGIFY(name), \ + &g_conf.name, 0, def_val, 0, type } + +#define OPTION_OPT_U64(section, name, type, def_val) \ + { STRINGIFY(section) + TYCHECK(g_conf.name, uint64_t), \ + NULL, STRINGIFY(name), \ + &g_conf.name, 0, def_val, 0, type } #define OPTION_OPT_DOUBLE(section, name, type, def_val) \ - { STRINGIFY(section), NULL, STRINGIFY(name), \ - &g_conf.name, 0, 0, def_val, type } -#define OPTION_OPT_FLOAT OPTION_OPT_DOUBLE + { STRINGIFY(section) + TYCHECK(g_conf.name, double), \ + NULL, STRINGIFY(name), \ + &g_conf.name, 0, 0, def_val, type } -#define OPTION(name, type, def_val) OPTION_##type("global", name, type, def_val) +#define OPTION_OPT_FLOAT(section, name, type, def_val) \ + { STRINGIFY(section) + TYCHECK(g_conf.name, float), \ + NULL, STRINGIFY(name), \ + &g_conf.name, 0, 0, def_val, type } -#define OPTION_ALT(section, conf_name, name, type, def_val) \ - { STRINGIFY(section), NULL, STRINGIFY(conf_name), \ - &g_conf.name, STRINGIFY(def_val), type } +#define OPTION(name, type, def_val) OPTION_##type("global", name, type, def_val) struct config_option config_optionsp[] = { OPTION(host, OPT_STR, "localhost"), diff --git a/src/common/static_assert.h b/src/common/static_assert.h new file mode 100644 index 0000000000000..97f7bcb1e06c2 --- /dev/null +++ b/src/common/static_assert.h @@ -0,0 +1,24 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2011 New Dream Network + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_COMMON_STATIC_ASSERT +#define CEPH_COMMON_STATIC_ASSERT + +/* Create a compiler error if condition is false. + * Also produce a result of value 0 and type size_t. + * This expression can be used anywhere, even in structure initializers. + */ +#define STATIC_ASSERT(x) (sizeof(int[((x)==0) ? -1 : 0])) + +#endif -- 2.39.5