summaryrefslogtreecommitdiff
path: root/src/warnings.hpp
blob: 9f184a5c31d4765a4f8e02b2d58a1124311ddd12 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
// no include guards
// This is the first file in every compilation, passed by the makefile.
// This file contains only preprocessor directions.

// This file is currently targeted at:
// GCC 4.6 (incomplete due to bugs)
// GCC 4.7 (for few minor workarounds)
// GCC 4.8 (zarro boogs found)
// clang 3.1 (may ICE later)
// clang 3.2 (with a few major workarounds)

// List of warnings that require arguments,
// and thus cannot reliably be activated:
//  gcc 4.6:
//      -Wlarger-than=<1024>
//      -Wnormalized=<id|nfc|nfd>
//      -Wsuggest-attribute=<noreturn,const,pure,format>
//  gcc 4.7:
//      -Wstack-usage=<8192>
//  ???
//      -Wstrict-aliasing=<1>
//      -Wstrict-overflow=<1>

// options that enable other options
// only warnings so I can catch the errors
#pragma GCC diagnostic warning "-Wall"
#pragma GCC diagnostic warning "-Wextra"
#pragma GCC diagnostic warning "-Wunused"
#pragma GCC diagnostic warning "-Wformat"

#ifdef __clang__
# if __clang_major__ < 3
#  error "your clang is way too old"
# elif __clang_major__ == 3
#  if __clang_minor__ < 1
#   error "your clang is too old"
#  endif // __clang_minor__
# endif // __clang_major__
#else // __clang__
# if __GNUC__ < 4
#  error "your gcc is way too old"
#  if __GNUC_MINOR__ < 6
#   error "your gcc is too old"
#  elif __GNUC_MINOR__ == 6
#   if __GNUC_PATCHLEVEL__ < 3
#    error "TODO: test this patchlevel"
#   endif // __GNUC_PATCHLEVEL__
#  elif __GNUC_MINOR__ == 7
#   if __GNUC_PATCHLEVEL__ < 2
#    error "your gcc has a known bad patchlevel"
#   endif // __GNUC_PATCHLEVEL__
#  endif // __GNUC_MINOR__
# endif // __GNUC__
#endif // __clang__

// BEGIN Macros to make my life easier

// stringification requirement - #sw within #ar
#define P(ar) _Pragma(#ar)

// Use "GCC diagnostic" for warnings applicable to all versions.
#define I(sw) P(GCC diagnostic ignored #sw)
#define W(sw) P(GCC diagnostic warning #sw)
#define E(sw) P(GCC diagnostic error #sw)
// configurable thing (also change in clang below!)
#define X(sw) I(sw)


#ifdef __clang__

// Use "clang diagnostic" for warnings specific to clang
# define IC(sw) P(clang diagnostic ignored #sw)
# define WC(sw) P(clang diagnostic warning #sw)
# define EC(sw) P(clang diagnostic error #sw)
# define XC(sw) IC(sw) // this is below

// warning specific to gcc
# define IG(sw) static_assert('I', #sw "skipped for clang");
# define WG(sw) static_assert('W', #sw "skipped for clang");
# define EG(sw) static_assert('E', #sw "skipped for clang");
# define XG(sw) static_assert('X', #sw "skipped for clang");

# define IG47(sw) static_assert('I', #sw "only for gcc 4.7+");
# define WG47(sw) static_assert('W', #sw "only for gcc 4.7+");
# define EG47(sw) static_assert('E', #sw "only for gcc 4.7+");
# define XG47(sw) static_assert('X', #sw "only for gcc 4.7+");

# define IG48(sw) static_assert('I', #sw "only for gcc 4.8+");
# define WG48(sw) static_assert('W', #sw "only for gcc 4.8+");
# define EG48(sw) static_assert('E', #sw "only for gcc 4.8+");
# define XG48(sw) static_assert('X', #sw "only for gcc 4.8+");

# define I47(sw) I(sw)
# define W47(sw) W(sw)
# define E47(sw) E(sw)
# define X47(sw) X(sw)

# define I48(sw) I(sw)
# define W48(sw) W(sw)
# define E48(sw) E(sw)
# define X48(sw) X(sw)

#else

// warnings specific to clang
# define IC(sw) static_assert('I', #sw "skipped for gcc");
# define WC(sw) static_assert('W', #sw "skipped for gcc");
# define EC(sw) static_assert('E', #sw "skipped for gcc");
# define XC(sw) static_assert('X', #sw "skipped for gcc");

// warnings specific to gcc
# define IG(sw) I(sw)
# define WG(sw) W(sw)
# define EG(sw) E(sw)
# define XG(sw) X(sw)

// used both for warnings not implemented in a version
// and for warnings that falsely trigger
# if __GNUC__ == 4
#  if __GNUC_MINOR__ >= 7
#   define IG47(sw) IG(sw)
#   define WG47(sw) WG(sw)
#   define EG47(sw) EG(sw)
#   define XG47(sw) XG(sw)

#   define I47(sw) I(sw)
#   define W47(sw) W(sw)
#   define E47(sw) E(sw)
#   define X47(sw) X(sw)
#  else
#   define IG47(sw) static_assert('I', #sw "only for gcc 4.7+");
#   define WG47(sw) static_assert('W', #sw "only for gcc 4.7+");
#   define EG47(sw) static_assert('E', #sw "only for gcc 4.7+");
#   define XG47(sw) static_assert('X', #sw "only for gcc 4.7+");

#   define I47(sw) static_assert('I', #sw "only for gcc 4.7+ or clang");
#   define W47(sw) static_assert('W', #sw "only for gcc 4.7+ or clang");
#   define E47(sw) static_assert('E', #sw "only for gcc 4.7+ or clang");
#   define X47(sw) static_assert('X', #sw "only for gcc 4.7+ or clang");
#  endif // __GNUC_MINOR__
#  if __GNUC_MINOR__ >= 8
#   define IG48(sw) IG(sw)
#   define WG48(sw) WG(sw)
#   define EG48(sw) EG(sw)
#   define XG48(sw) XG(sw)

#   define I48(sw) IG(sw)
#   define W48(sw) WG(sw)
#   define E48(sw) EG(sw)
#   define X48(sw) XG(sw)
#  else
#   define IG48(sw) static_assert('I', #sw "only for gcc 4.8+");
#   define WG48(sw) static_assert('W', #sw "only for gcc 4.8+");
#   define EG48(sw) static_assert('E', #sw "only for gcc 4.8+");
#   define XG48(sw) static_assert('X', #sw "only for gcc 4.8+");

#   define I48(sw) static_assert('I', #sw "only for gcc 4.8+ or clang");
#   define W48(sw) static_assert('W', #sw "only for gcc 4.8+ or clang");
#   define E48(sw) static_assert('E', #sw "only for gcc 4.8+ or clang");
#   define X48(sw) static_assert('X', #sw "only for gcc 4.8+ or clang");
#  endif // __GNUC_MINOR__
# endif // __GNUC__
#endif // __clang__

// END macros to make my life easier


/// Warn about things that will change when compiling
/// with an ABI-compliant compiler
// see note about -fabi-version=6 in the makefile
E(-Wabi)

/// Warn if a subobject has an abi_tag attribute that
/// the complete object type does not have
WG48(-Wabi-tag)

/// Warn about suspicious uses of memory addresses
E(-Waddress)

/// Warn about returning structures, unions or arrays
I(-Waggregate-return)

/// Warn if an array is accessed out of bounds
E(-Warray-bounds)

/// Warn about inappropriate attribute usage
E(-Wattributes)

/// Warn when a built-in preprocessor macro is
// undefined or redefined
E(-Wbuiltin-macro-redefined)

/// Warn about C++ constructs whose meaning differs
/// between ISO C++ 1998 and ISO C++ 2011
// This has gone funky lately. It probably doesn't do anything useful anyway.
//E(-Wc++0x-compat)
//W(-Wc++11-compat)
I(-Wc++0x-compat)

/// Warn about pointer casts which increase alignment
X(-Wcast-align)

/// Warn about casts which discard qualifiers
E(-Wcast-qual)

/// Warn about subscripts whose type is "char"
E(-Wchar-subscripts)

/// Warn about variables that might be changed by
/// "longjmp" or "vfork"
EG(-Wclobbered)

/// Warn about possibly nested block comments, and
/// C++ comments spanning more than one physical line
E(-Wcomment)

// A fixable difference between c++11 and c++14
#ifdef __clang__
# if __has_warning("-Wconstexpr-not-const")
EC(-Wconstexpr-not-const)
# else
static_assert('E', "-Wconstexpr-not-const not in this clang version");
# endif
#else
static_assert('E', "-Wconstexpr-not-const not in GCC");
#endif

/// Warn for implicit type conversions that may
/// change a value
X(-Wconversion)

/// Warn for converting NULL from/to a non-pointer
/// type
E(-Wconversion-null)

/// Warn in case profiles in -fprofile-use do not
/// match
WG(-Wcoverage-mismatch)

///
XC(-Wcovered-switch-default)

/// Warn when a #warning directive is encountered
WG(-Wcpp)

/// Warn when all constructors and destructors are
/// private
E(-Wctor-dtor-privacy)

/// Warn about deleting polymorphic objects with non-
/// virtual destructors
E47(-Wdelete-non-virtual-dtor)

/// Warn if a deprecated compiler feature, class,
/// method, or field is used
W(-Wdeprecated)

/// Warn about uses of __attribute__((deprecated))
/// declarations
W(-Wdeprecated-declarations)
#ifdef QUIET
I(-Wdeprecated-declarations)
#endif

/// Warn when an optimization pass is disabled
W(-Wdisabled-optimization)

/// Warn about compile-time integer division by zero
E(-Wdiv-by-zero)

///
WC(-Wdocumentation)

/// Warn about implicit conversions from "float" to
/// "double"
IG(-Wdouble-promotion)

/// Warn about violations of Effective C++ style rules
I(-Weffc++)

/// Warn about an empty body in an if or else
/// statement
E(-Wempty-body)

/// Warn about stray tokens after #elif and #endif
E(-Wendif-labels)

/// Warn about comparison of different enum types
E(-Wenum-compare)

///
EC(-Wextra-semi)

/// Warn if testing floating point numbers for
/// equality
E(-Wfloat-equal)

/// Warn about printf/scanf/strftime/strfmon format
/// string anomalies
// see below
EG(-Wformat)
// but gcc 4.8 warns on %ms, since we enabled -Wpedantic.
//WG48(-Wformat)

/// Warn about format strings that contain NUL bytes
EG(-Wformat-contains-nul)

/// Warn if passing too many arguments to a function
/// for its format string
E(-Wformat-extra-args)

/// Warn about format strings that are not literals
EG(-Wformat-nonliteral)
// Available in clang, but not smart enough to handle constexpr.
IC(-Wformat-nonliteral)

/// Warn about possible security problems with format
/// functions
EG(-Wformat-security)
// Same.
IC(-Wformat-security)

/// Warn about strftime formats yielding 2-digit years
E(-Wformat-y2k)

/// Warn about zero-length formats
I(-Wformat-zero-length)

/// Warn when attempting to free a non-heap object
EG47(-Wfree-nonheap-object)

// -Wgnu is a clang alias for -Wpedantic

/// Warn whenever type qualifiers are ignored.
E(-Wignored-qualifiers)

///
EC(-Wimplicit-fallthrough)

/// Warn about C++11 inheriting constructors when the
/// base has a variadic constructor
WG48(-Winherited-variadic-ctor)

/// Warn about variables which are initialized to
/// themselves
E(-Winit-self)

/// Warn when an inlined function cannot be inlined
X(-Winline)

/// Warn when there is a cast to a pointer from an
/// integer of a different size
E(-Wint-to-pointer-cast)

/// Warn when an atomic memory model parameter is
/// known to be outside the valid range.
WG47(-Winvalid-memory-model)

/// Warn about invalid uses of the "offsetof" macro
E(-Winvalid-offsetof)

/// Warn about PCH files that are found but not used
E(-Winvalid-pch)

/// Warn when a string or character literal is
/// followed by a ud-suffix which does not begin with
/// an underscore.
WG48(-Wliteral-suffix)

/// Warn when a logical operator is suspiciously
/// always evaluating to true or false
WG(-Wlogical-op)

/// Do not warn about using "long long" when -pedantic
I(-Wlong-long)

/// Warn about suspicious declarations of "main"
E(-Wmain)

/// Warn about maybe uninitialized automatic variables
EG47(-Wmaybe-uninitialized)

/// Warn about possibly missing braces around
/// initializers
// beware of things like std::array!
E(-Wmissing-braces)

/// Warn about global functions without previous
/// declarations
// This doesn't work for clang, it wants -Wmissing-prototypes instead.
E(-Wmissing-declarations)

/// Warn about missing fields in struct initializers
// Actually supported by GCC, but gives warnings when I don't want, e.g.:
// Foo foo = {};
EC(-Wmissing-field-initializers)
IG(-Wmissing-field-initializers)

/// Warn about functions which might be candidates
/// for format attributes
E(-Wmissing-format-attribute)

/// Warn about user-specified include directories
/// that do not exist
E(-Wmissing-include-dirs)

/// Warn about functions which might be candidates
/// for __attribute__((noreturn))
W(-Wmissing-noreturn)

// clang uses this instead of -Wmissing-declarations
EC(-Wmissing-prototypes)

///
// like -Wmissing-declarations but for variables instead of functions
EC(-Wmissing-variable-declarations)

/// Warn about constructs not instrumented by
/// -fmudflap
EG(-Wmudflap)

/// Warn about use of multi-character character
/// constants
E(-Wmultichar)

/// Warn about narrowing conversions within { } that
/// are ill-formed in C++11
EG47(-Wnarrowing)

/// Warn when a noexcept expression evaluates to
/// false even though the expression can't actually
/// throw
WG(-Wnoexcept)

/// Warn when non-templatized friend functions are
/// declared within a template
EG(-Wnon-template-friend)

/// Warn about non-virtual destructors
E(-Wnon-virtual-dtor)

/// Warn about NULL being passed to argument slots
/// marked as requiring non-NULL
E(-Wnonnull)

///
XC(-Wnull-conversion)

/// Warn if a C-style cast is used in a program
E(-Wold-style-cast)

/// Warn about overflow in arithmetic expressions
W(-Woverflow)

/// Warn if a string is longer than the maximum
/// portable length specified by the standard
//X(-Woverlength-strings)

/// Warn about overloaded virtual function names
E(-Woverloaded-virtual)

/// Warn when the packed attribute has no effect on
/// struct layout
E(-Wpacked)

/// Warn about packed bit-fields whose offset changed
/// in GCC 4.4
WG(-Wpacked-bitfield-compat)

/// Warn when padding is required to align structure
/// members
I(-Wpadded)

/// Warn about possibly missing parentheses
E(-Wparentheses)

/// Issue warnings needed for strict compliance to
/// the standard
//EG48(-Wpedantic)
// lots of minor extensions are used
IG48(-Wpedantic)
// a bit too noisy
XC(-Wpedantic)

/// Warn when converting the type of pointers to
/// member functions
EG(-Wpmf-conversions)

/// Warn about function pointer arithmetic
E(-Wpointer-arith)

/// Warn about misuses of pragmas
EG(-Wpragmas)

/// Warn about multiple declarations of the same
/// object
W(-Wredundant-decls)

/// Warn when the compiler reorders code
E(-Wreorder)

/// Warn about returning a pointer/reference to a
/// local or temporary variable.
WG48(-Wreturn-local-addr)

/// Warn whenever a function's return type defaults
/// to "int" (C), or about inconsistent return types
/// (C++)
E(-Wreturn-type)

/// Warn about possible violations of sequence point
/// rules
E(-Wsequence-point)

/// Warn when one local variable shadows another
E(-Wshadow)

/// Warn about signed-unsigned comparisons
X(-Wsign-compare)

/// Warn when overload promotes from unsigned to
/// signed
X(-Wsign-promo)

/// This switch lacks documentation
WG48(-Wsizeof-pointer-memaccess)

/// Warn when not issuing stack smashing protection
/// for some reason
X(-Wstack-protector)

/// Warn about code which might break strict aliasing
/// rules
E(-Wstrict-aliasing)

/// Warn about uncasted NULL used as sentinel
WG(-Wstrict-null-sentinel)

/// Warn about optimizations that assume that signed
/// overflow is undefined
X(-Wstrict-overflow)

/// Warn about enumerated switches, with no default,
/// missing a case
X(-Wswitch)

/// Warn about enumerated switches missing a
/// "default:" statement
X(-Wswitch-default)

/// Warn about all enumerated switches missing a
/// specific case
X(-Wswitch-enum)

/// Warn when __sync_fetch_and_nand and
/// __sync_nand_and_fetch built-in functions are used
WG(-Wsync-nand)

/// Warn whenever a trampoline is generated
EG(-Wtrampolines)

/// Warn if trigraphs are encountered that might
/// affect the meaning of the program
E(-Wtrigraphs)

/// Warn if a comparison is always true or always
/// false due to the limited range of the data type
E(-Wtype-limits)

/// Warn if an undefined macro is used in an #if
/// directive
E(-Wundef)

/// Warn about uninitialized automatic variables
E(-Wuninitialized)

/// Warn about unrecognized pragmas
E(-Wunknown-pragmas)

///
// Not an error because of some remaining enum+default
WC(-Wunreachable-code)

/// Warn if the loop cannot be optimized due to
/// nontrivial assumptions.
XG(-Wunsafe-loop-optimizations)

/// Warn when a function parameter is only set,
/// otherwise unused
EG(-Wunused-but-set-parameter)

/// Warn when a variable is only set, otherwise unused
EG(-Wunused-but-set-variable)

/// Warn when a function is unused
E(-Wunused-function)

/// Warn when a label is unused
E(-Wunused-label)

/// Warn when typedefs locally defined in a function
/// are not used
EG47(-Wunused-local-typedefs)

/// Warn about macros defined in the main file that
/// are not used
W(-Wunused-macros)

/// Warn when a function parameter is unused
E(-Wunused-parameter)

/// Warn if a caller of a function, marked with
/// attribute warn_unused_result, does not use its
/// return value
W(-Wunused-result)

/// Warn when an expression value is unused
E(-Wunused-value)

/// Warn when a variable is unused
E(-Wunused-variable)

/// Warn about useless casts
EG48(-Wuseless-cast)

/// Warn about questionable usage of the macros used
/// to retrieve variable arguments
EG48(-Wvarargs)

/// Warn about using variadic macros
W(-Wvariadic-macros)

/// Warn when a vector operation is compiled
/// outside the SIMD
WG47(-Wvector-operation-performance)

/// Warn if a virtual base has a non-trivial move
/// assignment operator
EG48(-Wvirtual-move-assign)

/// Warn if a variable length array is used
I(-Wvla)

/// Warn when a register variable is declared volatile
E(-Wvolatile-register-var)

/// In C++, nonzero means warn about deprecated
/// conversion from string literals to 'char *'.  In
/// C, similar warning, except that the conversion is
/// of course not deprecated by the ISO C standard.
E(-Wwrite-strings)

/// Warn when a literal '0' is used as null
/// pointer
XG47(-Wzero-as-null-pointer-constant)


// clean up after myself
#undef P

#undef I
#undef W
#undef E
#undef X

#undef IC
#undef WC
#undef EC
#undef XC

#undef IG
#undef WG
#undef EG
#undef XG

#undef IG47
#undef WG47
#undef EG47
#undef XG47

#undef IG48
#undef WG48
#undef EG48
#undef XG48

#undef I47
#undef W47
#undef E47
#undef X47

#undef I48
#undef W48
#undef E48
#undef X48