<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// 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 "cling/Interpreter/LookupHelper.h"

#include "TransactionUnloader.h"
#include "cling/Interpreter/Interpreter.h"

#include "clang/AST/ASTContext.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"

using namespace clang;

namespace cling {

  ///\brief Cleanup Parser state after a failed lookup.
  ///
  /// After a failed lookup we need to discard the remaining unparsed input,
  /// restore the original state of the incremental parsing flag, clear any
  /// pending diagnostics, restore the suppress diagnostics flag, and restore
  /// the spell checking language options.
  ///
  class ParserStateRAII {
  private:
    Parser* P;
    Preprocessor& PP;
    bool ResetIncrementalProcessing;
    bool OldSuppressAllDiagnostics;
    bool OldSpellChecking;
    DestroyTemplateIdAnnotationsRAIIObj CleanupTemplateIds;

  public:
    ParserStateRAII(Parser& p)
      : P(&p), PP(p.getPreprocessor()),
        ResetIncrementalProcessing(p.getPreprocessor()
                                   .isIncrementalProcessingEnabled()),
        OldSuppressAllDiagnostics(p.getPreprocessor().getDiagnostics()
                                  .getSuppressAllDiagnostics()),
        OldSpellChecking(p.getPreprocessor().getLangOpts().SpellChecking),
        CleanupTemplateIds(p)
    {
    }

    ~ParserStateRAII()
    {
      //
      // Advance the parser to the end of the file, and pop the include stack.
      //
      // Note: Consuming the EOF token will pop the include stack.
      //
      P->SkipUntil(tok::eof);
      PP.enableIncrementalProcessing(ResetIncrementalProcessing);
      // Doesn't reset the diagnostic mappings
      P->getActions().getDiagnostics().Reset(/*soft=*/true);
      PP.getDiagnostics().setSuppressAllDiagnostics(OldSuppressAllDiagnostics);
      const_cast<LangOptions&>(PP.getLangOpts()).SpellChecking =
         OldSpellChecking;
    }
  };

  ///\brief Class to help with the custom allocation of clang::Expr
  ///
  struct ExprAlloc {
     char fBuffer[sizeof(clang::OpaqueValueExpr)];
  };

  // pin *tor here so that we can have clang::Parser defined and be able to call
  // the dtor on the OwningPtr
  LookupHelper::LookupHelper(clang::Parser* P, Interpreter* interp)
    : m_Parser(P), m_Interpreter(interp) {}

  LookupHelper::~LookupHelper() {}

  static void prepareForParsing(Parser& P,
                                const Interpreter* Interp,
                                llvm::StringRef code,
                                llvm::StringRef bufferName,
                                LookupHelper::DiagSetting diagOnOff) {
    //Parser& P = *m_Parser;
    Sema& S = P.getActions();
    Preprocessor& PP = P.getPreprocessor();
    //
    //  Tell the diagnostic engine to ignore all diagnostics.
    //
    PP.getDiagnostics().setSuppressAllDiagnostics(
                                                  diagOnOff == LookupHelper::NoDiagnostics);
    //
    //  Tell the parser to not attempt spelling correction.
    //
    const_cast<LangOptions&>(PP.getLangOpts()).SpellChecking = 0;
    //
    //  Turn on ignoring of the main file eof token.
    //
    //  Note: We need this because token readahead in the following
    //        routine calls ends up parsing it multiple times.
    //
    if (!PP.isIncrementalProcessingEnabled()) {
      PP.enableIncrementalProcessing();
    }
    if (!code.empty()) {
      //
      //  Create a fake file to parse the type name.
      //
      llvm::MemoryBuffer* SB
      = llvm::MemoryBuffer::getMemBufferCopy(code.str() + "\n",
                                             bufferName.str());
      SourceLocation NewLoc = Interp->getNextAvailableLoc();
      FileID FID = S.getSourceManager().createFileID(SB, SrcMgr::C_User,
                                                     /*LoadedID*/0,
                                                     /*LoadedOffset*/0, NewLoc);
      //
      //  Switch to the new file the way #include does.
      //
      //  Note: To switch back to the main file we must consume an eof token.
      //
      PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc);
      PP.Lex(const_cast<Token&>(P.getCurToken()));
    }
  }

  QualType LookupHelper::findType(llvm::StringRef typeName,
                                  DiagSetting diagOnOff) const {
    //
    //  Our return value.
    //
    QualType TheQT;

    if (typeName.empty()) return TheQT;

    // Could trigger deserialization of decls.
    Interpreter::PushTransactionRAII RAII(m_Interpreter);

    // Use P for shortness
    Parser& P = *m_Parser;<commit_msg>PrepareForParsing should no longer be called with empty code<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// 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 "cling/Interpreter/LookupHelper.h"

#include "TransactionUnloader.h"
#include "cling/Interpreter/Interpreter.h"

#include "clang/AST/ASTContext.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"

using namespace clang;

namespace cling {

  ///\brief Cleanup Parser state after a failed lookup.
  ///
  /// After a failed lookup we need to discard the remaining unparsed input,
  /// restore the original state of the incremental parsing flag, clear any
  /// pending diagnostics, restore the suppress diagnostics flag, and restore
  /// the spell checking language options.
  ///
  class ParserStateRAII {
  private:
    Parser* P;
    Preprocessor& PP;
    bool ResetIncrementalProcessing;
    bool OldSuppressAllDiagnostics;
    bool OldSpellChecking;
    DestroyTemplateIdAnnotationsRAIIObj CleanupTemplateIds;

  public:
    ParserStateRAII(Parser& p)
      : P(&p), PP(p.getPreprocessor()),
        ResetIncrementalProcessing(p.getPreprocessor()
                                   .isIncrementalProcessingEnabled()),
        OldSuppressAllDiagnostics(p.getPreprocessor().getDiagnostics()
                                  .getSuppressAllDiagnostics()),
        OldSpellChecking(p.getPreprocessor().getLangOpts().SpellChecking),
        CleanupTemplateIds(p)
    {
    }

    ~ParserStateRAII()
    {
      //
      // Advance the parser to the end of the file, and pop the include stack.
      //
      // Note: Consuming the EOF token will pop the include stack.
      //
      P->SkipUntil(tok::eof);
      PP.enableIncrementalProcessing(ResetIncrementalProcessing);
      // Doesn't reset the diagnostic mappings
      P->getActions().getDiagnostics().Reset(/*soft=*/true);
      PP.getDiagnostics().setSuppressAllDiagnostics(OldSuppressAllDiagnostics);
      const_cast<LangOptions&>(PP.getLangOpts()).SpellChecking =
         OldSpellChecking;
    }
  };

  ///\brief Class to help with the custom allocation of clang::Expr
  ///
  struct ExprAlloc {
     char fBuffer[sizeof(clang::OpaqueValueExpr)];
  };

  // pin *tor here so that we can have clang::Parser defined and be able to call
  // the dtor on the OwningPtr
  LookupHelper::LookupHelper(clang::Parser* P, Interpreter* interp)
    : m_Parser(P), m_Interpreter(interp) {}

  LookupHelper::~LookupHelper() {}

  static void prepareForParsing(Parser& P,
                                const Interpreter* Interp,
                                llvm::StringRef code,
                                llvm::StringRef bufferName,
                                LookupHelper::DiagSetting diagOnOff) {
    //Parser& P = *m_Parser;
    Sema& S = P.getActions();
    Preprocessor& PP = P.getPreprocessor();
    //
    //  Tell the diagnostic engine to ignore all diagnostics.
    //
    PP.getDiagnostics().setSuppressAllDiagnostics(
                                                  diagOnOff == LookupHelper::NoDiagnostics);
    //
    //  Tell the parser to not attempt spelling correction.
    //
    const_cast<LangOptions&>(PP.getLangOpts()).SpellChecking = 0;
    //
    //  Turn on ignoring of the main file eof token.
    //
    //  Note: We need this because token readahead in the following
    //        routine calls ends up parsing it multiple times.
    //
    if (!PP.isIncrementalProcessingEnabled()) {
      PP.enableIncrementalProcessing();
    }
    assert(!code.empty()&&"prepareForParsing should only be called when needd");

    //
    //  Create a fake file to parse the type name.
    //
    llvm::MemoryBuffer* SB
      = llvm::MemoryBuffer::getMemBufferCopy(code.str() + "\n",
                                             bufferName.str());
    SourceLocation NewLoc = Interp->getNextAvailableLoc();
    FileID FID = S.getSourceManager().createFileID(SB, SrcMgr::C_User,
                                                   /*LoadedID*/0,
                                                   /*LoadedOffset*/0, NewLoc);
    //
    //  Switch to the new file the way #include does.
    //
    //  Note: To switch back to the main file we must consume an eof token.
    //
    PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc);
    PP.Lex(const_cast<Token&>(P.getCurToken()));
  }

  QualType LookupHelper::findType(llvm::StringRef typeName,
                                  DiagSetting diagOnOff) const {
    //
    //  Our return value.
    //
    QualType TheQT;

    if (typeName.empty()) return TheQT;

    // Could trigger deserialization of decls.
    Interpreter::PushTransactionRAII RAII(m_Interpreter);

    // Use P for shortness
    Parser& P = *m_Parser;
{'fraction_non_alphanumeric': 0.1345464831227607, 'fraction_numerical': 0.0007542900245144258, 'mean_word_length': 2.1224609949955844, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6339508', 'n_tokens_mistral': 2956, 'n_tokens_neox': 2921, 'n_words': 756}