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

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TClingCallFunc                                                       //
//                                                                      //
// Emulation of the CINT CallFunc class.                                //
//                                                                      //
// The CINT C++ interpreter provides an interface for calling           //
// functions through the generated wrappers in dictionaries with        //
// the CallFunc class. This class provides the same functionality,      //
// using an interface as close as possible to CallFunc but the          //
// function metadata and calling service comes from the Cling           //
// C++ interpreter and the Clang C++ compiler, not CINT.                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TClingCallFunc.h"

#include "TClingClassInfo.h"
#include "TClingMethodInfo.h"

#include "TError.h"
#include "TCling.h"

#include "cling/Interpreter/CompilationOptions.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/LookupHelper.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Transaction.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Lookup.h"

#include "llvm/ADT/APInt.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/LLVMContext.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Type.h"

#include "clang/Sema/SemaInternal.h"

#include <string>
#include <vector>

// This ought to be declared by the implementer .. oh well...
extern void unresolvedSymbol();

llvm::GenericValue TClingCallFunc::convertIntegralToArg(const cling::Value& val,
                                                        const llvm::Type* targetType) const {
   // Do "extended" integral conversion, at least as CINT's dictionaries
   // would have done it: everything is a long, then gets cast to whatever
   // type is expected. "Whatever type" is an llvm type here, thus we do
   // integral conversion, integral to ptr, integral to floating point.

   assert(val.isValid() && "cling::Value must not be invalid!");

   // If both are not builtins but pointers no conversion needed.
   if (val.getLLVMType()->isPointerTy() && targetType->isPointerTy())
      return val.getGV();

   clang::QualType ClangQT = val.getClangType();

   // We support primitive array to ptr conversions like:
   // const char[N] to const char* 
   if (ClangQT->isArrayType() 
       && ClangQT->getArrayElementTypeNoTypeQual()->isCharType()) {
      return val.getGV();
   }

   assert((ClangQT->isBuiltinType() || ClangQT->isPointerType() || ClangQT->isReferenceType())
          && "Conversions supported only on builtin types!");

   llvm::GenericValue result;
   switch(val.getLLVMType()->getTypeID()) {
   case llvm::Type::IntegerTyID : {
      const llvm::APInt& intVal = val.getGV().IntVal;
      switch(targetType->getTypeID()) {
      case llvm::Type::IntegerTyID :
         // We need to match the bitwidths, because this makes LLVM build 
         // different types. Eg. BitWidth = 64 -> i64, BitWidth = 32 -> i32. 
         // If we don't do a bitwidth conversion, later on when making the call 
         // the types mismatch and we are screwed.
         if (ClangQT->isSignedIntegerType())
            result.IntVal
               = intVal.sextOrTrunc(targetType->getPrimitiveSizeInBits());
         else
            result.IntVal 
               = intVal.zextOrTrunc(targetType->getPrimitiveSizeInBits());

         return result;
      case llvm::Type::HalfTyID : /*16 bit floating point*/ 
      case llvm::Type::FloatTyID : 
         if (ClangQT->isSignedIntegerType())
            result.FloatVal = (float)intVal.getSExtValue();
         else
            result.FloatVal = (float)intVal.getZExtValue();               

         return result;
         case llvm::Type::DoubleTyID :
            if (ClangQT->isSignedIntegerType())
               result.DoubleVal = (double)intVal.getSExtValue();
            else
               result.DoubleVal = (double)intVal.getZExtValue();               

            return result;
      case llvm::Type::PointerTyID :
         if (ClangQT->isSignedIntegerType())
            return llvm::PTOGV((void*)intVal.getSExtValue());
         return llvm::PTOGV((void*)intVal.getZExtValue());
      default: 
         return val.getGV();
      }
      break;
   }
   case llvm::Type::PointerTyID : {
      switch(targetType->getTypeID()) {
      case llvm::Type::IntegerTyID: {
         clang::ASTContext& C = fInterp->getSema().getASTContext();
         unsigned long res = (unsigned long)val.getGV().PointerVal;
         llvm::APInt LongAPInt(C.getTypeSize(C.UnsignedLongTy), res);
         result.IntVal = LongAPInt;
         return result;
      }
      default:
         return val.getGV();
      }
      break;
   }

   default : 
      return val.getGV();
   }

   llvm_unreachable("Must be able to convert.");
   // Make the compiler happy:
   return val.getGV();
}

std::string TClingCallFunc::ExprToString(const clang::Expr* expr) const
{
   // Get a string representation of an expression

   clang::PrintingPolicy policy(fInterp->getCI()->
                                getASTContext().getPrintingPolicy());
   policy.SuppressTagKeyword = true;
   policy.SuppressUnwrittenScope = false;
   policy.SuppressInitializers = false;
   policy.AnonymousTagLocations = false;

   std::string buf;
   llvm::raw_string_ostream out(buf);
   expr->printPretty(out, /*Helper=*/0, policy, /*Indentation=*/0);
   out << ';'; // no value printing<commit_msg>Add missing double to float conversion, reported by Wim.<commit_after>// @(#)root/core/meta:$Id$
// Author: <NAME>   30/07/2012
// Author: <NAME>   9/02/2013

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

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TClingCallFunc                                                       //
//                                                                      //
// Emulation of the CINT CallFunc class.                                //
//                                                                      //
// The CINT C++ interpreter provides an interface for calling           //
// functions through the generated wrappers in dictionaries with        //
// the CallFunc class. This class provides the same functionality,      //
// using an interface as close as possible to CallFunc but the          //
// function metadata and calling service comes from the Cling           //
// C++ interpreter and the Clang C++ compiler, not CINT.                //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TClingCallFunc.h"

#include "TClingClassInfo.h"
#include "TClingMethodInfo.h"

#include "TError.h"
#include "TCling.h"

#include "cling/Interpreter/CompilationOptions.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/LookupHelper.h"
#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Transaction.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/Type.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Lookup.h"

#include "llvm/ADT/APInt.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/LLVMContext.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Type.h"

#include "clang/Sema/SemaInternal.h"

#include <string>
#include <vector>

// This ought to be declared by the implementer .. oh well...
extern void unresolvedSymbol();

llvm::GenericValue TClingCallFunc::convertIntegralToArg(const cling::Value& val,
                                                        const llvm::Type* targetType) const {
   // Do "extended" integral conversion, at least as CINT's dictionaries
   // would have done it: everything is a long, then gets cast to whatever
   // type is expected. "Whatever type" is an llvm type here, thus we do
   // integral conversion, integral to ptr, integral to floating point.

   assert(val.isValid() && "cling::Value must not be invalid!");

   // If both are not builtins but pointers no conversion needed.
   if (val.getLLVMType()->isPointerTy() && targetType->isPointerTy())
      return val.getGV();

   clang::QualType ClangQT = val.getClangType();

   // We support primitive array to ptr conversions like:
   // const char[N] to const char* 
   if (ClangQT->isArrayType() 
       && ClangQT->getArrayElementTypeNoTypeQual()->isCharType()) {
      return val.getGV();
   }

   assert((ClangQT->isBuiltinType() || ClangQT->isPointerType() || ClangQT->isReferenceType())
          && "Conversions supported only on builtin types!");

   llvm::GenericValue result;
   switch(val.getLLVMType()->getTypeID()) {
   case llvm::Type::IntegerTyID : {
      const llvm::APInt& intVal = val.getGV().IntVal;
      switch(targetType->getTypeID()) {
      case llvm::Type::IntegerTyID :
         // We need to match the bitwidths, because this makes LLVM build 
         // different types. Eg. BitWidth = 64 -> i64, BitWidth = 32 -> i32. 
         // If we don't do a bitwidth conversion, later on when making the call 
         // the types mismatch and we are screwed.
         if (ClangQT->isSignedIntegerType())
            result.IntVal
               = intVal.sextOrTrunc(targetType->getPrimitiveSizeInBits());
         else
            result.IntVal 
               = intVal.zextOrTrunc(targetType->getPrimitiveSizeInBits());

         return result;
      case llvm::Type::HalfTyID : /*16 bit floating point*/ 
      case llvm::Type::FloatTyID : 
         if (ClangQT->isSignedIntegerType())
            result.FloatVal = (float)intVal.getSExtValue();
         else
            result.FloatVal = (float)intVal.getZExtValue();               

         return result;
      case llvm::Type::DoubleTyID :
         if (ClangQT->isSignedIntegerType())
            result.DoubleVal = (double)intVal.getSExtValue();
         else
            result.DoubleVal = (double)intVal.getZExtValue();               

         return result;
      case llvm::Type::PointerTyID :
         if (ClangQT->isSignedIntegerType())
            return llvm::PTOGV((void*)intVal.getSExtValue());
         return llvm::PTOGV((void*)intVal.getZExtValue());
      default: 
         return val.getGV();
      }
      break;
   }
   case llvm::Type::PointerTyID : {
      switch(targetType->getTypeID()) {
      case llvm::Type::IntegerTyID: {
         clang::ASTContext& C = fInterp->getSema().getASTContext();
         unsigned long res = (unsigned long)val.getGV().PointerVal;
         llvm::APInt LongAPInt(C.getTypeSize(C.UnsignedLongTy), res);
         result.IntVal = LongAPInt;
         return result;
      }
      default:
         return val.getGV();
      }
      break;
   }

   case llvm::Type::DoubleTyID: {
      switch (targetType->getTypeID()) {
      case llvm::Type::FloatTyID :
         result.FloatVal = (float)val.getGV().DoubleVal;
         return result;

      default:
         return val.getGV();
      }
   }

   default : 
      return val.getGV();
   }

   llvm_unreachable("Must be able to convert.");
   // Make the compiler happy:
   return val.getGV();
}

std::string TClingCallFunc::ExprToString(const clang::Expr* expr) const
{
   // Get a string representation of an expression

   clang::PrintingPolicy policy(fInterp->getCI()->
                                getASTContext().getPrintingPolicy());
   policy.SuppressTagKeyword = true;
   policy.SuppressUnwrittenScope = false;
   policy.SuppressInitializers = false;
   policy.AnonymousTagLocations = false;

   std::string buf;
   llvm::raw_string_ostream out(buf);
   expr->printPretty(out, /*Helper=*/0, policy, /*Indentation=*/0);
   out << ';'; // no value printing
{'fraction_non_alphanumeric': 0.15674901539563194, 'fraction_numerical': 0.005012531328320802, 'mean_word_length': 2.0235981814245507, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 62, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 42, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2247312', 'n_tokens_mistral': 3920, 'n_tokens_neox': 3748, 'n_words': 912}