Massive Atomic Warnings


#1

Recently, we’ve been able to build with -W -Wall and get (almost) no warnings from JUCE, which is very nice, thank you Jules.

[EDIT: Found that enabling -O3 causes the warnings, apparently -O2 and above activate -fstrict-aliasing]

However, compiling with -O3 produces tons of warnings involving juce_Atomic.h. This is beyond my league, but googling lets me know it’s not only a cosmetic warning but may sometimes cause very serious and hard-to-debug problems.

I assume we should be able to safely compile JUCE with -O2 or -O3? I know I want to, since -march=native + -O3 gives me about 300% performance improvement on dot product vector operations (SSE).

../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h: In static member function ‘static juce::int64 juce::Atomic<Type>::castTo64Bit(Type) [with Type = char*, juce::int64 = long long int]’: ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:347:141: instantiated from ‘bool juce::Atomic<Type>::compareAndSetBool(Type, Type) [with Type = char*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:281:5: instantiated from ‘Type juce::Atomic<Type>::exchange(Type) [with Type = char*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/juce_CharPointer_UTF8.h:555:102: instantiated from here ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:156:83: warning: dereferencing type-punned pointer will break strict-aliasing rules ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h: In static member function ‘static juce::int32 juce::Atomic<Type>::castTo32Bit(Type) [with Type = char*, juce::int32 = int]’: ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:347:141: instantiated from ‘bool juce::Atomic<Type>::compareAndSetBool(Type, Type) [with Type = char*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:281:5: instantiated from ‘Type juce::Atomic<Type>::exchange(Type) [with Type = char*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/juce_CharPointer_UTF8.h:555:102: instantiated from here ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:155:83: warning: dereferencing type-punned pointer will break strict-aliasing rules ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h: In static member function ‘static juce::int64 juce::Atomic<Type>::castTo64Bit(Type) [with Type = short int*, juce::int64 = long long int]’: ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:347:141: instantiated from ‘bool juce::Atomic<Type>::compareAndSetBool(Type, Type) [with Type = short int*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:281:5: instantiated from ‘Type juce::Atomic<Type>::exchange(Type) [with Type = short int*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/juce_CharPointer_UTF16.h:471:103: instantiated from here ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:156:83: warning: dereferencing type-punned pointer will break strict-aliasing rules ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h: In static member function ‘static juce::int32 juce::Atomic<Type>::castTo32Bit(Type) [with Type = short int*, juce::int32 = int]’: ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:347:141: instantiated from ‘bool juce::Atomic<Type>::compareAndSetBool(Type, Type) [with Type = short int*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:281:5: instantiated from ‘Type juce::Atomic<Type>::exchange(Type) [with Type = short int*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/juce_CharPointer_UTF16.h:471:103: instantiated from here ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:155:83: warning: dereferencing type-punned pointer will break strict-aliasing rules ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h: In static member function ‘static juce::int64 juce::Atomic<Type>::castTo64Bit(Type) [with Type = wchar_t*, juce::int64 = long long int]’: ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:347:141: instantiated from ‘bool juce::Atomic<Type>::compareAndSetBool(Type, Type) [with Type = wchar_t*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:281:5: instantiated from ‘Type juce::Atomic<Type>::exchange(Type) [with Type = wchar_t*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/juce_CharPointer_UTF32.h:367:103: instantiated from here ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:156:83: warning: dereferencing type-punned pointer will break strict-aliasing rules ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h: In static member function ‘static juce::int32 juce::Atomic<Type>::castTo32Bit(Type) [with Type = wchar_t*, juce::int32 = int]’: ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:347:141: instantiated from ‘bool juce::Atomic<Type>::compareAndSetBool(Type, Type) [with Type = wchar_t*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:281:5: instantiated from ‘Type juce::Atomic<Type>::exchange(Type) [with Type = wchar_t*]’ ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/juce_CharPointer_UTF32.h:367:103: instantiated from here ../../Source/../JuceLibraryCode/modules/juce_audio_basics/../juce_core/system/../logging/../text/../memory/juce_Atomic.h:155:83: warning: dereferencing type-punned pointer will break strict-aliasing rules


#2

Maybe you enabled strict aliasing?


#3

Exactly, see edited post above. Solution?


#4

http://blog.qt.digia.com/blog/2011/06/10/type-punning-and-strict-aliasing/


#5

Yeah, I had to bend some rules a bit to get all that horrible stuff to work on all platforms.

What I’m planning to do soon is to start migrating my atomics over to the new C++11 atomics where they’re available, so eventually all the hackery will go away. In the meantime, a pragma to avoid the warning might be simplest.


#6

Deal. For the record, this is how I build atm:

Which leaves us with the following warnings, in case you might want to amend them. For therapeutic reasons if nothing else:

[code]…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp: In member function ‘void juce::SHA256Processor::processFullBlock(const void*)’:
In file included from …/…/JuceLibraryCode/modules/juce_cryptography/juce_cryptography.cpp:49:0:
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[8]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[7]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[6]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[5]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[13]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[4]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[12]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[3]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[11]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[2]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[10]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[15]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[1]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[9]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[14]’ may be used uninitialized in this function
…/…/JuceLibraryCode/modules/juce_cryptography/hashing/juce_SHA256.cpp:57:24: warning: ‘block[0]’ may be used uninitialized in this function

…/…/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.cpp: In copy constructor ‘juce::Drawable::Drawable(const juce::Drawable&)’:
In file included from …/…/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp:161:0:
…/…/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.cpp:32:1: warning: base class ‘class juce::Component’ should be explicitly initialized in the copy constructor
…/…/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp: In copy constructor ‘juce::KeyPressMappingSet::KeyPressMappingSet(const juce::KeyPressMappingSet&)’:
In file included from …/…/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp:241:0:
…/…/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp:32:1: warning: base class ‘class juce::ChangeBroadcaster’ should be explicitly initialized in the copy constructor
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/system/…/maths/juce_MathsFunctions.h: In member function ‘int juce::TextEditor::findWordBreakAfter(int) const’:
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/system/…/maths/juce_MathsFunctions.h:103:116: warning: assuming signed overflow does not occur when assuming that (X + c) >= X is always true
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/system/…/maths/juce_MathsFunctions.h: In member function ‘int juce::TextEditor::findWordBreakBefore(int) const’:
In file included from …/…/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp:224:0:
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/system/…/maths/juce_MathsFunctions.h:103:116: warning: assuming signed overflow does not occur when assuming that (X - c) <= X is always true
Compiling juce_gui_extra.cpp
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/containers/…/maths/juce_Range.h: In member function ‘bool juce::TextEditor::deleteForwards(bool)’:
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/containers/…/maths/juce_Range.h:133:9: warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/containers/…/maths/juce_Range.h: In member function ‘bool juce::TextEditor::deleteBackwards(bool)’:
…/…/JuceLibraryCode/modules/juce_gui_basics/…/juce_graphics/…/juce_core/containers/…/maths/juce_Range.h:107:9: warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false
[/code]


#7

Watch out for that crypto stuff! If you get too keen cleaning it up, it gets predictable. Notably, some algorithms expect uninitialized memory to act as a random seed. There was a case of over-zealous warning clean up with OpenSSL (I think) in a Linux distro a while ago.

Bruce


#8

Those SHA256 warnings were bogus, but I’ve rearranged the code now so that the compiler might stand a better chance of understanding it correctly.


#9

Did something change in the implementation of Atomics over the last 6 months?


#10

[size=150]ATOMIC WARNING[/size]


#11

Not sure, but it must be at least a few months since I’ve tinkered with that stuff.


#12

Ah, very good Vincent!
It took me some time to actually see the faces in the atomic cloud…


#13

[quote=“X-Ryl669”]Ah, very good Vincent!
It took me some time to actually see the faces in the atomic cloud…[/quote]

Oh god, I’d never have seen them till you pointed them out, and now I have they’re giving my the heebie-jeebies! Creepy clown faces in a mushroom cloud. I need a drink…


#14

Not sure, but it must be at least a few months since I’ve tinkered with that stuff.[/quote]

Okay; was just bitten by this. The short story is that our build enables “strict-aliasing” by default, and like a lot of people, we just ignored the supposedly “cosmetic” warnings by gcc-4.7 on android.

Thence came The Bug.

Suffice to say, the optimizer did not Play Nice with the atomic aliasing. No idea why.

But I made it all go away with the attached patch. It just checks for clang or gcc4+ and enables the “may_alias” attribute.

Hope someone finds it helpful!

-Andrew.


#15

Ah, that’ll teach you to ignore warnings! Thanks for the heads-up though.

Out of interest, looking at that code, it could be written more cleanly with unions, e.g.

[code] template <typename Dest, typename Source>
static inline Dest castTo (Source value) noexcept { union { Dest d; Source s; } u; u.s = value; return u.d; }

static inline Type castFrom32Bit (int32 value) noexcept   { return castTo <Type, int32> (value); }
static inline Type castFrom64Bit (int64 value) noexcept   { return castTo <Type, int64> (value); }
static inline int32 castTo32Bit (Type value) noexcept     { return castTo <int32, Type> (value); }
static inline int64 castTo64Bit (Type value) noexcept     { return castTo <int64, Type> (value); }

[/code]

…and I think that might solve your aliasing issue too - would be interested to hear if it works or not?