IncrementalParser::EParseResult 
  IncrementalParser::Compile(llvm::StringRef input) {
    // Just in case when Parse is called, we want to complete the transaction
    // coming from parse and then start new one.
    m_Consumer->HandleTranslationUnit(getCI()->getASTContext());

    // Reset the module builder to clean up global initializers, c'tors, d'tors:
    if (GetCodeGenerator()) {
      GetCodeGenerator()->Initialize(getCI()->getASTContext());
    }

    EParseResult Result = Parse(input);

    // Check for errors coming from our custom consumers.
    DiagnosticConsumer& DClient = m_CI->getDiagnosticClient();
    DClient.BeginSourceFile(getCI()->getLangOpts(), &getCI()->getPreprocessor());
    m_Consumer->HandleTranslationUnit(getCI()->getASTContext());

    DClient.EndSourceFile();
    m_CI->getDiagnostics().Reset();

    if (!m_SyntaxOnly) {
      m_Interpreter->runStaticInitializersOnce();
    }

    return Result;
  }
Esempio n. 2
0
 void Interpreter::storeInterpreterState(const std::string& name) const {
   // This may induce deserialization
   PushTransactionRAII RAII(this);
   CodeGenerator* CG = m_IncrParser->getCodeGenerator();
   ClangInternalState* state
     = new ClangInternalState(getCI()->getASTContext(),
                              getCI()->getPreprocessor(),
                              CG ? CG->GetModule() : 0,
                              CG, name);
   m_StoredStates.push_back(state);
 }
Esempio n. 3
0
  void Interpreter::AddIncludePath(llvm::StringRef incpath)
  {
    // Add the given path to the list of directories in which the interpreter
    // looks for include files. Only one path item can be specified at a
    // time, i.e. "path1:path2" is not supported.

    CompilerInstance* CI = getCI();
    HeaderSearchOptions& headerOpts = CI->getHeaderSearchOpts();
    const bool IsFramework = false;
    const bool IsSysRootRelative = true;

    // Avoid duplicates; just return early if incpath is already in UserEntries.
    for (std::vector<HeaderSearchOptions::Entry>::const_iterator
           I = headerOpts.UserEntries.begin(),
           E = headerOpts.UserEntries.end(); I != E; ++I)
      if (I->Path == incpath)
        return;

    headerOpts.AddPath(incpath, frontend::Angled, IsFramework,
                       IsSysRootRelative);

    Preprocessor& PP = CI->getPreprocessor();
    clang::ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), headerOpts,
                                    PP.getLangOpts(),
                                    PP.getTargetInfo().getTriple());
  }
Esempio n. 4
0
 Interpreter::~Interpreter() {
   if (m_Executor)
     m_Executor->shuttingDown();
   for (size_t i = 0, e = m_StoredStates.size(); i != e; ++i)
     delete m_StoredStates[i];
   getCI()->getDiagnostics().getClient()->EndSourceFile();
 }
Esempio n. 5
0
  void IncrementalParser::codeGenTransaction(Transaction* T) {
    // codegen the transaction
    assert(T->getCompilationOpts().CodeGeneration && "CodeGen turned off");
    assert(T->getState() == Transaction::kCompleted && "Must be completed");
    assert(hasCodeGenerator() && "No CodeGen");

    // Could trigger derserialization of decls.
    Transaction* deserT = beginTransaction(CompilationOptions());


    // Commit this transaction first - T might need symbols from it, so
    // trigger emission of weak symbols by providing use.
    ParseResultTransaction PRT = endTransaction(deserT);
    commitTransaction(PRT);
    deserT = PRT.getPointer();

    // This llvm::Module is done; finalize it and pass it to the execution
    // engine.
    if (!T->isNestedTransaction() && hasCodeGenerator()) {
      // The initializers are emitted to the symbol "_GLOBAL__sub_I_" + filename.
      // Make that unique!
      deserT = beginTransaction(CompilationOptions());
      // Reset the module builder to clean up global initializers, c'tors, d'tors
      getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
      auto PRT = endTransaction(deserT);
      commitTransaction(PRT);
      deserT = PRT.getPointer();

      std::unique_ptr<llvm::Module> M(getCodeGenerator()->ReleaseModule());

      if (M) {
        m_Interpreter->addModule(M.get(), T->getCompilationOpts().OptLevel);
        T->setModule(std::move(M));
      }

      if (T->getIssuedDiags() != Transaction::kNone) {
        // Module has been released from Codegen, reset the Diags now.
        DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics();
        Diags.Reset(/*soft=*/true);
        Diags.getClient()->clear();
      }

      // Create a new module.
      StartModule();
    }
  }
Esempio n. 6
0
  llvm::StringRef Interpreter::createUniqueWrapper() {
    const size_t size
      = sizeof(utils::Synthesize::UniquePrefix) + sizeof(m_UniqueCounter);
    llvm::SmallString<size> out(utils::Synthesize::UniquePrefix);
    llvm::raw_svector_ostream(out) << m_UniqueCounter++;

    return (getCI()->getASTContext().Idents.getOwn(out)).getName();
  }
Esempio n. 7
0
  void IncrementalParser::rollbackTransaction(Transaction* T) const {
    ASTNodeEraser NodeEraser(&getCI()->getSema());

    if (NodeEraser.RevertTransaction(T))
      T->setState(Transaction::kRolledBack);
    else
      T->setState(Transaction::kRolledBackWithErrors);
  }
  // Each input line is contained in separate memory buffer. The SourceManager
  // assigns sort-of invalid FileID for each buffer, i.e there is no FileEntry
  // for the MemoryBuffer's FileID. That in turn is problem because invalid
  // SourceLocations are given to the diagnostics. Thus the diagnostics cannot
  // order the overloads, for example
  //
  // Our work-around is creating a virtual file, which doesn't exist on the disk
  // with enormous size (no allocation is done). That file has valid FileEntry 
  // and so on... We use it for generating valid SourceLocations with valid
  // offsets so that it doesn't cause any troubles to the diagnostics.
  //
  // +---------------------+
  // | Main memory buffer  |
  // +---------------------+
  // |  Virtual file SLoc  |
  // |    address space    |<-----------------+
  // |         ...         |<------------+    |
  // |         ...         |             |    |
  // |         ...         |<----+       |    |
  // |         ...         |     |       |    |
  // +~~~~~~~~~~~~~~~~~~~~~+     |       |    |
  // |     input_line_1    | ....+.......+..--+
  // +---------------------+     |       |   
  // |     input_line_2    | ....+.....--+
  // +---------------------+     |
  // |          ...        |     |
  // +---------------------+     |
  // |     input_line_N    | ..--+  
  // +---------------------+
  //
  void IncrementalParser::CreateSLocOffsetGenerator() {
    SourceManager& SM = getCI()->getSourceManager();
    FileManager& FM = SM.getFileManager();
    const FileEntry* FE 
      = FM.getVirtualFile("Interactrive/InputLineIncluder", 1U << 15U, time(0));
    m_VirtualFileID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);

    assert(!m_VirtualFileID.isInvalid() && "No VirtualFileID created?");
  }
Esempio n. 9
0
  Interpreter::CompilationResult
  Interpreter::loadModuleForHeader(const std::string& headerFile) {
    Preprocessor& PP = getCI()->getPreprocessor();
    //Copied from clang's PPDirectives.cpp
    bool isAngled = false;
    // Clang doc says:
    // "LookupFrom is set when this is a \#include_next directive, it specifies
    // the file to start searching from."
    const DirectoryLookup* LookupFrom = 0;
    const DirectoryLookup* CurDir = 0;

    ModuleMap::KnownHeader suggestedModule;
    // PP::LookupFile uses it to issue 'nice' diagnostic
    SourceLocation fileNameLoc;
    PP.LookupFile(fileNameLoc, headerFile, isAngled, LookupFrom, CurDir,
                  /*SearchPath*/0, /*RelativePath*/ 0, &suggestedModule,
                  /*SkipCache*/false, /*OpenFile*/ false, /*CacheFail*/ false);
    if (!suggestedModule)
      return Interpreter::kFailure;

    // Copied from PPDirectives.cpp
    SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> path;
    for (Module *mod = suggestedModule.getModule(); mod; mod = mod->Parent) {
      IdentifierInfo* II
        = &getSema().getPreprocessor().getIdentifierTable().get(mod->Name);
      path.push_back(std::make_pair(II, fileNameLoc));
    }

    std::reverse(path.begin(), path.end());

    // Pretend that the module came from an inclusion directive, so that clang
    // will create an implicit import declaration to capture it in the AST.
    bool isInclude = true;
    SourceLocation includeLoc;
    if (getCI()->loadModule(includeLoc, path, Module::AllVisible, isInclude)) {
      // After module load we need to "force" Sema to generate the code for
      // things like dynamic classes.
      getSema().ActOnEndOfTranslationUnit();
      return Interpreter::kSuccess;
    }

    return Interpreter::kFailure;
  }
Esempio n. 10
0
void Correlation::computeCI(double ci)
{
  if(isSort==No)
    sortParameters();
  if(ci==-1)
    {
      ci=defaultCI;
    }
  for(int i=0;i<nbparameter;i++)
    {
      getCI(sortparameters[i],nbsample,ci,&CIbuffer[i][0],&CIbuffer[i][1]);
    }
}
Esempio n. 11
0
  void Interpreter::GenerateAutoloadingMap(llvm::StringRef inFile,
                                           llvm::StringRef outFile,
                                           bool enableMacros,
                                           bool enableLogs) {

    const char *const dummy="cling";
    // Create an interpreter without any runtime, producing the fwd decls.
    cling::Interpreter fwdGen(1, &dummy, nullptr, true);

    // Copy the same header search options to the new instance.
    Preprocessor& fwdGenPP = fwdGen.getCI()->getPreprocessor();
    HeaderSearchOptions headerOpts = getCI()->getHeaderSearchOpts();
    clang::ApplyHeaderSearchOptions(fwdGenPP.getHeaderSearchInfo(), headerOpts,
                                    fwdGenPP.getLangOpts(),
                                    fwdGenPP.getTargetInfo().getTriple());


    CompilationOptions CO;
    CO.DeclarationExtraction = 0;
    CO.ValuePrinting = 0;
    CO.ResultEvaluation = 0;
    CO.DynamicScoping = 0;
    CO.Debug = isPrintingDebug();


    std::string includeFile = std::string("#include \"") + inFile.str() + "\"";
    cling::Transaction* T = fwdGen.m_IncrParser->Parse(includeFile , CO);

    // If this was already #included we will get a T == 0.
    if (!T)
      return;

    std::string err;
    llvm::raw_fd_ostream out(outFile.data(), err,
                             llvm::sys::fs::OpenFlags::F_None);
    if (enableLogs){
      llvm::raw_fd_ostream log(llvm::Twine(outFile).concat(llvm::Twine(".skipped")).str().c_str(),
                             err, llvm::sys::fs::OpenFlags::F_None);
      log << "Generated for :" << inFile << "\n";
      ForwardDeclPrinter visitor(out, log, fwdGen.getSema().getSourceManager(), *T);
      visitor.printStats();
    }
    else {
      llvm::raw_null_ostream sink;
      ForwardDeclPrinter visitor(out, sink, fwdGen.getSema().getSourceManager(), *T);
    }
    // Avoid assertion in the ~IncrementalParser.
    T->setState(Transaction::kCommitted);
    // unload(1);
    return;
  }
Esempio n. 12
0
  IncrementalParser::ParseResultTransaction
  IncrementalParser::endTransaction(Transaction* T) {
    assert(T && "Null transaction!?");
    assert(T->getState() == Transaction::kCollecting);

#ifndef NDEBUG
    if (T->hasNestedTransactions()) {
      for(Transaction::const_nested_iterator I = T->nested_begin(),
            E = T->nested_end(); I != E; ++I)
        assert((*I)->isCompleted() && "Nested transaction not completed!?");
    }
#endif

    T->setState(Transaction::kCompleted);

    DiagnosticsEngine& Diag = getCI()->getSema().getDiagnostics();

    //TODO: Make the enum orable.
    EParseResult ParseResult = kSuccess;

    assert((Diag.hasFatalErrorOccurred() ? Diag.hasErrorOccurred() : true)
            && "Diag.hasFatalErrorOccurred without Diag.hasErrorOccurred !");

    if (Diag.hasErrorOccurred() || T->getIssuedDiags() == Transaction::kErrors) {
      T->setIssuedDiags(Transaction::kErrors);
      ParseResult = kFailed;
    } else if (Diag.getNumWarnings() > 0) {
      T->setIssuedDiags(Transaction::kWarnings);
      ParseResult = kSuccessWithWarnings;
    }

    // Empty transaction, send it back to the pool.
    if (T->empty()) {
      assert((!m_Consumer->getTransaction()
              || (m_Consumer->getTransaction() == T))
             && "Cannot release different T");
      // If a nested transaction the active one should be its parent
      // from now on. FIXME: Merge conditional with commitTransaction
      if (T->isNestedTransaction())
        m_Consumer->setTransaction(T->getParent());
      else
        m_Consumer->setTransaction((Transaction*)0);

      m_TransactionPool->releaseTransaction(T);
      return ParseResultTransaction(nullptr, ParseResult);
    }

    addTransaction(T);
    return ParseResultTransaction(T, ParseResult);
  }
Esempio n. 13
0
  void IncrementalParser::unloadTransaction(Transaction* T) {
    if (!T)
      T = getLastTransaction();

    assert(T->getState() == Transaction::kCommitted && 
           "Unloading not commited transaction?");
    assert(T->getModule() && 
           "Trying to uncodegen transaction taken in syntax only mode. ");

    ASTNodeEraser NodeEraser(&getCI()->getSema());
    NodeEraser.RevertTransaction(T);

    InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();
    if (callbacks)
      callbacks->TransactionUnloaded(*T);
  }
Esempio n. 14
0
  Interpreter::ExecutionResult
  Interpreter::RunFunction(const FunctionDecl* FD, Value* res /*=0*/) {
    if (getCI()->getDiagnostics().hasErrorOccurred())
      return kExeCompilationError;

    if (isInSyntaxOnlyMode()) {
      return kExeNoCodeGen;
    }

    if (!FD)
      return kExeUnkownFunction;

    std::string mangledNameIfNeeded;
    utils::Analyze::maybeMangleDeclName(FD, mangledNameIfNeeded);
    IncrementalExecutor::ExecutionResult ExeRes =
       m_Executor->executeFunction(mangledNameIfNeeded.c_str(), res);
    return ConvertExecutionResult(ExeRes);
  }
Esempio n. 15
0
  void IncrementalParser::codeGenTransaction(Transaction* T) {
    // codegen the transaction
    assert(T->getCompilationOpts().CodeGeneration && "CodeGen turned off");
    assert(hasCodeGenerator() && "No CodeGen");

    T->setModule(getCodeGenerator()->GetModule());

    for (size_t Idx = 0; Idx < T->size() /*can change in the loop!*/; ++Idx) {
      // Copy DCI; it might get relocated below.
      Transaction::DelayCallInfo I = (*T)[Idx];

      if (I.m_Call == Transaction::kCCIHandleTopLevelDecl)
        getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
      else if (I.m_Call == Transaction::kCCIHandleInterestingDecl) {
        // Usually through BackendConsumer which doesn't implement
        // HandleInterestingDecl() and thus calls
        // ASTConsumer::HandleInterestingDecl()
        getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
      } else if(I.m_Call == Transaction::kCCIHandleTagDeclDefinition) {
        TagDecl* TD = cast<TagDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleTagDeclDefinition(TD);
      }
      else if (I.m_Call == Transaction::kCCIHandleVTable) {
        CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleVTable(CXXRD, /*isRequired*/true);
      }
      else if (I.m_Call
               == Transaction::kCCIHandleCXXImplicitFunctionInstantiation) {
        FunctionDecl* FD = cast<FunctionDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleCXXImplicitFunctionInstantiation(FD);
      }
      else if (I.m_Call
               == Transaction::kCCIHandleCXXStaticMemberVarInstantiation) {
        VarDecl* VD = cast<VarDecl>(I.m_DGR.getSingleDecl());
        getCodeGenerator()->HandleCXXStaticMemberVarInstantiation(VD);
      }
      else if (I.m_Call == Transaction::kCCINone)
        ; // We use that internally as delimiter in the Transaction.
      else
        llvm_unreachable("We shouldn't have decl without call info.");
    }

    getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
  }
Esempio n. 16
0
  Interpreter::CompilationResult
  Interpreter::parseForModule(const std::string& input) {
    CompilationOptions CO;
    CO.CodeGeneration = 1;
    CO.CodeGenerationForModule = 1;
    CO.DeclarationExtraction = 0;
    CO.ValuePrinting = 0;
    CO.ResultEvaluation = 0;
    CO.DynamicScoping = isDynamicLookupEnabled();
    CO.Debug = isPrintingDebug();

    // When doing parseForModule avoid warning about the user code
    // being loaded ... we probably might as well extend this to
    // ALL warnings ... but this will suffice for now (working
    // around a real bug in QT :().
    DiagnosticsEngine& Diag = getCI()->getDiagnostics();
    Diag.setSeverity(clang::diag::warn_field_is_uninit,
                     clang::diag::Severity::Ignored, SourceLocation());
    return DeclareInternal(input, CO);
  }
Esempio n. 17
0
  Value Interpreter::Evaluate(const char* expr, DeclContext* DC,
                                       bool ValuePrinterReq) {
    Sema& TheSema = getCI()->getSema();
    // The evaluation should happen on the global scope, because of the wrapper
    // that is created.
    //
    // We can't PushDeclContext, because we don't have scope.
    Sema::ContextRAII pushDC(TheSema,
                             TheSema.getASTContext().getTranslationUnitDecl());

    Value Result;
    getCallbacks()->SetIsRuntime(true);
    if (ValuePrinterReq)
      echo(expr, &Result);
    else
      evaluate(expr, Result);
    getCallbacks()->SetIsRuntime(false);

    return Result;
  }
Esempio n. 18
0
  void IncrementalParser::Initialize() {
    if (hasCodeGenerator())
      getCodeGenerator()->Initialize(getCI()->getASTContext());

    CompilationOptions CO;
    CO.DeclarationExtraction = 0;
    CO.ValuePrinting = CompilationOptions::VPDisabled;
    CO.CodeGeneration = hasCodeGenerator();

    // pull in PCHs
    const std::string& PCHFileName
      = m_CI->getInvocation ().getPreprocessorOpts().ImplicitPCHInclude;
    if (!PCHFileName.empty()) {
      
      Transaction* CurT = beginTransaction(CO);
      m_CI->createPCHExternalASTSource(PCHFileName,
                                       true /*DisablePCHValidation*/,
                                       true /*AllowPCHWithCompilerErrors*/,
                                       0 /*DeserializationListener*/);
      Transaction* EndedT = endTransaction(CurT);
      commitTransaction(EndedT);
    }

    Transaction* CurT = beginTransaction(CO);
    Sema* TheSema = &m_CI->getSema();
    m_Parser.reset(new Parser(m_CI->getPreprocessor(), *TheSema,
                              false /*skipFuncBodies*/));
    m_CI->getPreprocessor().EnterMainSourceFile();
    // Initialize the parser after we have entered the main source file.
    m_Parser->Initialize();
    // Perform initialization that occurs after the parser has been initialized
    // but before it parses anything. Initializes the consumers too.
    TheSema->Initialize();

    ExternalASTSource *External = TheSema->getASTContext().getExternalSource();
    if (External)
      External->StartTranslationUnit(m_Consumer);

    Transaction* EndedT = endTransaction(CurT);
    commitTransaction(EndedT);
  }
Esempio n. 19
0
  Transaction* IncrementalParser::endTransaction() const {
    Transaction* CurT = m_Consumer->getTransaction();
    assert(CurT->getState() == Transaction::kCollecting);
    CurT->setState(Transaction::kCompleted);
    const DiagnosticsEngine& Diags = getCI()->getSema().getDiagnostics();

    //TODO: Make the enum orable.
    if (Diags.getNumWarnings() > 0)
      CurT->setIssuedDiags(Transaction::kWarnings);

    if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
      CurT->setIssuedDiags(Transaction::kErrors);

      
    if (CurT->hasNestedTransactions()) {
      for(Transaction::const_nested_iterator I = CurT->nested_begin(),
            E = CurT->nested_end(); I != E; ++I)
        assert((*I)->isCompleted() && "Nested transaction not completed!?");
    }

    return CurT;
  }
Esempio n. 20
0
  Interpreter::ExecutionResult
  Interpreter::runStaticInitializersOnce(const Transaction& T) const {
    assert(!isInSyntaxOnlyMode() && "Running on what?");
    assert(T.getState() == Transaction::kCommitted && "Must be committed");
    // Forward to IncrementalExecutor; should not be called by
    // anyone except for IncrementalParser.
    llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule();
    IncrementalExecutor::ExecutionResult ExeRes
       = m_Executor->runStaticInitializersOnce(module);

    // Avoid eternal additions to llvm.ident; see
    // CodeGenModule::EmitVersionIdentMetadata().
    llvm::NamedMDNode *IdentMetadata = module->getNamedMetadata("llvm.ident");
    if (IdentMetadata)
      module->eraseNamedMetadata(IdentMetadata);

    // Reset the module builder to clean up global initializers, c'tors, d'tors
    ASTContext& C = getCI()->getASTContext();
    m_IncrParser->getCodeGenerator()->HandleTranslationUnit(C);

    return ConvertExecutionResult(ExeRes);
  }
Esempio n. 21
0
  std::string Interpreter::lookupFileOrLibrary(llvm::StringRef file) {
    std::string canonicalFile = DynamicLibraryManager::normalizePath(file);
    if (canonicalFile.empty())
      canonicalFile = file;
    const FileEntry* FE = 0;

    //Copied from clang's PPDirectives.cpp
    bool isAngled = false;
    // Clang doc says:
    // "LookupFrom is set when this is a \#include_next directive, it
    // specifies the file to start searching from."
    const DirectoryLookup* LookupFrom = 0;
    const DirectoryLookup* CurDir = 0;
    Preprocessor& PP = getCI()->getPreprocessor();
    // PP::LookupFile uses it to issue 'nice' diagnostic
    SourceLocation fileNameLoc;
    FE = PP.LookupFile(fileNameLoc, canonicalFile, isAngled, LookupFrom, CurDir,
                       /*SearchPath*/0, /*RelativePath*/ 0,
                       /*suggestedModule*/0, /*SkipCache*/false,
                       /*OpenFile*/ false, /*CacheFail*/ false);
    if (FE)
      return FE->getName();
    return getDynamicLibraryManager()->lookupLibrary(canonicalFile);
  }
Esempio n. 22
0
 // Each input line is contained in separate memory buffer. The SourceManager
 // assigns sort-of invalid FileID for each buffer, i.e there is no FileEntry
 // for the MemoryBuffer's FileID. That in turn is problem because invalid
 // SourceLocations are given to the diagnostics. Thus the diagnostics cannot
 // order the overloads, for example
 //
 // Our work-around is creating a virtual file, which doesn't exist on the disk
 // with enormous size (no allocation is done). That file has valid FileEntry
 // and so on... We use it for generating valid SourceLocations with valid
 // offsets so that it doesn't cause any troubles to the diagnostics.
 //
 // +---------------------+
 // | Main memory buffer  |
 // +---------------------+
 // |  Virtual file SLoc  |
 // |    address space    |<-----------------+
 // |         ...         |<------------+    |
 // |         ...         |             |    |
 // |         ...         |<----+       |    |
 // |         ...         |     |       |    |
 // +~~~~~~~~~~~~~~~~~~~~~+     |       |    |
 // |     input_line_1    | ....+.......+..--+
 // +---------------------+     |       |
 // |     input_line_2    | ....+.....--+
 // +---------------------+     |
 // |          ...        |     |
 // +---------------------+     |
 // |     input_line_N    | ..--+
 // +---------------------+
 //
 void IncrementalParser::CreateSLocOffsetGenerator() {
   SourceManager& SM = getCI()->getSourceManager();
   m_VirtualFileID = SM.getMainFileID();
   assert(!m_VirtualFileID.isInvalid() && "No VirtualFileID created?");
 }
Esempio n. 23
0
  void IncrementalParser::commitTransaction(Transaction* T) {
    //Transaction* CurT = m_Consumer->getTransaction();
    assert(T->isCompleted() && "Transaction not ended!?");
    assert(T->getState() != Transaction::kCommitted
           && "Committing an already committed transaction.");

    // Check for errors...
    if (T->getIssuedDiags() == Transaction::kErrors) {
      rollbackTransaction(T);
      return;
    }

    if (T->hasNestedTransactions()) {
      for(Transaction::const_nested_iterator I = T->nested_begin(),
            E = T->nested_end(); I != E; ++I)
        if ((*I)->getState() != Transaction::kCommitted)
          commitTransaction(*I);
    }

    // We are sure it's safe to pipe it through the transformers
    bool success = true;
    for (size_t i = 0; i < m_TTransformers.size(); ++i) {
      success = m_TTransformers[i]->TransformTransaction(*T);
      if (!success) {
        break;
      }
    }

    m_CI->getDiagnostics().Reset(); // FIXME: Should be in rollback transaction.

    if (!success) {
      // Roll back on error in a transformer
      rollbackTransaction(T);
      return;
    }

    // Pull all template instantiations in that came from the consumers.
    getCI()->getSema().PerformPendingInstantiations();

    m_Consumer->HandleTranslationUnit(getCI()->getASTContext());

    if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
      // codegen the transaction
      for (size_t Idx = 0; Idx < T->size() /*can change in the loop!*/; ++Idx) {
        // Copy DCI; it might get relocated below.
        Transaction::DelayCallInfo I = (*T)[Idx];
        if (I.m_Call == Transaction::kCCIHandleTopLevelDecl)
          getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
        else if (I.m_Call == Transaction::kCCIHandleInterestingDecl) {
          // Usually through BackendConsumer which doesn't implement
          // HandleInterestingDecl() and thus calls
          // ASTConsumer::HandleInterestingDecl()
          getCodeGenerator()->HandleTopLevelDecl(I.m_DGR);
        } else if(I.m_Call == Transaction::kCCIHandleTagDeclDefinition) {
          TagDecl* TD = cast<TagDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleTagDeclDefinition(TD);
        }
        else if (I.m_Call == Transaction::kCCIHandleVTable) {
          CXXRecordDecl* CXXRD = cast<CXXRecordDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleVTable(CXXRD, /*isRequired*/true);
        }
        else if (I.m_Call
                 == Transaction::kCCIHandleCXXImplicitFunctionInstantiation) {
          FunctionDecl* FD = cast<FunctionDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleCXXImplicitFunctionInstantiation(FD);
        }
        else if (I.m_Call
                 == Transaction::kCCIHandleCXXStaticMemberVarInstantiation) {
          VarDecl* VD = cast<VarDecl>(I.m_DGR.getSingleDecl());
          getCodeGenerator()->HandleCXXStaticMemberVarInstantiation(VD);
        }
        else if (I.m_Call == Transaction::kCCINone)
          ; // We use that internally as delimiter in the Transaction.
        else
          llvm_unreachable("We shouldn't have decl without call info.");
      }

      getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
      T->setModule(getCodeGenerator()->GetModule());

      // The static initializers might run anything and can thus cause more
      // decls that need to end up in a transaction. But this one is done
      // with CodeGen...
      T->setState(Transaction::kCommitting);

      // run the static initializers that came from codegenning
      if (m_Interpreter->runStaticInitializersOnce()
          >= Interpreter::kExeFirstError) {
        // Roll back on error in a transformer
        rollbackTransaction(T);
        return;
      }
    } else
      T->setState(Transaction::kCommitting);

    InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();

    if (callbacks) {
      callbacks->TransactionCommitted(*T);
    }
    if (T->hasNestedTransactions()) {
      Transaction* SubTransactionWhileCommitting = *T->rnested_begin();
      if (SubTransactionWhileCommitting->getState()
          == Transaction::kCollecting) {
        // A nested transaction was created while committing this
        // transaction; commit it now.
        SubTransactionWhileCommitting->setState(Transaction::kCompleted);
        commitTransaction(SubTransactionWhileCommitting);
      }
    }

    T->setState(Transaction::kCommitted);

    // If the transaction is empty do nothing.
    // Except it was nested transaction and we want to reuse it later on.
    if (T->empty() && T->isNestedTransaction()) {
      // We need to remove the marker from its parent.
      Transaction* ParentT = T->getParent();
      for (size_t i = 0; i < ParentT->size(); ++i)
        if ((*ParentT)[i].m_DGR.isNull())
          ParentT->erase(i);
    }

    if (T->isNestedTransaction()) {
      // TODO: Add proper logic in the case where there are multiple nested
      // transaction. This now won't handle the case where there are more than
      // one level 1 nested transactions.
      m_Consumer->setTransaction(T->getParent());
    }
  }
  // Add the input to the memory buffer, parse it, and add it to the AST.
  IncrementalParser::EParseResult 
  IncrementalParser::Parse(llvm::StringRef input) {
    Preprocessor& PP = m_CI->getPreprocessor();
    DiagnosticConsumer& DClient = m_CI->getDiagnosticClient();

    PP.enableIncrementalProcessing();

    DClient.BeginSourceFile(m_CI->getLangOpts(), &PP);
    // Reset the transaction information
    getLastTransaction().setBeforeFirstDecl(getCI()->getSema().CurContext);
    

    if (input.size()) {
      std::ostringstream source_name;
      source_name << "input_line_" << (m_MemoryBuffer.size() + 1);
      llvm::MemoryBuffer* MB  
        = llvm::MemoryBuffer::getMemBufferCopy(input, source_name.str());
      m_MemoryBuffer.push_back(MB);
      SourceManager& SM = getCI()->getSourceManager();

      // Create SourceLocation, which will allow clang to order the overload
      // candidates for example
      SourceLocation NewLoc = SM.getLocForStartOfFile(m_VirtualFileID);
      NewLoc = NewLoc.getLocWithOffset(m_MemoryBuffer.size() + 1);
      
      // Create FileID for the current buffer
      FileID FID = SM.createFileIDForMemBuffer(m_MemoryBuffer.back(),
                                               /*LoadedID*/0,
                                               /*LoadedOffset*/0, NewLoc);
      
      PP.EnterSourceFile(FID, 0, NewLoc);      
    }

    Parser::DeclGroupPtrTy ADecl;

    while (!m_Parser->ParseTopLevelDecl(ADecl)) {
      // Not end of file.
      // If we got a null return and something *was* parsed, ignore it.  This
      // is due to a top-level semicolon, an action override, or a parse error
      // skipping something.
      if (ADecl) {
        DeclGroupRef DGR = ADecl.getAsVal<DeclGroupRef>();
        for (DeclGroupRef::iterator i=DGR.begin(); i< DGR.end(); ++i) {
         if (!m_FirstTopLevelDecl)
           m_FirstTopLevelDecl = *((*i)->getDeclContext()->decls_begin());

          m_LastTopLevelDecl = *i;
        } 
        m_Consumer->HandleTopLevelDecl(DGR);
      } // ADecl
    };
    
    // Process any TopLevelDecls generated by #pragma weak.
    for (llvm::SmallVector<Decl*,2>::iterator
           I = getCI()->getSema().WeakTopLevelDecls().begin(),
           E = getCI()->getSema().WeakTopLevelDecls().end(); I != E; ++I) {
      m_Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
    }

    getCI()->getSema().PerformPendingInstantiations();

    DClient.EndSourceFile();

    PP.enableIncrementalProcessing(false);

    DiagnosticsEngine& Diag = getCI()->getSema().getDiagnostics();
    if (Diag.hasErrorOccurred())
      return IncrementalParser::kFailed;
    else if (Diag.getNumWarnings())
      return IncrementalParser::kSuccessWithWarnings;

    return IncrementalParser::kSuccess;
  }
Esempio n. 25
0
  Interpreter::CompilationResult
  Interpreter::EvaluateInternal(const std::string& input,
                                const CompilationOptions& CO,
                                Value* V, /* = 0 */
                                Transaction** T /* = 0 */) {
    StateDebuggerRAII stateDebugger(this);

    // Wrap the expression
    std::string WrapperName;
    std::string Wrapper = input;
    WrapInput(Wrapper, WrapperName);

    // Disable warnings which doesn't make sense when using the prompt
    // This gets reset with the clang::Diagnostics().Reset(/*soft*/=false)
    // using clang's API we simulate:
    // #pragma warning push
    // #pragma warning ignore ...
    // #pragma warning ignore ...
    // #pragma warning pop
    SourceLocation Loc = getNextAvailableLoc();
    DiagnosticsEngine& Diags = getCI()->getDiagnostics();
    Diags.pushMappings(Loc);
    // The source locations of #pragma warning ignore must be greater than
    // the ones from #pragma push
    Diags.setSeverity(clang::diag::warn_unused_expr,
                      clang::diag::Severity::Ignored, SourceLocation());
    Diags.setSeverity(clang::diag::warn_unused_call,
                      clang::diag::Severity::Ignored, SourceLocation());
    Diags.setSeverity(clang::diag::warn_unused_comparison,
                      clang::diag::Severity::Ignored, SourceLocation());
    Diags.setSeverity(clang::diag::ext_return_has_expr,
                      clang::diag::Severity::Ignored, SourceLocation());
    if (Transaction* lastT = m_IncrParser->Compile(Wrapper, CO)) {
      Loc = m_IncrParser->getLastMemoryBufferEndLoc().getLocWithOffset(1);
      // if the location was the same we are in recursive calls and to avoid an
      // assert in clang we should increment by a value.
      if (SourceLocation::getFromRawEncoding(m_LastCustomPragmaDiagPopPoint)
          == Loc)
        // Nested #pragma pop-s must be on different source locations.
        Loc = Loc.getLocWithOffset(1);
      m_LastCustomPragmaDiagPopPoint = Loc.getRawEncoding();

      Diags.popMappings(Loc);
      assert((lastT->getState() == Transaction::kCommitted
              || lastT->getState() == Transaction::kRolledBack)
             && "Not committed?");
      if (lastT->getIssuedDiags() != Transaction::kErrors) {
        Value resultV;
        if (!V)
          V = &resultV;
        if (!lastT->getWrapperFD()) // no wrapper to run
          return Interpreter::kSuccess;
        else if (RunFunction(lastT->getWrapperFD(), V) < kExeFirstError){
          if (lastT->getCompilationOpts().ValuePrinting
              != CompilationOptions::VPDisabled
              && V->isValid()
              // the !V->needsManagedAllocation() case is handled by
              // dumpIfNoStorage.
              && V->needsManagedAllocation())
            V->dump();
          return Interpreter::kSuccess;
        }
      }
      if (V)
        *V = Value();

      return Interpreter::kFailure;
    }
    Diags.popMappings(Loc.getLocWithOffset(1));
    return Interpreter::kSuccess;
  }
Esempio n. 26
0
 const Sema& Interpreter::getSema() const {
   return getCI()->getSema();
 }
Esempio n. 27
0
 Sema& Interpreter::getSema() {
   return getCI()->getSema();
 }
Esempio n. 28
0
  // Add the input to the memory buffer, parse it, and add it to the AST.
  IncrementalParser::EParseResult
  IncrementalParser::ParseInternal(llvm::StringRef input) {
    if (input.empty()) return IncrementalParser::kSuccess;

    Sema& S = getCI()->getSema();

    assert(!(S.getLangOpts().Modules
             && m_Consumer->getTransaction()->getCompilationOpts()
              .CodeGenerationForModule)
           && "CodeGenerationForModule should be removed once modules are available!");

    // Recover resources if we crash before exiting this method.
    llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(&S);

    Preprocessor& PP = m_CI->getPreprocessor();
    if (!PP.getCurrentLexer()) {
       PP.EnterSourceFile(m_CI->getSourceManager().getMainFileID(),
                          0, SourceLocation());
    }
    assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode!?");
    PP.enableIncrementalProcessing();

    std::ostringstream source_name;
    source_name << "input_line_" << (m_MemoryBuffers.size() + 1);

    // Create an uninitialized memory buffer, copy code in and append "\n"
    size_t InputSize = input.size(); // don't include trailing 0
    // MemBuffer size should *not* include terminating zero
    llvm::MemoryBuffer* MB
      = llvm::MemoryBuffer::getNewUninitMemBuffer(InputSize + 1,
                                                  source_name.str());
    char* MBStart = const_cast<char*>(MB->getBufferStart());
    memcpy(MBStart, input.data(), InputSize);
    memcpy(MBStart + InputSize, "\n", 2);

    m_MemoryBuffers.push_back(MB);
    SourceManager& SM = getCI()->getSourceManager();

    // Create SourceLocation, which will allow clang to order the overload
    // candidates for example
    SourceLocation NewLoc = SM.getLocForStartOfFile(m_VirtualFileID);
    NewLoc = NewLoc.getLocWithOffset(m_MemoryBuffers.size() + 1);

    // Create FileID for the current buffer
    FileID FID = SM.createFileIDForMemBuffer(m_MemoryBuffers.back(),
                                             SrcMgr::C_User,
                                             /*LoadedID*/0,
                                             /*LoadedOffset*/0, NewLoc);

    PP.EnterSourceFile(FID, /*DirLookup*/0, NewLoc);

    Parser::DeclGroupPtrTy ADecl;

    while (!m_Parser->ParseTopLevelDecl(ADecl)) {
      // If we got a null return and something *was* parsed, ignore it.  This
      // is due to a top-level semicolon, an action override, or a parse error
      // skipping something.
      if (ADecl)
        m_Consumer->HandleTopLevelDecl(ADecl.getAsVal<DeclGroupRef>());
    };

    // Process any TopLevelDecls generated by #pragma weak.
    for (llvm::SmallVector<Decl*,2>::iterator I = S.WeakTopLevelDecls().begin(),
           E = S.WeakTopLevelDecls().end(); I != E; ++I) {
      m_Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
    }

    DiagnosticsEngine& Diag = S.getDiagnostics();
    if (Diag.hasErrorOccurred())
      return IncrementalParser::kFailed;
    else if (Diag.getNumWarnings())
      return IncrementalParser::kSuccessWithWarnings;

    return IncrementalParser::kSuccess;
  }
Esempio n. 29
0
  const FunctionDecl* Interpreter::DeclareCFunction(StringRef name,
                                                    StringRef code,
                                                    bool withAccessControl) {
    /*
    In CallFunc we currently always (intentionally and somewhat necessarily)
    always fully specify member function template, however this can lead to
    an ambiguity with a class template.  For example in
    roottest/cling/functionTemplate we get:

    input_line_171:3:15: warning: lookup of 'set' in member access expression
    is ambiguous; using member of 't'
    ((t*)obj)->set<int>(*(int*)args[0]);
               ^
    roottest/cling/functionTemplate/t.h:19:9: note: lookup in the object type
    't' refers here
    void set(T targ) {
         ^
    /usr/include/c++/4.4.5/bits/stl_set.h:87:11: note: lookup from the
    current scope refers here
    class set
          ^
    This is an intention warning implemented in clang, see
    http://llvm.org/viewvc/llvm-project?view=revision&revision=105518

    which 'should have been' an error:

    C++ [basic.lookup.classref] requires this to be an error, but,
    because it's hard to work around, Clang downgrades it to a warning as
    an extension.</p>

    // C++98 [basic.lookup.classref]p1:
    // In a class member access expression (5.2.5), if the . or -> token is
    // immediately followed by an identifier followed by a <, the identifier
    // must be looked up to determine whether the < is the beginning of a
    // template argument list (14.2) or a less-than operator. The identifier
    // is first looked up in the class of the object expression. If the
    // identifier is not found, it is then looked up in the context of the
    // entire postfix-expression and shall name a class or function template. If
    // the lookup in the class of the object expression finds a template, the
    // name is also looked up in the context of the entire postfix-expression
    // and
    // -- if the name is not found, the name found in the class of the
    // object expression is used, otherwise
    // -- if the name is found in the context of the entire postfix-expression
    // and does not name a class template, the name found in the class of the
    // object expression is used, otherwise
    // -- if the name found is a class template, it must refer to the same
    // entity as the one found in the class of the object expression,
    // otherwise the program is ill-formed.

    See -Wambiguous-member-template

    An alternative to disabling the diagnostics is to use a pointer to
    member function:

    #include <set>
    using namespace std;

    extern "C" int printf(const char*,...);

    struct S {
    template <typename T>
    void set(T) {};

    virtual void virtua() { printf("S\n"); }
    };

    struct T: public S {
    void virtua() { printf("T\n"); }
    };

    int main() {
    S *s = new T();
    typedef void (S::*Func_p)(int);
    Func_p p = &S::set<int>;
    (s->*p)(12);

    typedef void (S::*Vunc_p)(void);
    Vunc_p q = &S::virtua;
    (s->*q)(); // prints "T"
    return 0;
    }
    */
    DiagnosticsEngine& Diag = getCI()->getDiagnostics();
    Diag.setSeverity(clang::diag::ext_nested_name_member_ref_lookup_ambiguous,
                     clang::diag::Severity::Ignored, SourceLocation());


    LangOptions& LO = const_cast<LangOptions&>(getCI()->getLangOpts());
    bool savedAccessControl = LO.AccessControl;
    LO.AccessControl = withAccessControl;
    cling::Transaction* T = 0;
    cling::Interpreter::CompilationResult CR = declare(code, &T);
    LO.AccessControl = savedAccessControl;

    if (CR != cling::Interpreter::kSuccess)
      return 0;

    for (cling::Transaction::const_iterator I = T->decls_begin(),
           E = T->decls_end(); I != E; ++I) {
      if (I->m_Call != cling::Transaction::kCCIHandleTopLevelDecl)
        continue;
      if (const LinkageSpecDecl* LSD
          = dyn_cast<LinkageSpecDecl>(*I->m_DGR.begin())) {
        DeclContext::decl_iterator DeclBegin = LSD->decls_begin();
        if (DeclBegin == LSD->decls_end())
          continue;
        if (const FunctionDecl* D = dyn_cast<FunctionDecl>(*DeclBegin)) {
          const IdentifierInfo* II = D->getDeclName().getAsIdentifierInfo();
          if (II && II->getName() == name)
            return D;
        }
      }
    }
    return 0;
  }
Esempio n. 30
0
  void IncrementalParser::commitTransaction(Transaction* T) {
    //Transaction* CurT = m_Consumer->getTransaction();
    assert(T->isCompleted() && "Transaction not ended!?");
    assert(T->getState() != Transaction::kCommitted
           && "Committing an already committed transaction.");

    // If committing a nested transaction the active one should be its parent
    // from now on.
    if (T->isNestedTransaction())
      m_Consumer->setTransaction(T->getParent());

    // Check for errors...
    if (T->getIssuedDiags() == Transaction::kErrors) {
      rollbackTransaction(T);
      return;
    }

    if (T->hasNestedTransactions()) {
      for(Transaction::const_nested_iterator I = T->nested_begin(),
            E = T->nested_end(); I != E; ++I)
        if ((*I)->getState() != Transaction::kCommitted)
          commitTransaction(*I);
    }

    if (!transformTransactionAST(T))
      return;

    // Here we expect a template instantiation. We need to open the transaction
    // that we are currently work with.
    Transaction::State oldState = T->getState();
    T->setState(Transaction::kCollecting);
    // Pull all template instantiations in that came from the consumers.
    getCI()->getSema().PerformPendingInstantiations();
    T->setState(oldState);

    m_Consumer->HandleTranslationUnit(getCI()->getASTContext());

    if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
      codeGenTransaction(T);
      transformTransactionIR(T);
    }

    // The static initializers might run anything and can thus cause more
    // decls that need to end up in a transaction. But this one is done
    // with CodeGen...
    T->setState(Transaction::kCommitted);

    if (T->getCompilationOpts().CodeGeneration && hasCodeGenerator()) {
      runStaticInitOnTransaction(T);
    }

    InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();

    if (callbacks)
      callbacks->TransactionCommitted(*T);

    // If the transaction is empty do nothing.
    // Except it was nested transaction and we want to reuse it later on.
    if (T->empty() && T->isNestedTransaction()) {
      // We need to remove the marker from its parent.
      Transaction* ParentT = T->getParent();
      for (size_t i = 0; i < ParentT->size(); ++i)
        if ((*ParentT)[i].m_DGR.isNull())
          ParentT->erase(i);
    }
  }