Fixed UBsan warning "call to function through pointer to incorrect function type"
[libcds.git] / cds / intrusive / impl / ellen_bintree.h
index be8f88b05c13460a2d290e496202c04f1fb0cd95..f935c13f5d9ce65dd122be34494bf050e59e4482 100644 (file)
@@ -1,11 +1,11 @@
 /*
     This file is a part of libcds - Concurrent Data Structures library
 
-    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
 
     Source code repo: http://github.com/khizmax/libcds/
     Download: http://sourceforge.net/projects/libcds/files/
-    
+
     Redistribution and use in source and binary forms, with or without
     modification, are permitted provided that the following conditions are met:
 
@@ -168,13 +168,13 @@ namespace cds { namespace intrusive {
         {
             static internal_node const& to_internal_node( tree_node const& n )
             {
-                assert( n.is_internal() );
+                assert( n.is_internal());
                 return static_cast<internal_node const&>( n );
             }
 
             static leaf_node const& to_leaf_node( tree_node const& n )
             {
-                assert( n.is_leaf() );
+                assert( n.is_leaf());
                 return static_cast<leaf_node const&>( n );
             }
         };
@@ -243,9 +243,9 @@ namespace cds { namespace intrusive {
 
     protected:
         //@cond
-        static void free_leaf_node( value_type * p )
+        static void free_leaf_node( void* p )
         {
-            disposer()( );
+            disposer()( reinterpret_cast<value_type*>( p ));
         }
 
         internal_node * alloc_internal_node() const
@@ -255,15 +255,15 @@ namespace cds { namespace intrusive {
             return pNode;
         }
 
-        static void free_internal_node( internal_node * pNode )
+        static void free_internal_node( void* pNode )
         {
-            cxx_node_allocator().Delete( pNode );
+            cxx_node_allocator().Delete( reinterpret_cast<internal_node*>( pNode ));
         }
 
         struct internal_node_deleter {
-            void operator()( internal_node * p) const
+            void operator()( internal_node* p) const
             {
-                free_internal_node( p );
+                cxx_node_allocator().Delete( p );
             }
         };
 
@@ -275,14 +275,14 @@ namespace cds { namespace intrusive {
             return cxx_update_desc_allocator().New();
         }
 
-        static void free_update_desc( update_desc * pDesc )
+        static void free_update_desc( void* pDesc )
         {
-            cxx_update_desc_allocator().Delete( pDesc );
+            cxx_update_desc_allocator().Delete( reinterpret_cast<update_desc*>( pDesc ));
         }
 
         void retire_node( tree_node * pNode ) const
         {
-            if ( pNode->is_leaf() ) {
+            if ( pNode->is_leaf()) {
                 assert( static_cast<leaf_node *>( pNode ) != &m_LeafInf1 );
                 assert( static_cast<leaf_node *>( pNode ) != &m_LeafInf2 );
 
@@ -366,8 +366,8 @@ namespace cds { namespace intrusive {
             back_off bkoff;
 
             for ( ;; ) {
-                if ( search( res, val, node_compare() )) {
-                    if ( pNewInternal.get() )
+                if ( search( res, val, node_compare())) {
+                    if ( pNewInternal.get())
                         m_Stat.onInternalNodeDeleted() ;    // unique_internal_node_ptr deletes internal node
                     m_Stat.onInsertFailed();
                     return false;
@@ -375,8 +375,8 @@ namespace cds { namespace intrusive {
 
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
 
-                    if ( !pNewInternal.get() )
-                        pNewInternal.reset( alloc_internal_node() );
+                    if ( !pNewInternal.get())
+                        pNewInternal.reset( alloc_internal_node());
 
                     if ( try_insert( val, pNewInternal.get(), res )) {
                         f( val );
@@ -433,9 +433,9 @@ namespace cds { namespace intrusive {
             back_off bkoff;
 
             for ( ;; ) {
-                if ( search( res, val, node_compare() )) {
+                if ( search( res, val, node_compare())) {
                     func( false, *node_traits::to_value_ptr( res.pLeaf ), val );
-                    if ( pNewInternal.get() )
+                    if ( pNewInternal.get())
                         m_Stat.onInternalNodeDeleted() ;    // unique_internal_node_ptr deletes internal node
                     m_Stat.onUpdateExist();
                     return std::make_pair( true, false );
@@ -445,8 +445,8 @@ namespace cds { namespace intrusive {
                     if ( !bAllowInsert )
                         return std::make_pair( false, false );
 
-                    if ( !pNewInternal.get() )
-                        pNewInternal.reset( alloc_internal_node() );
+                    if ( !pNewInternal.get())
+                        pNewInternal.reset( alloc_internal_node());
 
                     if ( try_insert( val, pNewInternal.get(), res )) {
                         func( true, val, val );
@@ -499,7 +499,7 @@ namespace cds { namespace intrusive {
             unlinks it from the tree, and returns \p true.
             If the item with key equal to \p key is not found the function return \p false.
 
-            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q 
+            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q
             that can be not the same as \p value_type.
         */
         template <typename Q>
@@ -550,7 +550,7 @@ namespace cds { namespace intrusive {
 
             If the item with key equal to \p key is not found the function return \p false.
 
-            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q 
+            Note the \p Traits::less and/or \p Traits::compare predicate should accept a parameter of type \p Q
             that can be not the same as \p value_type.
         */
         template <typename Q, typename Func>
@@ -662,7 +662,7 @@ namespace cds { namespace intrusive {
         bool contains( Q const& key ) const
         {
             search_result    res;
-            if ( search( res, key, node_compare() )) {
+            if ( search( res, key, node_compare())) {
                 m_Stat.onFindSuccess();
                 return true;
             }
@@ -697,7 +697,7 @@ namespace cds { namespace intrusive {
             > compare_functor;
 
             search_result    res;
-            if ( search( res, key, compare_functor() )) {
+            if ( search( res, key, compare_functor())) {
                 m_Stat.onFindSuccess();
                 return true;
             }
@@ -807,7 +807,7 @@ namespace cds { namespace intrusive {
             this sequence
             \code
             tree.clear();
-            assert( tree.empty() );
+            assert( tree.empty());
             \endcode
             the assertion could be raised.
 
@@ -834,7 +834,7 @@ namespace cds { namespace intrusive {
                 tree_node *     pLeaf = const_cast<internal_node *>( &m_Root );
 
                 // Get leftmost leaf
-                while ( pLeaf->is_internal() ) {
+                while ( pLeaf->is_internal()) {
                     pGrandParent = pParent;
                     pParent = static_cast<internal_node *>( pLeaf );
                     pLeaf = pParent->m_pLeft.load( memory_model::memory_order_relaxed );
@@ -848,10 +848,10 @@ namespace cds { namespace intrusive {
                 // Remove leftmost leaf and its parent node
                 assert( pGrandParent );
                 assert( pParent );
-                assert( pLeaf->is_leaf() );
+                assert( pLeaf->is_leaf());
 
                 pGrandParent->m_pLeft.store( pParent->m_pRight.load( memory_model::memory_order_relaxed ), memory_model::memory_order_relaxed );
-                free_leaf_node( node_traits::to_value_ptr( static_cast<leaf_node *>( pLeaf ) ) );
+                free_leaf_node( node_traits::to_value_ptr( static_cast<leaf_node *>( pLeaf )));
                 free_internal_node( pParent );
             }
         }
@@ -900,11 +900,11 @@ namespace cds { namespace intrusive {
                 && node_compare()( *pLeft, *pRight ) < 0 )
             {
                 bool bRet = true;
-                if ( pLeft->is_internal() )
-                    bRet = check_consistency( static_cast<internal_node *>( pLeft ) );
+                if ( pLeft->is_internal())
+                    bRet = check_consistency( static_cast<internal_node *>( pLeft ));
                 assert( bRet );
 
-                if ( bRet && pRight->is_internal() )
+                if ( bRet && pRight->is_internal())
                     bRet = bRet && check_consistency( static_cast<internal_node *>( pRight ));
                 assert( bRet );
 
@@ -972,7 +972,7 @@ namespace cds { namespace intrusive {
             updParent = nullptr;
             bRightLeaf = false;
             tree_node * pLeaf = const_cast<internal_node *>( &m_Root );
-            while ( pLeaf->is_internal() ) {
+            while ( pLeaf->is_internal()) {
                 res.guards.copy( search_result::Guard_GrandParent, search_result::Guard_Parent );
                 pGrandParent = pParent;
                 res.guards.copy( search_result::Guard_Parent, search_result::Guard_Leaf );
@@ -983,7 +983,7 @@ namespace cds { namespace intrusive {
 
                 updParent = search_protect_update( res, pParent->m_pUpdate );
 
-                switch ( updParent.bits() ) {
+                switch ( updParent.bits()) {
                     case update_desc::DFlag:
                     case update_desc::Mark:
                         m_Stat.onSearchRetry();
@@ -1000,8 +1000,8 @@ namespace cds { namespace intrusive {
                 }
             }
 
-            assert( pLeaf->is_leaf() );
-            nCmp = cmp( key, *static_cast<leaf_node *>(pLeaf) );
+            assert( pLeaf->is_leaf());
+            nCmp = cmp( key, *static_cast<leaf_node *>(pLeaf));
 
             res.pGrandParent    = pGrandParent;
             res.pParent         = pParent;
@@ -1026,7 +1026,7 @@ namespace cds { namespace intrusive {
             pGrandParent = nullptr;
             updParent = nullptr;
             tree_node *     pLeaf = const_cast<internal_node *>( &m_Root );
-            while ( pLeaf->is_internal() ) {
+            while ( pLeaf->is_internal()) {
                 res.guards.copy( search_result::Guard_GrandParent, search_result::Guard_Parent );
                 pGrandParent = pParent;
                 res.guards.copy( search_result::Guard_Parent, search_result::Guard_Leaf );
@@ -1036,7 +1036,7 @@ namespace cds { namespace intrusive {
 
                 updParent = search_protect_update( res, pParent->m_pUpdate );
 
-                switch ( updParent.bits() ) {
+                switch ( updParent.bits()) {
                     case update_desc::DFlag:
                     case update_desc::Mark:
                         m_Stat.onSearchRetry();
@@ -1055,7 +1055,7 @@ namespace cds { namespace intrusive {
 
             res.pGrandParent    = pGrandParent;
             res.pParent         = pParent;
-            assert( pLeaf->is_leaf() );
+            assert( pLeaf->is_leaf());
             res.pLeaf           = static_cast<leaf_node *>( pLeaf );
             res.updParent       = updParent;
             res.updGrandParent  = updGrandParent;
@@ -1080,7 +1080,7 @@ namespace cds { namespace intrusive {
             updParent = nullptr;
             bRightLeaf = false;
             tree_node * pLeaf = const_cast<internal_node *>( &m_Root );
-            while ( pLeaf->is_internal() ) {
+            while ( pLeaf->is_internal()) {
                 res.guards.copy( search_result::Guard_GrandParent, search_result::Guard_Parent );
                 pGrandParent = pParent;
                 res.guards.copy( search_result::Guard_Parent, search_result::Guard_Leaf );
@@ -1091,7 +1091,7 @@ namespace cds { namespace intrusive {
 
                 updParent = search_protect_update( res, pParent->m_pUpdate );
 
-                switch ( updParent.bits() ) {
+                switch ( updParent.bits()) {
                     case update_desc::DFlag:
                     case update_desc::Mark:
                         m_Stat.onSearchRetry();
@@ -1111,7 +1111,7 @@ namespace cds { namespace intrusive {
 
             res.pGrandParent    = pGrandParent;
             res.pParent         = pParent;
-            assert( pLeaf->is_leaf() );
+            assert( pLeaf->is_leaf());
             res.pLeaf           = static_cast<leaf_node *>( pLeaf );
             res.updParent       = updParent;
             res.updGrandParent  = updGrandParent;
@@ -1125,18 +1125,18 @@ namespace cds { namespace intrusive {
         void help( update_ptr pUpdate )
         {
             // pUpdate must be guarded!
-            switch ( pUpdate.bits() ) {
+            switch ( pUpdate.bits()) {
                 case update_desc::IFlag:
-                    help_insert( pUpdate.ptr() );
+                    help_insert( pUpdate.ptr());
                     m_Stat.onHelpInsert();
                     break;
                 case update_desc::DFlag:
-                    help_delete( pUpdate.ptr() );
+                    help_delete( pUpdate.ptr());
                     m_Stat.onHelpDelete();
                     break;
                 case update_desc::Mark:
                     //m_Stat.onHelpMark();
-                    //help_marked( pUpdate.ptr() );
+                    //help_marked( pUpdate.ptr());
                     break;
             }
         }
@@ -1209,7 +1209,7 @@ namespace cds { namespace intrusive {
         static tree_node * protect_sibling( typename gc::Guard& guard, atomics::atomic<tree_node *>& sibling )
         {
             tree_node * pSibling = guard.protect( sibling, [](tree_node * p) -> internal_node* { return static_cast<internal_node *>(p); } );
-            if ( pSibling->is_leaf() )
+            if ( pSibling->is_leaf())
                 guard.assign( node_traits::to_value_ptr( static_cast<leaf_node *>( pSibling )));
             return pSibling;
         }
@@ -1240,7 +1240,7 @@ namespace cds { namespace intrusive {
         bool try_insert( value_type& val, internal_node * pNewInternal, search_result& res )
         {
             assert( res.updParent.bits() == update_desc::Clean );
-            assert( res.pLeaf->is_leaf() );
+            assert( res.pLeaf->is_leaf());
 
             // check search result
             if ( res.pParent->get_child( res.bRightLeaf, memory_model::memory_order_acquire ) == res.pLeaf ) {
@@ -1249,7 +1249,7 @@ namespace cds { namespace intrusive {
                 int nCmp = node_compare()(val, *res.pLeaf);
                 if ( nCmp < 0 ) {
                     if ( res.pGrandParent ) {
-                        assert( !res.pLeaf->infinite_key() );
+                        assert( !res.pLeaf->infinite_key());
                         pNewInternal->infinite_key( 0 );
                         key_extractor()(pNewInternal->m_Key, *node_traits::to_value_ptr( res.pLeaf ));
                     }
@@ -1261,13 +1261,13 @@ namespace cds { namespace intrusive {
                     pNewInternal->m_pRight.store( static_cast<tree_node *>(res.pLeaf), memory_model::memory_order_release );
                 }
                 else {
-                    assert( !res.pLeaf->is_internal() );
+                    assert( !res.pLeaf->is_internal());
 
                     pNewInternal->infinite_key( 0 );
                     key_extractor()(pNewInternal->m_Key, val);
                     pNewInternal->m_pLeft.store( static_cast<tree_node *>(res.pLeaf), memory_model::memory_order_relaxed );
                     pNewInternal->m_pRight.store( static_cast<tree_node *>(pNewLeaf), memory_model::memory_order_release );
-                    assert( !res.pLeaf->infinite_key() );
+                    assert( !res.pLeaf->infinite_key());
                 }
 
                 typename gc::Guard guard;
@@ -1279,9 +1279,9 @@ namespace cds { namespace intrusive {
                 pOp->iInfo.pLeaf = res.pLeaf;
                 pOp->iInfo.bRightLeaf = res.bRightLeaf;
 
-                update_ptr updCur( res.updParent.ptr() );
+                update_ptr updCur( res.updParent.ptr());
                 if ( res.pParent->m_pUpdate.compare_exchange_strong( updCur, update_ptr( pOp, update_desc::IFlag ),
-                    memory_model::memory_order_acquire, atomics::memory_order_relaxed ) ) {
+                    memory_model::memory_order_acquire, atomics::memory_order_relaxed )) {
                     // do insert
                     help_insert( pOp );
                     retire_update_desc( pOp );
@@ -1304,7 +1304,7 @@ namespace cds { namespace intrusive {
             back_off bkoff;
 
             for ( ;; ) {
-                if ( !search( res, val, cmp ) || !eq( val, *res.pLeaf ) ) {
+                if ( !search( res, val, cmp ) || !eq( val, *res.pLeaf )) {
                     if ( pOp )
                         retire_update_desc( pOp );
                     m_Stat.onEraseFailed();
@@ -1314,7 +1314,7 @@ namespace cds { namespace intrusive {
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
                     if ( !pOp )
                         pOp = alloc_update_desc();
-                    if ( check_delete_precondition( res ) ) {
+                    if ( check_delete_precondition( res )) {
                         typename gc::Guard guard;
                         guard.assign( pOp );
 
@@ -1325,12 +1325,12 @@ namespace cds { namespace intrusive {
                         pOp->dInfo.bRightParent = res.bRightParent;
                         pOp->dInfo.bRightLeaf = res.bRightLeaf;
 
-                        update_ptr updGP( res.updGrandParent.ptr() );
+                        update_ptr updGP( res.updGrandParent.ptr());
                         if ( res.pGrandParent->m_pUpdate.compare_exchange_strong( updGP, update_ptr( pOp, update_desc::DFlag ),
-                            memory_model::memory_order_acquire, atomics::memory_order_relaxed ) ) {
-                            if ( help_delete( pOp ) ) {
+                            memory_model::memory_order_acquire, atomics::memory_order_relaxed )) {
+                            if ( help_delete( pOp )) {
                                 // res.pLeaf is not deleted yet since it is guarded
-                                f( *node_traits::to_value_ptr( res.pLeaf ) );
+                                f( *node_traits::to_value_ptr( res.pLeaf ));
                                 break;
                             }
                             pOp = nullptr;
@@ -1365,7 +1365,7 @@ namespace cds { namespace intrusive {
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
                     if ( !pOp )
                         pOp = alloc_update_desc();
-                    if ( check_delete_precondition( res ) ) {
+                    if ( check_delete_precondition( res )) {
                         typename gc::Guard guard;
                         guard.assign( pOp );
 
@@ -1376,9 +1376,9 @@ namespace cds { namespace intrusive {
                         pOp->dInfo.bRightParent = res.bRightParent;
                         pOp->dInfo.bRightLeaf = res.bRightLeaf;
 
-                        update_ptr updGP( res.updGrandParent.ptr() );
+                        update_ptr updGP( res.updGrandParent.ptr());
                         if ( res.pGrandParent->m_pUpdate.compare_exchange_strong( updGP, update_ptr( pOp, update_desc::DFlag ),
-                            memory_model::memory_order_acquire, atomics::memory_order_relaxed ) ) {
+                            memory_model::memory_order_acquire, atomics::memory_order_relaxed )) {
                             if ( help_delete( pOp ))
                                 break;
                             pOp = nullptr;
@@ -1432,7 +1432,7 @@ namespace cds { namespace intrusive {
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
                     if ( !pOp )
                         pOp = alloc_update_desc();
-                    if ( check_delete_precondition( res ) ) {
+                    if ( check_delete_precondition( res )) {
                         typename gc::Guard guard;
                         guard.assign( pOp );
 
@@ -1443,11 +1443,11 @@ namespace cds { namespace intrusive {
                         pOp->dInfo.bRightParent = res.bRightParent;
                         pOp->dInfo.bRightLeaf = res.bRightLeaf;
 
-                        update_ptr updGP( res.updGrandParent.ptr() );
+                        update_ptr updGP( res.updGrandParent.ptr());
                         if ( res.pGrandParent->m_pUpdate.compare_exchange_strong( updGP, update_ptr( pOp, update_desc::DFlag ),
-                                memory_model::memory_order_acquire, atomics::memory_order_relaxed ) )
+                                memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
                         {
-                            if ( help_delete( pOp ) )
+                            if ( help_delete( pOp ))
                                 break;
                             pOp = nullptr;
                         }
@@ -1481,7 +1481,7 @@ namespace cds { namespace intrusive {
                 if ( res.updGrandParent.bits() == update_desc::Clean && res.updParent.bits() == update_desc::Clean ) {
                     if ( !pOp )
                         pOp = alloc_update_desc();
-                    if ( check_delete_precondition( res ) ) {
+                    if ( check_delete_precondition( res )) {
                         typename gc::Guard guard;
                         guard.assign( pOp );
 
@@ -1492,7 +1492,7 @@ namespace cds { namespace intrusive {
                         pOp->dInfo.bRightParent = res.bRightParent;
                         pOp->dInfo.bRightLeaf = res.bRightLeaf;
 
-                        update_ptr updGP( res.updGrandParent.ptr() );
+                        update_ptr updGP( res.updGrandParent.ptr());
                         if ( res.pGrandParent->m_pUpdate.compare_exchange_strong( updGP, update_ptr( pOp, update_desc::DFlag ),
                             memory_model::memory_order_acquire, atomics::memory_order_relaxed ))
                         {
@@ -1516,7 +1516,7 @@ namespace cds { namespace intrusive {
         bool find_( Q& val, Func f ) const
         {
             search_result    res;
-            if ( search( res, val, node_compare() )) {
+            if ( search( res, val, node_compare())) {
                 assert( res.pLeaf );
                 f( *node_traits::to_value_ptr( res.pLeaf ), val );
 
@@ -1539,7 +1539,7 @@ namespace cds { namespace intrusive {
             > compare_functor;
 
             search_result    res;
-            if ( search( res, val, compare_functor() )) {
+            if ( search( res, val, compare_functor())) {
                 assert( res.pLeaf );
                 f( *node_traits::to_value_ptr( res.pLeaf ), val );
 
@@ -1555,7 +1555,7 @@ namespace cds { namespace intrusive {
         guarded_ptr get_( Q const& val ) const
         {
             search_result    res;
-            if ( search( res, val, node_compare() ) ) {
+            if ( search( res, val, node_compare())) {
                 assert( res.pLeaf );
                 m_Stat.onFindSuccess();
                 return guarded_ptr( res.guards.release( search_result::Guard_Leaf ));
@@ -1568,6 +1568,8 @@ namespace cds { namespace intrusive {
         template <typename Q, typename Less>
         guarded_ptr get_with_( Q const& val, Less pred ) const
         {
+            CDS_UNUSED( pred );
+
             typedef ellen_bintree::details::compare<
                 key_type,
                 value_type,
@@ -1576,7 +1578,7 @@ namespace cds { namespace intrusive {
             > compare_functor;
 
             search_result    res;
-            if ( search( res, val, compare_functor() ) ) {
+            if ( search( res, val, compare_functor())) {
                 assert( res.pLeaf );
                 m_Stat.onFindSuccess();
                 return guarded_ptr( res.guards.release( search_result::Guard_Leaf ));