Index: include/llvm/Option/OptTable.h =================================================================== --- include/llvm/Option/OptTable.h +++ include/llvm/Option/OptTable.h @@ -147,11 +147,33 @@ /// Zero is the default which includes all flags. /// \param FlagsToExclude - Don't parse options with this flag. Zero /// is the default and means exclude nothing. + /// \param IndexToTranslate - If not null, points to the index of option in + /// \c Args, on exit provides index of corresponding element in the returned + /// array. /// \return An InputArgList; on error this will contain all the options /// which could be parsed. + /// + /// Argument \c IndexToTranslate is added to assist using configuration file. + /// It allows to determine correspondence between elements of \c Args that + /// came from configuration file and elements in the result list that + /// correspond to them. Due to options that require separate arguments these + /// numbers can be different. For instance, the two elements in \c Argc: + /// \verbatim + /// -triple x86_64-apple-darwin + /// \endverbatim + /// result in one argument. + /// + /// If \c IndexToTranslate is not null, the function expects it points to a + /// variable that contains index of the first element past the content of + /// config file. Upon exit this variable is assigned the index of + /// corresponding element in the result. If the last option in config file + /// requires separate argument and that argument is not provided in the file + /// (for instance, config file contains only \c -triple), the index is written + /// with negative sign. InputArgList ParseArgs(ArrayRef Args, unsigned &MissingArgIndex, unsigned &MissingArgCount, unsigned FlagsToInclude = 0, - unsigned FlagsToExclude = 0) const; + unsigned FlagsToExclude = 0, + int *IndexToTranslate = nullptr) const; /// \brief Render the help text for an option table. /// Index: lib/Option/OptTable.cpp =================================================================== --- lib/Option/OptTable.cpp +++ lib/Option/OptTable.cpp @@ -249,12 +249,16 @@ unsigned &MissingArgIndex, unsigned &MissingArgCount, unsigned FlagsToInclude, - unsigned FlagsToExclude) const { + unsigned FlagsToExclude, + int *IndexToTranslate) const { InputArgList Args(ArgArr.begin(), ArgArr.end()); // FIXME: Handle '@' args (or at least error on them). MissingArgIndex = MissingArgCount = 0; + unsigned ToTranslate = 0; + if (IndexToTranslate) + ToTranslate = static_cast(*IndexToTranslate); unsigned Index = 0, End = ArgArr.size(); while (Index < End) { // Ingore nullptrs, they are response file's EOL markers @@ -283,6 +287,17 @@ } Args.append(A); + + // Check if the index to translate is reached. + if (ToTranslate && Prev < ToTranslate) { + if (Index == ToTranslate) { + *IndexToTranslate = static_cast(Args.size()); + ToTranslate = 0; + } else if (Index > ToTranslate) { + *IndexToTranslate = -static_cast(Args.size()); + ToTranslate = 0; + } + } } return Args; Index: unittests/Option/OptionParsingTest.cpp =================================================================== --- unittests/Option/OptionParsingTest.cpp +++ unittests/Option/OptionParsingTest.cpp @@ -265,3 +265,38 @@ EXPECT_EQ(1U, AL.getAllArgValues(OPT_B).size()); EXPECT_EQ("", AL.getAllArgValues(OPT_B)[0]); } + +TEST(Option, IndexTranslation) { + TestOptTable T; + unsigned MAI, MAC; + + // Check that the number of config options successfully converted into the + // number of arguments. + const char *MyArgs[] = { "-A", "-C", "000", "-C", "foo", "-Bbar" }; + int Ndx = 5; + InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC, 0, 0, &Ndx); + EXPECT_EQ(AL.size(), 4U); + EXPECT_TRUE(AL.hasArg(OPT_A)); + EXPECT_TRUE(AL.hasArg(OPT_B)); + EXPECT_EQ("bar", AL.getLastArgValue(OPT_B)); + EXPECT_TRUE(AL.hasArg(OPT_C)); + EXPECT_EQ("foo", AL.getLastArgValue(OPT_C)); + EXPECT_EQ(Ndx, 3); +} + +TEST(Option, IndexTranslationWrong) { + TestOptTable T; + unsigned MAI, MAC; + + // Check that the the case when an option is split in the middle is detected. + const char *MyArgs[] = { "-A", "-C", "000", "-C", "foo", "-Bbar" }; + int Ndx = 4; + InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC, 0, 0, &Ndx); + EXPECT_EQ(AL.size(), 4U); + EXPECT_TRUE(AL.hasArg(OPT_A)); + EXPECT_TRUE(AL.hasArg(OPT_B)); + EXPECT_EQ("bar", AL.getLastArgValue(OPT_B)); + EXPECT_TRUE(AL.hasArg(OPT_C)); + EXPECT_EQ("foo", AL.getLastArgValue(OPT_C)); + EXPECT_EQ(Ndx, -3); +}