This is an archive of the discontinued LLVM Phabricator instance.

Fix PR17239 by changing the semantics of the RemainingArgsClass Option kind
ClosedPublic

Authored by rafaelauler on Aug 13 2014, 10:17 PM.

Details

Summary

This patch contains the LLVM side of the fix of PR17239 (I will submit an additional patch for the clang side), a bug that happens because the /link (clang-cl.exe argument) is marked as "consume all remaining arguments". However, when inside a response file, /link should only consume all remaining arguments inside the response file where it is located, not the entire command line after expansion.

My patch will change the semantics of the RemainingArgsClass kind to always consume only until the end of the response file when the option originally came from a response file. There are only two options in this class: dash dash (--) and /link.

To do this, I had to change how response file expansion works in the CommandLine[.cpp|h] component. Now, the expansion returns not only the expanded argv vector, but also a vector with pairs of numbers that marks the first and last arguments that come from response files. With this information, I am able to fix this bug.

The problem is how to encapsulate this into a clean interface. To solve this, I created the ExpandedArgs class, which manages an argv vector after response files expansion. I was reluctant to implement a new class because Clang Driver already has ArgLists and InputInfos, that is, two other layers for input argument processing. However, ExpandedArgs was necessary as a first argv wrapper to manage (and keep correct) the response file indexes while driver.cpp (in clang) fiddles with the argument vector by adding/changing elements.

Diff Detail

Event Timeline

rafaelauler retitled this revision from to Fix PR17239 by changing the semantics of the RemainingArgsClass Option kind.
rafaelauler updated this object.
rafaelauler edited the test plan for this revision. (Show Details)
rafaelauler added a reviewer: rafael.
rafaelauler added a subscriber: Unknown Object (MLST).

The Clang side of this patch is available at http://reviews.llvm.org/D4900

rafael edited edge metadata.Aug 15 2014, 11:47 AM
rafael added a subscriber: rnk.

This seems more than what is needed.

If all that we need is to find the end of the response file following an argument, can't we just change ExpandResponseFiles to include a null in NewArgv every time a response file ends?

That way the processing of /link would claim all arguments until the null. Regular processing in cl::ParseCommandLineOptions would just ignore the null entries. There are only 3 calls to ExpandResponseFiles. One llvm, one in clang and one in lld.

rnk added a comment.Aug 15 2014, 12:36 PM

So, /link actually only consumes arguments until end-of-line. See http://llvm.org/PR17239. If we're going to add support for /link in response files, we should actually get it right. We haven't fixed this yet because most MSVC build systems don't use the compiler to run the link step.

Hi Rafael,

Regarding the generality of this approach, I agree that it seems more that what is needed. However, I ran into a problem when trying to implement a simpler way. Consider the following situation (in my test case):

clang-cl /link @response.txt /align...(some linker flag)

If we implement the "null" approach here, we would insert a null after response.txt and would prematurely end which arguments "/link" get.

Regards,
Rafael Auler

Hi Reid,

Thanks for pointing out the end-of-line issue. Looks like I overlooked this and made it expand to all arguments in response file. I will fix this patch.

Regards,
Rafael Auler

One issue remains, though. Should we also make dash dash (--) and all options in the RemainingArgsClass only expand until the end of line? Or should we create a new kind, say, RemainingArgsEndOfLineClass, just for "/link"?

Regards,
Rafael Auler

rnk added a comment.Aug 15 2014, 1:24 PM

Hi Rafael,

Regarding the generality of this approach, I agree that it seems more that what is needed. However, I ran into a problem when trying to implement a simpler way. Consider the following situation (in my test case):

clang-cl /link @response.txt /align...(some linker flag)

If we implement the "null" approach here, we would insert a null after response.txt and would prematurely end which arguments "/link" get.

It appears we don't need to support "/link @t.rsp". MSVC doesn't support nested response files, and when cl invokes the linker, it uses a response file. It does not expand response files after /link, so you end up with a nested response file and link.exe errors out because it thinks it's an input file.

In D4899#11, @rnk wrote:

Hi Rafael,

Regarding the generality of this approach, I agree that it seems more that what is needed. However, I ran into a problem when trying to implement a simpler way. Consider the following situation (in my test case):

clang-cl /link @response.txt /align...(some linker flag)

If we implement the "null" approach here, we would insert a null after response.txt and would prematurely end which arguments "/link" get.

It appears we don't need to support "/link @t.rsp". MSVC doesn't support nested response files, and when cl invokes the linker, it uses a response file. It does not expand response files after /link, so you end up with a nested response file and link.exe errors out because it thinks it's an input file.

That's great, that allows for a much simpler patch. I'll simplify it.

rafaelauler edited edge metadata.

I implemented the suggestions of Rafael & Reid, using nullptrs.

Populating a string vector with nullptrs may be dangerous if the existing users of ExpandResponseFiles assumes that all strings are valid pointers. To avoid headaches, I added a flag "MarkEOLs" in ExpandResponseFiles that is false by default. ExpandResponseFiles will only populate the Argv vector with nullptrs if this flag is true. I also updated the Option library to cope with nullptrs while parsing the Argv vector.

I will also upload the clang side in D4900. Let me know if you have more suggestions!

Cheers,
Rafael Auler

rnk accepted this revision.Aug 22 2014, 10:38 AM
rnk added a reviewer: rnk.

Thanks, lgtm.

Do you need someone to commit this?

This revision is now accepted and ready to land.Aug 22 2014, 10:38 AM

Thanks for putting in time to review this. Yes, I don't have commit access, could you please commit it?

rnk closed this revision.Aug 22 2014, 2:53 PM

Landed in r216280.