how to avoid passing new clang front end option to the linker?

I’m attempting to implement a new clang front end option for my project (-fmyopt=blah), and have made the changes required that I can access and act on it in my Target class when compiling. When linking, it causes a bit of trouble, as clang passes it on to gcc in the link phase:

“/usr/lib64/ccache/gcc” -g -D QSIZE -fpic -MD -fmyopt=blah -v -m64 -o tryit /run/user/1002/tryit-46641b.o

which gcc objects to.

What part of the code is the link command line constructed in, and what is the mechanism used to select which options get passed to other stages (or an example of that)?

The linker command line would be constructed in the driver (clang/lib/Driver/…) and exactly where the code is depends on your triple. You could grep for ‘Linker::ConstructJob’ and see what looks most likely, or try stepping through the driver in a debugger to see which one is invoked. I am a little surprised that arbitrary –f options would be passed through in the link phase.

HTH,

–paulr

I think that I’ve probably declared my option inappropriately. It was:

// Options.td
def fmyopt_EQ : Joined<[“-”], “fmyopt=”>, Group<f_clang>, Flags<[CC1Option]>,

HelpText<“…”>;

I think that the choice of whether or not to propagate it to the linker comes from here:

static bool forwardToGCC(const Option &O) {

// Don’t forward inputs from the original command line. They are added from

// InputInfoList.

return O.getKind() != Option::InputClass &&

!O.hasFlag(options::DriverOption) && !O.hasFlag(options::LinkerInput);

}

i.e. the LinkerInput flag. Perhaps this is implied by CC1Option in my Options.td line?

I tried changing to

def fmyopt_EQ : Joined<[“-”], “fmyopt=”>, Group<f_clang>, Flags<[DriverOption]>,

HelpText<“…”>;

but now my option is no longer recognized in the compilation phase.

Hmm, wondering if I should have put this in CC1Options.td instead, which I just spotted?

I think that I’ve probably declared my option inappropriately. It was:

// Options.td
def fmyopt_EQ : Joined<[“-”], “fmyopt=”>, Group<f_clang>, Flags<[CC1Option]>,

HelpText<“…”>;

I think that the choice of whether or not to propagate it to the linker comes from here:

static bool forwardToGCC(const Option &O) {

// Don’t forward inputs from the original command line. They are added from

// InputInfoList.

return O.getKind() != Option::InputClass &&

!O.hasFlag(options::DriverOption) && !O.hasFlag(options::LinkerInput);

}

i.e. the LinkerInput flag. Perhaps this is implied by CC1Option in my Options.td line?

I’m not sure, there is a ! in front the the LinkerInput test, so it’ll return true if it is not a LinkerInput.

I tried changing to

def fmyopt_EQ : Joined<[“-”], “fmyopt=”>, Group<f_clang>, Flags<[DriverOption]>,

HelpText<"…”>;

Maybe:

def fmyopt_EQ : Joined<[“-”], “fmyopt=”>, Group<f_clang>, Flags<[DriverOption, CC1Option]>,

?

The debugger shows that this forwardToGcc path does get hit. Setting a breakpoint just before it, I find my option:

6681 for (const auto &A : Args) {

6682 if (A->getOption().matches(options::OPT_fmyopt_EQ)) {

6683 printf(“here\n”);

6684 }

6685 if (forwardToGCC(A->getOption())) {

$3 = {

Opt = {

Info = 0x7ffff43f00d0 <InfoTable+28336>,

Owner = 0x45c170

},

BaseArg = 0x0,

Spelling = {

static npos = 18446744073709551615,

Data = 0x7fffffffdd1e “-fmyopt=extended”,

Length = 10

},

}

then in the forward code:

/home/pjoot/llvm.pragmas/tools/clang/lib/Driver/Tools.cpp:295

295 auto pk = O.getKind() != Option::InputClass ;

296 auto pd = O.hasFlag(options::DriverOption) ;

297 auto pl = O.hasFlag(options::LinkerInput);

298 return pk && !pd && !pl;

$4 = true

$5 = false

$6 = false

DriverOption and LinkerInput are both false so the result is true:

$7 = true

That’s very odd, because other options that are defined in similar ways (e.g. –fparse-all-comments) do not get forwarded to the linker. Comparing how your option behaves relative to other similar options might help diagnose the problem.

–paulr