Bug 30988 - [4.2 Regression] Incorrect "no return statement" warning with __attribute__ ((noreturn)) and __FUNCTION__
Summary: [4.2 Regression] Incorrect "no return statement" warning with __attribute__ (...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.1
: P2 minor
Target Milestone: 4.3.0
Assignee: Jakub Jelinek
URL:
Keywords: diagnostic
: 30993 (view as bug list)
Depends on:
Blocks:
 
Reported: 2007-02-27 22:18 UTC by Geoffrey Irving
Modified: 2009-03-30 21:43 UTC (History)
3 users (show)

See Also:
Host: x86_64-redhat-linux
Target: x86_64-redhat-linux
Build: x86_64-redhat-linux
Known to work: 3.3.3 4.3.0
Known to fail: 3.4.0 4.0.0 4.1.0 4.2.0 4.2.5
Last reconfirmed: 2007-11-18 22:21:37


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Geoffrey Irving 2007-02-27 22:18:52 UTC
The following code incorrectly warns that the function g is missing a return statement.  The warning goes away if __FUNCTION__ is replaced by
(const char*)__FUNCTION__.

================ BEGIN CODE ==================
void f(const char*) __attribute__ ((noreturn));

template<class T>
class A
{
    int g()
    {
        f(__FUNCTION__);
        //f((const char*)__FUNCTION__);
    }
};

template class A<int>;
============================ END code

wedge:scratch% g++ -O3 -Wall -c -v noreturn.cpp
Using built-in specs.
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=x86_64-redhat-linux
Thread model: posix
gcc version 4.1.1 20060525 (Red Hat 4.1.1-1)
 /usr/libexec/gcc/x86_64-redhat-linux/4.1.1/cc1plus -quiet -v -D_GNU_SOURCE noreturn.cpp -quiet -dumpbase noreturn.cpp -mtune=generic -auxbase noreturn -O3 -Wall -version -o /tmp/ccVj3EZ3.s
ignoring nonexistent directory "/usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../x86_64-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1
 /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/x86_64-redhat-linux
 /usr/lib/gcc/x86_64-redhat-linux/4.1.1/../../../../include/c++/4.1.1/backward
 /usr/local/include
 /usr/lib/gcc/x86_64-redhat-linux/4.1.1/include
 /usr/include
End of search list.
GNU C++ version 4.1.1 20060525 (Red Hat 4.1.1-1) (x86_64-redhat-linux)
        compiled by GNU C version 4.1.1 20060525 (Red Hat 4.1.1-1).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 56236c31509b2b0d4a3c4ac0327da7d9
noreturn.cpp: In member function ‘int A<T>::g()’:
noreturn.cpp:10: warning: no return statement in function returning non-void
 as -V -Qy -o noreturn.o /tmp/ccVj3EZ3.s
GNU assembler version 2.16.91.0.6 (x86_64-redhat-linux) using BFD version 2.16.91.0.6 20060212
Comment 1 Andrew Pinski 2007-02-28 00:26:15 UTC
*** Bug 30993 has been marked as a duplicate of this bug. ***
Comment 2 Andrew Pinski 2007-03-03 21:50:09 UTC
Confirmed, a regression from 3.3.3.  I made sure in 3.3.3, we would warn about the function if we removed the attribute noreturn so I know the warning works for that case.
Comment 3 Seongbae Park 2007-03-13 22:57:26 UTC
This is somewhat complicated. 
The extra type cast causes
different code paths to be taken.
In particular, in finish_call_expr() in cp/semantics.c:

  if (processing_template_decl)
    {
      if (type_dependent_expression_p (fn)
          || any_type_dependent_arguments_p (args))
        {
          result = build_nt_call_list (fn, args);
          KOENIG_LOOKUP_P (result) = koenig_p;
          return result;
        }
      if (!BASELINK_P (fn)
          && TREE_CODE (fn) != PSEUDO_DTOR_EXPR
          && TREE_TYPE (fn) != unknown_type_node)
        fn = build_non_dependent_expr (fn);
      args = build_non_dependent_args (orig_args);



With the type cast, 
build_over_call() is called eventually
which checks TREE_THIS_VOLATILE() for the callee function decl
and mark the current function (i.e. caller A::g) as returns_abnormally.
The lack of the type cast triggers
any_type_dependent_arguments_p(args) above,
leading to build_nt_call_list() which doesn't do this marking
of the returns_abnormally.

Now, not being familiar with the c++ frontend,
I'm not sure where exactly we should do the checking
of TREE_THIS_VOLATILE() for the callee decl.

The following patch seems to fix the problem 
(though I can't even tell whether this is the right approach):

diff -r 15a559a8fcf0 gcc/cp/semantics.c
--- a/gcc/cp/semantics.c        Mon Mar 12 15:38:22 2007 -0700
+++ b/gcc/cp/semantics.c        Tue Mar 13 15:48:45 2007 -0700
@@ -1816,6 +1816,10 @@ finish_call_expr (tree fn, tree args, bo
          || any_type_dependent_arguments_p (args))
        {
          result = build_nt_call_list (fn, args);
+
+         if (fn && TREE_THIS_VOLATILE (fn) && cfun)
+           current_function_returns_abnormally = 1;
+
          KOENIG_LOOKUP_P (result) = koenig_p;
          return result;
        }



Comment 4 Jakub Jelinek 2007-11-17 12:33:55 UTC
IMNSHO this is not a regression.
void f (const char *)
#ifdef NORET
__attribute__ ((noreturn))
#endif
;

template <class T> struct A
{
  int g ()
  {
#ifdef TEST1
    f (__FUNCTION__);
#elif defined TEST2
    f ((const char*) __FUNCTION__);
#else
    f ((const char *) 0);
#endif
  }
};

for k in gcc-2.96-rh gcc-3.2 gcc-3.3 gcc-3.4 gcc-4.1 gcc-4.2 gcc-4.3; do for i in " -DNORET" ""; do \
  for j in -DTEST1 -DTEST3 -DTEST3; do \
    /usr/src/$k/obj/gcc/cc1plus $i $j pr30988.C -O3 -Wall -quiet 2>&1 \
      | sed -n "/warning:/s/^/$k$i $j /p"; done; done; done
gcc-3.2 -DNORET -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.2 -DNORET -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.2 -DNORET -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.2 -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.2 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.2 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.4 -DNORET -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.4 -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.4 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-3.4 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.1 -DNORET -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.1 -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.1 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.1 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.2 -DNORET -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.2 -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.2 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.2 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.3 -DNORET -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.3 -DTEST1 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.3 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void
gcc-4.3 -DTEST3 pr30988.C:18: warning: no return statement in function returning non-void

So, gcc-2.96-RH and 3.3 wouldn't warn ever in templates, even for cases where it should warn, e.g. when the argument is not type dependent and neither the called function has noreturn attribute.
Comment 5 Jakub Jelinek 2007-11-17 12:35:55 UTC
Oops, sorry for the typo (twice -DTEST3, never -DTEST2).  But with -DTEST2 the output is always identical to -DTEST3 with all compilers.
Comment 6 Jakub Jelinek 2007-11-18 22:21:05 UTC
Subject: Bug 30988

Author: jakub
Date: Sun Nov 18 22:20:54 2007
New Revision: 130280

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=130280
Log:
	PR c++/30988
	semantics.c (finish_call_expr): Set current_function_returns_abnormally
	if fn is noreturn FUNCTION_DECL or OVERLOAD with all noreturn
	functions.

	* g++.dg/warn/noreturn-4.C: New test.
	* g++.dg/warn/noreturn-5.C: New test.
	* g++.dg/warn/noreturn-6.C: New test.
	* g++.dg/warn/noreturn-7.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/warn/noreturn-4.C
    trunk/gcc/testsuite/g++.dg/warn/noreturn-5.C
    trunk/gcc/testsuite/g++.dg/warn/noreturn-6.C
    trunk/gcc/testsuite/g++.dg/warn/noreturn-7.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/semantics.c
    trunk/gcc/testsuite/ChangeLog

Comment 7 Jakub Jelinek 2007-11-18 22:21:37 UTC
Fixed on the trunk.
Comment 8 Joseph S. Myers 2008-07-04 21:59:42 UTC
Closing 4.1 branch.
Comment 9 Joseph S. Myers 2009-03-30 21:40:37 UTC
Closing 4.2 branch, fixed in 4.3.
Comment 10 Geoffrey Irving 2009-03-30 21:43:18 UTC
(In reply to comment #9)
> Closing 4.2 branch, fixed in 4.3.

Thanks!