diff --git a/bindings/pyroot/ROOT.py b/bindings/pyroot/ROOT.py index a03b5337bbf80..06cef7445e5e1 100755 --- a/bindings/pyroot/ROOT.py +++ b/bindings/pyroot/ROOT.py @@ -132,11 +132,12 @@ def ismethod( object ): ### configuration --------------------------------------------------------------- class _Configuration( object ): - __slots__ = [ 'IgnoreCommandLineOptions', 'StartGuiThread', '_gts' ] + __slots__ = [ 'IgnoreCommandLineOptions', 'StartGuiThread', 'ExposeCppMacros', '_gts' ] def __init__( self ): self.IgnoreCommandLineOptions = 0 self.StartGuiThread = True + self.ExposeCppMacros = False self._gts = [] def __setGTS( self, value ): @@ -455,7 +456,7 @@ def __getattr2( self, name ): # "running" getattr return self.module.__all__ # lookup into ROOT (which may cause python-side enum/class/global creation) - attr = _root.LookupRootEntity( name ) + attr = _root.LookupRootEntity( name, PyConfig.ExposeCppMacros ) # the call above will raise AttributeError as necessary; so if we get here, # attr is valid: cache as appropriate, so we don't come back @@ -564,6 +565,9 @@ def _finishSchedule( ROOT = self ): for name in self.module.__pseudo__all__ + _memPolicyAPI + _sigPolicyAPI: self.__dict__[ name ] = getattr( _root, name ) + # the macro NULL is not available from Cling globals, but might be useful + setattr( _root, 'NULL', 0 ) + for name in std.stlclasses: setattr( _root, name, getattr( std, name ) ) diff --git a/bindings/pyroot/src/Pythonize.cxx b/bindings/pyroot/src/Pythonize.cxx index be646af6cabf1..ecb052267bd1d 100644 --- a/bindings/pyroot/src/Pythonize.cxx +++ b/bindings/pyroot/src/Pythonize.cxx @@ -35,9 +35,11 @@ // Standard #include #include -#include #include +#include +#include // only needed for Cling TMinuit workaround + namespace { @@ -1525,6 +1527,31 @@ namespace PyROOT { // workaround for Intel icc on Linux } }; +//- TMinuit behavior ---------------------------------------------------------- + void TMinuitPyCallback( void* vpyfunc, Long_t /* npar */, + Int_t& a0, Double_t* a1, Double_t& a2, Double_t* a3, Int_t a4 ) { + // a void* was passed to keep the interface on builtin types only + PyObject* pyfunc = (PyObject*)vpyfunc; + + // prepare arguments + PyObject* pya0 = BufFac_t::Instance()->PyBuffer_FromMemory( &a0, 1 ); + PyObject* pya1 = BufFac_t::Instance()->PyBuffer_FromMemory( a1, a0 ); + PyObject* pya2 = BufFac_t::Instance()->PyBuffer_FromMemory( &a2, 1 ); + PyObject* pya3 = BufFac_t::Instance()->PyBuffer_FromMemory( a3, -1 ); // size unknown + + // perform actual call + PyObject* result = PyObject_CallFunction( + pyfunc, (char*)"OOOOi", pya0, pya1, pya2, pya3, a4 ); + Py_DECREF( pya3 ); Py_DECREF( pya2 ); Py_DECREF( pya1 ); Py_DECREF( pya0 ); + + if ( ! result ) { + PyErr_Print(); + throw std::runtime_error( "TMinuit python fit function call failed" ); + } + + Py_XDECREF( result ); + } + //- TFN behavior -------------------------------------------------------------- double TFNPyCallback( void* vpyfunc, Long_t npar, double* a0, double* a1 ) { // a void* was passed to keep the interface on builtin types only @@ -1579,49 +1606,6 @@ namespace { return self; } -//- TMinuit behavior ---------------------------------------------------------- -/* TODO: implement for Cling - int TMinuitPyCallback( G__value* res, G__CONST char*, struct G__param* libp, int hash ) - { - // CINT-installable callback function to allow Minuit to call into python. - PyObject* result = 0; - - // retrieve function information - PyObject* pyfunc = PyROOT::Utility::GetInstalledMethod( G__value_get_tagnum(res) ); - if ( ! pyfunc ) - return 0; - - // prepare arguments - PyObject* arg1 = BufFac_t::Instance()->PyBuffer_FromMemory( - G__Intref(&libp->para[0]), 1 ); - int npar = *G__Intref(&libp->para[0]); - - PyObject* arg2 = BufFac_t::Instance()->PyBuffer_FromMemory( - (Double_t*)G__int(libp->para[1]), npar ); - - PyObject* arg3 = BufFac_t::Instance()->PyBuffer_FromMemory( - G__Doubleref(&libp->para[2]), 1 ); - - PyObject* arg4 = BufFac_t::Instance()->PyBuffer_FromMemory( - (Double_t*)G__int(libp->para[3]), -1 ); // size unknown - - // perform actual call - result = PyObject_CallFunction( pyfunc, (char*)"OOOOi", - arg1, arg2, arg3, arg4, (int)G__int(libp->para[4]) ); - Py_DECREF( arg4 ); Py_DECREF( arg3 ); Py_DECREF( arg2 ); Py_DECREF( arg1 ); - - if ( ! result ) { - PyErr_Print(); - throw std::runtime_error( "TMinuit python fit function call failed" ); - } - - Py_XDECREF( result ); - - G__setnull( res ); - return ( 1 || hash || res || libp ); - } - -*/ //____________________________________________________________________________ class TPretendInterpreted: public PyCallable { @@ -1768,7 +1752,6 @@ namespace { //- TMinuit behavior ----------------------------------------------------------- -/* TODO: implement for Cling class TMinuitSetFCN : public TPretendInterpreted { public: TMinuitSetFCN( int nArgs = 1 ) : TPretendInterpreted( nArgs ) {} @@ -1798,28 +1781,50 @@ namespace { if ( ! IsCallable( pyfunc ) ) return 0; - // use callable name (if available) as identifier - PyObject* pyname = PyObject_GetAttr( pyfunc, PyStrings::gName ); - const char* name = "dummy"; - if ( pyname != 0 ) - name = PyROOT_PyUnicode_AsString( pyname ); + // create signature + std::vector signature; signature.reserve( 5 ); + signature.push_back( "Int_t&" ); + signature.push_back( "Double_t*" ); + signature.push_back( "Double_t&" ); + signature.push_back( "Double_t*" ); + signature.push_back( "Int_t" ); - // registration with CINT - Long_t fid = Utility::InstallMethod( 0, pyfunc, name, 0, - "i - - 1 - - D - - 0 - - d - - 1 - - D - - 0 - - i - - 0 - -", - (void*)TMinuitPyCallback, 5 ); - Py_XDECREF( pyname ); + // registration with Cling + void* fptr = Utility::CreateWrapperMethod( + pyfunc, 5, "void", signature, "TMinuitPyCallback" ); + if ( ! fptr /* PyErr was set */ ) + return 0; - // get function + // get setter function MethodProxy* method = (MethodProxy*)PyObject_GetAttr( (PyObject*)self, PyStrings::gSetFCN ); + // CLING WORKAROUND: SetFCN(void* fun) is deprecated but for whatever reason + // still available yet not functional; select the correct one based on its + // signature of the full function pointer + PyCallable* setFCN = 0; + const MethodProxy::Methods_t& methods = method->fMethodInfo->fMethods; + for ( MethodProxy::Methods_t::const_iterator im = methods.begin(); im != methods.end(); ++im ) { + PyObject* sig = (*im)->GetSignature(); + if ( strstr( PyROOT_PyUnicode_AsString( sig ), "Double_t&" ) ) { + // the comparison was not exact, but this is just a workaround + setFCN = *im; + Py_DECREF( sig ); + break; + } + Py_DECREF( sig ); + } + // END CLING WORKAROUND + // build new argument array PyObject* newArgs = PyTuple_New( 1 ); - PyTuple_SET_ITEM( newArgs, 0, PyROOT_PyCapsule_New( (void*)fid, NULL, NULL ) ); + PyTuple_SET_ITEM( newArgs, 0, PyROOT_PyCapsule_New( fptr, NULL, NULL ) ); // re-run - PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs ); + // CLING WORKAROUND: this is to be the call once TMinuit is fixed: + // PyObject* result = PyObject_CallObject( (PyObject*)method, newArgs ); + PyObject* result = setFCN->operator()( self, newArgs, NULL ); + // END CLING WORKAROUND // done, may have worked, if not: 0 is returned Py_DECREF( newArgs ); @@ -1856,14 +1861,13 @@ namespace { return TMinuitSetFCN::operator()( self, args, 0, 0, release_gil ); } }; -*/ //- Fit::TFitter behavior ------------------------------------------------------ PyObject* gFitterPyCallback = 0; void FitterPyCallback( int& npar, double* gin, double& f, double* u, int flag ) { - // CINT-callable callback for Fit::Fitter derived objects. + // Cling-callable callback for Fit::Fitter derived objects. PyObject* result = 0; // prepare arguments @@ -1891,7 +1895,6 @@ namespace { Py_XDECREF( result ); } - class TFitterFitFCN : public TPretendInterpreted { public: TFitterFitFCN() : TPretendInterpreted( 2 ) {} @@ -2300,13 +2303,11 @@ Bool_t PyROOT::Pythonize( PyObject* pyclass, const std::string& name ) if ( name == "TFunction" ) // allow direct call return Utility::AddToClass( pyclass, "__call__", (PyCFunction) TFunctionCall ); -/* TODO: implement for Cling if ( name == "TMinuit" ) // allow call with python callable return Utility::AddToClass( pyclass, "SetFCN", new TMinuitSetFCN ); if ( name == "TFitter" ) // allow call with python callable (this is not correct) return Utility::AddToClass( pyclass, "SetFCN", new TMinuitFitterSetFCN ); -*/ if ( name == "Fitter" ) // really Fit::Fitter, allow call with python callable return Utility::AddToClass( pyclass, "FitFCN", new TFitterFitFCN ); diff --git a/bindings/pyroot/src/RootModule.cxx b/bindings/pyroot/src/RootModule.cxx index 0739dbe6f5df9..c8bfb857fb2f0 100644 --- a/bindings/pyroot/src/RootModule.cxx +++ b/bindings/pyroot/src/RootModule.cxx @@ -24,6 +24,7 @@ // Standard #include +#include //- from Python's dictobject.c ------------------------------------------------- @@ -73,10 +74,10 @@ namespace { PyObject* LookupRootEntity( PyObject* pyname, PyObject* args ) { // Find a match within the ROOT module for something with name 'pyname'. - const char* cname = 0; + const char* cname = 0; long macro_ok = 0; if ( pyname && PyROOT_PyUnicode_CheckExact( pyname ) ) cname = PyROOT_PyUnicode_AsString( pyname ); - else if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "s" ), &cname ) ) ) + else if ( ! ( args && PyArg_ParseTuple( args, const_cast< char* >( "s|l" ), &cname, ¯o_ok ) ) ) return 0; // we may have been destroyed if this code is called during shutdown @@ -111,6 +112,20 @@ namespace { TObject* object = gROOT->FindObject( name.c_str() ); if ( object != 0 ) return BindRootObject( object, object->IsA() ); + + // 5th attempt: check macro's (debatable, but this worked in CINT) + if ( macro_ok ) { + PyErr_Clear(); + std::ostringstream ismacro; + ismacro << "#ifdef " << name << "\n_pyroot_" << name << "=" << name + << ";true;\n#else\nfalse;\n#endif"; + if ( gROOT->ProcessLine( ismacro.str().c_str() ) ) { + // can now retrieve this as a global + attr = GetRootGlobalFromString( "_pyroot_"+name ); + if ( attr != 0 ) + return attr; + } + } } // still here? raise attribute error diff --git a/bindings/pyroot/src/TPyClassGenerator.cxx b/bindings/pyroot/src/TPyClassGenerator.cxx index 5d879b0617d17..e3d21d8cd5278 100644 --- a/bindings/pyroot/src/TPyClassGenerator.cxx +++ b/bindings/pyroot/src/TPyClassGenerator.cxx @@ -80,10 +80,6 @@ TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load, Bool_t silen std::ostringstream proxyCode; proxyCode << "class " << clName << " {\nprivate:\n PyObject* fPyObject;\npublic:\n"; -/* -// special case: constructor; add method and store callback - PyROOT::Utility::InstallMethod( &gcl, pyclass, clName, 0, "ellipsis", (void*)PyCtorCallback ); -*/ // loop over and add member functions Bool_t hasConstructor = kFALSE; for ( int i = 0; i < PyList_GET_SIZE( attrs ); ++i ) { @@ -139,10 +135,6 @@ TClass* TPyClassGenerator::GetClass( const char* name, Bool_t load, Bool_t silen else proxyCode << " TPyArg::CallConstructor(fPyObject, (PyObject*)" << (void*)pyclass << ", v)"; proxyCode << ";\n }\n"; -/* if ( mtName != "__init__" ) { - PyROOT::Utility::InstallMethod( - &gcl, attr, mtName, "TPyReturn", "ellipsis", (void*)PyMemFuncCallback ); - } */ } // no decref of attr for now (b/c of hard-wired ptr); need cleanup somehow diff --git a/core/utils/src/rootcling.cxx b/core/utils/src/rootcling.cxx index 0495784f1da42..5e75ddb78882b 100644 --- a/core/utils/src/rootcling.cxx +++ b/core/utils/src/rootcling.cxx @@ -234,7 +234,7 @@ template struct IsPointer { enum { kVal = 0 }; }; namespace std {} using namespace std; namespace genreflex { - bool verbose = false; + bool verbose = true; } #include "TClassEdit.h" @@ -3275,65 +3275,65 @@ unsigned int checkHeadersNames(std::vector& headersNames) } //______________________________________________________________________________ -unsigned int extractArgs(int& argc, char** argv, std::vector& args) +unsigned int extractArgs(int argc, char** argv, std::vector& args) { // Extract the arguments from the command line - + // loop on argv, spot strings which are not preceeded by something // starting with "-" and do not start with "-" - std::vector argsIndeces; +// std::vector argsIndeces; + unsigned int argvCounter=0; for (int i=1;i newArgv (newArgc); - unsigned int argvCounter=0; - for (int i=0;i newArgv (newArgc); +// unsigned int argvCounter=0; +// for (int i=0;i::iterator it = args.begin(); it < args.end();++it){ std::cout << i << ") " << *it << std::endl; ++i; } - + } - - argc=newArgc; - return args.size(); + +// for (int i=0;iarg << std::endl; + optionIndex++; values.push_back(opt->arg); nValues++; } @@ -3603,7 +3607,7 @@ void RiseWarningIfPresent(std::vector& options, if (options[optionIndex]){ ROOT::TMetaUtils::Warning(0, - "*** genereflex: %s are not supported anymore.\n", + "*** genereflex: %s is not supported anymore.\n", descriptor); } } @@ -3823,34 +3827,38 @@ int GenReflex(int argc, char **argv) {NOMEMBERTYPEDEFS, STRING , "" , "no_membertypedefs" , - option::FullArg::Required, + option::FullArg::None, ""}, {NOTEMPLATETYPEDEFS, STRING , "" , "no_templatetypedefs" , - option::FullArg::Required, + option::FullArg::None, ""}, {0,0,0,0,0,0} }; std::vector headersNames; - int originalArgc=argc; - extractArgs(argc,argv,headersNames); // The only args are the headers here + const int originalArgc=argc; + // The only args are the headers here + const int extractedArgs = extractArgs(argc,argv,headersNames); - // skip program name argv[0] if present - int newArgc = argc-(argc>0); - char** newArgv = argv+(argc>0); + const int offset = 1 + extractedArgs; // skip argv[0] and the headers + argc-=offset; + argv+=offset; // Parse the options - option::Stats stats(genreflexUsageDescriptor, newArgc, newArgv); + option::Stats stats(genreflexUsageDescriptor, argc, argv); std::vector options(stats.options_max);// non POD var size arrays are not C++! std::vector buffer(stats.buffer_max); // The 4 is the minimum size of the abbreviation lenght. // For example, --selction_file can be abbreviated with --sele at least. - option::Parser parse(genreflexUsageDescriptor, newArgc, newArgv, &options[0], &buffer[0], 4); + std::cout << "Parsing\n"; + option::Parser parse(genreflexUsageDescriptor, argc, argv, &options[0], &buffer[0], 5); + std::cout << "Parsing END\n"; + if (parse.error()){ ROOT::TMetaUtils::Error(0, "*** genreflex: Argument parsing error!\n"); return 1; diff --git a/graf2d/postscript/src/TTeXDump.cxx b/graf2d/postscript/src/TTeXDump.cxx index fcacf1e768454..4ddc82dd82064 100644 --- a/graf2d/postscript/src/TTeXDump.cxx +++ b/graf2d/postscript/src/TTeXDump.cxx @@ -392,7 +392,7 @@ void TTeXDump::DrawPolyMarker(Int_t n, Double_t *xw, Double_t *yw) } PrintStr("}{\\draw[mark options={color=c,fill=c},mark size="); - PrintStr(Form("%fpt,mark=",14./3*fMarkerSize)); + PrintStr(Form("%fpt,mark=",8./3.33*fMarkerSize)); switch (fMarkerStyle) { case 1 : PrintStr("*"); diff --git a/hist/doc/v600/index.md b/hist/doc/v600/index.md index cc4f7b16449c5..44c548fe496ac 100644 --- a/hist/doc/v600/index.md +++ b/hist/doc/v600/index.md @@ -119,6 +119,10 @@ histo2->Draw("same"); } ``` +- In `TGraph2DPainter::PaintLevels` the colour levels used to paint + the triangles did not match the minimum and maximum set by the + user on the `TGraph2D`. This problem was reported + [here](http://root.cern.ch/phpBB3/viewtopic.php?f=3&t=16937&p=72314#p72314) ### TPaletteAxis @@ -158,6 +162,8 @@ `TGraph2D` after a `Clear` is performed. - In `GetHistogram()` the lower and higher axis limits are always different. +- Protection added to avoid a Seg Fault on `.q` when `SetHistogram()` + is called on a `TGraph2D`. ### TF1 diff --git a/hist/hist/inc/TGraph2D.h b/hist/hist/inc/TGraph2D.h index b21a33c4d9f54..e1b16149ba737 100644 --- a/hist/hist/inc/TGraph2D.h +++ b/hist/hist/inc/TGraph2D.h @@ -113,6 +113,8 @@ class TGraph2D : public TNamed, public TAttLine, public TAttFill, public TAttMar virtual Double_t GetErrorY(Int_t bin) const; virtual Double_t GetErrorZ(Int_t bin) const; Double_t GetMargin() const {return fMargin;} + Double_t GetMaximum() const {return fMaximum;}; + Double_t GetMinimum() const {return fMinimum;}; TAxis *GetXaxis() const ; TAxis *GetYaxis() const ; TAxis *GetZaxis() const ; diff --git a/hist/hist/src/TGraph2D.cxx b/hist/hist/src/TGraph2D.cxx index 20a14c74d0efe..8fbc184ac2b68 100644 --- a/hist/hist/src/TGraph2D.cxx +++ b/hist/hist/src/TGraph2D.cxx @@ -614,7 +614,7 @@ void TGraph2D::Clear(Option_t * /*option = "" */) delete [] fZ; fZ = 0; fSize = fNpoints = 0; - if (fHistogram) { + if (fHistogram && !fUserHisto) { delete fHistogram; fHistogram = 0; } diff --git a/hist/histpainter/src/TGraph2DPainter.cxx b/hist/histpainter/src/TGraph2DPainter.cxx index 04bbd4c9eeaa9..e683acf711e56 100644 --- a/hist/histpainter/src/TGraph2DPainter.cxx +++ b/hist/histpainter/src/TGraph2DPainter.cxx @@ -589,8 +589,12 @@ void TGraph2DPainter::PaintLevels(Int_t *t,Double_t *x, Double_t *y, Double_t x0 = x[0] , x2 = x[0]; Double_t y0 = y[0] , y2 = y[0]; Double_t z0 = fZ[p0], z2 = fZ[p0]; - Double_t zmin = fZmin; - Double_t zmax = fZmax; + Double_t zmin = fGraph2D->GetMinimum(); + Double_t zmax = fGraph2D->GetMaximum(); + if (zmin==-1111 && zmax==-1111) { + zmin = fZmin; + zmax = fZmax; + } // Order along Z axis the points (xi,yi,zi) where "i" belongs to {0,1,2} // After this z0 < z1 < z2 @@ -773,7 +777,7 @@ void TGraph2DPainter::PaintPolyMarker(Option_t *option) Bool_t colors = opt.Contains("pcol"); Int_t ncolors = gStyle->GetNumberOfColors(); Int_t it, theColor; - + // Initialize the levels on the Z axis if (colors) { Int_t ndiv = gCurrentHist->GetContour(); @@ -783,7 +787,7 @@ void TGraph2DPainter::PaintPolyMarker(Option_t *option) } if (gCurrentHist->TestBit(TH1::kUserContour) == 0) gCurrentHist->SetContour(ndiv); } - + Double_t *xm = new Double_t[fNpoints]; Double_t *ym = new Double_t[fNpoints]; Double_t hzmin = gCurrentHist->GetMinimum(); diff --git a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp index b287909288d2c..ed9075642608f 100644 --- a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp +++ b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.cpp @@ -57,6 +57,57 @@ extern "C" { using namespace clang; namespace cling { + typedef std::map > nonnull_map_t; + + // NonNullDeclFinder finds the function decls with nonnull attribute args. + class NonNullDeclFinder + : public RecursiveASTVisitor { + private: + Sema* m_Sema; + llvm::SmallVector m_NonNullDeclNames; + nonnull_map_t m_NonNullArgIndexs; + + public: + NonNullDeclFinder(Sema* S) : m_Sema(S) {} + const llvm::SmallVector& getDeclNames() const { + return m_NonNullDeclNames; + } + + const nonnull_map_t& getArgIndexs() const { + return m_NonNullArgIndexs; + } + + // Deal with all the call expr in the transaction. + bool VisitCallExpr(CallExpr* TheCall) { + if (FunctionDecl* FDecl = TheCall->getDirectCallee()) { + std::bitset<32> ArgIndexs; + for (specific_attr_iterator + I = FDecl->specific_attr_begin(), + E = FDecl->specific_attr_end(); I != E; ++I) { + NonNullAttr *NonNull = *I; + + // Store all the null attr argument's index into "ArgIndexs". + for (NonNullAttr::args_iterator i = NonNull->args_begin(), + e = NonNull->args_end(); i != e; ++i) + ArgIndexs.set(*i); + } + + if (ArgIndexs.any()) { + + // Get the function decl's name. + llvm::StringRef FName = FDecl->getName(); + + // Store the function decl's name into the vector. + m_NonNullDeclNames.push_back(FName); + + // Store the function decl's name with its null attr args' indexes + // into the map. + m_NonNullArgIndexs.insert(std::make_pair(FName, ArgIndexs)); + } + } + return true; // returning false will abort the in-depth traversal. + } + }; NullDerefProtectionTransformer::NullDerefProtectionTransformer(Sema *S) : TransactionTransformer(S), FailBB(0), Builder(0), Inst(0) {} @@ -65,7 +116,6 @@ namespace cling { {} void NullDerefProtectionTransformer::Transform() { - using namespace clang; FunctionDecl* FD = getTransaction()->getWrapperFD(); if (!FD) return; @@ -105,8 +155,39 @@ namespace cling { // Find the function in the module. llvm::Function* F = getTransaction()->getModule()->getFunction(mangledName); - if (F) - runOnFunction(*F); + if (!F) return; + + llvm::IRBuilder<> TheBuilder(F->getContext()); + Builder = &TheBuilder; + runOnFunction(*F); + + NonNullDeclFinder Finder(m_Sema); + + // Find all the function decls with null attribute arguments. + for (size_t Idx = 0, E = getTransaction()->size(); Idx < E; ++Idx) { + Transaction::DelayCallInfo I = (*getTransaction())[Idx]; + for (DeclGroupRef::const_iterator J = I.m_DGR.begin(), + JE = I.m_DGR.end(); J != JE; ++J) + if ((*J)->hasBody()) + Finder.TraverseStmt((*J)->getBody()); + } + + const llvm::SmallVector& + FDeclNames = Finder.getDeclNames(); + if (FDeclNames.empty()) return; + + llvm::Module* M = F->getParent(); + + for (llvm::SmallVector::const_iterator + i = FDeclNames.begin(), e = FDeclNames.end(); i != e; ++i) { + const nonnull_map_t& ArgIndexs = Finder.getArgIndexs(); + nonnull_map_t::const_iterator it = ArgIndexs.find(*i); + + if (it != ArgIndexs.end()) { + const std::bitset<32>& ArgNums = it->second; + handleNonNullArgCall(*M, *i, ArgNums); + } + } } llvm::BasicBlock* @@ -115,6 +196,7 @@ namespace cling { llvm::Module* Md = Fn->getParent(); llvm::LLVMContext& ctx = Fn->getContext(); + llvm::BasicBlock::iterator PreInsertInst = Builder->GetInsertPoint(); FailBB = llvm::BasicBlock::Create(ctx, "FailBlock", Fn); Builder->SetInsertPoint(FailBB); @@ -157,6 +239,7 @@ namespace cling { llvm::BranchInst::Create(HandleBB, BB, Cmp, FailBB); llvm::ReturnInst::Create(Fn->getContext(), HandleBB); + Builder->SetInsertPoint(PreInsertInst); return FailBB; } @@ -182,8 +265,6 @@ namespace cling { } bool NullDerefProtectionTransformer::runOnFunction(llvm::Function &F) { - llvm::IRBuilder<> TheBuilder(F.getContext()); - Builder = &TheBuilder; std::vector WorkList; for (llvm::inst_iterator i = inst_begin(F), e = inst_end(F); i != e; ++i) { @@ -195,6 +276,7 @@ namespace cling { for (std::vector::iterator i = WorkList.begin(), e = WorkList.end(); i != e; ++i) { Inst = *i; + Builder->SetInsertPoint(Inst); llvm::LoadInst* I = llvm::cast(*i); // Find all the instructions that uses the instruction I. @@ -243,4 +325,62 @@ namespace cling { } return true; } + + void NullDerefProtectionTransformer::instrumentCallInst(llvm::Instruction* + TheCall, const std::bitset<32>& ArgIndexs) { + llvm::Type* Int8PtrTy = llvm::Type::getInt8PtrTy(TheCall->getContext()); + llvm::CallSite CS = TheCall; + + for (int index = 0; index < 32; ++index) { + if (!ArgIndexs.test(index)) continue; + llvm::Value* Arg = CS.getArgument(index); + if (!Arg) continue; + llvm::Type* ArgTy = Arg->getType(); + if (ArgTy != Int8PtrTy) + continue; + + llvm::BasicBlock* OldBB = TheCall->getParent(); + llvm::ICmpInst* Cmp + = new llvm::ICmpInst(TheCall, llvm::CmpInst::ICMP_EQ, Arg, + llvm::Constant::getNullValue(ArgTy), ""); + + llvm::Instruction* Inst = Builder->GetInsertPoint(); + llvm::BasicBlock* NewBB = OldBB->splitBasicBlock(Inst); + + OldBB->getTerminator()->eraseFromParent(); + llvm::BranchInst::Create(getTrapBB(NewBB), NewBB, Cmp, OldBB); + } + } + + void NullDerefProtectionTransformer::handleNonNullArgCall(llvm::Module& M, + const llvm::StringRef& name, const std::bitset<32>& ArgIndexs) { + + // Get the function by the name. + llvm::Function* func = M.getFunction(name); + if (!func) + return; + + // Find all the instructions that calls the function. + std::vector WorkList; + for (llvm::Value::use_iterator I = func->use_begin(), E = func->use_end(); + I != E; ++I) { + llvm::CallSite CS(*I); + if (!CS || CS.getCalledValue() != func) + continue; + WorkList.push_back(CS.getInstruction()); + } + + // There is no call instructions that call the function and return. + if (WorkList.empty()) + return; + + // Instrument all the call instructions that call the function. + for (std::vector::iterator I = WorkList.begin(), + E = WorkList.end(); I != E; ++I) { + Inst = *I; + Builder->SetInsertPoint(Inst); + instrumentCallInst(Inst, ArgIndexs); + } + return; + } } // end namespace cling diff --git a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h index ac2214934e2fa..1d9e54f9ca65f 100644 --- a/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h +++ b/interpreter/cling/lib/Interpreter/NullDerefProtectionTransformer.h @@ -38,6 +38,11 @@ namespace cling { llvm::BasicBlock* getTrapBB(llvm::BasicBlock* BB); void instrumentInst(llvm::Instruction* Inst, llvm::Value* Arg); bool runOnFunction(llvm::Function& F); + void instrumentCallInst(llvm::Instruction* TheCall, + const std::bitset<32>& ArgIndexs); + void handleNonNullArgCall(llvm::Module& M, + const llvm::StringRef& FName, + const std::bitset<32>& ArgIndexs); public: NullDerefProtectionTransformer(clang::Sema* S); diff --git a/interpreter/cling/test/NullDeref/NonNullArg.C b/interpreter/cling/test/NullDeref/NonNullArg.C new file mode 100644 index 0000000000000..3a0aa411f468d --- /dev/null +++ b/interpreter/cling/test/NullDeref/NonNullArg.C @@ -0,0 +1,8 @@ +// RUN: cat %s | %cling -Xclang -verify +//This file checks a call instruction. The called function has arguments with nonnull attribute. +#include +char *p; +strcmp("a", p); // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}} + +strcmp(p, "a"); // expected-warning {{you are about to dereference null ptr, which probably will lead to seg violation. Do you want to proceed?[y/n]}} +.q diff --git a/math/mathmore/src/GSLMultiFit.h b/math/mathmore/src/GSLMultiFit.h index 3713101770403..c40632a84ef6e 100644 --- a/math/mathmore/src/GSLMultiFit.h +++ b/math/mathmore/src/GSLMultiFit.h @@ -108,7 +108,9 @@ class GSLMultiFit { if (npts == 0) return -1; unsigned int npar = funcVec[0].NDim(); - typedef typename std::vector FuncVec; + // Remove unused typedef to remove warning in GCC48 + // http://gcc.gnu.org/gcc-4.8/porting_to.html + // typedef typename std::vector FuncVec; //FuncIt funcIter = funcVec.begin(); fFunc.SetFunction(funcVec, npts, npar); // create solver object diff --git a/proof/proof/inc/TProof.h b/proof/proof/inc/TProof.h index 7dd4a61723558..c7747e498aa8d 100644 --- a/proof/proof/inc/TProof.h +++ b/proof/proof/inc/TProof.h @@ -679,7 +679,7 @@ friend class TXProofServ; // to access EUrgent Int_t HandleInputMessage(TSlave *wrk, TMessage *m, Bool_t deactonfail = kFALSE); void HandleSubmerger(TMessage *mess, TSlave *sl); void SetMonitor(TMonitor *mon = 0, Bool_t on = kTRUE); - Bool_t PollForNewWorkers(); + Int_t PollForNewWorkers(); void ReleaseMonitor(TMonitor *mon); diff --git a/proof/proof/src/TProof.cxx b/proof/proof/src/TProof.cxx index 3c21f18a761c8..c65e43f049dd4 100644 --- a/proof/proof/src/TProof.cxx +++ b/proof/proof/src/TProof.cxx @@ -2827,17 +2827,25 @@ Int_t TProof::Collect(TMonitor *mon, Long_t timeout, Int_t endtype, Bool_t deact } //______________________________________________________________________________ -Bool_t TProof::PollForNewWorkers() +Int_t TProof::PollForNewWorkers() { // Asks the PROOF Serv for new workers in Dynamic Startup mode and activates - // them. Returns the number of new workers found. + // them. Returns the number of new workers found, or <0 on errors. // Requests for worker updates Int_t dummy = 0; TList *reqWorkers = new TList(); reqWorkers->SetOwner(kFALSE); - R__ASSERT(gProofServ); + if (!TestBit(TProof::kIsMaster)) { + Error("PollForNewWorkers", "Can't invoke: not on a master -- should not happen!"); + return -1; + } + if (!gProofServ) { + Error("PollForNewWorkers", "No ProofServ available -- should not happen!"); + return -1; + } + gProofServ->GetWorkers(reqWorkers, dummy, kTRUE); // last 2 are dummy // List of new workers only (TProofNodeInfo) @@ -2876,10 +2884,14 @@ Bool_t TProof::PollForNewWorkers() Int_t nNewWorkers = newWorkers->GetEntries(); // Add the new workers - if (newWorkers->GetEntries() > 0) { + if (nNewWorkers > 0) { PDB(kGlobal, 1) Info("PollForNewWorkers", "Requesting to add %d new worker(s)", newWorkers->GetEntries()); - AddWorkers(newWorkers); + Int_t rv = AddWorkers(newWorkers); + if (rv < 0) { + Error("PollForNewWorkers", "Call to AddWorkers() failed (got %d < 0)", rv); + return -1; + } // Don't delete newWorkers: AddWorkers() will do that } else { @@ -6927,8 +6939,14 @@ Int_t TProof::GoMoreParallel(Int_t nWorkersToAdd) // is sent back to the client when we go "more" parallel. // Returns -1 on error, number of total (not added!) workers on success. - if (!IsValid() || !IsMaster() || IsIdle()) + if (!IsValid() || !IsMaster() || IsIdle()) { + Error("GoMoreParallel", "Can't invoke here -- should not happen!"); + return -1; + } + if (!gProofServ) { + Error("GoMoreParallel", "No ProofServ available -- should not happen!"); return -1; + } TSlave *sl = 0x0; TIter next( fSlaves ); @@ -7004,7 +7022,6 @@ Int_t TProof::GoMoreParallel(Int_t nWorkersToAdd) // Notify the client that we've got more workers, and print info on // Master's log as well - R__ASSERT(gProofServ); TString s; s.Form("PROOF just went more parallel (%d additional worker%s, %d worker%s total)", nAddedWorkers, (nAddedWorkers == 1) ? "" : "s", diff --git a/test/Makefile b/test/Makefile index 026c770e6d855..20d8e21b82200 100644 --- a/test/Makefile +++ b/test/Makefile @@ -276,27 +276,36 @@ STRESSHISTO = stressHistogram.$(ObjSuf) STRESSHISTS = stressHistogram.$(SrcSuf) STRESSHIST = stressHistogram$(ExeSuf) +ifeq ($(shell $(RC) --has-sqlite),yes) +SQLITETESTO = sqlitetest.$(ObjSuf) +SQLITETESTS = sqlitetest.$(SrcSuf) +SQLITETEST = sqlitetest$(ExeSuf) +endif + -OBJS = $(EVENTO) $(MAINEVENTO) $(EVENTMTO) $(HWORLDO) $(HSIMPLEO) $(MINEXAMO) \ +OBJS = $(EVENTO) $(MAINEVENTO) $(EVENTMTO) $(HWORLDO) $(HSIMPLEO) \ + $(MINEXAMO) \ $(TSTRINGO) $(TCOLLEXO) $(VVECTORO) $(VMATRIXO) $(VLAZYO) \ $(HELLOO) $(ACLOCKO) $(STRESSO) $(TBENCHO) $(BENCHO) \ $(STRESSSHAPESO) $(TCOLLBMO) $(STRESSGEOMETRYO) $(STRESSLO) \ - $(STRESSGO) $(STRESSSPO) $(TESTBITSO) \ + $(STRESSGO) $(STRESSSPO) $(TESTBITSO) \ $(CTORTUREO) $(QPRANDOMO) $(THREADSO) $(STRESSVECO) \ - $(STRESSMATHO) $(STRESSFITO) $(STRESSHISTOFITO) $(STRESSHEPIXO) \ - $(STRESSENTRYLISTO) $(STRESSROOFITO) $(STRESSROOSTATSO) $(STRESSPROOFO) \ - $(STRESSMATHMOREO) $(STRESSTMVAO) $(STRESSINTERPO) $(STRESSITERO) \ - $(STRESSHISTO) $(STRESSGUIO) - -PROGRAMS = $(EVENT) $(EVENTMTSO) $(HWORLD) $(HSIMPLE) $(MINEXAM) $(TSTRING) \ - $(TCOLLEX) $(TCOLLBM) $(VVECTOR) $(VMATRIX) $(VLAZY) \ - $(HELLOSO) $(ACLOCKSO) $(STRESS) $(TBENCHSO) $(BENCH) \ + $(STRESSMATHO) $(STRESSFITO) $(STRESSHISTOFITO) \ + $(STRESSHEPIXO) $(STRESSENTRYLISTO) $(STRESSROOFITO) \ + $(STRESSROOSTATSO) $(STRESSPROOFO) $(STRESSMATHMOREO) \ + $(STRESSTMVAO) $(STRESSINTERPO) $(STRESSITERO) \ + $(STRESSHISTO) $(STRESSGUIO) $(SQLITETESTO) + +PROGRAMS = $(EVENT) $(EVENTMTSO) $(HWORLD) $(HSIMPLE) $(MINEXAM) \ + $(TSTRING) $(TCOLLEX) $(TCOLLBM) $(VVECTOR) $(VMATRIX) \ + $(VLAZY) $(HELLOSO) $(ACLOCKSO) $(STRESS) $(TBENCHSO) $(BENCH) \ $(STRESSSHAPES) $(STRESSGEOMETRY) $(STRESSL) $(STRESSG) \ $(TESTBITS) $(CTORTURE) $(QPRANDOM) $(THREADS) $(STRESSSP) \ $(STRESSVEC) $(STRESSFIT) $(STRESSHISTOFIT) $(STRESSHEPIX) \ - $(STRESSENTRYLIST) $(STRESSROOFIT) $(STRESSROOSTATS) $(STRESSPROOF) $(STRESSMATH) \ - $(STRESSMATHMORE) $(STRESSTMVA) $(STRESSINTERP) $(STRESSITER) \ - $(STRESSHIST) $(STRESSGUI) + $(STRESSENTRYLIST) $(STRESSROOFIT) $(STRESSROOSTATS) \ + $(STRESSPROOF) $(STRESSMATH) \ + $(STRESSMATHMORE) $(STRESSTMVA) $(STRESSINTERP) $(STRESSITER) \ + $(STRESSHIST) $(STRESSGUI) $(SQLITETEST) OBJS += $(GUITESTO) $(GUIVIEWERO) $(TETRISO) @@ -719,6 +728,11 @@ $(STRESSHIST): $(STRESSHISTO) $(MT_EXE) @echo "$@ done" +$(SQLITETEST): $(SQLITETESTO) + $(LD) $(LDFLAGS) $^ $(LIBS) $(OutPutOpt)$@ + $(MT_EXE) + @echo "$@ done" + clean: @rm -f $(OBJS) $(TRACKMATHSRC) core *Dict.* @@ -726,7 +740,7 @@ distclean: clean -@(mv -f stressRooStats_ref.root stressRooStats_ref.root- >/dev/null 2>&1;true) @rm -f $(PROGRAMS) $(EVENTSO) $(EVENTLIB) *Dict.* *.def *.exp \ *.root *.ps *.so *.lib *.dll *.d *.log .def so_locations \ - files/* *.pcm + files/* *.pcm testdb.sqlite @rm -rf cxx_repository -@(mv -f stressRooStats_ref.root- stressRooStats_ref.root >/dev/null 2>&1;true) -@cd RootShower && $(MAKE) distclean diff --git a/test/sqlitetest.cxx b/test/sqlitetest.cxx new file mode 100644 index 0000000000000..16daf43395af3 --- /dev/null +++ b/test/sqlitetest.cxx @@ -0,0 +1,208 @@ +#include +#include +#include + +#include "TSQLServer.h" +#include "TSQLResult.h" +#include "TSQLRow.h" +#include "TSQLStatement.h" +#include "TTimeStamp.h" +#include "TList.h" + +int main() { + + // Create a new DB called testdb: + TSQLServer *serv=TSQLServer::Connect("sqlite://testdb.sqlite", "", ""); + if (serv == NULL) { + std::cerr << "Connection failed!" << std::endl; + _exit(1); + } + + // First, some debug-checks: + std::cout << "DB: " << serv->GetDB() << std::endl; + std::cout << "DBMS: " << serv->GetDBMS() << std::endl; + std::cout << "HOST: " << serv->GetHost() << std::endl; + std::cout << "PORT: " << serv->GetPort() << std::endl; + std::cout << "Info: " << serv->ServerInfo() << std::endl; + + // Create table: + if ((serv!=0) && serv->IsConnected()) { + // create statement instance + TSQLStatement* stmt = serv->Statement("CREATE TABLE TESTTABLE (ID1 FOO, ID2 FOO, ID3 FOO, ID4 FOO, ID5 FOO, ID6 FOO, ID7 FOO, ID8 FOO, ID9 FOO, ID10 FOO)"); + // process statement + stmt->Process(); + // destroy object + delete stmt; + } + + serv->StartTransaction();//Exec("BEGIN TRANSACTION;"); + + // Fill with data: + TSQLStatement* stmt = serv->Statement("INSERT INTO TESTTABLE (ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", 100); + std::cout << "statement pars: " << stmt->GetNumParameters() << std::endl; + + + for (int n=0;n<10;n++) { + if (stmt->NextIteration()) { + stmt->SetInt(0, n); + stmt->SetUInt(1, n); + stmt->SetLong(2, n); + stmt->SetULong64(3, n); + stmt->SetDate(4, 2013,1,n); + stmt->SetTime(5, 1,1,n); + stmt->SetDatime(6, 2013,1,n,1,1,n); + stmt->SetTimestamp(7, 2013,1,1,1,1,n,102+n); + TString foo; + foo.Form("testbinary %d", n); + void *binary=const_cast(foo.Data()); + stmt->SetBinary(8, binary, foo.Length()); + stmt->SetString(9, Form("%d", n), 200); + } + } + + stmt->Process(); + delete stmt; + + serv->Commit(); + + delete serv; + + std::cout << "Testing tool created DB with sample data. Now reopening and selecting all." << std::endl; + + serv=TSQLServer::Connect("sqlite://testdb.sqlite", "", ""); + if (serv == NULL) { + std::cerr << "Connection failed!" << std::endl; + _exit(1); + } + + std::cout << "Select table names:" << std::endl; + TSQLResult *res=serv->GetTables(NULL, NULL); + + int fields=res->GetFieldCount(); + std::cout << "Table list has field count: " << fields << std::endl; + + int rowcount=res->GetRowCount(); + std::cout << "Table list has row count: " << rowcount << std::endl; + + TSQLRow *row=NULL; + while ((row=res->Next()) != NULL) { + for (int i=0; iGetField(i); + TSQLResult *res2=serv->GetColumns(NULL, row->GetField(i), NULL); + if (res2 == NULL) continue; + std::cout << "|"; + int fields2=res2->GetFieldCount(); + std::cout << "Cols: " << fields2 << " "; + TSQLRow *row2=NULL; + while ((row2=res2->Next()) != NULL) { + std::cout << "("; + for (int ii=0; iiGetField(ii) == NULL) continue; + std::cout << row2->GetField(ii) << "|"; + } + std::cout << ")"; + delete row2; + } + } + std::cout << std::endl; + delete row; + } + delete res; + std::cout << std::endl; + + std::cout << "Alternate way using GetTablesList:" << std::endl; + serv->GetTablesList()->Print(); + + std::cout << "Completed listing tables. Now selecting * from testtable, first using Query() and string output:" << std::endl; + row=NULL; + res=serv->Query("SELECT * from TESTTABLE;"); + fields=res->GetFieldCount(); + for (int i=0; iGetFieldName(i) << "|"; + } + std::cout << std::endl; + while ((row=res->Next()) != NULL) { + for (int i=0; iGetField(i) << "|"; + } + std::cout << std::endl; + delete row; + } + delete res; + std::cout << std::endl; + + std::cout << "Now using TSQLStatement-methods with appropriate types:" << std::endl; + + stmt = serv->Statement("SELECT * FROM TESTTABLE;", 100); + // process statement + if (stmt->Process()) { + std::cout << "iteration..." << std::endl; + // store result of statement in buffer + stmt->StoreResult(); + + // display info about selected field + std::cout << "NumFields = " << stmt->GetNumFields() << std::endl; + for (int n=0;nGetNumFields();n++) { + std::cout << "|" << std::setw(19) << stmt->GetFieldName(n) << "|"; + } + std::cout << std::endl; + + // extract rows one after another + while (stmt->NextResultRow()) { + Int_t id1 = stmt->GetInt(0); + std::cout << "|" << std::setw(19) << id1 << "|"; + + UInt_t id2 = stmt->GetUInt(1); + std::cout << "|" << std::setw(19) << id2 << "|"; + + Long_t id3 = stmt->GetLong(2); + std::cout << "|" << std::setw(19) << id3 << "|"; + + ULong64_t id4 = stmt->GetULong64(3); + std::cout << "|" << std::setw(19) << id4 << "|"; + + Int_t year=0, month=0, day=0, hour=0, minute=0, second=0, frac=0; + + stmt->GetDate(4, year, month, day); + TString id5; + id5.Form("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, 0, 0, 0); + std::cout << "|" << std::setw(19) << id5 << "|"; + + stmt->GetTime(5, hour, minute, second); + TString id6; + id6.Form("%04d-%02d-%02d %02d:%02d:%02d", 2000, 01, 01, hour, minute, second); + std::cout << "|" << std::setw(19) << id6 << "|"; + + stmt->GetDatime(6, year, month, day, hour, minute, second); + TString id7; + id7.Form("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second); + std::cout << "|" << std::setw(19) << id7 << "|"; + + stmt->GetTimestamp(7, year, month, day, hour, minute, second, frac); + TTimeStamp ts(year,month,day,hour,minute,second); + TString id8; + id8.Form("%lu.%d", ts.GetSec(), frac); + std::cout << "|" << std::setw(19) << id8 << "|"; + + void* id9 = new unsigned char[1]; + Long_t binSize=1; + stmt->GetBinary(8, id9, binSize); + char* id9str = new char[binSize+1]; + memcpy(id9str, id9, binSize); + id9str[binSize]='\0'; + std::cout << "|" << std::setw(19) << id9str << "|"; + delete [] (unsigned char*) id9; + delete [] id9str; + + TString id10 = stmt->GetString(9); + std::cout << "|" << std::setw(19) << id10 << "|"; + + std::cout << std::endl; + } + } + delete stmt; + + delete serv; + + return 0; +} diff --git a/tree/treeplayer/src/TTreePlayer.cxx b/tree/treeplayer/src/TTreePlayer.cxx index 7da170289083b..6fa8574ed6def 100644 --- a/tree/treeplayer/src/TTreePlayer.cxx +++ b/tree/treeplayer/src/TTreePlayer.cxx @@ -837,6 +837,18 @@ Int_t TTreePlayer::MakeClass(const char *classname, const char *option) chain->LoadTree(0); } + fprintf(fp,"\n"); + if (opt.Contains("selector")) { + fprintf(fp,"class %s : public TSelector {\n",classname); + fprintf(fp,"public :\n"); + fprintf(fp," TTree *fChain; //!pointer to the analyzed TTree or TChain\n"); + } else { + fprintf(fp,"class %s {\n",classname); + fprintf(fp,"public :\n"); + fprintf(fp," TTree *fChain; //!pointer to the analyzed TTree or TChain\n"); + fprintf(fp," Int_t fCurrent; //!current Tree number in a TChain\n"); + } + fprintf(fp,"\n// Fixed size dimensions of array or collections stored in the TTree if any.\n"); leaves = fTree->GetListOfLeaves(); for (l=0;l