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
*** Bug 30993 has been marked as a duplicate of this bug. ***
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.
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; }
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.
Oops, sorry for the typo (twice -DTEST3, never -DTEST2). But with -DTEST2 the output is always identical to -DTEST3 with all compilers.
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
Fixed on the trunk.
Closing 4.1 branch.
Closing 4.2 branch, fixed in 4.3.
(In reply to comment #9) > Closing 4.2 branch, fixed in 4.3. Thanks!