diff mbox

[v2,2/2] fix: give a type to bad cond expr with known condition

Message ID 20170804160622.18260-3-luc.vanoostenryck@gmail.com (mailing list archive)
State Mainlined, archived
Headers show

Commit Message

Luc Van Oostenryck Aug. 4, 2017, 4:06 p.m. UTC
Conditional expressions whose second & third operands
have non-compatible types are not conform to the C standard
and sparse emit a warning for them and return the expression
as being erroneous. In consequence, such expressions are not
given a type. This, in turn, makes that some further processing
cannot be done (correctly).

It seems that neither GCC nor clang emit a warning when
there is a type mismatch but the condition is a constant.

In the case we're interested here (the slow compilation of a file)
the operation that cannot be done is the expansion its operands.
This, in turn and among other things, makes that builtins like
__builtin_constant_p() are not evaluated with disatrous consequence
for the amount of work done in the next phases.

Fix this by giving to conditional expressions with constant
condition the same type as the operand selected by the conditional
(but keeping the warning) as GCC & clang seems to do.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c                   | 12 ++++++++++++
 validation/cond-err-expand.c | 27 +++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)
 create mode 100644 validation/cond-err-expand.c

Comments

Christopher Li Aug. 4, 2017, 7:50 p.m. UTC | #1
On Fri, Aug 4, 2017 at 12:06 PM, Luc Van Oostenryck
<luc.vanoostenryck@gmail.com> wrote:
> Conditional expressions whose second & third operands
> have non-compatible types are not conform to the C standard
> and sparse emit a warning for them and return the expression
> as being erroneous. In consequence, such expressions are not
> given a type. This, in turn, makes that some further processing
> cannot be done (correctly).
>
> It seems that neither GCC nor clang emit a warning when
> there is a type mismatch but the condition is a constant.
>
> In the case we're interested here (the slow compilation of a file)
> the operation that cannot be done is the expansion its operands.
> This, in turn and among other things, makes that builtins like
> __builtin_constant_p() are not evaluated with disatrous consequence
> for the amount of work done in the next phases.
>
> Fix this by giving to conditional expressions with constant
> condition the same type as the operand selected by the conditional
> (but keeping the warning) as GCC & clang seems to do.

Looks good to me.

Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/evaluate.c b/evaluate.c
index cf3cf244d..649e132b8 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1220,6 +1220,18 @@  static struct symbol *evaluate_conditional_expression(struct expression *expr)
 
 Err:
 	expression_error(expr, "incompatible types in conditional expression (%s)", typediff);
+	/*
+	 * if the condition is constant, the type is in fact known
+	 * so use it, as gcc & clang do.
+	 */
+	switch (expr_truth_value(expr->conditional)) {
+	case 1:	expr->ctype = ltype;
+		break;
+	case 0: expr->ctype = rtype;
+		break;
+	default:
+		break;
+	}
 	return NULL;
 
 out:
diff --git a/validation/cond-err-expand.c b/validation/cond-err-expand.c
new file mode 100644
index 000000000..93bbac153
--- /dev/null
+++ b/validation/cond-err-expand.c
@@ -0,0 +1,27 @@ 
+static inline void f(void)
+{
+	__builtin_constant_p(0);
+}
+
+void foo(void)
+{
+	0 ? 0 : f();
+}
+
+void bar(void)
+{
+	1 ? f() : 0;
+}
+
+/*
+ * check-name: cond-err-expand.c
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-error-start
+cond-err-expand.c:8:11: error: incompatible types in conditional expression (different base types)
+cond-err-expand.c:13:11: error: incompatible types in conditional expression (different base types)
+ * check-error-end
+ *
+ * check-output-ignore
+ * check-excludes: call.* __builtin_constant_p
+ */