<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  <NAME> <<EMAIL>>
// author:  <NAME> <<EMAIL>>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "NullDerefProtectionTransformer.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Lookup.h"
#include "clang/AST/Expr.h"

#include <bitset>
#include <map>

using namespace clang;

namespace cling {
  NullDerefProtectionTransformer::NullDerefProtectionTransformer(clang::Sema* S)
    : WrapperTransformer(S) {
  }

  NullDerefProtectionTransformer::~NullDerefProtectionTransformer()
  { }

  class PointerCheckInjector : public RecursiveASTVisitor<PointerCheckInjector> {
  private:
    Sema& m_Sema;
    typedef llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > decl_map_t;
    llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > m_NonNullArgIndexs;

    ///\brief Needed for the AST transformations, owned by Sema.
    ///
    ASTContext& m_Context;

    ///\brief cling_runtime_internal_throwIfInvalidPointer cache.
    ///
    LookupResult* m_clingthrowIfInvalidPointerCache;

  public:
    PointerCheckInjector(Sema& S) : m_Sema(S), m_Context(S.getASTContext()),
    m_clingthrowIfInvalidPointerCache(0) {}

    bool VisitStmt(Stmt* S) {
      for (auto child: S->children()) {
        if (child)
            VisitStmt(child);
      }
      return true;
    }

    bool VisitUnaryOperator(UnaryOperator* UnOp) {
      VisitStmt(UnOp->getSubExpr());
      if (UnOp->getOpcode() == UO_Deref)
        if (UnOp->getSubExpr()->getType().getTypePtr()->isPointerType())
          UnOp->setSubExpr(SynthesizeCheck(UnOp->getSubExpr()));
      return true;
    }

    bool VisitMemberExpr(MemberExpr* ME) {
      VisitStmt(ME->getBase());
      if (ME->isArrow())
        ME->setBase(SynthesizeCheck(ME->getBase()));
      return true;
    }

    bool VisitCallExpr(CallExpr* CE) {
      VisitStmt(CE->getCallee());
      FunctionDecl* FDecl = CE->getDirectCallee();
      if (FDecl && isDeclCandidate(FDecl)) {
        decl_map_t::const_iterator it = m_NonNullArgIndexs.find(FDecl);
        const std::bitset<32>& ArgIndexs = it->second;
        Sema::ContextRAII pushedDC(m_Sema, FDecl);
        for (int index = 0; index < 32; ++index) {
          if (ArgIndexs.test(index)) {
            // Get the argument with the nonnull attribute.
            Expr* Arg = CE->getArg(index);
              CE->setArg(index, SynthesizeCheck(Arg));
          }
        }
      }
      return true;
    }

    bool VisitFunctionDecl(FunctionDecl* FD) {<commit_msg>Fix bug - check only for function arguments of pointer types.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author:  <NAME> <<EMAIL>>
// author:  <NAME> <<EMAIL>>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "NullDerefProtectionTransformer.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Lookup.h"
#include "clang/AST/Expr.h"

#include <bitset>
#include <map>

using namespace clang;

namespace cling {
  NullDerefProtectionTransformer::NullDerefProtectionTransformer(clang::Sema* S)
    : WrapperTransformer(S) {
  }

  NullDerefProtectionTransformer::~NullDerefProtectionTransformer()
  { }

  class PointerCheckInjector : public RecursiveASTVisitor<PointerCheckInjector> {
  private:
    Sema& m_Sema;
    typedef llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > decl_map_t;
    llvm::DenseMap<clang::FunctionDecl*, std::bitset<32> > m_NonNullArgIndexs;

    ///\brief Needed for the AST transformations, owned by Sema.
    ///
    ASTContext& m_Context;

    ///\brief cling_runtime_internal_throwIfInvalidPointer cache.
    ///
    LookupResult* m_clingthrowIfInvalidPointerCache;

  public:
    PointerCheckInjector(Sema& S) : m_Sema(S), m_Context(S.getASTContext()),
    m_clingthrowIfInvalidPointerCache(0) {}

    bool VisitStmt(Stmt* S) {
      for (auto child: S->children()) {
        if (child)
            VisitStmt(child);
      }
      return true;
    }

    bool VisitUnaryOperator(UnaryOperator* UnOp) {
      VisitStmt(UnOp->getSubExpr());
      if (UnOp->getOpcode() == UO_Deref)
        if (UnOp->getSubExpr()->getType().getTypePtr()->isPointerType())
          UnOp->setSubExpr(SynthesizeCheck(UnOp->getSubExpr()));
      return true;
    }

    bool VisitMemberExpr(MemberExpr* ME) {
      VisitStmt(ME->getBase());
      if (ME->isArrow())
        ME->setBase(SynthesizeCheck(ME->getBase()));
      return true;
    }

    bool VisitCallExpr(CallExpr* CE) {
      VisitStmt(CE->getCallee());
      FunctionDecl* FDecl = CE->getDirectCallee();
      if (FDecl && isDeclCandidate(FDecl)) {
        decl_map_t::const_iterator it = m_NonNullArgIndexs.find(FDecl);
        const std::bitset<32>& ArgIndexs = it->second;
        Sema::ContextRAII pushedDC(m_Sema, FDecl);
        for (int index = 0; index < 32; ++index) {
          if (ArgIndexs.test(index)) {
            // Get the argument with the nonnull attribute.
            Expr* Arg = CE->getArg(index);
            if (Arg->getType().getTypePtr()->isPointerType())
              CE->setArg(index, SynthesizeCheck(Arg));
          }
        }
      }
      return true;
    }

    bool VisitFunctionDecl(FunctionDecl* FD) {
{'fraction_non_alphanumeric': 0.17833662064431297, 'fraction_numerical': 0.003287310979618672, 'mean_word_length': 2.643712574850299, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4627760', 'n_tokens_mistral': 1942, 'n_tokens_neox': 1905, 'n_words': 381}