InputArgList *OptTable::ParseArgs(const char* const *ArgBegin, const char* const *ArgEnd, unsigned &MissingArgIndex, unsigned &MissingArgCount) const { InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); // FIXME: Handle '@' args (or at least error on them). MissingArgIndex = MissingArgCount = 0; unsigned Index = 0, End = ArgEnd - ArgBegin; while (Index < End) { // Ignore empty arguments (other things may still take them as arguments). if (Args->getArgString(Index)[0] == '\0') { ++Index; continue; } unsigned Prev = Index; Arg *A = ParseOneArg(*Args, Index); assert(Index > Prev && "Parser failed to consume argument."); // Check for missing argument error. if (!A) { assert(Index >= End && "Unexpected parser error."); assert(Index - Prev - 1 && "No missing arguments!"); MissingArgIndex = Prev; MissingArgCount = Index - Prev - 1; break; } Args->append(A); } return Args; }
InputArgList *Driver::ParseArgStrings(const char **ArgBegin, const char **ArgEnd) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); InputArgList *Args = new InputArgList(ArgBegin, ArgEnd); // FIXME: Handle '@' args (or at least error on them). unsigned Index = 0, End = ArgEnd - ArgBegin; while (Index < End) { // gcc's handling of empty arguments doesn't make // sense, but this is not a common use case. :) // // We just ignore them here (note that other things may // still take them as arguments). if (Args->getArgString(Index)[0] == '\0') { ++Index; continue; } unsigned Prev = Index; Arg *A = getOpts().ParseOneArg(*Args, Index); assert(Index > Prev && "Parser failed to consume argument."); // Check for missing argument error. if (!A) { assert(Index >= End && "Unexpected parser error."); Diag(clang::diag::err_drv_missing_argument) << Args->getArgString(Prev) << (Index - Prev - 1); break; } if (A->getOption().isUnsupported()) { Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; } Args->append(A); } return Args; }
InputArgList *Driver::ParseArgStrings(const char **ArgBegin, const char **ArgEnd) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); unsigned MissingArgIndex, MissingArgCount; InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount); // Check for missing argument error. if (MissingArgCount) Diag(clang::diag::err_drv_missing_argument) << Args->getArgString(MissingArgIndex) << MissingArgCount; // Check for unsupported options. for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); it != ie; ++it) { Arg *A = *it; if (A->getOption().isUnsupported()) { Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; } } return Args; }
// FIXME: Define the need for this testing away. static int cc1_test(Diagnostic &Diags, const char **ArgBegin, const char **ArgEnd) { using namespace clang::driver; llvm::errs() << "cc1 argv:"; for (const char **i = ArgBegin; i != ArgEnd; ++i) llvm::errs() << " \"" << *i << '"'; llvm::errs() << "\n"; // Parse the arguments. OptTable *Opts = createCC1OptTable(); unsigned MissingArgIndex, MissingArgCount; InputArgList *Args = Opts->ParseArgs(ArgBegin, ArgEnd, MissingArgIndex, MissingArgCount); // Check for missing argument error. if (MissingArgCount) Diags.Report(clang::diag::err_drv_missing_argument) << Args->getArgString(MissingArgIndex) << MissingArgCount; // Dump the parsed arguments. llvm::errs() << "cc1 parsed options:\n"; for (ArgList::const_iterator it = Args->begin(), ie = Args->end(); it != ie; ++it) (*it)->dump(); // Create a compiler invocation. llvm::errs() << "cc1 creating invocation.\n"; CompilerInvocation Invocation; CompilerInvocation::CreateFromArgs(Invocation, ArgBegin, ArgEnd, Diags); // Convert the invocation back to argument strings. std::vector<std::string> InvocationArgs; Invocation.toArgs(InvocationArgs); // Dump the converted arguments. SmallVector<const char*, 32> Invocation2Args; llvm::errs() << "invocation argv :"; for (unsigned i = 0, e = InvocationArgs.size(); i != e; ++i) { Invocation2Args.push_back(InvocationArgs[i].c_str()); llvm::errs() << " \"" << InvocationArgs[i] << '"'; } llvm::errs() << "\n"; // Convert those arguments to another invocation, and check that we got the // same thing. CompilerInvocation Invocation2; CompilerInvocation::CreateFromArgs(Invocation2, Invocation2Args.begin(), Invocation2Args.end(), Diags); // FIXME: Implement CompilerInvocation comparison. if (true) { //llvm::errs() << "warning: Invocations differ!\n"; std::vector<std::string> Invocation2Args; Invocation2.toArgs(Invocation2Args); llvm::errs() << "invocation2 argv:"; for (unsigned i = 0, e = Invocation2Args.size(); i != e; ++i) llvm::errs() << " \"" << Invocation2Args[i] << '"'; llvm::errs() << "\n"; } return 0; }
bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, ArrayRef<const char *> Argv, DiagnosticsEngine &Diags) { bool Success = true; // Parse the arguments. std::unique_ptr<OptTable> OptTbl(createDriverOptTable()); const unsigned IncludedFlagsBitmask = options::CC1AsOption; unsigned MissingArgIndex, MissingArgCount; InputArgList Args = OptTbl->ParseArgs(Argv, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask); // Check for missing argument error. if (MissingArgCount) { Diags.Report(diag::err_drv_missing_argument) << Args.getArgString(MissingArgIndex) << MissingArgCount; Success = false; } // Issue errors on unknown arguments. for (const Arg *A : Args.filtered(OPT_UNKNOWN)) { auto ArgString = A->getAsString(Args); std::string Nearest; if (OptTbl->findNearest(ArgString, Nearest, IncludedFlagsBitmask) > 1) Diags.Report(diag::err_drv_unknown_argument) << ArgString; else Diags.Report(diag::err_drv_unknown_argument_with_suggestion) << ArgString << Nearest; Success = false; } // Construct the invocation. // Target Options Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); Opts.CPU = Args.getLastArgValue(OPT_target_cpu); Opts.Features = Args.getAllArgValues(OPT_target_feature); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); // Language Options Opts.IncludePaths = Args.getAllArgValues(OPT_I); Opts.NoInitialTextSection = Args.hasArg(OPT_n); Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels); // Any DebugInfoKind implies GenDwarfForAssembly. Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ); if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections, OPT_compress_debug_sections_EQ)) { if (A->getOption().getID() == OPT_compress_debug_sections) { // TODO: be more clever about the compression type auto-detection Opts.CompressDebugSections = llvm::DebugCompressionType::GNU; } else { Opts.CompressDebugSections = llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue()) .Case("none", llvm::DebugCompressionType::None) .Case("zlib", llvm::DebugCompressionType::Z) .Case("zlib-gnu", llvm::DebugCompressionType::GNU) .Default(llvm::DebugCompressionType::None); } } Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); // Frontend Options if (Args.hasArg(OPT_INPUT)) { bool First = true; for (const Arg *A : Args.filtered(OPT_INPUT)) { if (First) { Opts.InputFile = A->getValue(); First = false; } else { Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args); Success = false; } } } Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); Opts.OutputPath = Args.getLastArgValue(OPT_o); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); if (Arg *A = Args.getLastArg(OPT_filetype)) { StringRef Name = A->getValue(); unsigned OutputType = StringSwitch<unsigned>(Name) .Case("asm", FT_Asm) .Case("null", FT_Null) .Case("obj", FT_Obj) .Default(~0U); if (OutputType == ~0U) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else Opts.OutputType = FileType(OutputType); } Opts.ShowHelp = Args.hasArg(OPT_help); Opts.ShowVersion = Args.hasArg(OPT_version); // Transliterate Options Opts.OutputAsmVariant = getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags); Opts.ShowEncoding = Args.hasArg(OPT_show_encoding); Opts.ShowInst = Args.hasArg(OPT_show_inst); // Assemble Options Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); Opts.IncrementalLinkerCompatible = Args.hasArg(OPT_mincremental_linker_compatible); Opts.SymbolDefs = Args.getAllArgValues(OPT_defsym); // EmbedBitcode Option. If -fembed-bitcode is enabled, set the flag. // EmbedBitcode behaves the same for all embed options for assembly files. if (auto *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) { Opts.EmbedBitcode = llvm::StringSwitch<unsigned>(A->getValue()) .Case("all", 1) .Case("bitcode", 1) .Case("marker", 1) .Default(0); } return Success; }
bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, ArrayRef<const char *> Argv, DiagnosticsEngine &Diags) { bool Success = true; // Parse the arguments. std::unique_ptr<OptTable> OptTbl(createDriverOptTable()); const unsigned IncludedFlagsBitmask = options::CC1AsOption; unsigned MissingArgIndex, MissingArgCount; InputArgList Args = OptTbl->ParseArgs(Argv, MissingArgIndex, MissingArgCount, IncludedFlagsBitmask); // Check for missing argument error. if (MissingArgCount) { Diags.Report(diag::err_drv_missing_argument) << Args.getArgString(MissingArgIndex) << MissingArgCount; Success = false; } // Issue errors on unknown arguments. for (const Arg *A : Args.filtered(OPT_UNKNOWN)) { Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args); Success = false; } // Construct the invocation. // Target Options Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); Opts.CPU = Args.getLastArgValue(OPT_target_cpu); Opts.Features = Args.getAllArgValues(OPT_target_feature); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); // Language Options Opts.IncludePaths = Args.getAllArgValues(OPT_I); Opts.NoInitialTextSection = Args.hasArg(OPT_n); Opts.SaveTemporaryLabels = Args.hasArg(OPT_msave_temp_labels); // Any DebugInfoKind implies GenDwarfForAssembly. Opts.GenDwarfForAssembly = Args.hasArg(OPT_debug_info_kind_EQ); Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 2, Diags); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.DwarfDebugProducer = Args.getLastArgValue(OPT_dwarf_debug_producer); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); // Frontend Options if (Args.hasArg(OPT_INPUT)) { bool First = true; for (arg_iterator it = Args.filtered_begin(OPT_INPUT), ie = Args.filtered_end(); it != ie; ++it, First = false) { const Arg *A = it; if (First) Opts.InputFile = A->getValue(); else { Diags.Report(diag::err_drv_unknown_argument) << A->getAsString(Args); Success = false; } } } Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm); Opts.OutputPath = Args.getLastArgValue(OPT_o); if (Arg *A = Args.getLastArg(OPT_filetype)) { StringRef Name = A->getValue(); unsigned OutputType = StringSwitch<unsigned>(Name) .Case("asm", FT_Asm) .Case("null", FT_Null) .Case("obj", FT_Obj) .Default(~0U); if (OutputType == ~0U) { Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; Success = false; } else Opts.OutputType = FileType(OutputType); } Opts.ShowHelp = Args.hasArg(OPT_help); Opts.ShowVersion = Args.hasArg(OPT_version); // Transliterate Options Opts.OutputAsmVariant = getLastArgIntValue(Args, OPT_output_asm_variant, 0, Diags); Opts.ShowEncoding = Args.hasArg(OPT_show_encoding); Opts.ShowInst = Args.hasArg(OPT_show_inst); // Assemble Options Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.NoExecStack = Args.hasArg(OPT_mno_exec_stack); Opts.FatalWarnings = Args.hasArg(OPT_massembler_fatal_warnings); Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); Opts.IncrementalLinkerCompatible = Args.hasArg(OPT_mincremental_linker_compatible); return Success; }