Repository: JuliaLang/julia
File: src/pipeline.cpp (C++)

Code before:

// Parse LLVM-style option string into PrintOptions using LLVM's tokenizer
void parseLLVMOptions(const char *options, PrintOptions &out) JL_NOTSAFEPOINT {
    if (!options || options[0] == '\0')
        return;

    // Tokenize the options string using LLVM's GNU command line tokenizer
    BumpPtrAllocator Alloc;
    StringSaver Saver(Alloc);
    SmallVector<const char *, 16> Argv;
    cl::TokenizeGNUCommandLine(options, Saver, Argv);

    // Process each token
    for (size_t i = 0; i < Argv.size(); ++i) {
        StringRef Arg(Argv[i]);

        if (Arg == "-print-after-all") {
            out.print_after_all = true;
        } else if (Arg == "-print-before-all") {
            out.print_before_all = true;
        } else if (Arg == "-print-module-scope") {
            out.print_module_scope = true;
        } else if (Arg == "-print-changed") {
            out.print_changed = true;
        } else if (Arg.starts_with("-print-after=")) {
            out.print_after = Arg.substr(13).str();
        } else if (Arg.starts_with("-print-before=")) {
            out.print_before = Arg.substr(14).str();
        } else if (Arg.starts_with("-filter-print-funcs=")) {
            out.filter_print_funcs = Arg.substr(20).str();
        } else {
            errs() << "Warning: unknown llvm_options flag: " << Arg << "\n";
        }
    }
}

NewPM::NewPM(std::unique_ptr<TargetMachine> TM, OptimizationLevel O, OptimizationOptions options, PrintOptions print_options) :
    TM(std::move(TM)), O(O), options(options), print_options(print_options), TimePasses() {}


NewPM::~NewPM() = default;

AnalysisManagers::AnalysisManagers(TargetMachine &TM, PassBuilder &PB, OptimizationLevel O) : LAM(), FAM(createFAM(O, TM)), CGAM(), MAM() {
    PB.registerLoopAnalyses(LAM);
    PB.registerFunctionAnalyses(FAM);
    PB.registerCGSCCAnalyses(CGAM);
    PB.registerModuleAnalyses(MAM);
    PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
}

AnalysisManagers::AnalysisManagers(PassBuilder &PB) : LAM(), FAM(), CGAM(), MAM() {

Review comment (suggestion):
```suggestion
        } else if (Arg.starts_with("-print-after=")) {
            out.print_after = Arg.substr(13).str();
        } else if (Arg == "-print-after") {
            out.print_after = std::string(Argv[++i]);
```
and so on, with bounds checking of course

Code after:

// Parse LLVM-style option string into PrintOptions using LLVM's tokenizer
void parseLLVMOptions(const char *options, PrintOptions &out) JL_NOTSAFEPOINT {
    if (!options || options[0] == '\0')
        return;

    // Tokenize the options string using LLVM's GNU command line tokenizer
    BumpPtrAllocator Alloc;
    StringSaver Saver(Alloc);
    SmallVector<const char *, 16> Argv;
    cl::TokenizeGNUCommandLine(options, Saver, Argv);

    // Helper to match an option and get its value
    // option should include trailing "=" (e.g., "-print-after=")
    // Returns the value if matched, empty StringRef if no match
    // Supports both "-option=value" and "-option value" syntax
    auto getNextValue = [&](size_t &idx, StringRef Arg, StringRef option) JL_NOTSAFEPOINT -> StringRef {
        StringRef optionName = option.drop_back(); // remove trailing "="
        // Check for "-option=value" syntax
        if (Arg.starts_with(option)) {
            return Arg.substr(option.size());
        }
        // Check for "-option value" syntax (exact match on option name)
        if (Arg == optionName) {
            if (idx + 1 < Argv.size()) {
                return StringRef(Argv[++idx]);
            }
            raw_string_ostream err_stream(out.error);
            err_stream << "Warning: " << optionName << " requires a value\n";
        }
        return StringRef();
    };

    // Helper to split a comma-separated value and append to a vector
    auto addCommaSeparated = [](SmallVector<std::string, 1> &vec, StringRef val) JL_NOTSAFEPOINT {
        SmallVector<StringRef, 4> parts;
        val.split(parts, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
        for (auto &part : parts) {
            vec.push_back(part.str());
        }
    };

    // Process each token
    for (size_t i = 0; i < Argv.size(); ++i) {
        StringRef Arg(Argv[i]);

        if (Arg == "-print-after-all") {
            out.print_after_all = true;
        } else if (Arg == "-print-before-all") {
            out.print_before_all = true;
        } else if (Arg == "-print-module-scope") {