[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#343898: marked as done (fix for unreadable error messages in g++ when #define'ing min or max)



Your message dated Sun, 11 Apr 2010 14:30:34 +0000
with message-id <E1O0yBG-0008R0-RT@ravel.debian.org>
and subject line C++ and mudflap packages not built anymore from the gcc-4.1 source
has caused the Debian Bug report #343898,
regarding fix for unreadable error messages in g++ when #define'ing min or max
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
343898: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=343898
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: libstdc++6-4.0-dev
Version: 4.0.2-5
Tags: patch

Good day,

It seems there is an old and thorny issue that has addled my mind for
years.  It relates to the changing rules in C++ regarding max and min; in early
versions, it was perfectly legal to #define max or min as you please, and
indeed this is a standard idiom in many C programs.  When templates came in
later versions of C++ this practice was "outlawed" because the C preprocessor
lacks much of the enormous power that templates provide when combined within
the complex type / overloading system that was finally standardized.  The
language became so complex that very few people could understand it in its
entirety, and perhaps no part of C++ was more feared than template
instantiation such as STL.  In particular, the error messages generated when a
template error occurs are often delocalized with respect to the originating
"root cause", and usually full of many levels of difficult and technical
jargon due to many nested inline template instantiations.  I myself have on
at least 4 occasions over the years been confused when I wound up accidentally
#define'ing max or min  (sometime from somebody else's C #include file)
only to waste hours trying to parse the error messages that gcc provided
before I remembered to look for the offending min or max.
A typical error message goes like the one reported to

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12221

in 2003.  There you can find the history showing that the developer decided
it was "beyond the scope of V3".  It is an understatement to call these
error messages opaque for the vast majority of users.

Today I realized a simple solution to the problem.  I just wrapped all the
include files that use std::min or std::max with #ifdef checks to print
an error message that is easier to understand in the event of an accidental
definition of max or min that is contrary to the C++ standard.  I modified
less than two dozen files in a very generic and uncreative way.  The only
deviation was one place where I removed two #undef statements.  The sum
total effect of all this is that now whenever somebody accidentally breaks
the standard by #defining min or max, they get an error message they can read.
And oftentimes the rest of the distracting error messages disappear.  You can
see this bug for yourself using a very simple piece of code like the following:

#include <iostream>
#define min(a,b) ((a<b) ? (a) : (b))
#include <fstream>

int main(int argc, char **argv)
{
  return 0;
}

--

I have already made a patch implementing this change.  I hope that
it is included with a future version of libstdc++6-4.0-dev .  Using it,
the error messages from the above erroneous code are less than one-third
the original size and substantially clearer.

I would like to offer my patch as a gift to the many people who are struggling
every day to get past this too-difficult puzzle as they try to compile many
of their own various and interesting programs using g++.

Thanks a bunch for your time.  I include the patch below.

Rudi Cilibrasi
http://cilibrar.com/

--

diff -rNu /usr/include/c++/4.0.3/backward/algobase.h 43good/backward/algobase.h
--- /usr/include/c++/4.0.3/backward/algobase.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/backward/algobase.h	2005-12-18 15:26:12.000000000 +0100
@@ -55,6 +55,13 @@
 #ifndef _BACKWARD_ALGOBASE_H
 #define _BACKWARD_ALGOBASE_H 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #include "backward_warning.h"
 #include "pair.h"
 #include "iterator.h"
@@ -88,6 +95,10 @@
 // Names from ext/memory
 using __gnu_cxx::uninitialized_copy_n;
 
+#endif /* min/max protection */
+
+#endif
+
 #endif /* _BACKWARD_ALGOBASE_H */
 
 // Local Variables:
diff -rNu /usr/include/c++/4.0.3/bits/deque.tcc 43good/bits/deque.tcc
--- /usr/include/c++/4.0.3/bits/deque.tcc	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/deque.tcc	2005-12-18 15:28:16.000000000 +0100
@@ -61,6 +61,13 @@
 #ifndef _DEQUE_TCC
 #define _DEQUE_TCC 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 namespace _GLIBCXX_STD
 {
   template <typename _Tp, typename _Alloc>
@@ -764,4 +771,8 @@
     }
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/fstream.tcc 43good/bits/fstream.tcc
--- /usr/include/c++/4.0.3/bits/fstream.tcc	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/fstream.tcc	2005-12-18 15:28:45.000000000 +0100
@@ -40,6 +40,13 @@
 #ifndef _FSTREAM_TCC
 #define _FSTREAM_TCC 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #pragma GCC system_header
 
 namespace std
@@ -901,4 +908,8 @@
 #endif
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/istream.tcc 43good/bits/istream.tcc
--- /usr/include/c++/4.0.3/bits/istream.tcc	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/istream.tcc	2005-12-18 15:29:04.000000000 +0100
@@ -40,6 +40,13 @@
 #ifndef _ISTREAM_TCC
 #define _ISTREAM_TCC 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #pragma GCC system_header
 
 #include <locale>
@@ -1283,4 +1290,8 @@
 #endif
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/locale_facets.tcc 43good/bits/locale_facets.tcc
--- /usr/include/c++/4.0.3/bits/locale_facets.tcc	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/locale_facets.tcc	2005-12-18 15:29:33.000000000 +0100
@@ -36,6 +36,13 @@
 #ifndef _LOCALE_FACETS_TCC
 #define _LOCALE_FACETS_TCC 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #pragma GCC system_header
 
 #include <limits>		// For numeric_limits
@@ -2756,4 +2763,8 @@
 #endif
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/sstream.tcc 43good/bits/sstream.tcc
--- /usr/include/c++/4.0.3/bits/sstream.tcc	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/sstream.tcc	2005-12-18 15:30:02.000000000 +0100
@@ -40,6 +40,13 @@
 #ifndef _SSTREAM_TCC
 #define _SSTREAM_TCC 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #pragma GCC system_header
 
 #include <sstream>
@@ -235,4 +242,8 @@
 #endif
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/stl_algobase.h 43good/bits/stl_algobase.h
--- /usr/include/c++/4.0.3/bits/stl_algobase.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/stl_algobase.h	2005-12-18 15:30:36.000000000 +0100
@@ -61,6 +61,13 @@
 #ifndef _ALGOBASE_H
 #define _ALGOBASE_H 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #include <bits/c++config.h>
 #include <cstring>
 #include <climits>
@@ -166,9 +173,6 @@
 	iter_swap(__a, __b);
     }
 
-  #undef min
-  #undef max
-
   /**
    *  @brief This does what you think it does.
    *  @param  a  A thing of arbitrary type.
@@ -909,4 +913,8 @@
 
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/stl_algo.h 43good/bits/stl_algo.h
--- /usr/include/c++/4.0.3/bits/stl_algo.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/stl_algo.h	2005-12-18 15:30:51.000000000 +0100
@@ -61,6 +61,13 @@
 #ifndef _ALGO_H
 #define _ALGO_H 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #include <bits/stl_heap.h>
 #include <bits/stl_tempbuf.h>     // for _Temporary_buffer
 #include <debug/debug.h>
@@ -5161,4 +5168,8 @@
 
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif /* _ALGO_H */
diff -rNu /usr/include/c++/4.0.3/bits/stl_bvector.h 43good/bits/stl_bvector.h
--- /usr/include/c++/4.0.3/bits/stl_bvector.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/stl_bvector.h	2005-12-18 15:31:05.000000000 +0100
@@ -61,6 +61,13 @@
 #ifndef _BVECTOR_H
 #define _BVECTOR_H 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 namespace _GLIBCXX_STD
 {
   typedef unsigned long _Bit_type;
@@ -947,4 +954,8 @@
   };
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/stl_deque.h 43good/bits/stl_deque.h
--- /usr/include/c++/4.0.3/bits/stl_deque.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/stl_deque.h	2005-12-18 15:31:20.000000000 +0100
@@ -61,6 +61,13 @@
 #ifndef _DEQUE_H
 #define _DEQUE_H 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #include <bits/concept_check.h>
 #include <bits/stl_iterator_base_types.h>
 #include <bits/stl_iterator_base_funcs.h>
@@ -1531,4 +1538,8 @@
     { __x.swap(__y); }
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif /* _DEQUE_H */
diff -rNu /usr/include/c++/4.0.3/bits/stl_function.h 43good/bits/stl_function.h
--- /usr/include/c++/4.0.3/bits/stl_function.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/stl_function.h	2005-12-18 15:31:38.000000000 +0100
@@ -61,6 +61,13 @@
 #ifndef _FUNCTION_H
 #define _FUNCTION_H 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 namespace std
 {
   // 20.3.1 base classes
@@ -891,6 +898,10 @@
 
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif /* _FUNCTION_H */
 
 // Local Variables:
diff -rNu /usr/include/c++/4.0.3/bits/streambuf.tcc 43good/bits/streambuf.tcc
--- /usr/include/c++/4.0.3/bits/streambuf.tcc	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/streambuf.tcc	2005-12-18 15:31:50.000000000 +0100
@@ -40,6 +40,13 @@
 #ifndef _STREAMBUF_TCC
 #define _STREAMBUF_TCC 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #pragma GCC system_header
 
 namespace std
@@ -151,4 +158,8 @@
 #endif
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif
diff -rNu /usr/include/c++/4.0.3/bits/vector.tcc 43good/bits/vector.tcc
--- /usr/include/c++/4.0.3/bits/vector.tcc	2005-12-18 16:15:35.000000000 +0100
+++ 43good/bits/vector.tcc	2005-12-18 15:32:19.000000000 +0100
@@ -61,6 +61,13 @@
 #ifndef _VECTOR_TCC
 #define _VECTOR_TCC 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 namespace _GLIBCXX_STD
 {
   template<typename _Tp, typename _Alloc>
@@ -491,4 +498,8 @@
       }
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
 #endif /* _VECTOR_TCC */
diff -rNu /usr/include/c++/4.0.3/ext/codecvt_specializations.h 43good/ext/codecvt_specializations.h
--- /usr/include/c++/4.0.3/ext/codecvt_specializations.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/ext/codecvt_specializations.h	2005-12-18 15:33:35.000000000 +0100
@@ -42,6 +42,13 @@
   // Define this here so codecvt.cc can have _S_max_size definition.
 #define _GLIBCXX_USE_ENCODING_STATE 1
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 namespace __gnu_cxx
 {
   /// @brief  Extension to use icov for dealing with character encodings.
@@ -503,3 +510,7 @@
     { return 1; }
 } // namespace std
 
+#endif /* min/max protection */
+
+#endif
+
diff -rNu /usr/include/c++/4.0.3/ext/ropeimpl.h 43good/ext/ropeimpl.h
--- /usr/include/c++/4.0.3/ext/ropeimpl.h	2005-12-18 16:15:35.000000000 +0100
+++ 43good/ext/ropeimpl.h	2005-12-18 15:33:57.000000000 +0100
@@ -45,6 +45,13 @@
  *  You should not attempt to use it directly.
  */
 
+#ifdef min
+#error "It is illegal to #define min in C++."
+#else
+#ifdef max
+#error "It is illegal to #define max in C++."
+#else
+
 #include <cstdio>
 #include <ostream>
 #include <bits/functexcept.h>
@@ -1704,3 +1711,7 @@
 // Local Variables:
 // mode:C++
 // End:
+
+#endif /* min/max protection */
+
+#endif

-- System Information
Package files:
 100 /var/lib/dpkg/status
     release a=now
 500 http://security.debian.org etch/updates/contrib Packages
     release o=Debian,a=testing,l=Debian-Security,c=contrib
     origin security.debian.org
 500 http://security.debian.org etch/updates/main Packages
     release o=Debian,a=testing,l=Debian-Security,c=main
     origin security.debian.org
 500 http://ftp.surfnet.nl etch/contrib Packages
     release o=Debian,a=testing,l=Debian,c=contrib
     origin ftp.surfnet.nl
 500 http://ftp.surfnet.nl etch/main Packages
     release o=Debian,a=testing,l=Debian,c=main
     origin ftp.surfnet.nl
Pinned packages:
Shell: /bin/zsh
Locale: LANG=en_US, LC_CTYPE=zh_CN.UTF-8
Linux gosu 2.6.14.2alc #4 PREEMPT Sun Dec 11 22:49:50 CET 2005 i686 GNU/Linux

--
Package: libstdc++6-4.0-dev
Versions: 
4.0.2-5(/var/lib/apt/lists/ftp.surfnet.nl_os_Linux_distr_debian_dists_etch_main_binary-i386_Packages)(/var/lib/dpkg/status)

Reverse Depends: 
  libstdc++6-4.0-pic,libstdc++6-4.0-dev 4.0.2-5
  libstdc++6-4.0-dbg,libstdc++6-4.0-dev 4.0.2-5
  libgcj6-dev,libstdc++6-4.0-dev 4.0.1
  lib64stdc++6-4.0-dbg,libstdc++6-4.0-dev 4.0.2-5
  g++-4.0,libstdc++6-4.0-dev 4.0.2-5
Dependencies: 
4.0.2-5 - gcc-4.0-base (5 4.0.2-5) g++-4.0 (5 4.0.2-5) libstdc++6 (2 4.0.2-5) libc6-dev (2 2.3.5-5) libstdc++6-4.0-doc (0 (null)) stl-manual (0 (null)) libg++27-dev (0 (null)) libg++272-dev (3 2.7.2.8-1) libstdc++2.8-dev (0 (null)) libg++2.8-dev (0 (null)) libstdc++2.9-dev (0 (null)) libstdc++2.9-glibc2.1-dev (0 (null)) libstdc++2.10-dev (3 1:2.95.3-2) libstdc++3.0-dev (0 (null)) libstdc++6-0-dev (0 (null)) libstdc++6-0-dev (0 (null)) 
Provides: 
4.0.2-5 - libstdc++-dev 
Reverse Provides: 


--- End Message ---
--- Begin Message ---
The C++ and mudflap binary packages are not built anymore from the
gcc-4.1 source package.  Tagging this report as won't fix, and closing
the report.

Please check if the problem is fixed in gcc-4.4 (or gcc-4.5/gcc-snapshot).
If the problem is not fixed, and not yet reported for the new compiler
version(s), open a new report.


--- End Message ---

Reply to: