aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2008-01-16 09:44:23 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2008-01-16 09:44:23 +0000
commiteb1387a0511b0b71c901c7a9458cea1cc2f911c4 (patch)
tree4a6974a6ea8f6fdba10c4b24af2794548a43d1dd /gcc
parent4349e292879d8bc589a8a2b52defe5e754d75a16 (diff)
downloadgcc-eb1387a0511b0b71c901c7a9458cea1cc2f911c4.zip
gcc-eb1387a0511b0b71c901c7a9458cea1cc2f911c4.tar.gz
gcc-eb1387a0511b0b71c901c7a9458cea1cc2f911c4.tar.bz2
re PR c/34768 (Wrong code with conditional function invocation)
2008-01-16 Richard Guenther <rguenther@suse.de> PR c/34768 * c-typeck.c (common_pointer_type): Do not merge inconsistent type qualifiers for function types. * gcc.c-torture/execute/pr34768-1.c: New testcase. * gcc.c-torture/execute/pr34768-2.c: Likewise. From-SVN: r131568
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/c-typeck.c14
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr34768-1.c26
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr34768-2.c28
5 files changed, 76 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 90e422e..dd099a4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2008-01-16 Richard Guenther <rguenther@suse.de>
+
+ PR c/34768
+ * c-typeck.c (common_pointer_type): Do not merge inconsistent
+ type qualifiers for function types.
+
2008-01-15 Sebastian Pop <sebastian.pop@amd.com>
* tree-parloops (gen_parallel_loop): Revert my fix.
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 6d94cab..fb2e47f 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -530,6 +530,7 @@ common_pointer_type (tree t1, tree t2)
tree pointed_to_1, mv1;
tree pointed_to_2, mv2;
tree target;
+ unsigned target_quals;
/* Save time if the two types are the same. */
@@ -557,10 +558,15 @@ common_pointer_type (tree t1, tree t2)
if (TREE_CODE (mv2) != ARRAY_TYPE)
mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
target = composite_type (mv1, mv2);
- t1 = build_pointer_type (c_build_qualified_type
- (target,
- TYPE_QUALS (pointed_to_1) |
- TYPE_QUALS (pointed_to_2)));
+
+ /* For function types do not merge const qualifiers, but drop them
+ if used inconsistently. The middle-end uses these to mark const
+ and noreturn functions. */
+ if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
+ target_quals = TYPE_QUALS (pointed_to_1) & TYPE_QUALS (pointed_to_2);
+ else
+ target_quals = TYPE_QUALS (pointed_to_1) | TYPE_QUALS (pointed_to_2);
+ t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
return build_type_attribute_variant (t1, attributes);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7a2d834..b69ff98 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2008-01-16 Richard Guenther <rguenther@suse.de>
+
+ PR c/34768
+ * gcc.c-torture/execute/pr34768-1.c: New testcase.
+ * gcc.c-torture/execute/pr34768-2.c: Likewise.
+
2008-01-16 Tobias Burnus <burnus@net-b.de>
PR fortran/34796
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr34768-1.c b/gcc/testsuite/gcc.c-torture/execute/pr34768-1.c
new file mode 100644
index 0000000..eb16adb
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr34768-1.c
@@ -0,0 +1,26 @@
+int x;
+
+void __attribute__((noinline)) foo (void)
+{
+ x = -x;
+}
+void __attribute__((const,noinline)) bar (void)
+{
+}
+
+int __attribute__((noinline))
+test (int c)
+{
+ int tmp = x;
+ (c ? foo : bar) ();
+ return tmp + x;
+}
+
+extern void abort (void);
+int main()
+{
+ x = 1;
+ if (test (1) != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr34768-2.c b/gcc/testsuite/gcc.c-torture/execute/pr34768-2.c
new file mode 100644
index 0000000..917bf9e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr34768-2.c
@@ -0,0 +1,28 @@
+int x;
+
+int __attribute__((noinline)) foo (void)
+{
+ x = -x;
+ return 0;
+}
+int __attribute__((const,noinline)) bar (void)
+{
+ return 0;
+}
+
+int __attribute__((noinline))
+test (int c)
+{
+ int tmp = x;
+ int res = (c ? foo : bar) ();
+ return tmp + x + res;
+}
+
+extern void abort (void);
+int main()
+{
+ x = 1;
+ if (test (1) != 0)
+ abort ();
+ return 0;
+}