summaryrefslogtreecommitdiff
path: root/include/common.h
diff options
context:
space:
mode:
authorRaul E Rangel <rrangel@chromium.org>2019-05-03 12:48:41 -0600
committerchrome-bot <chrome-bot@chromium.org>2019-05-15 13:36:18 -0700
commitaaba1d5efd51082d143ce2ac64e6caf9cb14d5e5 (patch)
tree2f270d3141f77192078c6578ef78648491477779 /include/common.h
parent1598a615eb150916ea323e212b87298c3a6fcfb6 (diff)
downloadchrome-ec-aaba1d5efd51082d143ce2ac64e6caf9cb14d5e5.tar.gz
ec: common: Make IS_ENABLED fail on unknown values
If IS_ENABLED is called with any unknown values, a compiler error will be thrown. This change requires that the optimizer always be enabled, otherwise errors will be thrown when a value is not defined. BUG=none BRANCH=none TEST=make runtests TEST_LIST_HOST="is_enabled_error is_enabled" Change-Id: I1b166311f81d07e48b3665f4bc0e9502d2ccc4c6 Signed-off-by: Raul E Rangel <rrangel@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1592728 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Jack Rosenthal <jrosenth@chromium.org> Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'include/common.h')
-rw-r--r--include/common.h52
1 files changed, 36 insertions, 16 deletions
diff --git a/include/common.h b/include/common.h
index da8b4b73e2..b275b27e1f 100644
--- a/include/common.h
+++ b/include/common.h
@@ -236,29 +236,49 @@ enum ec_error_list {
/*
* Getting something that works in C and CPP for an arg that may or may
- * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER"
- * we match on the placeholder define, insert the "0," for arg1 and generate
- * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
- * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
- * the last step cherry picks the 2nd arg, we get a zero.
+ * not be defined is tricky. Here, if we have "#define CONFIG_FOO"
+ * we match on the placeholder define, insert the "_, 1," for arg1 and generate
+ * the triplet (_, 1, _, (...)). Then the last step cherry picks the 2nd arg
+ * (a one).
+ * When CONFIG_FOO is not defined, we generate a (_, (...)) pair, and when
+ * the last step cherry picks the 2nd arg, we get a code block that verifies
+ * the value of the option. Since the preprocessor won't replace an unknown
+ * token, we compare the option name with the value string. If they are
+ * identical we assume that the value was undefined and return 0. If the value
+ * happens to be anything else we call an undefined method that will raise
+ * a compiler error. This technique requires that the optimizer be enabled so it
+ * can remove the undefined function call.
+ *
*/
-#define __ARG_PLACEHOLDER_ 0,
-#define config_enabled(cfg) _config_enabled(cfg)
-#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
-#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0, 0)
+#define __ARG_PLACEHOLDER_ _, 1,
+#define _config_enabled(cfg, value) \
+ __config_enabled(__ARG_PLACEHOLDER_##value, cfg, value)
+#define __config_enabled(arg1_or_junk, cfg, value) ___config_enabled( \
+ arg1_or_junk _,\
+ ({ \
+ int __undefined = __builtin_strcmp(cfg, #value) == 0; \
+ extern int IS_ENABLED_BAD_ARGS(void) __attribute__(( \
+ error(cfg " must be <blank>, or not defined.")));\
+ if (!__undefined) \
+ IS_ENABLED_BAD_ARGS(); \
+ 0; \
+ }))
#define ___config_enabled(__ignored, val, ...) val
/**
- * Checks if a config option is defined to an empty value.
+ * Checks if a config option is enabled or disabled
+ *
+ * Enabled examples:
+ * #define CONFIG_FOO
*
- * IS_ENABLED(CONFIG_MY_OPTION) will return 1 in the following case:
- * #define CONFIG_MY_OPTION
+ * Disabled examples:
+ * #undef CONFIG_FOO
*
- * Otherwise if the option has not been defined or defined with a value, it will
- * return 0.
+ * If the option is defined to any value a compiler error will be thrown.
*
- * @param CONFIG_OPTION
+ * Note: This macro will only function inside a code block due to the way
+ * it checks for unknown values.
*/
-#define IS_ENABLED(option) config_enabled(option)
+#define IS_ENABLED(option) _config_enabled(#option, option)
#endif /* __CROS_EC_COMMON_H */