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 <msebor@redhat.com> 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 <msebor@redhat.com> PR c/71115 * gcc.dg/init-excess-2.c: New test. From-SVN: r236549
This commit is contained in:
parent
55c8849f5d
commit
79063edd74
|
@ -1,3 +1,10 @@
|
|||
2016-05-20 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c/71115
|
||||
* c-typeck.c (error_init): Use
|
||||
expansion_point_location_if_in_system_header.
|
||||
(warning_init): Same.
|
||||
|
||||
2016-05-19 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR c/71171
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2016-05-20 Martin Sebor <msebor@redhat.com>
|
||||
|
||||
PR c/71115
|
||||
* gcc.dg/init-excess-2.c: New test.
|
||||
|
||||
2016-05-20 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gnat.dg/opt53.adb: New test.
|
||||
|
|
|
@ -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 <int I>
|
||||
constexpr int f (int (*)[div_zero_0 (I, 0)] = 0) { return 0; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[vflow_0 (I)] = 0) { return 1; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[vflow_0 (I)] = 0) { return 1; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[nullptr_sub_0 (I, 0)] = 0) { return 0; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[nullptr_ref_0 (I)] = 0) { return 1; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 1; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; }
|
||||
|
||||
template <int I>
|
||||
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 <int I>
|
||||
constexpr int f (int (*)[undefined_if_0 (I)] = 0) { return 0; }
|
||||
|
||||
template <int I>
|
||||
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);
|
||||
|
||||
}
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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 <stddef.h>
|
||||
|
||||
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" } */
|
||||
};
|
Loading…
Reference in New Issue