diff options
author | Martin Sebor <msebor@redhat.com> | 2017-12-19 22:09:00 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2017-12-19 15:09:00 -0700 |
commit | 5837edca5cf5eb7cc45a2a61f69543264b50bbc8 (patch) | |
tree | 4edb5b94d34e42be541d40917ea365d8ba308efd /gcc | |
parent | 0cbe950d2475c51d8df2cc3a5afd55ff537d25cc (diff) | |
download | gcc-5837edca5cf5eb7cc45a2a61f69543264b50bbc8.zip gcc-5837edca5cf5eb7cc45a2a61f69543264b50bbc8.tar.gz gcc-5837edca5cf5eb7cc45a2a61f69543264b50bbc8.tar.bz2 |
PR c++/83394 - always_inline vs. noinline no longer diagnosed
PR c++/83394 - always_inline vs. noinline no longer diagnosed
PR c++/83322 - ICE: tree check: expected class ‘type’, have ‘exceptional’
gcc/cp/ChangeLog:
PR c++/83394
PR c++/83322
* decl2.c (cplus_decl_attributes): Look up member functions
in the scope of their class.
gcc/testsuite/ChangeLog:
PR c++/83394
* g++.dg/Wattributes-3.C: New test.
* g++.dg/Wattributes-4.C: New test.
* g++.dg/Wattributes-5.C: New test.
From-SVN: r255844
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 69 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/Wattributes-3.C | 90 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/Wattributes-4.C | 29 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/Wattributes-5.C | 34 |
6 files changed, 214 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8a66949..831cb23 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2017-12-19 Martin Sebor <msebor@redhat.com> + + PR c++/83394 + PR c++/83322 + * decl2.c (cplus_decl_attributes): Look up member functions + in the scope of their class. + 2017-12-19 Jakub Jelinek <jakub@redhat.com> * name-lookup.c (get_std_name_hint): Replace Yoda conditions with diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 5a87f30..d5111d5 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1445,6 +1445,52 @@ cp_omp_mappable_type (tree type) return true; } +/* Return the last pushed declaration for the symbol DECL or NULL + when no such declaration exists. */ + +static tree +find_last_decl (tree decl) +{ + tree last_decl = NULL_TREE; + + if (tree name = DECL_P (decl) ? DECL_NAME (decl) : NULL_TREE) + { + /* Look up the declaration in its scope. */ + tree pushed_scope = NULL_TREE; + if (tree ctype = DECL_CONTEXT (decl)) + pushed_scope = push_scope (ctype); + + last_decl = lookup_name (name); + + if (pushed_scope) + pop_scope (pushed_scope); + + /* The declaration may be a member conversion operator + or a bunch of overfloads (handle the latter below). */ + if (last_decl && BASELINK_P (last_decl)) + last_decl = BASELINK_FUNCTIONS (last_decl); + } + + if (!last_decl) + return NULL_TREE; + + if (DECL_P (last_decl) || TREE_CODE (last_decl) == OVERLOAD) + { + /* A set of overloads of the same function. */ + for (lkp_iterator iter (last_decl); iter; ++iter) + { + if (TREE_CODE (*iter) == OVERLOAD) + continue; + + if (decls_match (decl, *iter, /*record_decls=*/false)) + return *iter; + } + return NULL_TREE; + } + + return NULL_TREE; +} + /* Like decl_attributes, but handle C++ complexity. */ void @@ -1496,28 +1542,7 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags) } else { - tree last_decl = (DECL_P (*decl) && DECL_NAME (*decl) - ? lookup_name (DECL_NAME (*decl)) : NULL_TREE); - - if (last_decl && TREE_CODE (last_decl) == OVERLOAD) - for (ovl_iterator iter (last_decl, true); ; ++iter) - { - if (!iter) - { - last_decl = NULL_TREE; - break; - } - - if (TREE_CODE (*iter) == OVERLOAD) - continue; - - if (decls_match (*decl, *iter, /*record_decls=*/false)) - { - last_decl = *iter; - break; - } - } - + tree last_decl = find_last_decl (*decl); decl_attributes (decl, attributes, flags, last_decl); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7a52c37..cb9e012 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2017-12-19 Martin Sebor <msebor@redhat.com> + + PR c++/83394 + * g++.dg/Wattributes-3.C: New test. + * g++.dg/Wattributes-4.C: New test. + * g++.dg/Wattributes-5.C: New test. + 2017-12-19 Jakub Jelinek <jakub@redhat.com> PR target/82975 diff --git a/gcc/testsuite/g++.dg/Wattributes-3.C b/gcc/testsuite/g++.dg/Wattributes-3.C new file mode 100644 index 0000000..a70176b --- /dev/null +++ b/gcc/testsuite/g++.dg/Wattributes-3.C @@ -0,0 +1,90 @@ +// PR c++/83394 - always_inline vs. noinline no longer diagnosed +// { dg-do compile } +// { dg-options "-Wattributes" } + +#define ATTR(list) __attribute__ (list) + +struct A +{ + ATTR ((__noinline__)) operator int (); +}; + +ATTR ((__always_inline__)) +A::operator int () // { dg-warning "ignoring attribute .always_inline. because it conflicts with attribute .noinline." } +{ + return 0; +} + + +struct B +{ + operator char () const; + ATTR ((__always_inline__)) operator int () const; +}; + +B::operator char () const { return 0; } + +ATTR ((__noinline__)) +B::operator int () const // { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } +{ + return 0; +} + + +struct C +{ + operator char (); + ATTR ((__always_inline__)) operator short (); + operator int (); + ATTR ((__noinline__)) operator long (); +}; + +C::operator char () { return 0; } + +ATTR ((__noinline__)) +C::operator short () // { dg-warning "ignoring attribute .noinline. because it conflicts with attribute .always_inline." } +{ return 0; } + +inline ATTR ((__noinline__)) +C::operator int () +{ return 0; } + + +ATTR ((__always_inline__)) +C::operator long () // { dg-warning "ignoring attribute .always_inline. because it conflicts with attribute .noinline." } +{ return 0; } + + +struct D +{ + int foo (); + int foo (int); + int ATTR ((const)) foo (int, int); + int ATTR ((pure)) foo (int, int, int); + + int ATTR ((const)) foo (int, int, int, int); + + int foo (int, int, int, int, int); +}; + +int ATTR ((const)) +D::foo () +{ return 0; } + +int ATTR ((pure)) +D::foo (int) +{ return 0; } + +int ATTR ((pure)) +D::foo (int, int) // { dg-warning "ignoring attribute .pure. because it conflicts with attribute .const." } +{ return 0; } + +int ATTR ((const)) +D::foo (int, int, int) // { dg-warning "ignoring attribute .const. because it conflicts with attribute .pure." } +{ return 0; } + +int +D::foo (int, int, int, int) { return 0; } + +int ATTR ((const)) +D::foo (int, int, int, int, int) { return 0; } diff --git a/gcc/testsuite/g++.dg/Wattributes-4.C b/gcc/testsuite/g++.dg/Wattributes-4.C new file mode 100644 index 0000000..c925225 --- /dev/null +++ b/gcc/testsuite/g++.dg/Wattributes-4.C @@ -0,0 +1,29 @@ +// PR c++/83322 - ICE: tree check: expected class ‘type’, have ‘exceptional’ +// (baselink) in diag_attr_exclusions, at attribs.c:393 +// { dg-do compile } +// { dg-options "-Wattributes" } + +#define ATTR(list) __attribute__ (list) + +// Test case from comment #0. +struct A0 +{ + template <class T> operator T(); + ATTR ((always_inline)) operator int(); +}; + +// Test case from comment #4. +struct A1 +{ + void foo(); +}; + +struct B +{ + bool foo; +}; + +struct C: A1, B +{ + ATTR ((warn_unused_result)) int foo (); +}; diff --git a/gcc/testsuite/g++.dg/Wattributes-5.C b/gcc/testsuite/g++.dg/Wattributes-5.C new file mode 100644 index 0000000..70116c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/Wattributes-5.C @@ -0,0 +1,34 @@ +// { dg-do compile } +// { dg-options "-Wattributes" } + +#define ATTR(list) __attribute__ (list) + +template <int> +struct A +{ + int __attribute__ ((noinline)) + f (); // { dg-message "previous declaration here" } +}; + +template <int N> +int __attribute__ ((always_inline)) +A<N>::f () // { dg-warning "ignoring attribute .always_inline. because it conflicts with attribute .noinline." } */ +{ return 0; } + + +template <int> +struct B +{ + int __attribute__ ((always_inline)) + f (); +}; + +template <> +inline int __attribute__ ((always_inline)) +B<0>::f () +{ return 0; } + +template <> +int __attribute__ ((noinline)) +B<1>::f () +{ return 1; } |