From 79063edd747d348be1a86a5df5d4df046735d8fe Mon Sep 17 00:00:00 2001 From: Martin Sebor Date: Fri, 20 May 2016 22:23:10 +0000 Subject: [PATCH] PR c/71115 - [4.9/5/6/7 Regression] Missing warning: excess elements PR c/71115 - [4.9/5/6/7 Regression] Missing warning: excess elements in struct initializer gcc/c/ChangeLog: 2016-05-20 Martin Sebor PR c/71115 * c-typeck.c (error_init): Use expansion_point_location_if_in_system_header. (warning_init): Same. gcc/testsuite/ChangeLog: 2016-05-20 Martin Sebor PR c/71115 * gcc.dg/init-excess-2.c: New test. From-SVN: r236549 --- gcc/c/ChangeLog | 7 + gcc/c/c-typeck.c | 20 +- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/cpp1y/constexpr-sfinae.C | 287 ++++++++++++++++++ gcc/testsuite/gcc.dg/Woverride-init-1.c | 10 +- gcc/testsuite/gcc.dg/Woverride-init-2.c | 10 +- gcc/testsuite/gcc.dg/init-excess-2.c | 47 +++ 7 files changed, 371 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-sfinae.C create mode 100644 gcc/testsuite/gcc.dg/init-excess-2.c diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 5731048b087..c65f2e9e5e0 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2016-05-20 Martin Sebor + + PR c/71115 + * c-typeck.c (error_init): Use + expansion_point_location_if_in_system_header. + (warning_init): Same. + 2016-05-19 David Malcolm PR c/71171 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 30102404284..7c9b078ed1b 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -5879,16 +5879,21 @@ error_init (location_t loc, const char *gmsgid) component name is taken from the spelling stack. */ static void -pedwarn_init (location_t location, int opt, const char *gmsgid) +pedwarn_init (location_t loc, int opt, const char *gmsgid) { char *ofwhat; bool warned; + /* Use the location where a macro was expanded rather than where + it was defined to make sure macros defined in system headers + but used incorrectly elsewhere are diagnosed. */ + source_location exploc = expansion_point_location_if_in_system_header (loc); + /* The gmsgid may be a format string with %< and %>. */ - warned = pedwarn (location, opt, gmsgid); + warned = pedwarn (exploc, opt, gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat && warned) - inform (location, "(near initialization for %qs)", ofwhat); + inform (exploc, "(near initialization for %qs)", ofwhat); } /* Issue a warning for a bad initializer component. @@ -5903,11 +5908,16 @@ warning_init (location_t loc, int opt, const char *gmsgid) char *ofwhat; bool warned; + /* Use the location where a macro was expanded rather than where + it was defined to make sure macros defined in system headers + but used incorrectly elsewhere are diagnosed. */ + source_location exploc = expansion_point_location_if_in_system_header (loc); + /* The gmsgid may be a format string with %< and %>. */ - warned = warning_at (loc, opt, gmsgid); + warned = warning_at (exploc, opt, gmsgid); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); if (*ofwhat && warned) - inform (loc, "(near initialization for %qs)", ofwhat); + inform (exploc, "(near initialization for %qs)", ofwhat); } /* If TYPE is an array type and EXPR is a parenthesized string diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1a6a460f621..70354d4e4be 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-05-20 Martin Sebor + + PR c/71115 + * gcc.dg/init-excess-2.c: New test. + 2016-05-20 Eric Botcazou * gnat.dg/opt53.adb: New test. diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-sfinae.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-sfinae.C new file mode 100644 index 00000000000..a83d7f4e1de --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-sfinae.C @@ -0,0 +1,287 @@ +// Test exercising SFINAE depending on the well-definedness of constexpr +// functions. +// { dg-do compile { target c++14 } } + +#define Assert(e) static_assert ((e), #e) + +// Exercise SFINAE based on the absence of integer division by zero. +namespace DivByZero { + +// Define a pair of functions that have undefined and well-defined +// behavior, respectively, due to division by zero, depending on +// their arguments. + +// The following function is undefined when I is zero, well defined +// otherwise. +constexpr bool div_zero_0 (int i, int j) { return 1 + j / (i == 0); } + +// The following function is undefined when I is non-zero, and well +// defined otherwise. +constexpr bool div_zero_1 (int i, int j) { return 1 + j / (i != 0); } + +// Define a pair of overfloads each of which is viable when the constexpr +// function it invokes has well-defined semantics and not otherwise. +template +constexpr int f (int (*)[div_zero_0 (I, 0)] = 0) { return 0; } + +template +constexpr int f (int (*)[div_zero_1 (I, 0)] = 0) { return 1; } + +// Verify that the correct overload is selected based on the template +// argument and without triggering a compilation error for the undefined +// behavior in the non-viable constexpr function above. +Assert (f<0>() == 0); +Assert (f<1>() == 1); + +} + +// Exercise SFINAE based on the absence of signed integer overflow +// in addition. +namespace IntAddOverflow { + +constexpr int a [] = { 1234, __INT_MAX__ / 2 }; + +constexpr int vflow_0 (int i) { return a [!i] * 7; } +constexpr int vflow_1 (int i) { return a [i] * 11; } + +template +constexpr int f (int (*)[vflow_0 (I)] = 0) { return 1; } + +template +constexpr int f (int (*)[vflow_1 (I)] = 0) { return 0; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 0); +Assert (n1 == 1); + +} + +// Exercise SFINAE based on the absence of signed integer overflow +// in multiplication. +namespace IntMulOverflow { + +constexpr long a [] = { 1234, __LONG_MAX__ / 2 }; + +constexpr long vflow_0 (int i) { return a [!i] * 3; } +constexpr long vflow_1 (int i) { return a [i] * 7; } + +template +constexpr int f (int (*)[vflow_0 (I)] = 0) { return 1; } + +template +constexpr int f (int (*)[vflow_1 (I)] = 0) { return 0; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 0); +Assert (n1 == 1); + +} + +// Exercise SFINAE based on the absence of undefined pointer arithmetic +// involving null pointers. Subtracting one null pointer from another +// is well-defined, but subtracting a null pointer from a non-null one +// is not. +namespace NullPointerArithmetic { + +constexpr int i = 0; +constexpr const int* a[] = { 0, &i }; + +// Well-defined core constant expressoons involving null pointers. +constexpr __PTRDIFF_TYPE__ d00 = a [0] - a [0]; +constexpr __PTRDIFF_TYPE__ d11 = a [1] - a [1]; + +// Undefined core constant expressoons involving null pointers. +// constexpr __PTRDIFF_TYPE__ d01 = a [0] - a [1]; +// constexpr __PTRDIFF_TYPE__ d10 = a [1] - a [0]; + +constexpr bool nullptr_sub_0 (int i, int j) { return 1 + a [i != 0] - a [j]; } + +constexpr bool nullptr_sub_1 (int i, int j) { return 1 + a [i == 0] - a [j]; } + +template +constexpr int f (int (*)[nullptr_sub_0 (I, 0)] = 0) { return 0; } + +template +constexpr int f (int (*)[nullptr_sub_1 (I, 0)] = 0) { return 1; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 0); +Assert (n1 == 1); + +} + +// Exercise SFINAE based on the absence of undefined pointer arithmetic +// involving null poiinters. Subtracting one null pointer from another +// is well-defined, but subtracting a null pointer from a non-null one +// is not. +namespace NullPointerDereference { + +struct S { int a, b; }; + +constexpr S s = { }; +constexpr const S* a[] = { 0, &s }; + +constexpr bool nullptr_ref_0 (int i) { return &a [i != 0]->b == &s.b; } +constexpr bool nullptr_ref_1 (int i) { return &a [i == 0]->b == &s.b; } + +template +constexpr int f (int (*)[nullptr_ref_0 (I)] = 0) { return 1; } + +template +constexpr int f (int (*)[nullptr_ref_1 (I)] = 0) { return 0; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 0); +Assert (n1 == 1); + +} + +// Exercise SFINAE based on whether or not two constexpr function +// calls have a circular depency on one another such that a call +// to one would not terminate. +namespace CircularDependency { + +constexpr bool call_me (int i, bool (*f)(int)) { return f (i); } + +constexpr bool undefined_if_0 (int i) { + return i ? 1 : call_me (i, undefined_if_0); +} + +constexpr bool undefined_if_1 (int i) { + return i ? call_me (i, undefined_if_1) : 1; +} + +template +constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; } + +template +constexpr int f (int (*)[undefined_if_1 (I)] = 0) { return 1; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 1); +Assert (n1 == 0); + +} + +// Exercise SFINAE based on whether constexpr functions flow off +// the end without returning a value. +namespace FlowOffTheEnd { + +constexpr bool undefined_if_0 (int i) { switch (i) case 1: return 1; } +constexpr bool undefined_if_1 (int i) { switch (i) case 0: return 1; } + +template +constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 1; } + +template +constexpr int f (int (*)[undefined_if_1 (I)] = 0) { return 0; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 0); +Assert (n1 == 1); + +} + +// Exercise SFINAE based on the presence and absence of a left shift +// expression with a negative second operand. +namespace NegativeLeftShift { + +constexpr int a [] = { -1, 1 }; + +constexpr int undefined_if_0 (int i) { return 1 << a [i]; } +constexpr int undefined_if_1 (int i) { return 1 << a [!i]; } + +template +constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; } + +template +constexpr int f (int (*)[undefined_if_1 (I)] = 0) { return 1; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 1); +Assert (n1 == 0); + +} + +// Exercise SFINAE based on the presence and absence of a right shift +// expression with a negative second operand. +namespace NegativeRightShift { + +constexpr int a [] = { -1, 1 }; + +constexpr int undefined_if_0 (int i) { return 2 >> a [i]; } +constexpr int undefined_if_1 (int i) { return 2 >> a [!i]; } + +template +constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; } + +template +constexpr int f (int (*)[undefined_if_1 (I)] = 0) { return 1; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 1); +Assert (n1 == 0); + +} + +// Exercise SFINAE based on the absence of signed integer overflow +// in a signed left shift expression. +namespace LeftShiftOverflow { + +constexpr int a[] = { 1234, 1 }; + +constexpr int undefined_if_0 (int i) { return 1 << a [i]; } +constexpr int undefined_if_1 (int i) { return 1 << a [!i]; } + +template +constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; } + +template +constexpr int f (int (*)[undefined_if_1 (I)] = 0) { return 1; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 1); +Assert (n1 == 0); + +} + +// Exercise SFINAE based on the absence of using a negative array +// index. +namespace NegativeArrayIndex { + +constexpr int a [] = { -1, 1 }; + +constexpr int undefined_if_0 (int i) { return 2 + a [a [i]]; } +constexpr int undefined_if_1 (int i) { return 2 + a [a [!i]]; } + +template +constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; } + +template +constexpr int f (int (*)[undefined_if_1 (I)] = 0) { return 1; } + +constexpr int n0 = f<0>(); +constexpr int n1 = f<1>(); + +Assert (n0 == 1); +Assert (n1 == 0); + +} diff --git a/gcc/testsuite/gcc.dg/Woverride-init-1.c b/gcc/testsuite/gcc.dg/Woverride-init-1.c index 29eca3095cd..b01d8a29dcc 100644 --- a/gcc/testsuite/gcc.dg/Woverride-init-1.c +++ b/gcc/testsuite/gcc.dg/Woverride-init-1.c @@ -10,19 +10,19 @@ union u { char a; long long b; }; struct s s0 = { .a = 1, .b = 2, - .a = 3, /* { dg-warning "initialized field overwritten|near init" } */ - 4, /* { dg-warning "initialized field overwritten|near init" } */ + .a = 3, /* { dg-warning "initialized field overwritten" } */ + 4, /* { dg-warning "initialized field overwritten" } */ 5 }; union u u0 = { .a = 1, - .b = 2, /* { dg-warning "initialized field overwritten|near init" } */ - .a = 3 }; /* { dg-warning "initialized field overwritten|near init" } */ + .b = 2, /* { dg-warning "initialized field overwritten" } */ + .a = 3 }; /* { dg-warning "initialized field overwritten" } */ int a[5] = { [0] = 1, [1] = 2, - [0] = 3, /* { dg-warning "initialized field overwritten|near init" } */ + [0] = 3, /* { dg-warning "initialized field overwritten" } */ [2] = 4 }; diff --git a/gcc/testsuite/gcc.dg/Woverride-init-2.c b/gcc/testsuite/gcc.dg/Woverride-init-2.c index c5490b5ad35..d0ece89eb6d 100644 --- a/gcc/testsuite/gcc.dg/Woverride-init-2.c +++ b/gcc/testsuite/gcc.dg/Woverride-init-2.c @@ -10,19 +10,19 @@ union u { char a; long long b; }; struct s s0 = { .a = 1, .b = 2, - .a = 3, /* { dg-warning "initialized field overwritten|near init" } */ - 4, /* { dg-warning "initialized field overwritten|near init" } */ + .a = 3, /* { dg-warning "initialized field overwritten" } */ + 4, /* { dg-warning "initialized field overwritten" } */ 5 }; union u u0 = { .a = 1, - .b = 2, /* { dg-warning "initialized field overwritten|near init" } */ - .a = 3 }; /* { dg-warning "initialized field overwritten|near init" } */ + .b = 2, /* { dg-warning "initialized field overwritten" } */ + .a = 3 }; /* { dg-warning "initialized field overwritten" } */ int a[5] = { [0] = 1, [1] = 2, - [0] = 3, /* { dg-warning "initialized field overwritten|near init" } */ + [0] = 3, /* { dg-warning "initialized field overwritten" } */ [2] = 4 }; diff --git a/gcc/testsuite/gcc.dg/init-excess-2.c b/gcc/testsuite/gcc.dg/init-excess-2.c new file mode 100644 index 00000000000..1bf0a96a880 --- /dev/null +++ b/gcc/testsuite/gcc.dg/init-excess-2.c @@ -0,0 +1,47 @@ +/* Test for diagnostics about excess initializers when using a macro + defined in a system header: + c/71115 - Missing warning: excess elements in struct initializer. */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +#include + +int* a[1] = { + 0, + NULL /* { dg-warning "excess elements|near init" } */ +}; + +const char str[1] = { + 0, + NULL /* { dg-warning "excess elements|near init" } */ +}; + +struct S { + int *a; +} s = { + 0, + NULL /* { dg-warning "excess elements|near init" } */ +}; + +struct __attribute__ ((designated_init)) S2 { + int *a; +} s2 = { + NULL /* { dg-warning "positional initialization|near init" } */ +}; + +union U { + int *a; +} u = { + 0, + NULL /* { dg-warning "excess elements|near init" } */ +}; + +int __attribute__ ((vector_size (16))) ivec = { + 0, 0, 0, 0, + NULL /* { dg-warning "excess elements|near init" } */ +}; + +int* scal = { + 0, + NULL /* { dg-warning "excess elements|near init" } */ +}; -- 2.30.2