aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-09-30 03:45:27 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-09-30 03:45:27 +0200
commitfded889cd4b3e0b5eef95440d3f96723e76a78e9 (patch)
treeded6cc96dae997390c6419e1f38e9be2a2fba07b
parent0ca5ee15e9836fca976479fef8d90594d1e97adb (diff)
parentb8c706f3d0116b79f3935f36162fae610311c163 (diff)
downloadsparse-fded889cd4b3e0b5eef95440d3f96723e76a78e9.tar.gz
Merge branch 'relax-constexpr' into tip
-rw-r--r--evaluate.c28
-rw-r--r--validation/constexpr-constcond.c10
-rw-r--r--validation/ioc-typecheck.c4
3 files changed, 25 insertions, 17 deletions
diff --git a/evaluate.c b/evaluate.c
index 3268333a..d52fd9f9 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1178,20 +1178,22 @@ static struct symbol *evaluate_conditional_expression(struct expression *expr)
expr->flags = (expr->conditional->flags & (*cond)->flags &
expr->cond_false->flags & ~CEF_CONST_MASK);
/*
- * A conditional operator yields a particular constant
- * expression type only if all of its three subexpressions are
- * of that type [6.6(6), 6.6(8)].
- * As an extension, relax this restriction by allowing any
- * constant expression type for the condition expression.
- *
- * A conditional operator never yields an address constant
- * [6.6(9)].
- * However, as an extension, if the condition is any constant
- * expression, and the true and false expressions are both
- * address constants, mark the result as an address constant.
+ * In the standard, it is defined that an integer constant expression
+ * shall only have operands that are themselves constant [6.6(6)].
+ * While this definition is very clear for expressions that need all
+ * their operands to be evaluated, for conditional expressions with a
+ * constant condition things are much less obvious.
+ * So, as an extension, do the same as GCC seems to do:
+ * Consider a conditional expression with a constant condition
+ * as having the same constantness as the argument corresponding
+ * to the truth value (including in the case of address constants
+ * which are defined more stricly [6.6(9)]).
*/
- if (expr->conditional->flags & (CEF_ACE | CEF_ADDR))
- expr->flags = (*cond)->flags & expr->cond_false->flags & ~CEF_CONST_MASK;
+ if (expr->conditional->flags & (CEF_ACE | CEF_ADDR)) {
+ int is_true = expr_truth_value(expr->conditional);
+ struct expression *arg = is_true ? *cond : expr->cond_false;
+ expr->flags = arg->flags & ~CEF_CONST_MASK;
+ }
lclass = classify_type(ltype, &ltype);
rclass = classify_type(rtype, &rtype);
diff --git a/validation/constexpr-constcond.c b/validation/constexpr-constcond.c
new file mode 100644
index 00000000..d98da3dc
--- /dev/null
+++ b/validation/constexpr-constcond.c
@@ -0,0 +1,10 @@
+extern int var;
+
+static int a[] = {
+ [0 ? var : 1] = 0,
+ [1 ? 2 : var] = 0,
+};
+
+/*
+ * check-name: constexprness in constant conditionals
+ */
diff --git a/validation/ioc-typecheck.c b/validation/ioc-typecheck.c
index 34b37d31..7780773b 100644
--- a/validation/ioc-typecheck.c
+++ b/validation/ioc-typecheck.c
@@ -4,8 +4,4 @@ static unsigned iocnrs[] = {
};
/*
* check-name: integer constant & conditional expression
- * check-known-to-fail
- *
- * check-error-start
- * check-error-end
*/