<commit_before>// @(#)root/core/meta:$Id$
// Author: <NAME>   30/07/2012

/*************************************************************************
 * Copyright (C) 1995-2000, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TClingMethodInfo                                                     //
//                                                                      //
// Emulation of the CINT MethodInfo class.                              //
//                                                                      //
// The CINT C++ interpreter provides an interface to metadata about     //
// a function through the MethodInfo class.  This class provides the    //
// same functionality, using an interface as close as possible to       //
// MethodInfo but the typedef metadata comes from the Clang C++         //
// compiler, not CINT.                                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TClingMethodInfo.h"

#include "TClingCallFunc.h"
#include "TClingClassInfo.h"
#include "TClingMethodArgInfo.h"
#include "TDictionary.h"
#include "TClingTypeInfo.h"
#include "TError.h"
#include "TMetaUtils.h"

#include "cling/Interpreter/Interpreter.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Sema/Sema.h"

#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"

#include <string>

using namespace clang;

class TClingMethodInfo::SpecIterator
{
public:
   typedef clang::FunctionTemplateDecl::spec_iterator Iterator;
   
   SpecIterator(Iterator begin, Iterator end) : fIter(begin), fEnd(end) {}
   explicit SpecIterator(clang::FunctionTemplateDecl *decl) : fIter(decl->spec_begin()), fEnd(decl->spec_end()) {}

   FunctionDecl *operator* () const { return *fIter; }
   FunctionDecl *operator-> () const { return *fIter; }
   SpecIterator & operator++ () { ++fIter; return *this; }
   SpecIterator 	operator++ (int) {
      SpecIterator tmp(fIter,fEnd);
      ++(*this);
      return tmp;
   }
   bool operator!() { return fIter == fEnd; }
   operator bool() { return fIter != fEnd; }

private:

   Iterator fIter;
   Iterator fEnd;
};

TClingMethodInfo::TClingMethodInfo(const TClingMethodInfo &rhs) : 
   fInterp(rhs.fInterp),
   fContexts(rhs.fContexts),
   fFirstTime(rhs.fFirstTime), 
   fContextIdx(rhs.fContextIdx), 
   fIter(rhs.fIter),
   fTitle(rhs.fTitle), 
   fTemplateSpecIter(rhs.fTemplateSpecIter ? new SpecIterator(*rhs.fTemplateSpecIter) : 0), 
   fSingleDecl(rhs.fSingleDecl)
{
}
   

TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
                                   TClingClassInfo *ci)
   : fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(""), 
     fTemplateSpecIter(0), fSingleDecl(0)
{
   if (!ci || !ci->IsValid()) {
      return;
   }
   clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(const_cast<clang::Decl*>(ci->GetDecl()));
   if (cxxdecl) {
      // Make sure we have an entry for all the implicit function.
      fInterp->getSema().ForceDeclarationOfImplicitMembers(cxxdecl);
   }
   clang::DeclContext *dc =
      llvm::cast<clang::DeclContext>(const_cast<clang::Decl*>(ci->GetDecl()));
   dc->collectAllContexts(fContexts);
   fIter = dc->decls_begin();
   InternalNext();
   fFirstTime = true;
}

TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
                                   const clang::FunctionDecl *FD) 
   : fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(""), 
     fTemplateSpecIter(0), fSingleDecl(FD)
{

}

TClingMethodInfo::~TClingMethodInfo()
{
   delete fTemplateSpecIter;
}

const clang::FunctionDecl *TClingMethodInfo::GetMethodDecl() const
{
   if (!IsValid()) {
      return 0;
   }

   if (fSingleDecl)
      return fSingleDecl;
   
   if (fTemplateSpecIter)
      return *(*fTemplateSpecIter);

   return llvm::dyn_cast<clang::FunctionDecl>(*fIter);
}

void TClingMethodInfo::CreateSignature(TString &signature) const
{
   signature = "(";
   if (!IsValid()) {
      signature += ")";
      return;
   }
   TClingMethodArgInfo arg(fInterp, this);
   int idx = 0;
   while (arg.Next()) {
      if (idx) {
         signature += ", ";
      }
      signature += arg.Type()->Name();
      if (arg.Name() && strlen(arg.Name())) {
         signature += " ";
         signature += arg.Name();
      }
      if (arg.DefaultValue()) {
         signature += " = ";
         signature += arg.DefaultValue();
      }
      ++idx;
   }
   signature += ")";
}

void TClingMethodInfo::Init(const clang::FunctionDecl *decl)
{
   fContexts.clear();
   fFirstTime = true;
   fContextIdx = 0U;
   fIter = clang::DeclContext::decl_iterator();
   delete fTemplateSpecIter;
   fTemplateSpecIter = 0;
   fSingleDecl = decl;
}

void *TClingMethodInfo::InterfaceMethod() const
{
   if (!IsValid()) {
      return 0;
   }
   TClingCallFunc cf(fInterp);
   cf.SetFunc(this);
   return cf.InterfaceMethod();
}

bool TClingMethodInfo::IsValid() const
{
   if (fSingleDecl) return fSingleDecl;
   else if (fTemplateSpecIter) return *(*fTemplateSpecIter);
   return *fIter;
}

int TClingMethodInfo::NArg() const
{
   if (!IsValid()) {
      return -1;
   }
   const clang::FunctionDecl *fd = GetMethodDecl();
   unsigned num_params = fd->getNumParams();
   // Truncate cast to fit cint interface.
   return static_cast<int>(num_params);
}

int TClingMethodInfo::NDefaultArg() const
{
   if (!IsValid()) {
      return -1;
   }
   const clang::FunctionDecl *fd = GetMethodDecl();
   unsigned num_params = fd->getNumParams();
   unsigned min_args = fd->getMinRequiredArguments();
   unsigned defaulted_params = num_params - min_args;
   // Truncate cast to fit cint interface.
   return static_cast<int>(defaulted_params);
}

int TClingMethodInfo::InternalNext()
{

   assert(!fSingleDecl && "This is not an iterator!");

   if (!*fIter) {
      // Iterator is already invalid.
      return 0;
   }
   while (true) {
      // Advance to the next decl.
      if (fFirstTime) {
         // The cint semantics are weird.
         fFirstTime = false;
      }
      else {
         if (fTemplateSpecIter) {
            ++(*fTemplateSpecIter);
            if ( !(*fTemplateSpecIter) ) {
               // We reached the end of the template specialization.
               delete fTemplateSpecIter;
               fTemplateSpecIter = 0;
               ++fIter;
            } else {
               return 1;
            }
         } else {
            ++fIter;
         }
      }
      // Fix it if we have gone past the end of the current decl context.
      while (!*fIter) {
         ++fContextIdx;
         if (fContextIdx >= fContexts.size()) {
            // Iterator is now invalid.
            return 0;
         }
         clang::DeclContext *dc = fContexts[fContextIdx];
         fIter = dc->decls_begin();
         if (*fIter) {
            // Good, a non-empty context.
            break;
         }
      }

      clang::FunctionTemplateDecl *templateDecl = 
         llvm::dyn_cast<clang::FunctionTemplateDecl>(*fIter);
      if ( templateDecl ) {
         SpecIterator subiter(templateDecl);
         if (subiter) {
            fTemplateSpecIter = new SpecIterator(templateDecl);
            return 1;
         }
      }
      
      // Return if this decl is a function or method.
      if (llvm::isa<clang::FunctionDecl>(*fIter)) {
         // Iterator is now valid.
         return 1;
      }
   }
}

int TClingMethodInfo::Next()
{
   return InternalNext();
}

long TClingMethodInfo::Property() const
{
   if (!IsValid()) {
      return 0L;
   }
   long property = 0L;
   property |= kIsCompiled;
   const clang::FunctionDecl *fd = GetMethodDecl();
   switch (fd->getAccess()) {
      case clang::AS_public:
         property |= kIsPublic;
         break;
      case clang::AS_protected:<commit_msg>Add in comment code for not exposing to protected and private methods when listing methods ....<commit_after>// @(#)root/core/meta:$Id$
// Author: <NAME>   30/07/2012

/*************************************************************************
 * Copyright (C) 1995-2000, <NAME> and <NAME>.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TClingMethodInfo                                                     //
//                                                                      //
// Emulation of the CINT MethodInfo class.                              //
//                                                                      //
// The CINT C++ interpreter provides an interface to metadata about     //
// a function through the MethodInfo class.  This class provides the    //
// same functionality, using an interface as close as possible to       //
// MethodInfo but the typedef metadata comes from the Clang C++         //
// compiler, not CINT.                                                  //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TClingMethodInfo.h"

#include "TClingCallFunc.h"
#include "TClingClassInfo.h"
#include "TClingMethodArgInfo.h"
#include "TDictionary.h"
#include "TClingTypeInfo.h"
#include "TError.h"
#include "TMetaUtils.h"

#include "cling/Interpreter/Interpreter.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Sema/Sema.h"

#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/OwningPtr.h"

#include <string>

using namespace clang;

class TClingMethodInfo::SpecIterator
{
public:
   typedef clang::FunctionTemplateDecl::spec_iterator Iterator;
   
   SpecIterator(Iterator begin, Iterator end) : fIter(begin), fEnd(end) {}
   explicit SpecIterator(clang::FunctionTemplateDecl *decl) : fIter(decl->spec_begin()), fEnd(decl->spec_end()) {}

   FunctionDecl *operator* () const { return *fIter; }
   FunctionDecl *operator-> () const { return *fIter; }
   SpecIterator & operator++ () { ++fIter; return *this; }
   SpecIterator 	operator++ (int) {
      SpecIterator tmp(fIter,fEnd);
      ++(*this);
      return tmp;
   }
   bool operator!() { return fIter == fEnd; }
   operator bool() { return fIter != fEnd; }

private:

   Iterator fIter;
   Iterator fEnd;
};

TClingMethodInfo::TClingMethodInfo(const TClingMethodInfo &rhs) : 
   fInterp(rhs.fInterp),
   fContexts(rhs.fContexts),
   fFirstTime(rhs.fFirstTime), 
   fContextIdx(rhs.fContextIdx), 
   fIter(rhs.fIter),
   fTitle(rhs.fTitle), 
   fTemplateSpecIter(rhs.fTemplateSpecIter ? new SpecIterator(*rhs.fTemplateSpecIter) : 0), 
   fSingleDecl(rhs.fSingleDecl)
{
}
   

TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
                                   TClingClassInfo *ci)
   : fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(""), 
     fTemplateSpecIter(0), fSingleDecl(0)
{
   if (!ci || !ci->IsValid()) {
      return;
   }
   clang::CXXRecordDecl *cxxdecl = llvm::dyn_cast<clang::CXXRecordDecl>(const_cast<clang::Decl*>(ci->GetDecl()));
   if (cxxdecl) {
      // Make sure we have an entry for all the implicit function.
      fInterp->getSema().ForceDeclarationOfImplicitMembers(cxxdecl);
   }
   clang::DeclContext *dc =
      llvm::cast<clang::DeclContext>(const_cast<clang::Decl*>(ci->GetDecl()));
   dc->collectAllContexts(fContexts);
   fIter = dc->decls_begin();
   InternalNext();
   fFirstTime = true;
}

TClingMethodInfo::TClingMethodInfo(cling::Interpreter *interp,
                                   const clang::FunctionDecl *FD) 
   : fInterp(interp), fFirstTime(true), fContextIdx(0U), fTitle(""), 
     fTemplateSpecIter(0), fSingleDecl(FD)
{

}

TClingMethodInfo::~TClingMethodInfo()
{
   delete fTemplateSpecIter;
}

const clang::FunctionDecl *TClingMethodInfo::GetMethodDecl() const
{
   if (!IsValid()) {
      return 0;
   }

   if (fSingleDecl)
      return fSingleDecl;
   
   if (fTemplateSpecIter)
      return *(*fTemplateSpecIter);

   return llvm::dyn_cast<clang::FunctionDecl>(*fIter);
}

void TClingMethodInfo::CreateSignature(TString &signature) const
{
   signature = "(";
   if (!IsValid()) {
      signature += ")";
      return;
   }
   TClingMethodArgInfo arg(fInterp, this);
   int idx = 0;
   while (arg.Next()) {
      if (idx) {
         signature += ", ";
      }
      signature += arg.Type()->Name();
      if (arg.Name() && strlen(arg.Name())) {
         signature += " ";
         signature += arg.Name();
      }
      if (arg.DefaultValue()) {
         signature += " = ";
         signature += arg.DefaultValue();
      }
      ++idx;
   }
   signature += ")";
}

void TClingMethodInfo::Init(const clang::FunctionDecl *decl)
{
   fContexts.clear();
   fFirstTime = true;
   fContextIdx = 0U;
   fIter = clang::DeclContext::decl_iterator();
   delete fTemplateSpecIter;
   fTemplateSpecIter = 0;
   fSingleDecl = decl;
}

void *TClingMethodInfo::InterfaceMethod() const
{
   if (!IsValid()) {
      return 0;
   }
   TClingCallFunc cf(fInterp);
   cf.SetFunc(this);
   return cf.InterfaceMethod();
}

bool TClingMethodInfo::IsValid() const
{
   if (fSingleDecl) return fSingleDecl;
   else if (fTemplateSpecIter) return *(*fTemplateSpecIter);
   return *fIter;
}

int TClingMethodInfo::NArg() const
{
   if (!IsValid()) {
      return -1;
   }
   const clang::FunctionDecl *fd = GetMethodDecl();
   unsigned num_params = fd->getNumParams();
   // Truncate cast to fit cint interface.
   return static_cast<int>(num_params);
}

int TClingMethodInfo::NDefaultArg() const
{
   if (!IsValid()) {
      return -1;
   }
   const clang::FunctionDecl *fd = GetMethodDecl();
   unsigned num_params = fd->getNumParams();
   unsigned min_args = fd->getMinRequiredArguments();
   unsigned defaulted_params = num_params - min_args;
   // Truncate cast to fit cint interface.
   return static_cast<int>(defaulted_params);
}

int TClingMethodInfo::InternalNext()
{

   assert(!fSingleDecl && "This is not an iterator!");

   if (!*fIter) {
      // Iterator is already invalid.
      return 0;
   }
   while (true) {
      // Advance to the next decl.
      if (fFirstTime) {
         // The cint semantics are weird.
         fFirstTime = false;
      }
      else {
         if (fTemplateSpecIter) {
            ++(*fTemplateSpecIter);
            if ( !(*fTemplateSpecIter) ) {
               // We reached the end of the template specialization.
               delete fTemplateSpecIter;
               fTemplateSpecIter = 0;
               ++fIter;
            } else {
               return 1;
            }
         } else {
            ++fIter;
         }
      }
      // Fix it if we have gone past the end of the current decl context.
      while (!*fIter) {
         ++fContextIdx;
         if (fContextIdx >= fContexts.size()) {
            // Iterator is now invalid.
            return 0;
         }
         clang::DeclContext *dc = fContexts[fContextIdx];
         fIter = dc->decls_begin();
         if (*fIter) {
            // Good, a non-empty context.
            break;
         }
      }

      clang::FunctionTemplateDecl *templateDecl = 
         llvm::dyn_cast<clang::FunctionTemplateDecl>(*fIter);
      if ( templateDecl ) {
         SpecIterator subiter(templateDecl);
         if (subiter) {
            fTemplateSpecIter = new SpecIterator(templateDecl);
            return 1;
         }
      }
      
      // Return if this decl is a function or method.
      if (llvm::isa<clang::FunctionDecl>(*fIter)) {
         // Iterator is now valid.
         return 1;
      }
//      if (clang::FunctionDecl *fdecl = llvm::dyn_cast<clang::FunctionDecl>(*fIter)) {
//         if (fdecl->getAccess() == clang::AS_public || fdecl->getAccess() == clang::AS_none) {
//            // Iterator is now valid.
//            return 1;
//         }
//      }
   }
}

int TClingMethodInfo::Next()
{
   return InternalNext();
}

long TClingMethodInfo::Property() const
{
   if (!IsValid()) {
      return 0L;
   }
   long property = 0L;
   property |= kIsCompiled;
   const clang::FunctionDecl *fd = GetMethodDecl();
   switch (fd->getAccess()) {
      case clang::AS_public:
         property |= kIsPublic;
         break;
      case clang::AS_protected:
{'fraction_non_alphanumeric': 0.15694585735277494, 'fraction_numerical': 0.00423872499152255, 'mean_word_length': 2.1103884689752155, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4719503', 'n_tokens_mistral': 5308, 'n_tokens_neox': 5145, 'n_words': 1125}