diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3689,16 +3689,27 @@ Arg *FinalOutput = C.getArgs().getLastArg(options::OPT_o); // It is an error to provide a -o option if we are making multiple output - // files. There is one exception, IfsMergeJob: when generating interface stubs - // enabled we want to be able to generate the stub file at the same time that - // we generate the real library/a.out. So when a .o, .so, etc are the output, - // with clang interface stubs there will also be a .ifs and .ifso at the same - // location. + // files. There are exceptions: + // + // IfsMergeJob: when generating interface stubs enabled we want to be able to + // generate the stub file at the same time that we generate the real + // library/a.out. So when a .o, .so, etc are the output, with clang interface + // stubs there will also be a .ifs and .ifso at the same location. + // + // CompileJob of type TY_IFS_CPP: when generating interface stubs is enabled + // and -c is passed, we still want to be able to generate a .ifs file while + // we are also generating .o files. So we allow more than one output file in + // this case as well. + // if (FinalOutput) { unsigned NumOutputs = 0; + unsigned NumIfsOutputs = 0; for (const Action *A : C.getActions()) if (A->getType() != types::TY_Nothing && !(A->getKind() == Action::IfsMergeJobClass || + (A->getType() == clang::driver::types::TY_IFS_CPP && + A->getKind() == clang::driver::Action::CompileJobClass && + 0 == NumIfsOutputs++) || (A->getKind() == Action::BindArchClass && A->getInputs().size() && A->getInputs().front()->getKind() == Action::IfsMergeJobClass))) ++NumOutputs; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5828,8 +5828,16 @@ if (Output.getType() == types::TY_Dependencies) { // Handled with other dependency code. } else if (Output.isFilename()) { - CmdArgs.push_back("-o"); - CmdArgs.push_back(Output.getFilename()); + if (Output.getType() == clang::driver::types::TY_IFS_CPP || + Output.getType() == clang::driver::types::TY_IFS) { + SmallString<128> OutputFilename(Output.getFilename()); + llvm::sys::path::replace_extension(OutputFilename, "ifs"); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Args.MakeArgString(OutputFilename)); + } else { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } } else { assert(Output.isNothing() && "Invalid output."); } diff --git a/clang/test/InterfaceStubs/driver-test3.c b/clang/test/InterfaceStubs/driver-test3.c new file mode 100644 --- /dev/null +++ b/clang/test/InterfaceStubs/driver-test3.c @@ -0,0 +1,19 @@ +// REQUIRES: x86-registered-target +// REQUIRES: shell + +// RUN: mkdir -p %t; cd %t +// RUN: %clang -target x86_64-unknown-linux-gnu -c -emit-interface-stubs %s -o %t/driver-test3.o +// RUN: llvm-nm %t/driver-test3.o | FileCheck --check-prefix=CHECK-OBJ %s +// RUN: cat %t/driver-test3.ifs | FileCheck --check-prefix=CHECK-IFS %s + +// CHECK-OBJ: bar + +// CHECK-IFS: --- !experimental-ifs-v1 +// CHECK-IFS-NEXT: IfsVersion: +// CHECK-IFS-NEXT: Triple: +// CHECK-IFS-NEXT: ObjectFileFormat: +// CHECK-IFS-NEXT: Symbols: +// CHECK-IFS-NEXT: "bar" : { Type: Func } +// CHECK-IFS-NEXT: ... + +int bar(int a) { return a; }