aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-12-04 14:51:32 -0800
committerIan Lance Taylor <iant@golang.org>2020-12-04 14:51:32 -0800
commit945ae3ab27757d3261d99446f96105c5ebe70247 (patch)
treea8a120ef5393206d3bc9d2b5882bac1562824836 /gcc/testsuite
parentf012991e2db06cc95f7aac8ecb74a1ac5f51f3d2 (diff)
parent918a5b84a2c51dc9d011d39461cc276e6558069d (diff)
downloadgcc-945ae3ab27757d3261d99446f96105c5ebe70247.zip
gcc-945ae3ab27757d3261d99446f96105c5ebe70247.tar.gz
gcc-945ae3ab27757d3261d99446f96105c5ebe70247.tar.bz2
Merge from trunk revision 918a5b84a2c51dc9d011d39461cc276e6558069d
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/ChangeLog145
-rw-r--r--gcc/testsuite/g++.dg/asan/asan_test.cc2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/bit-cast6.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class40.C79
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc15.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc17.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/srcloc2.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/pr98130.C25
-rw-r--r--gcc/testsuite/g++.dg/template/pr98116.C6
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C274
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C124
-rw-r--r--gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s0
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C185
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C27
-rw-r--r--gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C212
-rw-r--r--gcc/testsuite/g++.dg/warn/delete-array-1.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/delete2.C2
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c279
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c57
-rw-r--r--gcc/testsuite/gcc.dg/Wfree-nonheap-object.c273
-rw-r--r--gcc/testsuite/gcc.dg/Wmismatched-dealloc.c252
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/malloc-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/attr-malloc.c75
-rw-r--r--gcc/testsuite/gcc.dg/free-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/free-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr98099.c2
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr71816.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr96226.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/pr98100.c9
-rw-r--r--gcc/testsuite/gnat.dg/opt91.adb11
-rw-r--r--gcc/testsuite/gnat.dg/opt91.ads10
-rw-r--r--gcc/testsuite/gnat.dg/opt91_pkg.adb12
-rw-r--r--gcc/testsuite/gnat.dg/opt91_pkg.ads19
39 files changed, 2169 insertions, 39 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3339d70..0e91a06 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,148 @@
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/concepts-nodiscard1.C: XFAIL.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ PR c++/90629
+ PR middle-end/94527
+ * g++.dg/asan/asan_test.cc: Fix a bug.
+ * g++.dg/warn/delete-array-1.C: Add expected warning.
+ * g++.old-deja/g++.other/delete2.C: Add expected warning.
+ * g++.dg/warn/Wfree-nonheap-object-2.C: New test.
+ * g++.dg/warn/Wfree-nonheap-object.C: New test.
+ * g++.dg/warn/Wmismatched-new-delete.C: New test.
+ * g++.dg/warn/Wmismatched-dealloc-2.C: New test.
+ * g++.dg/warn/Wmismatched-dealloc.C: New test.
+ * gcc.dg/Wmismatched-dealloc.c: New test.
+ * gcc.dg/analyzer/malloc-1.c: Prune out expected warning.
+ * gcc.dg/attr-malloc.c: New test.
+ * gcc.dg/free-1.c: Adjust text of expected warning.
+ * gcc.dg/free-2.c: Same.
+ * gcc.dg/torture/pr71816.c: Prune out expected warning.
+ * gcc.dg/tree-ssa/pr19831-2.c: Add an expected warning.
+ * gcc.dg/Wfree-nonheap-object-2.c: New test.
+ * gcc.dg/Wfree-nonheap-object-3.c: New test.
+ * gcc.dg/Wfree-nonheap-object.c: New test.
+ * g++.dg/warn/Wfree-nonheap-object.s: New file.
+
+2020-12-03 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/95342
+ * gfortran.dg/pr95342.f90: New test.
+
+2020-12-03 Ian Lance Taylor <iant@golang.org>
+
+ * go.test/go-test.exp (go-gc-tests): Add -I. when building all
+ sources in a directory (errorcheckdir, compiledir, rundir,
+ rundircmpout).
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/98019
+ * g++.dg/cpp2a/concepts-nodiscard1.C: New test.
+
+2020-12-03 Uroš Bizjak <ubizjak@gmail.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR target/98086
+ * gcc.target/i386/pr98086.c: New test.
+
+2020-12-03 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/98115
+ PR c++/98116
+ * g++.dg/template/pr98115.C: New.
+ * g++.dg/template/pr98116.C: New.
+
+2020-12-03 Andreas Krebbel <krebbel@linux.ibm.com>
+
+ * gcc.target/s390/stack-clash-4.c: New test.
+
+2020-12-03 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/undef_1.c: New test.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/pr98099.c: New test.
+
+2020-12-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * g++.dg/cpp2a/pr98082.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR libstdc++/93121
+ * g++.dg/cpp2a/bit-cast1.C: New test.
+ * g++.dg/cpp2a/bit-cast2.C: New test.
+ * g++.dg/cpp2a/bit-cast3.C: New test.
+ * g++.dg/cpp2a/bit-cast4.C: New test.
+ * g++.dg/cpp2a/bit-cast5.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp2a/consteval-defarg2.C: New test.
+
+2020-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/98104
+ * g++.dg/warn/pr98104.C: New test.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512bw-pr96906-1.c: New test.
+ * gcc.target/i386/pr96906-1.c: Add -mno-avx512f.
+
+2020-12-03 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512bw-vmovdqu16-1.c: Adjust testcase to
+ make sure only masked load instruction is generated.
+ * gcc.target/i386/avx512bw-vmovdqu8-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovapd-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovaps-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovdqa32-1.c: Ditto.
+ * gcc.target/i386/avx512f-vmovdqa64-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovapd-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovaps-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovdqa32-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vmovdqa64-1.c: Ditto.
+ * gcc.target/i386/pr97642-1.c: New test.
+ * gcc.target/i386/pr97642-2.c: New test.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/parse/defarg17.C: New test.
+
+2020-12-03 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp2a/consteval-defarg1.C: New test.
+
+2020-12-03 Hongyu Wang <hongyu.wang@intel.com>
+
+ PR target/97770
+ * gcc.target/i386/avx512bitalg-pr97770-1.c: New test.
+ * gcc.target/i386/avx512vpopcntdq-pr97770-1.c: Likewise.
+ * gcc.target/i386/avx512vpopcntdq-pr97770-2.c: Likewise.
+ * gcc.target/i386/avx512vpopcntdqvl-pr97770-1.c: Likewise.
+
+2020-12-03 Alexandre Oliva <oliva@adacore.com>
+
+ * lib/options.exp (check_for_options_with_filter): Detect
+ unavailable compiler for the selected language, and bail out
+ as unsupported.
+
+2020-12-03 Martin Sebor <msebor@redhat.com>
+
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-1.c: Adjust expected warnings
+ to correctly reflect the maximum object size.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-11.c: Same.
+ * gcc.dg/tree-ssa/builtin-sprintf-warn-18.c: Same.
+
+2020-12-03 Ilya Leoshkevich <iii@linux.ibm.com>
+
+ * gcc.target/s390/builtin-constant-p-threading.c: New test.
+
2020-12-03 Peter Bergner <bergner@linux.ibm.com>
PR c++/97947
diff --git a/gcc/testsuite/g++.dg/asan/asan_test.cc b/gcc/testsuite/g++.dg/asan/asan_test.cc
index 5f2e2c2..dbf1a6a 100644
--- a/gcc/testsuite/g++.dg/asan/asan_test.cc
+++ b/gcc/testsuite/g++.dg/asan/asan_test.cc
@@ -829,7 +829,7 @@ NOINLINE static int LargeFunction(bool do_bad_access) {
x[18]++;
x[19]++;
- delete x;
+ delete[] x;
return res;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C
new file mode 100644
index 0000000..4b70da1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast6.C
@@ -0,0 +1,31 @@
+// PR libstd++/93121
+// { dg-do compile { target c++20 } }
+
+namespace std
+{
+enum class byte : unsigned char {};
+template <typename To, typename From>
+constexpr To
+bit_cast (const From &from)
+{
+ return __builtin_bit_cast (To, from);
+}
+}
+
+struct S { unsigned short s[2]; };
+constexpr std::byte from1[sizeof (S)]{};
+constexpr auto to1 = std::bit_cast<S>(from1);
+constexpr unsigned char from2[sizeof (S)]{};
+constexpr auto to2 = std::bit_cast<S>(from2);
+
+constexpr bool
+cmp (const S &s1, const S &s2)
+{
+ for (int i = 0; i < sizeof (s1.s) / sizeof (s1.s[0]); i++)
+ if (s1.s[i] != s2.s[i])
+ return false;
+ return true;
+}
+
+static_assert (cmp (to1, S{}));
+static_assert (cmp (to2, S{}));
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
index 28ce29b..907e68b 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-nodiscard1.C
@@ -1,5 +1,6 @@
// PR c++/98019
// { dg-do compile { target c++20 } }
+// { dg-excess-errors *-*-* }
template <class T, class U> concept same_as = __is_same_as (T, U);
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
new file mode 100644
index 0000000..d193544
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class40.C
@@ -0,0 +1,79 @@
+// PR c++/93083
+// { dg-do compile { target c++20 } }
+
+template<unsigned N>
+struct FixedString
+{
+ char buf[N + 1]{};
+ constexpr FixedString(char const* s) {
+ for (unsigned i = 0; i != N; ++i) buf[i] = s[i];
+ }
+
+ auto operator<=>(const FixedString&) const = default;
+ constexpr operator char const*() const { return buf; }
+ constexpr static unsigned size() noexcept { return N; }
+};
+
+template<unsigned N> FixedString(char const (&)[N]) -> FixedString<N - 1>;
+
+template <FixedString... names>
+struct name_list
+{
+ template <FixedString name>
+ using add_name = name_list<
+ names...,
+ FixedString<name.size()>{ name }
+ >;
+};
+
+
+int main()
+{
+ using names =
+ name_list<>
+ ::add_name<"Zaphod Beeblebrox">;
+
+}
+
+// ----------------
+
+template <int N> struct literal {
+ constexpr literal(const char (&input)[N]) noexcept { }
+ constexpr literal(const literal &) noexcept { }
+};
+
+template <literal Name, int id> struct field { };
+
+template <literal Name> struct field<Name, 1u> { };
+
+// ----------------
+
+template <int N>
+struct use_as_nttp {};
+
+template <use_as_nttp Value>
+struct has_nttp {};
+
+template <use_as_nttp Value>
+using has_nttp_2 = has_nttp<Value>;
+
+// ----------------
+
+using size_t = decltype(sizeof(0));
+
+template <size_t N>
+struct string_literal
+{
+ constexpr string_literal(const char*) {}
+ string_literal(string_literal const&) = default;
+};
+template <size_t N>
+string_literal(const char (&)[N]) -> string_literal<N - 1>;
+
+template <string_literal Str>
+struct type_string { };
+
+template <string_literal Str>
+void foo() {
+ type_string<Str>{};
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc1.C b/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
index 6e19ff7..029a037 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc1.C
@@ -88,7 +88,7 @@ quux ()
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
- const char *function2 = __FUNCTION__;
+ const char *function2 = __PRETTY_FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc15.C b/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
index 30e5845..d02617e 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc15.C
@@ -44,12 +44,12 @@ struct S {
source_location loc = source_location::current ();
constexpr S (int l, source_location loc = source_location::current ())
- : func(__FUNCTION__), line(l), loc(loc)
+ : func(__PRETTY_FUNCTION__), line(l), loc(loc)
{}
constexpr S (double)
- : func(__FUNCTION__), line(__LINE__)
- // ^ column 38
+ : func(__PRETTY_FUNCTION__), line(__LINE__)
+ // ^ column 45
{}
};
@@ -73,7 +73,7 @@ bar ()
// ^ column 49
const source_location *d[3] = { &a, &b, &c };
const char *file1 = __FILE__;
- const char *function1 = __FUNCTION__;
+ const char *function1 = __PRETTY_FUNCTION__;
for (int j = 0; j < 3; j++)
{
int i= 0;
@@ -104,7 +104,7 @@ bar ()
return false;
if (e.loc.column () != 9)
return false;
- if (f.loc.column () != 38)
+ if (f.loc.column () != 45)
return false;
return true;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc17.C b/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
index 16704d0..a02ea48 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc17.C
@@ -46,12 +46,12 @@ struct S {
source_location loc = source_location::current ();
constexpr S (int l, source_location loc = source_location::current ())
- : func(__FUNCTION__), line(l), loc(loc)
+ : func(__PRETTY_FUNCTION__), line(l), loc(loc)
{}
constexpr S (double)
- : func(__FUNCTION__), line(__LINE__)
- // ^ column 38
+ : func(__PRETTY_FUNCTION__), line(__LINE__)
+ // ^ column 45
{}
};
@@ -76,7 +76,7 @@ bar ()
// ^ column 48
const source_location *d[3] = { &a, &b, &c };
const char *file1 = __FILE__;
- const char *function1 = b.function_name ();
+ const char *function1 = __PRETTY_FUNCTION__;
for (int j = 0; j < 3; j++)
{
int i= 0;
@@ -107,7 +107,7 @@ bar ()
return false;
if (e.loc.column () != 8)
return false;
- if (f.loc.column () != 38)
+ if (f.loc.column () != 45)
return false;
return true;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/srcloc2.C b/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
index 5ef09bb..4e0b960 100644
--- a/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/srcloc2.C
@@ -92,7 +92,7 @@ quux ()
const char *file1 = source_location::current ().file_name ();
const char *file2 = __FILE__;
const char *function1 = source_location::current ().function_name ();
- const char *function2 = __FUNCTION__;
+ const char *function2 = __PRETTY_FUNCTION__;
int line1 = source_location::current ().line ();
int line2 = __LINE__ - 1;
int column
diff --git a/gcc/testsuite/g++.dg/opt/pr98130.C b/gcc/testsuite/g++.dg/opt/pr98130.C
new file mode 100644
index 0000000..0af55ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr98130.C
@@ -0,0 +1,25 @@
+// PR c++/98130
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+
+#include <new>
+
+typedef int *T;
+
+static unsigned char storage[sizeof (T)] alignas (T);
+static T *p = (T *) storage;
+
+static inline __attribute__((__always_inline__)) void
+foo (T value)
+{
+ new (p) T(value);
+}
+
+int
+main ()
+{
+ int a;
+ foo (&a);
+ if (!*p)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/template/pr98116.C b/gcc/testsuite/g++.dg/template/pr98116.C
index d3398d2..874c590 100644
--- a/gcc/testsuite/g++.dg/template/pr98116.C
+++ b/gcc/testsuite/g++.dg/template/pr98116.C
@@ -1,5 +1,11 @@
// PR 98116, ICE with stripping typedef array type
// { dg-do compile { target c++11 } }
+// { dg-additional-options {--param=hash-table-verification-limit=10000000 -fchecking=2} }
+// { dg-ice "spec_hasher::equal" }
+
+// We get confused by alias templates that alias the same type.
+// { dg-prune-output "hash table checking failed" }
+
namespace std {
struct is_convertible;
template <typename _Tp> using remove_pointer_t = typename _Tp ::type;
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C
new file mode 100644
index 0000000..9d4d2a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object-2.C
@@ -0,0 +1,274 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced either directly
+ or through pointers is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern "C"
+{
+ void free (void*);
+ extern void* malloc (size_t);
+ extern void* realloc (void *p, size_t);
+}
+
+void sink (void*, ...);
+#define sink(...) sink (0, __VA_ARGS__)
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+void* source (void);
+
+void nowarn_free (void *p, void **pp, size_t n, intptr_t iptr)
+{
+ free (p);
+
+ p = 0;
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+
+ p = realloc (p, n * 2);
+ sink (p);
+ free (p);
+
+ free ((void*)iptr);
+
+ p = source ();
+ free (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ free (p);
+
+ free (*pp);
+}
+
+void warn_free_extern_arr (void)
+{
+ free (ecarr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_arr_offset (int i)
+{
+ char *p = ecarr + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_cstint (void)
+{
+ void *p = (void*)1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_func (void)
+{
+ void *p = (void*)warn_free_func;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_string (int i)
+{
+ {
+ char *p = (char*)"123";
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = (char*)"234" + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = (char*)"345" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ if (i >= 0)
+ {
+ char *p = (char*)"456" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+void warn_free_local_arr (int i)
+{
+ {
+ char a[4];
+ sink (a);
+ free (a); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char b[5];
+ sink (b);
+
+ char *p = b + 1;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char c[6];
+ sink (c);
+
+ char *p = c + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void warn_free_vla (int n, int i)
+{
+ {
+ int vla[n], *p = vla;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ {
+ int vla[n + 1], *p = vla + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ int vla[n + 2], *p = vla + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void nowarn_free_extern_ptrarr (void)
+{
+ free (*eparr);
+}
+
+void nowarn_free_extern_ptrarr_offset (int i)
+{
+ void *p = eparr[i];
+ free (p);
+}
+
+
+void warn_free_extern_ptrarr (void)
+{
+ free (eparr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_ptrarr_offset (int i)
+{
+ void *p = &eparr[i];
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_local_ptrarr (int i)
+{
+ void* a[4];
+ sink (a);
+ free (a[0]);
+ free (a[1]);
+ free (a[i]);
+}
+
+
+void nowarn_free_extern_ptr (void)
+{
+ free (eptr);
+}
+
+void nowarn_free_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ free (p);
+}
+
+void warn_free_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = eptr + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ free (q);
+}
+
+void nowarn_free_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ free (q);
+}
+
+void warn_free_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+struct Members
+{
+ char a[4], *p, *q;
+};
+
+extern struct Members em;
+
+void nowarn_free_member_ptr (struct Members *pm, int i)
+{
+ char *p = em.p;
+ free (p);
+ p = em.q + i;
+ free (p);
+
+ free (pm->q);
+ p = pm->p;
+ free (pm);
+ free (p);
+}
+
+void nowarn_free_struct_cast (intptr_t *p)
+{
+ struct Members *q = (struct Members*)*p;
+ if (q->p == 0)
+ free (q); // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_member_array (void)
+{
+ char *p = em.a;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_member_array_off (int i)
+{
+ char *p = em.a + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C
new file mode 100644
index 0000000..82b081a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.C
@@ -0,0 +1,124 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that attempts to deallocate objects by pointers with nonzero
+ offsets is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+char* source (void);
+
+void nowarn_op_delete (void *p, void ***ppp, size_t n, intptr_t iptr)
+{
+ operator delete (p);
+
+ p = 0;
+ operator delete (p);
+
+ p = operator new (n);
+ sink (p);
+ operator delete (p);
+
+ p = operator new (n);
+ sink (p);
+
+ operator delete ((void*)iptr);
+
+ p = source ();
+ operator delete (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ operator delete (p);
+
+ operator delete (**ppp);
+ operator delete (*ppp);
+ operator delete (ppp);
+}
+
+void warn_op_delete_cstaddr (void *p)
+{
+ operator delete (p);
+ p = (void*)~0;
+ operator delete (p); // { dg-warning "called on a pointer to an unallocated object" } */
+}
+
+void warn_op_delete_funcaddr ()
+{
+ void *p = (void*)&warn_op_delete_funcaddr;
+ operator delete (p); // { dg-warning "called on unallocated object 'void warn_op_delete_funcaddr()" } */
+}
+
+void warn_op_delete_string (void *p)
+{
+ operator delete (p);
+ p = (void*)"";
+ operator delete (p); // { dg-warning "called on a pointer to an unallocated object" } */
+}
+
+void warn_op_delete_ptr_to_self (void *p)
+{
+ operator delete (p);
+ p = &p;
+ operator delete (p); // { dg-warning "called on unallocated object 'p'" } */
+}
+
+void nowarn_op_new_delete (size_t n)
+{
+ void *p = operator new (n);
+ sink (p);
+ operator delete (p);
+}
+
+void nowarn_op_new_delete_ptr_plus (size_t n)
+{
+ void *p0_1 = operator new (n);
+ void *p1 = (char*)p0_1 + 1;
+ sink (p0_1, p1);
+ void *p0_2 = (char*)p1 - 1;
+ sink (p0_1, p1, p0_2);
+ operator delete (p0_2);
+}
+
+void warn_op_new_delete_cstoff (size_t n)
+{
+ void *p = operator new (n);
+ void *q = (char*)p + 1;
+ sink (p, q);
+ operator delete (q); // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer '\[^'\]+' with nonzero offset 1" }
+}
+
+void warn_op_new_delete_ptr_plus (size_t n)
+{
+ char *p = (char*)operator new (n);
+ sink (++p);
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset 1" }
+}
+
+void warn_op_delete_funcret_plus (size_t n)
+{
+ char *p = source ();
+ sink (++p);
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset 1" }
+}
+
+void warn_op_delete_eptr_plus (int i)
+{
+ extern char *ecp;
+
+ if (i < 1)
+ i = 1;
+
+ char *p = ecp + i;
+ sink (p);
+
+ operator delete (p); // { dg-warning "called on pointer '\[^']+' with nonzero offset \\\[1, \\d+]" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wfree-nonheap-object.s
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C
new file mode 100644
index 0000000..7ecc99a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc-2.C
@@ -0,0 +1,185 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ The detection doesn't require optimization.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+ void free (void *);
+ void* realloc (void *, size_t);
+}
+
+void sink (void *);
+
+void mydealloc (int, void*);
+void* A (mydealloc, 2) myalloc (void*);
+
+
+void my_delete (const char*, void*);
+void my_array_delete (const char*, void*);
+
+typedef void OpDelete1 (void*);
+typedef void OpDelete2 (void*, size_t);
+
+A ((OpDelete1*)operator delete, 1)
+#if __cplusplus >= 201402L
+A ((OpDelete2*)operator delete, 1)
+#endif
+A (my_delete, 2)
+int* my_new (size_t);
+
+A ((OpDelete1*)operator delete[], 1)
+#if __cplusplus >= 201402L
+A ((OpDelete2*)operator delete[], 1)
+#endif
+A (my_array_delete, 2)
+int* my_array_new (size_t);
+
+
+void test_my_new ()
+{
+ {
+ void *p = my_new (1);
+ operator delete (p);
+ }
+ {
+ void *p = my_new (1);
+ sink (p);
+ operator delete (p);
+ }
+ {
+ int *p = my_new (1);
+ sink (p);
+ delete p;
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ operator delete[] (p);
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete[] (p);
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ int *p = my_new (1);
+ sink (p);
+ delete[] p;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ my_delete ("1", p);
+ }
+ {
+ void *p = my_new (1);
+ sink (p);
+ my_delete ("2", p);
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ my_array_delete ("3", p);
+ // { dg-warning "'void my_array_delete\\\(const char\\\*, void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, 123);
+ // { dg-warning "'void\\\* realloc\\\(void\\\*, size_t\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+void test_my_array_new ()
+{
+ {
+ void *p = my_array_new (1);
+ operator delete[] (p);
+ }
+ {
+ void *p = my_array_new (1);
+ sink (p);
+ operator delete[] (p);
+ }
+ {
+ int *p = my_array_new (1);
+ sink (p);
+ delete[] p;
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+ {
+ int *p = my_array_new (1);
+ sink (p);
+ delete p;
+ // { dg-warning "'void operator delete\\\(void\\\*\[^\)\]*\\\)' called on pointer returned from a mismatched allocation function \\\[-Wmismatched-new-delete" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ my_array_delete ("1", p);
+ }
+ {
+ void *p = my_array_new (1);
+ sink (p);
+ my_array_delete ("2", p);
+ }
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ my_delete ("3", p);
+ // { dg-warning "'void my_delete\\\(const char\\\*, void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ void *p = my_array_new (1);
+ // { dg-message "returned from a call to 'int\\\* my_array_new\\\(size_t\\\)'" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, 123);
+ // { dg-warning "'void\\\* realloc\\\(void\\\*, size_t\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C
new file mode 100644
index 0000000..682db6f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-dealloc.C
@@ -0,0 +1,27 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ { dg-do compile { target c++11 } }
+ { dg-options "-Wall" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef __SIZE_TYPE__ size_t;
+
+void mydealloc (int, void*);
+void* A (mydealloc, 2) myalloc (void*);
+
+
+void* A (operator delete, 1)
+ bad_new (size_t); // { dg-error "attribute argument 1 is ambiguous" }
+void* A (operator delete[], 1)
+ bad_array_new (size_t); // { dg-error "attribute argument 1 is ambiguous" }
+
+void my_delete (const char*, void*);
+void my_array_delete (const char*, void*);
+
+typedef void OpDelete (void*);
+
+int* A ((OpDelete*)operator delete, 1) A (my_delete, 2)
+ my_new (size_t);
+int* A ((OpDelete*)operator delete[], 1) A (my_array_delete, 2)
+ my_array_new (size_t);
diff --git a/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C
new file mode 100644
index 0000000..ed1090b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wmismatched-new-delete.C
@@ -0,0 +1,212 @@
+/* PR c++/90629 - Support for -Wmismatched-new-delete
+ The detection doesn't require optimization.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" {
+ void free (void *);
+ void* malloc (size_t);
+ void* realloc (void *, size_t);
+ char* strdup (const char *);
+ char* strndup (const char *, size_t);
+}
+
+void sink (void *);
+
+void nowarn_op_new_delete (int n)
+{
+ void *p = operator new (n);
+ sink (p);
+ operator delete (p);
+}
+
+void nowarn_new_delete (int n)
+{
+ {
+ char *p = new char;
+ sink (p);
+ delete p;
+ }
+
+ {
+ char *p = new char[n];
+ sink (p);
+ delete[] p;
+ }
+}
+
+/* Verify a warning for calls to free() with a pointer returned from
+ a call to operator new() or the new expressopm. */
+
+void warn_new_free (int n)
+{
+ {
+ void *p = operator new (n);
+ // { dg-message "returned from a call to 'void\\\* operator new\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+ {
+ char *p = new char[n];
+ // { dg-message "returned from a call to 'void\\\* operator new \\\[" "note" { target *-*-* } .-1 }
+ sink (p);
+ free (p);
+ // { dg-warning "'void free\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for calls to realloc() with a pointer returned from
+ a call to operator new() or the new expressopm. */
+
+void warn_new_realloc (int n)
+{
+ {
+ void *p = operator new (n);
+ // { dg-message "returned from a call to 'void\\\* operator new\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, n * 2);
+ // { dg-warning "'void\\\* realloc\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ sink (p);
+ }
+ {
+ void *p = new char[n];
+ // { dg-message "returned from a call to 'void\\\* operator new \\\[" "note" { target *-*-* } .-1 }
+ sink (p);
+ p = realloc (p, n * 2);
+ // { dg-warning "'void\\\* realloc\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ sink (p);
+ }
+}
+
+
+/* Verify a warning for a call to operator_delete() with a pointer returned
+ from a call to malloc(). */
+
+void warn_malloc_op_delete (int n)
+{
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from a call to 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ operator delete (p);
+ // { dg-warning "'void operator delete\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to malloc(). */
+
+void warn_malloc_delete (int n)
+{
+ {
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from a call to 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete p;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *p = (char *)malloc (n);
+ // { dg-message "returned from a call to 'void\\\* malloc\\\(" "note" { target *-*-* } .-1 }
+ sink (p);
+ delete[] p;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to realloc(). */
+
+void warn_realloc_delete (void *p1, void *p2, int n)
+{
+ {
+ char *q = (char *)realloc (p1, n);
+ // { dg-message "returned from a call to 'void\\\* realloc\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = (char *)realloc (p2, n);
+ // { dg-message "returned from a call to 'void\\\* realloc\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to strdup(). */
+
+void warn_strdup_delete (const char *s1, const char *s2)
+{
+ {
+ char *q = strdup (s1);
+ // { dg-message "returned from a call to 'char\\\* strdup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = strdup (s2);
+ // { dg-message "returned from a call to 'char\\\* strdup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+
+/* Verify a warning for an invocation of either form of the delete
+ expression with a pointer returned from a call to strndup(). */
+
+void warn_strdup_delete (const char *s1, const char *s2, size_t n)
+{
+ {
+ char *q = strndup (s1, n);
+ // { dg-message "returned from a call to 'char\\\* strndup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ /* C++98 calls operator delete (void*) but later versions call
+ operator delete (void*, size_t). The difference doesn't matter
+ here so verify just that some operator delete is called. */
+ delete q;
+ // { dg-warning "'void operator delete\\\(\[^)\]+\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+
+ {
+ char *q = strndup (s2, n);
+ // { dg-message "returned from a call to 'char\\\* strndup\\\(" "note" { target *-*-* } .-1 }
+ sink (q);
+ delete[] q;
+ // { dg-warning "'void operator delete \\\[]\\\(void\\\*\\\)' called on pointer returned from a mismatched allocation function" "" { target *-*-* } .-1 }
+ }
+}
+
+
+struct Base { virtual ~Base (); };
+struct Derived: Base { };
+
+void warn_new_free_base_derived ()
+{
+ Base *p = new Derived ();
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wmismatched-new-delete" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/delete-array-1.C b/gcc/testsuite/g++.dg/warn/delete-array-1.C
index c3af713..95fa7d4 100644
--- a/gcc/testsuite/g++.dg/warn/delete-array-1.C
+++ b/gcc/testsuite/g++.dg/warn/delete-array-1.C
@@ -5,7 +5,7 @@ struct S { int a [1]; } s;
void foo (S *p)
{
- delete a; // { dg-warning "deleting array" }
- delete s.a; // { dg-warning "deleting array" }
- delete p->a; // { dg-warning "deleting array" }
+ delete a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
+ delete s.a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
+ delete p->a; // { dg-warning "deleting array|-Wfree-nonheap-object" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/delete2.C b/gcc/testsuite/g++.old-deja/g++.other/delete2.C
index 1d0554f..76ae355 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/delete2.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/delete2.C
@@ -9,5 +9,7 @@ void bar(foo a) {
delete[] a; // should be accepted
char b[1];
delete b; // { dg-warning "deleting array" } expecting pointer type
+ // { dg-warning "-Wfree-nonheap-object" "" { target *-*-* } .-1 }
delete[] b; // { dg-warning "deleting array" } expecting pointer type
+ // { dg-warning "-Wfree-nonheap-object" "" { target *-*-* } .-1 }
}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
new file mode 100644
index 0000000..2b00d77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-2.c
@@ -0,0 +1,279 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that attempting to reallocate unallocated objects referenced
+ either directly or through pointers is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* alloca (size_t);
+extern void* realloc (void*, size_t);
+
+void sink (void*, ...);
+
+extern void* eparr[];
+extern char *eptr;
+
+extern size_t n;
+
+
+void nowarn_realloc (void *p, size_t n)
+{
+ char *q = realloc (p, n);
+ sink (q);
+
+ q = realloc (0, n);
+ sink (q);
+
+ q = realloc (q, n * 2);
+ sink (q);
+}
+
+/* Verify that calling realloc on a pointer to an unknown object minus
+ some nonzero offset isn't diagnosed, but a pointer plus a positive
+ offset is (a positive offset cannot point at the beginning). */
+
+void test_realloc_offset (char *p1, char *p2, char *p3, size_t n, int i)
+{
+ char *q;
+ q = realloc (p1 - 1, n);
+ sink (q);
+
+ q = realloc (p2 + 1, n); // { dg-warning "'realloc' called on pointer 'p2' with nonzero offset 1" }
+ sink (q);
+
+ q = realloc (p3 + i, n);
+ sink (q);
+}
+
+void warn_realloc_extern_arr (void)
+{
+ extern char ecarr[]; // { gg-message "declared here" }
+ char *p = ecarr;
+ char *q = realloc (p, n); // { dg-warning "'realloc' called on unallocated object 'ecarr'" }
+ sink (q);
+}
+
+void warn_realloc_extern_arr_offset (int i)
+{
+ extern char ecarr[];
+ char *p = ecarr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void warn_realloc_string (int i)
+{
+ char *p, *q;
+ {
+ p = "123";
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "234" + 1;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = "123" + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_alloca (int n, int i)
+{
+ char *p, *q;
+ {
+ p = alloca (n);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 1);
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+ {
+ p = (char*)alloca (n + 2) + i;
+ sink (p);
+ q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+
+void warn_realloc_local_arr (int i)
+{
+ char *q;
+ {
+ char a[4];
+ sink (a);
+ q = realloc (a, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char b[5];
+ sink (b);
+ q = realloc (b + 1, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char c[6];
+ sink (c);
+ q = realloc (&c[2], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char d[7];
+ sink (d);
+ q = realloc (&d[i], n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void warn_realloc_vla (int n1, int n2, int i)
+{
+ char *q;
+ {
+ char vla[n1];
+ sink (vla);
+ q = realloc (vla, n2); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlb[n1 + 1];
+ sink (vlb);
+ q = realloc (vlb + 1, n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vlc[n1 + 2];
+ sink (vlc);
+ q = realloc (&vlc[2], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+
+ {
+ char vld[7];
+ sink (vld);
+ q = realloc (&vld[i], n2);// { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+ }
+}
+
+void nowarn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (*eparr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptrarr (void)
+{
+ char *q = realloc (eparr, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void warn_realloc_extern_ptrarr_offset (int i)
+{
+ void *p = eparr + i;
+ void *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_extern_ptr (void)
+{
+ char *q = realloc (eptr, n);
+ sink (q);
+}
+
+void nowarn_realloc_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ char *q = realloc (p, n);
+ sink (q);
+}
+
+
+void warn_realloc_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *p = eptr + i;
+ char *q = realloc (p, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+
+void nowarn_realloc_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void nowarn_realloc_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
+
+void nowarn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // The offset is from p, not *p.
+ void *q = *(p + i);
+ q = realloc (q, n);
+ sink (q);
+}
+
+void warn_realloc_deref_parm_pos_offset (void **p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ // Unlike in the function above the offset is from *p.
+ void *q = *p + i;
+ q = realloc (q, n); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ sink (q);
+}
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
new file mode 100644
index 0000000..a472b93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object-3.c
@@ -0,0 +1,57 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced indirectly through
+ pointers obtained from function calls is diagnosed.
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wfree-nonheap-object" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern char* memchr (const void*, int, size_t);
+extern char* strchr (const char*, int);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+
+void warn_free_memchr_ecarr (int x, size_t n)
+{
+ char *p = memchr (ecarr, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_ecarr_offset (int i, int j, int x, size_t n)
+{
+ char *p = memchr (ecarr + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_memchr_local_arr (int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a, x, n);
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_memchr_local_arr_offset (int i, int j, int x, size_t n)
+{
+ char a[8];
+ sink (a);
+
+ char *p = memchr (a + i, x, n);
+ char *q = p + j;
+ sink (p, q);
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
new file mode 100644
index 0000000..bb222cc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wfree-nonheap-object.c
@@ -0,0 +1,273 @@
+/* PR ????? - No warning on attempts to access free object
+ Verify that freeing unallocated objects referenced either directly
+ or through pointers is diagnosed. In most cases this doesn't require
+ optimization.
+ { dg-do compile }
+ { dg-options "-Wall -Wfree-nonheap-object" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __SIZE_TYPE__ size_t;
+
+extern void free (void*);
+extern void* malloc (size_t);
+extern void* realloc (void *p, size_t);
+
+void sink (void*, ...);
+
+extern char ecarr[];
+extern void* eparr[];
+
+extern char *eptr;
+
+void* source (void);
+
+void nowarn_free (void *p, void **pp, size_t n, intptr_t iptr)
+{
+ free (p);
+
+ p = 0;
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+ free (p);
+
+ p = malloc (n);
+ sink (p);
+
+ p = realloc (p, n * 2);
+ sink (p);
+ free (p);
+
+ free ((void*)iptr);
+
+ p = source ();
+ free (p);
+
+ p = source ();
+ p = (char*)p - 1;
+ free (p);
+
+ free (*pp);
+}
+
+void warn_free_extern_arr (void)
+{
+ free (ecarr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_arr_offset (int i)
+{
+ char *p = ecarr + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_cstint (void)
+{
+ void *p = (void*)1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_func (void)
+{
+ void *p = warn_free_func;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_string (int i)
+{
+ {
+ char *p = "123";
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "234" + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char *p = "345" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ if (i >= 0)
+ {
+ char *p = "456" + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+void warn_free_local_arr (int i)
+{
+ {
+ char a[4];
+ sink (a);
+ free (a); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char b[5];
+ sink (b);
+
+ char *p = b + 1;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ char c[6];
+ sink (c);
+
+ char *p = c + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void warn_free_vla (int n, int i)
+{
+ {
+ int vla[n], *p = vla;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+
+ {
+ int vla[n + 1], *p = vla + 1;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+ {
+ int vla[n + 2], *p = vla + i;
+ sink (p);
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+ }
+}
+
+
+void nowarn_free_extern_ptrarr (void)
+{
+ free (*eparr);
+}
+
+void nowarn_free_extern_ptrarr_offset (int i)
+{
+ char *p = eparr[i];
+ free (p);
+}
+
+
+void warn_free_extern_ptrarr (void)
+{
+ free (eparr); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_extern_ptrarr_offset (int i)
+{
+ void *p = &eparr[i];
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+void nowarn_free_local_ptrarr (int i)
+{
+ void* a[4];
+ sink (a);
+ free (a[0]);
+ free (a[1]);
+ free (a[i]);
+}
+
+
+void nowarn_free_extern_ptr (void)
+{
+ free (eptr);
+}
+
+void nowarn_free_extern_ptr_offset (int i)
+{
+ char *p = eptr + i;
+ free (p);
+}
+
+void nowarn_free_parm_offset (char *p, int i)
+{
+ char *q = p + i;
+ free (q);
+}
+
+void nowarn_free_parm_neg_offset (char *p, int i)
+{
+ if (i >= 0)
+ i = -1;
+
+ char *q = p + i;
+ free (q);
+}
+
+struct Members
+{
+ char a[4], *p, *q;
+};
+
+extern struct Members em;
+
+void nowarn_free_member_ptr (struct Members *pm, int i)
+{
+ char *p = em.p;
+ free (p);
+ p = em.q + i;
+ free (p);
+
+ free (pm->q);
+ p = pm->p;
+ free (pm);
+ free (p);
+}
+
+void nowarn_free_struct_cast (intptr_t *p)
+{
+ struct Members *q = (struct Members*)*p;
+ if (q->p == 0)
+ free (q); // { dg-bogus "\\\[-Wfree-nonheap-object" }
+}
+
+
+void warn_free_member_array (void)
+{
+ char *p = em.a;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_member_array_off (int i)
+{
+ char *p = em.a + i;
+ free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+
+// Range information requires optimization.
+#pragma GCC optimize "1"
+
+void warn_free_extern_ptr_pos_offset (int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = eptr + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
+
+void warn_free_parm_pos_offset (char *p, int i)
+{
+ if (i <= 0)
+ i = 1;
+
+ char *q = p + i;
+ free (q); // { dg-warning "\\\[-Wfree-nonheap-object" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
new file mode 100644
index 0000000..7c5d6ac
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wmismatched-dealloc.c
@@ -0,0 +1,252 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments has the expected
+ effect on diagnostics.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+void free (void*);
+void* malloc (size_t);
+void* realloc (void*, size_t);
+
+int fclose (FILE*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+
+A (fclose) A (freopen, 3)
+ FILE* fdopen (int);
+A (fclose) A (freopen, 3)
+ FILE* fopen (const char*, const char*);
+A (fclose) A (freopen, 3)
+ FILE* fmemopen(void *, size_t, const char *);
+A (fclose) A (freopen, 3)
+ FILE* freopen (const char*, const char*, FILE*);
+A (pclose) A (freopen, 3)
+ FILE* popen (const char*, const char*);
+A (fclose) A (freopen, 3)
+ FILE* tmpfile (void);
+
+void sink (FILE*);
+
+
+ void release (void*);
+A (release) FILE* acquire (void);
+
+void nowarn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ q = freopen ("1", "r", q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fdopen (0);
+ if (!q)
+ return;
+
+ sink (q);
+ }
+}
+
+
+void warn_fdopen (void)
+{
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0); // { dg-message "returned from a call to 'fdopen'" "note" }
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void nowarn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("2", "r");
+ sink (q);
+ q = freopen ("3", "r", q);
+ sink (q);
+ fclose (q);
+ }
+
+ {
+ FILE *q = fopen ("4", "r");
+ sink (q);
+ }
+}
+
+
+void warn_fopen (void)
+{
+ {
+ FILE *q = fopen ("1", "r");
+ sink (q);
+ release (q); // { dg-warning "'release' called on pointer returned from a mismatched allocation function" }
+ }
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ free (q); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *q = fdopen (0);
+ sink (q);
+ q = realloc (q, 7); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (q);
+ }
+}
+
+
+void test_popen (void)
+{
+ {
+ FILE *p = popen ("1", "r");
+ sink (p);
+ pclose (p);
+ }
+
+ {
+ FILE *p;
+ p = popen ("2", "r"); // { dg-message "returned from a call to 'popen'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ /* freopen() can close a stream open by popen() but pclose() can't
+ close the stream returned from freopen(). */
+ FILE *p = popen ("2", "r");
+ sink (p);
+ p = freopen ("3", "r", p); // { dg-message "returned from a call to 'freopen'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_tmpfile (void)
+{
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile ();
+ sink (p);
+ p = freopen ("1", "r", p);
+ sink (p);
+ fclose (p);
+ }
+
+ {
+ FILE *p = tmpfile (); // { dg-message "returned from a call to 'tmpfile'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void warn_malloc (void)
+{
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p);// { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = malloc (100); // { dg-message "returned from a call to 'malloc'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+}
+
+
+void test_acquire (void)
+{
+ {
+ FILE *p = acquire ();
+ release (p);
+ }
+
+ {
+ FILE *p = acquire ();
+ sink (p);
+ release (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ fclose (p); // { dg-warning "'fclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ pclose (p); // { dg-warning "'pclose' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ p = freopen ("1", "r", p); // { dg-warning "'freopen' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ free (p); // { dg-warning "'free' called on pointer returned from a mismatched allocation function" }
+ }
+
+ {
+ FILE *p = acquire (); // { dg-message "returned from a call to 'acquire'" "note" }
+ sink (p);
+ p = realloc (p, 123); // { dg-warning "'realloc' called on pointer returned from a mismatched allocation function" }
+ sink (p);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
index c5bf1227c..26d8288 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-1.c
@@ -609,3 +609,5 @@ int test_49 (int i)
*p = 1; /* { dg-warning "dereference of NULL 'p' \\\[CWE-476\\\]" } */
return x;
}
+
+/* { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/attr-malloc.c b/gcc/testsuite/gcc.dg/attr-malloc.c
new file mode 100644
index 0000000..14f1980
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-malloc.c
@@ -0,0 +1,75 @@
+/* PR middle-end/94527 - Add an attribute that marks a function as freeing
+ an object
+ Verify that attribute malloc with one or two arguments is accepted where
+ intended and rejected where it's invalid.
+ { dg-options "-Wall -ftrack-macro-expansion=0" } */
+
+#define A(...) __attribute__ ((malloc (__VA_ARGS__)))
+
+A (0) void* alloc_zero (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+A ("") void* alloc_string (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+int var;
+A (var) void* alloc_var (int); // { dg-error "'malloc' attribute argument 1 does not name a function" }
+
+typedef struct Type { int i; } Type;
+A (Type) void* alloc_type (int); // { dg-error "expected expression|identifier" }
+
+A (unknown) void* alloc_unknown (int); // { dg-error "'unknown' undeclared" }
+
+void fv_ (); // { dg-message "declared here" }
+A (fv_) void* alloc_fv_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument" }
+
+void fvi (int); // { dg-message "declared here" }
+A (fvi) void* alloc_fvi (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvv (void); // { dg-message "declared here" }
+A (fvv) void* alloc_fvv (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'void'" }
+
+void fvi_ (int, ...); // { dg-message "declared here" }
+A (fvi_) void* alloc_fvi_ (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'int'" }
+
+void fvi_vp (Type, void*); // { dg-message "declared here" }
+A (fvi_vp) void* alloc_fvi_vp (int); // { dg-error "'malloc' attribute argument 1 must take a pointer type as its first argument; have 'Type'" }
+
+
+void fpv (void*);
+A (fpv) void* alloc_fpv (int);
+
+void fpv_i (void*, int);
+A (fpv_i) void* alloc_fpv_i (int);
+
+void fpv_pv (void*, void*);
+A (fpv_i) void* alloc_fpv_pv (int);
+
+
+void gpc (char*);
+void hpi (int*);
+A (fpv) A (gpc) A (hpi) Type* alloc_fpv_gpv (int);
+
+
+/* Verify that the attribute can be applied to <stdio.h> functions. */
+typedef struct FILE FILE;
+typedef __SIZE_TYPE__ size_t;
+
+int fclose (FILE*);
+FILE* fdopen (int);
+FILE* fopen (const char*, const char*);
+FILE* freopen (const char*, const char*, FILE*);
+int pclose (FILE*);
+FILE* popen (const char*, const char*);
+FILE* tmpfile (void);
+
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fdopen (int);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fopen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* fmemopen(void *, size_t, const char *);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* freopen (const char*, const char*, FILE*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* popen (const char*, const char*);
+A (fclose) A (freopen, 3) A (pclose)
+ FILE* tmpfile (void);
diff --git a/gcc/testsuite/gcc.dg/free-1.c b/gcc/testsuite/gcc.dg/free-1.c
index 5496c84..ad49d78 100644
--- a/gcc/testsuite/gcc.dg/free-1.c
+++ b/gcc/testsuite/gcc.dg/free-1.c
@@ -13,14 +13,14 @@ void foo (void)
static char buf4[10], e;
char *q = buf;
free (p);
- free (q); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf2); /* { dg-warning "attempt to free a non-heap object" } */
- free (&c); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf3); /* { dg-warning "attempt to free a non-heap object" } */
- free (&d); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf4); /* { dg-warning "attempt to free a non-heap object" } */
- free (&e); /* { dg-warning "attempt to free a non-heap object" } */
+ free (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
free (&r->a);
- free ("abcd"); /* { dg-warning "attempt to free a non-heap object" } */
- free (L"abcd"); /* { dg-warning "attempt to free a non-heap object" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/free-2.c b/gcc/testsuite/gcc.dg/free-2.c
index eb94651..edbcdc7 100644
--- a/gcc/testsuite/gcc.dg/free-2.c
+++ b/gcc/testsuite/gcc.dg/free-2.c
@@ -13,14 +13,14 @@ void foo (void)
static char buf4[10], e;
char *q = buf;
free (p);
- free (q); /* At -O0 no warning is reported here. */
- free (buf2); /* { dg-warning "attempt to free a non-heap object" } */
- free (&c); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf3); /* { dg-warning "attempt to free a non-heap object" } */
- free (&d); /* { dg-warning "attempt to free a non-heap object" } */
- free (buf4); /* { dg-warning "attempt to free a non-heap object" } */
- free (&e); /* { dg-warning "attempt to free a non-heap object" } */
+ free (q); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf2); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&c); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf3); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&d); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (buf4); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (&e); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
free (&r->a);
- free ("abcd"); /* { dg-warning "attempt to free a non-heap object" } */
- free (L"abcd"); /* { dg-warning "attempt to free a non-heap object" } */
+ free ("abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
+ free (L"abcd"); /* { dg-warning "\\\[-Wfree-nonheap-object" } */
}
diff --git a/gcc/testsuite/gcc.dg/pr98099.c b/gcc/testsuite/gcc.dg/pr98099.c
index 34909f2..12e52f2 100644
--- a/gcc/testsuite/gcc.dg/pr98099.c
+++ b/gcc/testsuite/gcc.dg/pr98099.c
@@ -1,7 +1,7 @@
/* PR middle-end/98099 */
/* Reported by G. Steinmetz <gscfq@t-online.de> */
-/* { dg-do compile } */
+/* { dg-do compile { target dfp } } */
/* { dg-options "-fsso-struct=big-endian" } */
struct S { _Decimal128 a; };
diff --git a/gcc/testsuite/gcc.dg/torture/pr71816.c b/gcc/testsuite/gcc.dg/torture/pr71816.c
index be37ad9..cc143fa 100644
--- a/gcc/testsuite/gcc.dg/torture/pr71816.c
+++ b/gcc/testsuite/gcc.dg/torture/pr71816.c
@@ -20,3 +20,7 @@ struct ext2_icount_el *insert_icount_el() {
ext2fs_resize_mem(&insert_icount_el_icount_1);
return 0;
}
+
+/* Passing the address of a declared object to realloc triggers
+ -Wfree-nonheap-object unless -flto is used.
+ { dg-prune-output "\\\[-Wfree-nonheap-object" } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
index 6a03588..e6dd4be 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
int global;
int foo ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
index 464b1fb..b164067 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-6.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
int global;
int foo ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
index f43ce7d..f4d06fe 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-8.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=5" } */
int global;
int global1;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
index 55b4fd0..df4120d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19831-2.c
@@ -5,7 +5,7 @@ void test1(void)
{
int *p = __builtin_malloc (sizeof (int) * 4);
*p++ = 4;
- __builtin_free (p);
+ __builtin_free (p); // { dg-warning "\\\[-Wfree-nonheap-object" }
}
/* Undefined. We can't do anything here. */
diff --git a/gcc/testsuite/gcc.target/i386/pr96226.c b/gcc/testsuite/gcc.target/i386/pr96226.c
new file mode 100644
index 0000000..cc010fa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr96226.c
@@ -0,0 +1,16 @@
+/* PR target/96226 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-times "\troll\t" 4 } } */
+/* { dg-final { scan-assembler-times "\trolq\t" 4 { target { ! ia32 } } } } */
+
+int f1 (int x) { return ~(1U << (x & 0x1f)); }
+int f2 (int x) { return ~(1U << x); }
+int f3 (unsigned char *x) { return ~(1U << (x[0] & 0x1f)); }
+int f4 (unsigned char *x) { return ~(1U << x[0]); }
+#ifdef __x86_64__
+long int f5 (int x) { return ~(1ULL << (x & 0x3f)); }
+long int f6 (int x) { return ~(1ULL << x); }
+long int f7 (unsigned char *x) { return ~(1ULL << (x[0] & 0x3f)); }
+long int f8 (unsigned char *x) { return ~(1ULL << x[0]); }
+#endif
diff --git a/gcc/testsuite/gcc.target/i386/pr98100.c b/gcc/testsuite/gcc.target/i386/pr98100.c
new file mode 100644
index 0000000..4deda1a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr98100.c
@@ -0,0 +1,9 @@
+/* PR target/98100 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-avx -fvar-tracking-assignments -g0" } */
+
+__attribute__((target_clones("default","avx2"))) void
+foo ()
+{
+ __attribute__((__vector_size__(8 * sizeof(int)))) int b = {};
+}
diff --git a/gcc/testsuite/gnat.dg/opt91.adb b/gcc/testsuite/gnat.dg/opt91.adb
new file mode 100644
index 0000000..b0132f8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91.adb
@@ -0,0 +1,11 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -fchecking=1" }
+
+package body Opt91 is
+
+ function Custom_Image (Self : True_Relation_Rec) return String is
+ begin
+ return "<True>";
+ end;
+
+end Opt91;
diff --git a/gcc/testsuite/gnat.dg/opt91.ads b/gcc/testsuite/gnat.dg/opt91.ads
new file mode 100644
index 0000000..b31aa8d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91.ads
@@ -0,0 +1,10 @@
+with Opt91_Pkg; use Opt91_Pkg;
+
+package Opt91 is
+
+ type True_Relation_Rec is null record;
+ function Custom_Image (Self : True_Relation_Rec) return String;
+
+ package True_Relation is new Pure_Relation (Ty => True_Relation_Rec);
+
+end Opt91;
diff --git a/gcc/testsuite/gnat.dg/opt91_pkg.adb b/gcc/testsuite/gnat.dg/opt91_pkg.adb
new file mode 100644
index 0000000..5b95fb2e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91_pkg.adb
@@ -0,0 +1,12 @@
+package body Opt91_Pkg is
+
+ package body Pure_Relation is
+
+ overriding function Custom_Image (Self : Rel) return String is
+ begin
+ return Custom_Image (Self.Rel);
+ end Custom_Image;
+
+ end Pure_Relation;
+
+end Opt91_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt91_pkg.ads b/gcc/testsuite/gnat.dg/opt91_pkg.ads
new file mode 100644
index 0000000..9bfd0f0
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/opt91_pkg.ads
@@ -0,0 +1,19 @@
+package Opt91_Pkg is
+
+ type Base_Relation is abstract tagged null record;
+
+ function Custom_Image (Self : Base_Relation) return String is abstract;
+
+ generic
+ type Ty is private;
+ with function Custom_Image (Self : Ty) return String is <>;
+ package Pure_Relation is
+
+ type Rel is new Base_Relation with record
+ Rel : Ty;
+ end record;
+
+ overriding function Custom_Image (Self : Rel) return String;
+ end Pure_Relation;
+
+end Opt91_Pkg;