Exemplo n.º 1
0
bool CapturedDiagList::clearDiagnostic(llvm::ArrayRef<unsigned> IDs,
                                       SourceRange range) {
  if (range.isInvalid())
    return false;

  bool cleared = false;
  ListTy::iterator I = List.begin();
  while (I != List.end()) {
    FullSourceLoc diagLoc = I->getLocation();
    if ((IDs.empty() || // empty means clear all diagnostics in the range.
         std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
        !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
        (diagLoc == range.getEnd() ||
           diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
      cleared = true;
      ListTy::iterator eraseS = I++;
      while (I != List.end() && I->getLevel() == Diagnostic::Note)
        ++I;
      // Clear the diagnostic and any notes following it.
      List.erase(eraseS, I);
      continue;
    }

    ++I;
  }

  return cleared;
}
Exemplo n.º 2
0
 static void jitTopLevel(llvm::ArrayRef<TopLevelItemPtr> toplevels)
 {
     if (toplevels.empty()) {
         return;
     }
     if (printAST) {
         for (size_t i = 0; i < toplevels.size(); ++i) {
             llvm::errs() << i << ": " << toplevels[i] << "\n";
         }
     }
     addGlobals(module, toplevels);
 }
Exemplo n.º 3
0
void NetworkTable::SetIPAddress(llvm::ArrayRef<std::string> addresses) {
  auto inst = NetworkTableInstance::GetDefault();
  llvm::SmallVector<StringRef, 8> servers;
  for (const auto& ip_address : addresses) servers.emplace_back(ip_address);
  inst.SetServer(servers, s_port);

  // Stop the DS client if we're explicitly connecting to localhost
  if (!addresses.empty() &&
      (addresses[0] == "localhost" || addresses[0] == "127.0.0.1"))
    inst.StopDSClient();
  else if (s_enable_ds)
    inst.StartDSClient(s_port);
}
Exemplo n.º 4
0
void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd, llvm::ArrayRef<LLValue*> addr)
{
    if (!global.params.symdebug)
        return;

    Logger::println("D to dwarf local variable");
    LOG_SCOPE;

    if (gIR->func()->diSubprogram == vd->debugFunc) // ensure that the debug variable is created only once
        return;

    // get type description
    llvm::DIType TD = dwarfTypeDescription(vd->type, NULL);
    if ((llvm::MDNode*)TD == 0)
        return; // unsupported

    // get variable description
    assert(!vd->isDataseg() && "static variable");

    unsigned tag;
    if (vd->isParameter())
        tag = DW_TAG_arg_variable;
    else
        tag = DW_TAG_auto_variable;

    if (addr.empty()) {
        vd->debugVariable = gIR->dibuilder.createLocalVariable(
            tag, // tag
            getCurrentScope(), // scope
            vd->toChars(), // name
            DtoDwarfFile(vd->loc), // file
            vd->loc.linnum, // line num
            TD, // type
            true // preserve
        );
    } else {
        vd->debugVariable = gIR->dibuilder.createComplexVariable(
            tag, // tag
            getCurrentScope(), // scope
            vd->toChars(), // name
            DtoDwarfFile(vd->loc), // file
            vd->loc.linnum, // line num
            TD, // type
            addr
        );
    }
    vd->debugFunc = gIR->func()->diSubprogram;

    // declare
    dwarfDeclare(ll, vd->debugVariable);
}
Exemplo n.º 5
0
bool Log::DisableLogChannel(llvm::StringRef channel,
                            llvm::ArrayRef<const char *> categories,
                            llvm::raw_ostream &error_stream) {
  auto iter = g_channel_map->find(channel);
  if (iter == g_channel_map->end()) {
    error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
    return false;
  }
  uint32_t flags = categories.empty()
                       ? UINT32_MAX
                       : GetFlags(error_stream, *iter, categories);
  iter->second.Disable(flags);
  return true;
}
Exemplo n.º 6
0
bool Log::EnableLogChannel(
    const std::shared_ptr<llvm::raw_ostream> &log_stream_sp,
    uint32_t log_options, llvm::StringRef channel,
    llvm::ArrayRef<const char *> categories, llvm::raw_ostream &error_stream) {
  auto iter = g_channel_map->find(channel);
  if (iter == g_channel_map->end()) {
    error_stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
    return false;
  }
  uint32_t flags = categories.empty()
                       ? iter->second.m_channel.default_flags
                       : GetFlags(error_stream, *iter, categories);
  iter->second.Enable(log_stream_sp, log_options, flags);
  return true;
}
Exemplo n.º 7
0
    static void jitStatements(llvm::ArrayRef<StatementPtr> statements)
    {
        if (statements.empty()) {
            return;
        }

        if (printAST) {
            for (size_t i = 0; i < statements.size(); ++i) {
                llvm::errs() << statements[i] << "\n";
            }
        }

        IdentifierPtr fun = Identifier::get(newFunctionName());

        BlockPtr funBody = new Block(statements);
        ExternalProcedurePtr entryProc =
                new ExternalProcedure(NULL,
                                      fun,
                                      PRIVATE,
                                      vector<ExternalArgPtr>(),
                                      false,
                                      NULL,
                                      funBody.ptr(),
                                      new ExprList());

        entryProc->env = module->env;

        codegenBeforeRepl(module);
        try {
            codegenExternalProcedure(entryProc, true);
        }
        catch (std::exception) {
            return;
        }

        llvm::Function* ctor;
        llvm::Function* dtor;
        codegenAfterRepl(ctor, dtor);

        engine->runFunction(ctor, std::vector<llvm::GenericValue>());

        void* dtorLlvmFun = engine->getPointerToFunction(dtor);
        typedef void (*PFN)();
        atexit((PFN)(uintptr_t)dtorLlvmFun);
        engine->runFunction(entryProc->llvmFunc, std::vector<llvm::GenericValue>());
    }
Exemplo n.º 8
0
static Variable::RangeList
MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
              llvm::ArrayRef<LocalVariableAddrGap> gaps) {
  lldb::addr_t start =
      index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
  lldb::addr_t end = start + range.Range;

  Variable::RangeList result;
  while (!gaps.empty()) {
    const LocalVariableAddrGap &gap = gaps.front();

    lldb::addr_t size = gap.GapStartOffset - start;
    result.Append(start, size);
    start += gap.Range;
    gaps = gaps.drop_front();
  }

  result.Append(start, end - start);
  return result;
}
Exemplo n.º 9
0
bool CapturedDiagList::hasDiagnostic(llvm::ArrayRef<unsigned> IDs,
                                     SourceRange range) const {
  if (range.isInvalid())
    return false;

  ListTy::const_iterator I = List.begin();
  while (I != List.end()) {
    FullSourceLoc diagLoc = I->getLocation();
    if ((IDs.empty() || // empty means any diagnostic in the range.
         std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
        !diagLoc.isBeforeInTranslationUnitThan(range.getBegin()) &&
        (diagLoc == range.getEnd() ||
           diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
      return true;
    }

    ++I;
  }

  return false;
}
Exemplo n.º 10
0
bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
    if (Args.empty())
        return false;

    // Parse command line options using Options.td
    TestOptTable Table;
    unsigned MissingIndex;
    unsigned MissingCount;
    llvm::opt::InputArgList ParsedArgs =
        Table.ParseArgs(Args, MissingIndex, MissingCount);
    if (MissingCount) {
        llvm::errs() << "error: missing argument value for '"
                     << ParsedArgs.getArgString(MissingIndex) << "', expected "
                     << MissingCount << " argument(s)\n";
        return true;
    }

    for (auto InputArg : ParsedArgs) {
        switch (InputArg->getOption().getID()) {
        case OPT_req:
            Request = llvm::StringSwitch<SourceKitRequest>(InputArg->getValue())
                      .Case("version", SourceKitRequest::ProtocolVersion)
                      .Case("demangle", SourceKitRequest::DemangleNames)
                      .Case("mangle", SourceKitRequest::MangleSimpleClasses)
                      .Case("index", SourceKitRequest::Index)
                      .Case("complete", SourceKitRequest::CodeComplete)
                      .Case("complete.open", SourceKitRequest::CodeCompleteOpen)
                      .Case("complete.close", SourceKitRequest::CodeCompleteClose)
                      .Case("complete.update", SourceKitRequest::CodeCompleteUpdate)
                      .Case("complete.cache.ondisk", SourceKitRequest::CodeCompleteCacheOnDisk)
                      .Case("complete.setpopularapi", SourceKitRequest::CodeCompleteSetPopularAPI)
                      .Case("cursor", SourceKitRequest::CursorInfo)
                      .Case("related-idents", SourceKitRequest::RelatedIdents)
                      .Case("syntax-map", SourceKitRequest::SyntaxMap)
                      .Case("structure", SourceKitRequest::Structure)
                      .Case("format", SourceKitRequest::Format)
                      .Case("expand-placeholder", SourceKitRequest::ExpandPlaceholder)
                      .Case("doc-info", SourceKitRequest::DocInfo)
                      .Case("sema", SourceKitRequest::SemanticInfo)
                      .Case("interface-gen", SourceKitRequest::InterfaceGen)
                      .Case("interface-gen-open", SourceKitRequest::InterfaceGenOpen)
                      .Case("find-usr", SourceKitRequest::FindUSR)
                      .Case("find-interface", SourceKitRequest::FindInterfaceDoc)
                      .Case("open", SourceKitRequest::Open)
                      .Case("edit", SourceKitRequest::Edit)
                      .Case("print-annotations", SourceKitRequest::PrintAnnotations)
                      .Case("print-diags", SourceKitRequest::PrintDiags)
                      .Case("extract-comment", SourceKitRequest::ExtractComment)
                      .Case("module-groups", SourceKitRequest::ModuleGroups)
                      .Default(SourceKitRequest::None);
            if (Request == SourceKitRequest::None) {
                llvm::errs() << "error: invalid request, expected one of "
                             << "version/demangle/mangle/index/complete/cursor/related-idents/syntax-map/structure/"
                             "format/expand-placeholder/doc-info/sema/interface-gen/interface-gen-open/"
                             "find-usr/find-interface/open/edit/print-annotations/extract-comment/"
                             "module-groups\n";
                return true;
            }
            break;

        case OPT_offset:
            if (StringRef(InputArg->getValue()).getAsInteger(10, Offset)) {
                llvm::errs() << "error: expected integer for 'offset'\n";
                return true;
            }
            break;

        case OPT_length:
            if (StringRef(InputArg->getValue()).getAsInteger(10, Length)) {
                llvm::errs() << "error: expected integer for 'length'\n";
                return true;
            }
            break;

        case OPT_pos: {
            auto linecol = parseLineCol(InputArg->getValue());
            Line = linecol.first;
            Col = linecol.second;
            break;
        }

        case OPT_line:
            if (StringRef(InputArg->getValue()).getAsInteger(10, Line)) {
                llvm::errs() << "error: expected integer for 'line'\n";
                return true;
            }
            Col = 1;
            break;

        case OPT_replace:
            ReplaceText = InputArg->getValue();
            break;

        case OPT_module:
            ModuleName = InputArg->getValue();
            break;

        case OPT_group_name:
            ModuleGroupName = InputArg->getValue();
            break;

        case OPT_header:
            HeaderPath = InputArg->getValue();
            break;

        case OPT_text_input:
            TextInputFile = InputArg->getValue();
            break;

        case OPT_usr:
            USR = InputArg->getValue();
            break;

        case OPT_pass_as_sourcetext:
            PassAsSourceText = true;
            break;

        case OPT_cache_path:
            CachePath = InputArg->getValue();
            break;

        case OPT_req_opts:
            for (auto item : InputArg->getValues())
                RequestOptions.push_back(item);
            break;

        case OPT_check_interface_is_ascii:
            CheckInterfaceIsASCII = true;
            break;

        case OPT_print_response_as_json:
            PrintResponseAsJSON = true;
            break;

        case OPT_INPUT:
            SourceFile = InputArg->getValue();
            SourceText = llvm::None;
            Inputs.push_back(InputArg->getValue());
            break;

        case OPT_json_request_path:
            JsonRequestPath = InputArg->getValue();
            break;

        case OPT_simplified_demangling:
            SimplifiedDemangling = true;
            break;

        case OPT_synthesized_extension:
            SynthesizedExtensions = true;
            break;

        case OPT_UNKNOWN:
            llvm::errs() << "error: unknown argument: "
                         << InputArg->getAsString(ParsedArgs) << '\n';
            return true;
        }
    }

    return false;
}
Exemplo n.º 11
0
void BuildSystemInvocation::parse(llvm::ArrayRef<std::string> args,
                                  llvm::SourceMgr& sourceMgr) {
  auto error = [&](const Twine &message) {
    sourceMgr.PrintMessage(llvm::SMLoc{}, llvm::SourceMgr::DK_Error, message);
    hadErrors = true;
  };

  while (!args.empty()) {
    const auto& option = args.front();
    args = args.slice(1);

    if (option == "-") {
      for (const auto& arg: args) {
        positionalArgs.push_back(arg);
      }
      break;
    }

    if (!option.empty() && option[0] != '-') {
      positionalArgs.push_back(option);
      continue;
    }
    
    if (option == "--help") {
      showUsage = true;
      break;
    } else if (option == "--version") {
      showVersion = true;
      break;
    } else if (option == "--no-db") {
      dbPath = "";
    } else if (option == "--db") {
      if (args.empty()) {
        error("missing argument to '" + option + "'");
        break;
      }
      dbPath = args[0];
      args = args.slice(1);
    } else if (option == "-C" || option == "--chdir") {
      if (args.empty()) {
        error("missing argument to '" + option + "'");
        break;
      }
      chdirPath = args[0];
      args = args.slice(1);
    } else if (option == "-f") {
      if (args.empty()) {
        error("missing argument to '" + option + "'");
        break;
      }
      buildFilePath = args[0];
      args = args.slice(1);
    } else if (option == "--serial") {
      useSerialBuild = true;
    } else if (option == "-v" || option == "--verbose") {
      showVerboseStatus = true;
    } else if (option == "--trace") {
      if (args.empty()) {
        error("missing argument to '" + option + "'");
        break;
      }
      traceFilePath = args[0];
      args = args.slice(1);
    } else {
      error("invalid option '" + option + "'");
      break;
    }
  }
}
Exemplo n.º 12
0
Arquivo: loader.cpp Projeto: Blei/clay
static void initModule(ModulePtr m, llvm::ArrayRef<string>  importChain) {
    if (m->initState == Module::DONE) return;

    if (m->declaration != NULL) {
        if (m->moduleName == "")
            m->moduleName = toKey(m->declaration->name);
        else if (m->moduleName != toKey(m->declaration->name))
            error(m->declaration,
                "module imported by name " + m->moduleName
                + " but declared with name " + toKey(m->declaration->name)
            );
    } else if (m->moduleName == "")
        m->moduleName = "__main__";


    if (m->initState == Module::RUNNING && !importChain.empty()) {
        // allow prelude to import self
        if (importChain.back() == m->moduleName) {
            return;
        }
    }

    vector<string> importChainNext = importChain;
    importChainNext.push_back(m->moduleName);

    if (m->initState == Module::RUNNING) {
        circularImportsError(importChainNext);
    }

    m->initState = Module::RUNNING;

    vector<ImportPtr>::iterator ii, iend;
    for (ii = m->imports.begin(), iend = m->imports.end(); ii != iend; ++ii)
        initModule((*ii)->module, importChainNext);

    m->initState = Module::DONE;

    verifyAttributes(m);

    llvm::ArrayRef<TopLevelItemPtr> items = m->topLevelItems;
    TopLevelItemPtr const *ti, *tend;
    for (ti = items.begin(), tend = items.end(); ti != tend; ++ti) {
        Object *obj = ti->ptr();
        switch (obj->objKind) {
        case OVERLOAD :
            initOverload((Overload *)obj);
            break;
        case INSTANCE_DECL :
            initVariantInstance((InstanceDecl *)obj);
            break;
        case STATIC_ASSERT_TOP_LEVEL:
            checkStaticAssert((StaticAssertTopLevel *)obj);
            break;
        default:
            break;
        }
    }

    if (llvmDIBuilder != NULL) {
        llvm::DIFile file = m->location.ok()
            ? m->location.source->getDebugInfo()
            : llvm::DIFile(NULL);
        m->debugInfo = (llvm::MDNode*)llvmDIBuilder->createNameSpace(
            llvm::DICompileUnit(llvmDIBuilder->getCU()), // scope
            m->moduleName, // name
            file, // file
            1 // line
            );
    }
}
Exemplo n.º 13
0
llvm::Error AllTUsToolExecutor::execute(
    llvm::ArrayRef<
        std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>>
        Actions) {
  if (Actions.empty())
    return make_string_error("No action to execute.");

  if (Actions.size() != 1)
    return make_string_error(
        "Only support executing exactly 1 action at this point.");

  std::string ErrorMsg;
  std::mutex TUMutex;
  auto AppendError = [&](llvm::Twine Err) {
    std::unique_lock<std::mutex> LockGuard(TUMutex);
    ErrorMsg += Err.str();
  };

  auto Log = [&](llvm::Twine Msg) {
    std::unique_lock<std::mutex> LockGuard(TUMutex);
    llvm::errs() << Msg.str() << "\n";
  };

  std::vector<std::string> Files;
  llvm::Regex RegexFilter(Filter);
  for (const auto& File : Compilations.getAllFiles()) {
    if (RegexFilter.match(File))
      Files.push_back(File);
  }
  // Add a counter to track the progress.
  const std::string TotalNumStr = std::to_string(Files.size());
  unsigned Counter = 0;
  auto Count = [&]() {
    std::unique_lock<std::mutex> LockGuard(TUMutex);
    return ++Counter;
  };

  auto &Action = Actions.front();

  {
    llvm::ThreadPool Pool(ThreadCount == 0 ? llvm::hardware_concurrency()
                                           : ThreadCount);
    llvm::SmallString<128> InitialWorkingDir;
    if (auto EC = llvm::sys::fs::current_path(InitialWorkingDir)) {
      InitialWorkingDir = "";
      llvm::errs() << "Error while getting current working directory: "
                   << EC.message() << "\n";
    }
    for (std::string File : Files) {
      Pool.async(
          [&](std::string Path) {
            Log("[" + std::to_string(Count()) + "/" + TotalNumStr +
                "] Processing file " + Path);
            ClangTool Tool(Compilations, {Path});
            Tool.appendArgumentsAdjuster(Action.second);
            Tool.appendArgumentsAdjuster(getDefaultArgumentsAdjusters());
            for (const auto &FileAndContent : OverlayFiles)
              Tool.mapVirtualFile(FileAndContent.first(),
                                  FileAndContent.second);
            // Do not restore working dir from multiple threads to avoid races.
            Tool.setRestoreWorkingDir(false);
            if (Tool.run(Action.first.get()))
              AppendError(llvm::Twine("Failed to run action on ") + Path +
                          "\n");
          },
          File);
    }
    // Make sure all tasks have finished before resetting the working directory.
    Pool.wait();
    if (!InitialWorkingDir.empty()) {
      if (auto EC = llvm::sys::fs::set_current_path(InitialWorkingDir))
        llvm::errs() << "Error while restoring working directory: "
                     << EC.message() << "\n";
    }
  }

  if (!ErrorMsg.empty())
    return make_string_error(ErrorMsg);

  return llvm::Error::success();
}
Exemplo n.º 14
0
StatementPtr desugarCatchBlocks(llvm::ArrayRef<CatchPtr> catchBlocks,
                                CompilerState* cst) {
    assert(!catchBlocks.empty());
    Location firstCatchLocation = catchBlocks.front()->location;
    IdentifierPtr expVar = Identifier::get("%exp", firstCatchLocation);

    CallPtr activeException = new Call(primitive_expr_activeException(cst), new ExprList());
    activeException->location = firstCatchLocation;

    BindingPtr expBinding =
        new Binding(VAR,
                    identVtoFormalV(vector<IdentifierPtr>(1, expVar)),
                    new ExprList(activeException.ptr()));
    expBinding->location = firstCatchLocation;

    bool lastWasAny = false;
    IfPtr lastIf;
    StatementPtr result;
    for (size_t i = 0; i < catchBlocks.size(); ++i) {
        CatchPtr x = catchBlocks[i];
        if (lastWasAny)
            error(x, "unreachable catch block");
        if (x->exceptionType.ptr()) {
            ExprListPtr asTypeArgs = new ExprList(x->exceptionType);
            ExprPtr expVarName = new NameRef(expVar);
            expVarName->location = x->exceptionVar->location;
            asTypeArgs->add(expVarName);
            CallPtr cond = new Call(operator_expr_exceptionIsP(cst), asTypeArgs);
            cond->location = x->exceptionType->location;

            BlockPtr block = new Block();
            block->location = x->location;

            vector<IdentifierPtr> identifiers;
            makeExceptionVars(identifiers, x);

            CallPtr getter = new Call(operator_expr_exceptionAs(cst), asTypeArgs);
            getter->location = x->exceptionVar->location;
            BindingPtr binding =
                new Binding(VAR,
                            identVtoFormalV(identifiers),
                            new ExprList(getter.ptr()));
            binding->location = x->exceptionVar->location;

            BindingPtr exceptionVarForRethrow =
                new Binding(REF,
                            identVtoFormalV(vector<IdentifierPtr>(1, Identifier::get("%exception", x->location))),
                            new ExprList(new NameRef(Identifier::get(x->exceptionVar->str, x->location))));
            exceptionVarForRethrow->location = x->exceptionVar->location;

            block->statements.push_back(binding.ptr());
            block->statements.push_back(exceptionVarForRethrow.ptr());
            block->statements.push_back(x->body);

            IfPtr ifStatement = new If(cond.ptr(), block.ptr());
            ifStatement->location = x->location;
            if (!result)
                result = ifStatement.ptr();
            if (lastIf.ptr())
                lastIf->elsePart = ifStatement.ptr();
            lastIf = ifStatement;
        }
        else {
            BlockPtr block = new Block();
            block->location = x->location;

            vector<IdentifierPtr> identifiers;
            makeExceptionVars(identifiers, x);

            ExprListPtr asAnyArgs = new ExprList(new NameRef(expVar));
            CallPtr getter = new Call(operator_expr_exceptionAsAny(cst),
                                      asAnyArgs);
            getter->location = x->exceptionVar->location;
            BindingPtr binding =
                new Binding(VAR,
                            identVtoFormalV(identifiers),
                            new ExprList(getter.ptr()));
            binding->location = x->exceptionVar->location;

            BindingPtr exceptionVarForRethrow =
                new Binding(REF,
                            identVtoFormalV(vector<IdentifierPtr>(1, Identifier::get("%exception", x->location))),
                            new ExprList(new NameRef(Identifier::get(x->exceptionVar->str, x->location))));
            exceptionVarForRethrow->location = x->exceptionVar->location;

            block->statements.push_back(binding.ptr());
            block->statements.push_back(exceptionVarForRethrow.ptr());
            block->statements.push_back(x->body);

            if (!result)
                result = block.ptr();
            if (lastIf.ptr())
                lastIf->elsePart = block.ptr();

            lastWasAny = true;
            lastIf = NULL;
        }
    }
    assert(result.ptr());
    if (!lastWasAny) {
        assert(lastIf.ptr());
        BlockPtr block = new Block();
        block->location = firstCatchLocation;
        ExprPtr expVarName = new NameRef(expVar);
        expVarName->location = firstCatchLocation;
        ExprListPtr continueArgs = new ExprList(expVarName);
        CallPtr continueException = new Call(operator_expr_continueException(cst),
                                             continueArgs);
        continueException->location = firstCatchLocation;
        StatementPtr stmt = new ExprStatement(continueException.ptr());
        stmt->location = firstCatchLocation;
        block->statements.push_back(stmt);
        block->statements.push_back(new Unreachable());
        lastIf->elsePart = block.ptr();
    }

    BlockPtr block = new Block();
    block->location = firstCatchLocation;
    block->statements.push_back(expBinding.ptr());
    block->statements.push_back(result.ptr());

    return block.ptr();
}
Exemplo n.º 15
0
bool TestOptions::parseArgs(llvm::ArrayRef<const char *> Args) {
  if (Args.empty())
    return false;

  // Parse command line options using Options.td
  TestOptTable Table;
  unsigned MissingIndex;
  unsigned MissingCount;
  llvm::opt::InputArgList ParsedArgs =
      Table.ParseArgs(Args, MissingIndex, MissingCount);
  if (MissingCount) {
    llvm::errs() << "error: missing argument value for '"
        << ParsedArgs.getArgString(MissingIndex) << "', expected "
        << MissingCount << " argument(s)\n";
    return true;
  }

  for (auto InputArg : ParsedArgs) {
    switch (InputArg->getOption().getID()) {
    case OPT_req:
      Request = llvm::StringSwitch<SourceKitRequest>(InputArg->getValue())
        .Case("version", SourceKitRequest::ProtocolVersion)
        .Case("demangle", SourceKitRequest::DemangleNames)
        .Case("mangle", SourceKitRequest::MangleSimpleClasses)
        .Case("index", SourceKitRequest::Index)
        .Case("complete", SourceKitRequest::CodeComplete)
        .Case("complete.open", SourceKitRequest::CodeCompleteOpen)
        .Case("complete.close", SourceKitRequest::CodeCompleteClose)
        .Case("complete.update", SourceKitRequest::CodeCompleteUpdate)
        .Case("complete.cache.ondisk", SourceKitRequest::CodeCompleteCacheOnDisk)
        .Case("complete.setpopularapi", SourceKitRequest::CodeCompleteSetPopularAPI)
        .Case("cursor", SourceKitRequest::CursorInfo)
        .Case("related-idents", SourceKitRequest::RelatedIdents)
        .Case("syntax-map", SourceKitRequest::SyntaxMap)
        .Case("syntax-tree", SourceKitRequest::SyntaxTree)
        .Case("structure", SourceKitRequest::Structure)
        .Case("format", SourceKitRequest::Format)
        .Case("expand-placeholder", SourceKitRequest::ExpandPlaceholder)
        .Case("doc-info", SourceKitRequest::DocInfo)
        .Case("sema", SourceKitRequest::SemanticInfo)
        .Case("interface-gen", SourceKitRequest::InterfaceGen)
        .Case("interface-gen-open", SourceKitRequest::InterfaceGenOpen)
        .Case("find-usr", SourceKitRequest::FindUSR)
        .Case("find-interface", SourceKitRequest::FindInterfaceDoc)
        .Case("open", SourceKitRequest::Open)
        .Case("close", SourceKitRequest::Close)
        .Case("edit", SourceKitRequest::Edit)
        .Case("print-annotations", SourceKitRequest::PrintAnnotations)
        .Case("print-diags", SourceKitRequest::PrintDiags)
        .Case("extract-comment", SourceKitRequest::ExtractComment)
        .Case("module-groups", SourceKitRequest::ModuleGroups)
        .Case("range", SourceKitRequest::RangeInfo)
        .Case("syntactic-rename", SourceKitRequest::SyntacticRename)
        .Case("find-rename-ranges", SourceKitRequest::FindRenameRanges)
        .Case("find-local-rename-ranges", SourceKitRequest::FindLocalRenameRanges)
        .Case("translate", SourceKitRequest::NameTranslation)
        .Case("local-rename", SourceKitRequest::LocalRename)
        .Case("extract-expr", SourceKitRequest::ExtractExpr)
        .Case("extract-repeated", SourceKitRequest::ExtractRepeatedExpr)
        .Case("extract-func", SourceKitRequest::ExtractFunction)
        .Case("fill-stub", SourceKitRequest::FillProtocolStub)
        .Case("expand-default", SourceKitRequest::ExpandDefault)
        .Case("localize-string", SourceKitRequest::LocalizeString)
        .Case("markup-xml", SourceKitRequest::MarkupToXML)
        .Case("stats", SourceKitRequest::Statistics)
        .Case("track-compiles", SourceKitRequest::EnableCompileNotifications)
        .Default(SourceKitRequest::None);

      if (Request == SourceKitRequest::None) {
        llvm::errs() << "error: invalid request '" << InputArg->getValue()
            << "'\nexpected one of "
            << "version/demangle/mangle/index/complete/complete.open/complete.cursor/"
               "complete.update/complete.cache.ondisk/complete.cache.setpopularapi/"
               "cursor/related-idents/syntax-map/structure/format/expand-placeholder/"
               "doc-info/sema/interface-gen/interface-gen-openfind-usr/find-interface/"
               "open/close/edit/print-annotations/print-diags/extract-comment/module-groups/"
               "range/syntactic-rename/find-rename-ranges/translate/markup-xml/stats/"
               "track-compiles\n";
        return true;
      }
      break;

    case OPT_help: {
      printHelp(false);
      return true;
    }

    case OPT_offset:
      if (StringRef(InputArg->getValue()).getAsInteger(10, Offset)) {
        llvm::errs() << "error: expected integer for 'offset'\n";
        return true;
      }
      break;

    case OPT_length:
      if (StringRef(InputArg->getValue()).getAsInteger(10, Length)) {
        llvm::errs() << "error: expected integer for 'length'\n";
        return true;
      }
      break;

    case OPT_pos: {
      auto linecol = parseLineCol(InputArg->getValue());
      Line = linecol.first;
      Col = linecol.second;
      break;
    }

    case OPT_end_pos: {
      auto linecol = parseLineCol(InputArg->getValue());
      EndLine = linecol.first;
      EndCol = linecol.second;
      break;
    }

    case OPT_using_swift_args: {
      UsingSwiftArgs = true;
      break;
    }

    case OPT_swift_version:
      SwiftVersion = InputArg->getValue();
      break;

    case OPT_pass_version_as_string:
      PassVersionAsString = true;
      break;

    case OPT_line:
      if (StringRef(InputArg->getValue()).getAsInteger(10, Line)) {
        llvm::errs() << "error: expected integer for 'line'\n";
        return true;
      }
      Col = 1;
      break;

    case OPT_replace:
      ReplaceText = InputArg->getValue();
      break;

    case OPT_module:
      ModuleName = InputArg->getValue();
      break;

    case OPT_group_name:
      ModuleGroupName = InputArg->getValue();
      break;

    case OPT_interested_usr:
      InterestedUSR = InputArg->getValue();
      break;

    case OPT_header:
      HeaderPath = InputArg->getValue();
      break;

    case OPT_text_input:
      TextInputFile = InputArg->getValue();
      break;

    case OPT_usr:
      USR = InputArg->getValue();
      break;

    case OPT_pass_as_sourcetext:
      PassAsSourceText = true;
      break;

    case OPT_cache_path:
      CachePath = InputArg->getValue();
      break;

    case OPT_req_opts:
      for (auto item : InputArg->getValues())
        RequestOptions.push_back(item);
      break;

    case OPT_check_interface_is_ascii:
      CheckInterfaceIsASCII = true;
      break;

    case OPT_dont_print_request:
      PrintRequest = false;
      break;

    case OPT_print_response_as_json:
      PrintResponseAsJSON = true;
      break;

    case OPT_print_raw_response:
      PrintRawResponse = true;
      break;

    case OPT_dont_print_response:
      PrintResponse = false;
      break;

    case OPT_INPUT:
      SourceFile = InputArg->getValue();
      SourceText = llvm::None;
      Inputs.push_back(InputArg->getValue());
      break;

    case OPT_rename_spec:
      RenameSpecPath = InputArg->getValue();
      break;

    case OPT_json_request_path:
      JsonRequestPath = InputArg->getValue();
      break;

    case OPT_simplified_demangling:
      SimplifiedDemangling = true;
      break;

    case OPT_synthesized_extension:
      SynthesizedExtensions = true;
      break;

    case OPT_async:
      isAsyncRequest = true;
      break;

    case OPT_cursor_action:
      CollectActionables = true;
      break;

    case OPT_swift_name:
      SwiftName = InputArg->getValue();
      break;

    case OPT_objc_name:
      ObjCName = InputArg->getValue();
      break;

    case OPT_objc_selector:
      ObjCSelector = InputArg->getValue();
      break;

    case OPT_name:
      Name = InputArg->getValue();
      break;

    case OPT_cancel_on_subsequent_request:
      unsigned Cancel;
      if (StringRef(InputArg->getValue()).getAsInteger(10, Cancel)) {
        llvm::errs() << "error: expected integer for 'cancel-on-subsequent-request'\n";
        return true;
      }
      CancelOnSubsequentRequest = Cancel;
      break;

    case OPT_time_request:
      timeRequest = true;
      break;

    case OPT_repeat_request:
      if (StringRef(InputArg->getValue()).getAsInteger(10, repeatRequest)) {
        llvm::errs() << "error: expected integer for 'cancel-on-subsequent-request'\n";
        return true;
      } else if (repeatRequest < 1) {
        llvm::errs() << "error: repeat-request must be >= 1\n";
        return true;
      }
      break;

    case OPT_UNKNOWN:
      llvm::errs() << "error: unknown argument: "
                   << InputArg->getAsString(ParsedArgs) << '\n'
                   << "Use -h or -help for assistance" << '\n';
      return true;
    }
  }

  if (Request == SourceKitRequest::InterfaceGenOpen && isAsyncRequest) {
    llvm::errs()
        << "error: cannot use -async with interface-gen-open request\n";
    return true;
  }

  return false;
}