|
1 #ifndef BOOST_STATIC_WARNING_HPP |
|
2 #define BOOST_STATIC_WARNING_HPP |
|
3 |
|
4 // (C) Copyright Robert Ramey 2003. Jonathan Turkanis 2004. |
|
5 // Use, modification and distribution is subject to the Boost Software |
|
6 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
|
7 // MS compatible compilers support #pragma once |
|
8 #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
|
9 # pragma once |
|
10 #endif |
|
11 |
|
12 // http://www.boost.org/LICENSE_1_0.txt) |
|
13 |
|
14 // See http://www.boost.org/libs/static_assert for documentation. |
|
15 |
|
16 /* |
|
17 Revision history: |
|
18 15 June 2003 - Initial version. |
|
19 31 March 2004 - improved diagnostic messages and portability |
|
20 (Jonathan Turkanis) |
|
21 03 April 2004 - works on VC6 at class and namespace scope |
|
22 - ported to DigitalMars |
|
23 - static warnings disabled by default; when enabled, |
|
24 uses pragmas to enable required compiler warnings |
|
25 on MSVC, Intel, Metrowerks and Borland 5.x. |
|
26 (Jonathan Turkanis) |
|
27 30 May 2004 - tweaked for msvc 7.1 and gcc 3.3 |
|
28 - static warnings ENabled by default; when enabled, |
|
29 (Robert Ramey) |
|
30 */ |
|
31 |
|
32 #include <boost/config.hpp> |
|
33 |
|
34 // |
|
35 // Implementation |
|
36 // Makes use of the following warnings: |
|
37 // 1. GCC prior to 3.3: division by zero. |
|
38 // 2. BCC 6.0 preview: unreferenced local variable. |
|
39 // 3. DigitalMars: returning address of local automatic variable. |
|
40 // 4. VC6: class previously seen as struct (as in 'boost/mpl/print.hpp') |
|
41 // 5. All others: deletion of pointer to incomplete type. |
|
42 // |
|
43 // The trick is to find code which produces warnings containing the name of |
|
44 // a structure or variable. Details, with same numbering as above: |
|
45 // 1. static_warning_impl<B>::value is zero iff B is false, so diving an int |
|
46 // by this value generates a warning iff B is false. |
|
47 // 2. static_warning_impl<B>::type has a constructor iff B is true, so an |
|
48 // unreferenced variable of this type generates a warning iff B is false. |
|
49 // 3. static_warning_impl<B>::type overloads operator& to return a dynamically |
|
50 // allocated int pointer only is B is true, so returning the address of an |
|
51 // automatic variable of this type generates a warning iff B is fasle. |
|
52 // 4. static_warning_impl<B>::STATIC_WARNING is decalred as a struct iff B is |
|
53 // false. |
|
54 // 5. static_warning_impl<B>::type is incomplete iff B is false, so deleting a |
|
55 // pointer to this type generates a warning iff B is false. |
|
56 // |
|
57 |
|
58 //------------------Enable selected warnings----------------------------------// |
|
59 |
|
60 // Enable the warnings relied on by BOOST_STATIC_WARNING, where possible. The |
|
61 // only pragma which is absolutely necessary here is for Borland 5.x, since |
|
62 // W8073 is disabled by default. If enabling selected warnings is considered |
|
63 // unacceptable, this section can be replaced with: |
|
64 // #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x600) |
|
65 // pragma warn +stu |
|
66 // #endif |
|
67 |
|
68 # if defined(BOOST_MSVC) |
|
69 # pragma warning(2:4150) // C4150: deletion of pointer to incomplete type 'type'. |
|
70 # elif defined(BOOST_INTEL) && (defined(__WIN32__) || defined(WIN32)) |
|
71 # pragma warning(2:457) // #457: delete of pointer to incomplete class. |
|
72 # elif defined(__BORLANDC__) && (__BORLANDC__ <= 0x600) |
|
73 # pragma warn +stu // W8073: Undefined structure 'structure'. |
|
74 # elif defined(__MWERKS__) |
|
75 # pragma extended_errorcheck on // Enable 'extended error checking'. |
|
76 # endif |
|
77 |
|
78 //------------------Configure-------------------------------------------------// |
|
79 |
|
80 # if defined(__BORLANDC__) && (__BORLANDC__ >= 0x600) |
|
81 # define BOOST_HAS_DESCRIPTIVE_UNREFERENCED_VARIABLE_WARNING |
|
82 # elif defined(__GNUC__) && !defined(BOOST_INTEL) // && (__GNUC__ * 100 + __GNUC_MINOR__ <= 302) |
|
83 # define BOOST_HAS_DESCRIPTIVE_DIVIDE_BY_ZERO_WARNING |
|
84 # elif defined(__DMC__) |
|
85 # define BOOST_HAS_DESCRIPTIVE_RETURNING_ADDRESS_OF_TEMPORARY_WARNING |
|
86 # elif defined(BOOST_MSVC) // && (BOOST_MSVC < 1300) |
|
87 # define BOOST_NO_PREDEFINED_LINE_MACRO |
|
88 # pragma warning(disable:4094) // C4094: untagged 'stuct' declared no symbols |
|
89 #endif |
|
90 |
|
91 //------------------Helper templates------------------------------------------// |
|
92 |
|
93 namespace boost { |
|
94 |
|
95 struct STATIC_WARNING; |
|
96 |
|
97 template<bool> |
|
98 struct static_warning_impl; |
|
99 |
|
100 template<> |
|
101 struct static_warning_impl<false> { |
|
102 enum { value = 0 }; |
|
103 #if !defined(BOOST_HAS_DESCRIPTIVE_UNREFERENCED_VARIABLE_WARNING) && \ |
|
104 !defined(BOOST_HAS_DESCRIPTIVE_RETURNING_ADDRESS_OF_TEMPORARY_WARNING) |
|
105 typedef boost::STATIC_WARNING type; |
|
106 #else |
|
107 typedef int type; |
|
108 #endif |
|
109 #if defined(BOOST_NO_PREDEFINED_LINE_MACRO) |
|
110 struct STATIC_WARNING { }; |
|
111 #endif |
|
112 }; |
|
113 |
|
114 template<> |
|
115 struct static_warning_impl<true> { |
|
116 enum { value = 1 }; |
|
117 struct type { type() { } int* operator&() { return new int; } }; |
|
118 #if defined(BOOST_NO_PREDEFINED_LINE_MACRO) |
|
119 class STATIC_WARNING { }; |
|
120 #endif |
|
121 }; |
|
122 |
|
123 } // namespace boost |
|
124 |
|
125 //------------------Definition of BOOST_STATIC_WARNING------------------------// |
|
126 |
|
127 #if defined(BOOST_HAS_DESCRIPTIVE_UNREFERENCED_VARIABLE_WARNING) |
|
128 # define BOOST_STATIC_WARNING_IMPL(B) \ |
|
129 struct BOOST_JOIN(STATIC_WARNING, __LINE__) { \ |
|
130 void f() { \ |
|
131 ::boost::static_warning_impl<(bool)( B )>::type \ |
|
132 STATIC_WARNING; \ |
|
133 } \ |
|
134 } \ |
|
135 /**/ |
|
136 #elif defined(BOOST_HAS_DESCRIPTIVE_RETURNING_ADDRESS_OF_TEMPORARY_WARNING) |
|
137 # define BOOST_STATIC_WARNING_IMPL(B) \ |
|
138 struct BOOST_JOIN(STATIC_WARNING, __LINE__) { \ |
|
139 int* f() { \ |
|
140 ::boost::static_warning_impl<(bool)( B )>::type \ |
|
141 STATIC_WARNING; \ |
|
142 return &STATIC_WARNING; \ |
|
143 } \ |
|
144 } \ |
|
145 /**/ |
|
146 #elif defined(BOOST_HAS_DESCRIPTIVE_DIVIDE_BY_ZERO_WARNING) |
|
147 # define BOOST_STATIC_WARNING_IMPL(B) \ |
|
148 struct BOOST_JOIN(STATIC_WARNING, __LINE__) { \ |
|
149 int f() { int STATIC_WARNING = 1; \ |
|
150 return STATIC_WARNING / \ |
|
151 boost::static_warning_impl<(bool)( B )>::value; } \ |
|
152 } \ |
|
153 /**/ |
|
154 #elif defined(BOOST_NO_PREDEFINED_LINE_MACRO) |
|
155 // VC6; __LINE__ macro broken when -ZI is used see Q199057, so |
|
156 // non-conforming workaround is used. |
|
157 # define BOOST_STATIC_WARNING_IMPL(B) \ |
|
158 struct { \ |
|
159 struct S { \ |
|
160 typedef boost::static_warning_impl<(bool)( B )> f; \ |
|
161 friend class f::STATIC_WARNING; \ |
|
162 }; \ |
|
163 } \ |
|
164 /**/ |
|
165 #else // Deletion of pointer to incomplete type. |
|
166 # define BOOST_STATIC_WARNING_IMPL(B) \ |
|
167 struct BOOST_JOIN(STATIC_WARNING, __LINE__) { \ |
|
168 ::boost::static_warning_impl<(bool)( B )>::type* p; \ |
|
169 void f() { delete p; } \ |
|
170 } \ |
|
171 /**/ |
|
172 #endif |
|
173 |
|
174 #ifndef BOOST_DISABLE_STATIC_WARNINGS |
|
175 # define BOOST_STATIC_WARNING(B) BOOST_STATIC_WARNING_IMPL(B) |
|
176 #else // #ifdef BOOST_ENABLE_STATIC_WARNINGS //-------------------------------// |
|
177 # define BOOST_STATIC_WARNING(B) BOOST_STATIC_WARNING_IMPL(true) |
|
178 #endif |
|
179 |
|
180 #endif // BOOST_STATIC_WARNING_HPP |