From 24e7f2a974548c78a96403574fed35ecfc139e01 Mon Sep 17 00:00:00 2001
From: Wim Lavrijsen <WLavrijsen@lbl.gov>
Date: Tue, 5 Nov 2013 17:34:50 -0800
Subject: [PATCH] boat load of workaround for std::vector iterators; to be
 fixed by using collection proxy

---
 bindings/pyroot/src/Converters.cxx  | 22 ++++++++++++++++++++
 bindings/pyroot/src/Converters.h    |  8 ++++++++
 bindings/pyroot/src/Executors.cxx   |  2 +-
 bindings/pyroot/src/RootWrapper.cxx |  9 ++++++++
 bindings/pyroot/src/Utility.cxx     | 32 ++++++-----------------------
 5 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/bindings/pyroot/src/Converters.cxx b/bindings/pyroot/src/Converters.cxx
index fb0ad27822d..f3bda825424 100644
--- a/bindings/pyroot/src/Converters.cxx
+++ b/bindings/pyroot/src/Converters.cxx
@@ -918,6 +918,23 @@ Bool_t PyROOT::TRootObjectPtrConverter::ToMemory( PyObject* value, void* address
    return kFALSE;
 }
 
+//____________________________________________________________________________
+// CLING WORKAROUND -- classes for STL iterators are completely undefined in that
+// they come in a bazillion different guises, so just do whatever
+Bool_t PyROOT::TSTLIteratorConverter::SetArg(
+      PyObject* pyobject, TParameter_t& para, CallFunc_t* func, Long_t user )
+{
+   if ( ! ObjectProxy_Check( pyobject ) )
+      return kFALSE;
+
+// just set the pointer value, no check
+   ObjectProxy* pyobj = (ObjectProxy*)pyobject;
+   para.fVoidp = pyobj->GetObject();
+   if ( func ) gInterpreter->CallFunc_SetArg( func,  para.fLong );
+   return kTRUE;
+}
+// -- END CLING WORKAROUND
+
 //____________________________________________________________________________
 Bool_t PyROOT::TVoidPtrRefConverter::SetArg(
       PyObject* pyobject, TParameter_t& para, CallFunc_t* func, Long_t )
@@ -1048,6 +1065,11 @@ PyROOT::TConverter* PyROOT::CreateConverter( const std::string& fullType, Long_t
 // converters for known/ROOT classes and default (void*)
    TConverter* result = 0;
    if ( TClass* klass = TClass::GetClass( realType.c_str() ) ) {
+   // CLING WORKAROUND -- special case for STL iterators
+      if ( realType.find( "__gnu_cxx::__normal_iterator", 0 ) == 0 )
+         result = new TSTLIteratorConverter();
+      else
+   // -- CLING WORKAROUND
       if ( cpd == "**" || cpd == "*&" || cpd == "&*" )
          result = new TRootObjectPtrConverter( klass, control );
       else if ( cpd == "*" )
diff --git a/bindings/pyroot/src/Converters.h b/bindings/pyroot/src/Converters.h
index 6f3ab83c63e..42b0d467f20 100644
--- a/bindings/pyroot/src/Converters.h
+++ b/bindings/pyroot/src/Converters.h
@@ -203,6 +203,14 @@ namespace PyROOT {
       virtual Bool_t ToMemory( PyObject* value, void* address );
    };
 
+// CLING WORKAROUND -- classes for STL iterators are completely undefined in that
+// they come in a bazillion different guises, so just do whatever
+   class TSTLIteratorConverter : public TConverter {
+   public:
+      virtual Bool_t SetArg( PyObject*, TParameter_t&, CallFunc_t* = 0, Long_t = 0 );
+   };
+// -- END CLING WORKAROUND
+
    class TVoidPtrRefConverter : public TConverter {
    public:
       virtual Bool_t SetArg( PyObject*, TParameter_t&, CallFunc_t* = 0, Long_t = 0 );
diff --git a/bindings/pyroot/src/Executors.cxx b/bindings/pyroot/src/Executors.cxx
index 4036324e809..d22838b40f3 100644
--- a/bindings/pyroot/src/Executors.cxx
+++ b/bindings/pyroot/src/Executors.cxx
@@ -419,7 +419,7 @@ PyROOT::TExecutor* PyROOT::CreateExecutor( const std::string& fullType )
       return (h->second)();
 
 // resolve typedefs etc., and collect qualifiers
-   std::string resolvedType = TClassEdit::ResolveTypedef( fullType.c_str(), true );
+   std::string resolvedType = Utility::ResolveTypedef( fullType );
 
 // a full, qualified matching executor is preferred
    h = gExecFactories.find( resolvedType );
diff --git a/bindings/pyroot/src/RootWrapper.cxx b/bindings/pyroot/src/RootWrapper.cxx
index 14282e33a61..958e417dcf6 100644
--- a/bindings/pyroot/src/RootWrapper.cxx
+++ b/bindings/pyroot/src/RootWrapper.cxx
@@ -38,6 +38,10 @@
 #include <algorithm>
 #include <vector>
 
+//- FOR CLING WORKAROUND
+#include "TError.h"
+//
+
 
 //- data _______________________________________________________________________
 R__EXTERN PyObject* gRootModule;
@@ -763,7 +767,12 @@ PyObject* PyROOT::BindRootObject( void* address, TClass* klass, Bool_t isRef )
    }
 
 // get actual class for recycling checking and/or downcasting
+// CLING WORKAROUND -- silence:
+// Error in <TStreamerInfo::Build>: __gnu_cxx::__normal_iterator<int*,vector<int> >, discarding: int* _M_current, no [dimension]
+   Int_t oldval = gErrorIgnoreLevel;
+   gErrorIgnoreLevel = 5000;
    TClass* clActual = isRef ? 0 : klass->GetActualClass( address );
+   gErrorIgnoreLevel = oldval;
 
 // obtain pointer to TObject base class (if possible) for memory mgmt; this is
 // done before downcasting, as upcasting from the current class may be easier and
diff --git a/bindings/pyroot/src/Utility.cxx b/bindings/pyroot/src/Utility.cxx
index b217c1434ff..0a6a13cb5d8 100644
--- a/bindings/pyroot/src/Utility.cxx
+++ b/bindings/pyroot/src/Utility.cxx
@@ -22,6 +22,7 @@
 #include "TCollection.h"
 #include "TDataType.h"
 #include "TFunction.h"
+#include "TMethod.h"
 #include "TMethodArg.h"
 #include "TError.h"
 #include "TInterpreter.h"
@@ -351,39 +352,18 @@ Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const char* op, co
 
 //____________________________________________________________________________
 static inline TFunction* FindAndAddOperator( const std::string& lcname, const std::string& rcname,
-     const char* op, TCollection* funcs = 0 ) {
+     const char* op, TClass* klass = 0 ) {
 // Helper to find a function with matching signature in 'funcs'.
    std::string opname = "operator";
    opname += op;
+   std::string proto = lcname + ", " + rcname;
 
 // case of global namespace
-   if ( ! funcs ) {
-      std::string proto = lcname + ", " + rcname;
+   if ( ! klass )
       return gROOT->GetGlobalFunctionWithPrototype( opname.c_str(), proto.c_str() );
-   }
 
 // case of specific namespace
-   TIter ifunc( funcs );
-
-   TFunction* func = 0;
-   while ( (func = (TFunction*)ifunc.Next()) ) {
-      if ( func->GetListOfMethodArgs()->GetSize() != 2 )
-         continue;
-
-      if ( func->GetName() == opname ) {
-         if ( ( lcname == ResolveTypedef( TClassEdit::CleanType(
-                  ((TMethodArg*)func->GetListOfMethodArgs()->At(0))->GetTypeNormalizedName().c_str(), 1 ).c_str() ) ) &&
-              ( rcname == ResolveTypedef( TClassEdit::CleanType(
-                  ((TMethodArg*)func->GetListOfMethodArgs()->At(1))->GetTypeNormalizedName().c_str(), 1 ).c_str() ) ) ) {
-
-         // done; break out loop
-            return func;
-         }
-
-      }
-   }
-
-   return 0;
+   return klass->GetMethodWithPrototype( opname.c_str(), proto.c_str() );
 }
 
 Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const std::string& lcname,
@@ -396,7 +376,7 @@ Bool_t PyROOT::Utility::AddBinaryOperator( PyObject* pyclass, const std::string&
 
    PyCallable* pyfunc = 0;
    if ( gnucxx.GetClass() ) {
-      TFunction* func = FindAndAddOperator( lcname, rcname, op, gnucxx->GetListOfMethods() );
+      TFunction* func = FindAndAddOperator( lcname, rcname, op, gnucxx.GetClass() );
       if ( func ) pyfunc = new TFunctionHolder( TScopeAdapter::ByName( "__gnu_cxx" ), func );
    }
 
-- 
GitLab