diff mbox

[v4,22/25] constexpr: treat comparisons between types as integer constexpr

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

Commit Message

Luc Van Oostenryck March 31, 2017, 1:44 a.m. UTC
From: Nicolai Stange <nicstange@gmail.com>

The expression parsing code builds an EXPR_COMPARE expression around two
EXPR_TYPE expressions for __builtin_types_compatible_p().

The EXPR_TYPE expressions are tagged as being integer constant expressions
in order to trick the generic comparison evaluation code into flagging the
result as an integer constant expression again.

Avoid this trickery by making evaluate_compare() unconditionally tag a
comparison between types as an integer constant expression.

Signed-off-by: Nicolai Stange <nicstange@gmail.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 evaluate.c                                | 13 +++++++++----
 expression.c                              |  3 ---
 validation/constexpr-types-compatible-p.c |  8 ++++++++
 3 files changed, 17 insertions(+), 7 deletions(-)
 create mode 100644 validation/constexpr-types-compatible-p.c
diff mbox

Patch

diff --git a/evaluate.c b/evaluate.c
index 1ae370c7b..46ea10ed8 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1016,16 +1016,21 @@  static struct symbol *evaluate_compare(struct expression *expr)
 	struct symbol *ctype;
 	const char *typediff;
 
-	expr->flags = left->flags & right->flags & ~CEF_CONST_MASK;
-	expr->flags &= ~CEF_ADDR;
-
 	/* Type types? */
-	if (is_type_type(ltype) && is_type_type(rtype))
+	if (is_type_type(ltype) && is_type_type(rtype)) {
+		/*
+		 * __builtin_types_compatible_p() yields an integer
+		 * constant expression
+		 */
+		expr->flags = CEF_SET_ICE;
 		goto OK;
+	}
 
 	if (is_safe_type(left->ctype) || is_safe_type(right->ctype))
 		warning(expr->pos, "testing a 'safe expression'");
 
+	expr->flags = left->flags & right->flags & ~CEF_CONST_MASK & ~CEF_ADDR;
+
 	/* number on number */
 	if (lclass & rclass & TYPE_NUM) {
 		ctype = usual_conversions(expr->op, expr->left, expr->right,
diff --git a/expression.c b/expression.c
index e4b770fc0..e5ebad65b 100644
--- a/expression.c
+++ b/expression.c
@@ -131,7 +131,6 @@  static struct token *parse_type(struct token *token, struct expression **tree)
 {
 	struct symbol *sym;
 	*tree = alloc_expression(token->pos, EXPR_TYPE);
-	(*tree)->flags = CEF_SET_ICE; /* sic */
 	token = typename(token, &sym, NULL);
 	if (sym->ident)
 		sparse_error(token->pos,
@@ -459,8 +458,6 @@  struct token *primary_expression(struct token *token, struct expression **tree)
 		}
 		if (token->special == '[' && lookup_type(token->next)) {
 			expr = alloc_expression(token->pos, EXPR_TYPE);
-			/* sic */
-			expr->flags = CEF_SET_ICE;
 			token = typename(token->next, &expr->symbol, NULL);
 			token = expect(token, ']', "in type expression");
 			break;
diff --git a/validation/constexpr-types-compatible-p.c b/validation/constexpr-types-compatible-p.c
new file mode 100644
index 000000000..1969bf3bd
--- /dev/null
+++ b/validation/constexpr-types-compatible-p.c
@@ -0,0 +1,8 @@ 
+static int a[] = {[__builtin_types_compatible_p(int, int)] = 0};
+
+/*
+ * check-name: __builtin_types_compatible_p() constness verification.
+ *
+ * check-error-start
+ * check-error-end
+ */