Index: gcc/function.c |
diff --git a/gcc/function.c b/gcc/function.c |
index d582fea6e6539ff774d7463cd546d2163410a75f..035c056a8ed4b568f72017aa27a5661679f3f790 100644 |
--- a/gcc/function.c |
+++ b/gcc/function.c |
@@ -1826,6 +1826,30 @@ struct rtl_opt_pass pass_instantiate_virtual_regs = |
} |
}; |
+/* HACK: If |maybe_call| is a call expression, grab additional type attributes |
+ * from the expression (e.g., from a function pointer type) which may not |
+ * have been present in a function decl. This must NOT affect the original |
+ * function type/decl, so make a copy if it really changed. |
+ * We may be able to narrow this hack to just propagate the "pnaclcall" |
+ * attribute... |
+ */ |
+static tree copy_attributes_if_call (const_tree maybe_call, const_tree fntype) { |
+ if (TREE_CODE (maybe_call) == CALL_EXPR) { |
+ tree new_attributes = |
+ merge_type_attributes(fntype, |
+ TREE_TYPE (TREE_TYPE ( |
+ CALL_EXPR_FN (maybe_call)))); |
+ if (!attribute_list_equal (TYPE_ATTRIBUTES (fntype), |
+ new_attributes)) { |
+ tree new_fntype = copy_node (fntype); |
+ TYPE_ATTRIBUTES (new_fntype) = new_attributes; |
+ return new_fntype; |
+ } |
+ return fntype; |
+ } |
+ return fntype; |
+} |
+ |
/* Return 1 if EXP is an aggregate type (or a value with aggregate type). |
This means a type for which function calls must pass an address to the |
@@ -1853,10 +1877,14 @@ aggregate_value_p (const_tree exp, const_tree fntype) |
fntype = (fndecl |
? TREE_TYPE (fndecl) |
: TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (fntype)))); |
+ /* HACK to grab attributes from the callexp type as well as the decl. */ |
+ fntype = copy_attributes_if_call (exp, fntype); |
break; |
case FUNCTION_DECL: |
fndecl = fntype; |
fntype = TREE_TYPE (fndecl); |
+ /* HACK to grab attributes from the callexp type as well as the decl. */ |
+ fntype = copy_attributes_if_call (exp, fntype); |
break; |
case FUNCTION_TYPE: |
case METHOD_TYPE: |