dang updated this revision to Diff 416942. dang added a comment. Rebase on top of main to bring latest fixes to ExtractAPIAction
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D121936/new/ https://reviews.llvm.org/D121936 Files: clang/include/clang/Basic/DiagnosticDriverKinds.td clang/include/clang/Driver/Action.h clang/include/clang/Driver/Types.def clang/lib/Driver/Action.cpp clang/lib/Driver/Driver.cpp clang/lib/Driver/ToolChain.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/test/Driver/extract-api-multiheader-kind-diag.h clang/test/Driver/extract-api-multiheader.h clang/test/Driver/extract-api.c clang/test/Driver/extract-api.h clang/test/SymbolGraph/global_record.c
Index: clang/test/SymbolGraph/global_record.c =================================================================== --- clang/test/SymbolGraph/global_record.c +++ clang/test/SymbolGraph/global_record.c @@ -3,7 +3,7 @@ // RUN: sed -e "s@INPUT_DIR@%/t@g" %t/reference.output.json.in >> \ // RUN: %t/reference.output.json // RUN: %clang -extract-api -target arm64-apple-macosx \ -// RUN: %t/input.c -o %t/output.json | FileCheck -allow-empty %s +// RUN: %t/input.h -o %t/output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ @@ -13,7 +13,7 @@ // CHECK-NOT: error: // CHECK-NOT: warning: -//--- input.c +//--- input.h int num; /** @@ -80,7 +80,7 @@ "location": { "character": 5, "line": 1, - "uri": "file://INPUT_DIR/input.c" + "uri": "file://INPUT_DIR/input.h" }, "names": { "subHeading": [ @@ -272,7 +272,7 @@ "location": { "character": 6, "line": 9, - "uri": "file://INPUT_DIR/input.c" + "uri": "file://INPUT_DIR/input.h" }, "names": { "subHeading": [ Index: clang/test/Driver/extract-api.h =================================================================== --- clang/test/Driver/extract-api.h +++ clang/test/Driver/extract-api.h @@ -3,8 +3,8 @@ // RUN: FileCheck -check-prefix EXTRACT-API-PHASES -input-file %t %s // EXTRACT-API-PHASES: 0: input, -// EXTRACT-API-PHASES: , c -// EXTRACT-API-PHASES: 1: preprocessor, {0}, cpp-output -// EXTRACT-API-PHASES: 2: compiler, {1}, api-information +// EXTRACT-API-PHASES-SAME: , c-header +// EXTRACT-API-PHASES-NEXT: 1: preprocessor, {0}, c-header-cpp-output +// EXTRACT-API-PHASES-NEXT: 2: api-extractor, {1}, api-information // EXTRACT-API-PHASES-NOT: 3: // EXTRACT-API-PHASES: END Index: clang/test/Driver/extract-api-multiheader.h =================================================================== --- /dev/null +++ clang/test/Driver/extract-api-multiheader.h @@ -0,0 +1,23 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: %clang -target x86_64-unknown-unknown -ccc-print-phases -extract-api %t/first-header.h %t/second-header.h 2> %t1 +// RUN: echo 'END' >> %t1 +// RUN: FileCheck -check-prefix EXTRACT-API-PHASES -input-file %t1 %s + +// EXTRACT-API-PHASES: 0: input +// EXTRACT-API-PHASES-SAME: , c-header +// EXTRACT-API-PHASES-NEXT: 1: preprocessor, {0}, c-header-cpp-output +// EXTRACT-API-PHASES-NEXT: 2: input +// EXTRACT-API-PHASES-SAME: , c-header +// EXTRACT-API-PHASES-NEXT: 3: preprocessor, {2}, c-header-cpp-output +// EXTRACT-API-PHASES-NEXT: 4: api-extractor, {1, 3}, api-information +// EXTRACT-API-PHASES-NOT: 5: +// EXTRACT-API-PHASES: END + +//--- first-header.h + +void dummy_function(void); + +//--- second-header.h + +void other_dummy_function(void); Index: clang/test/Driver/extract-api-multiheader-kind-diag.h =================================================================== --- /dev/null +++ clang/test/Driver/extract-api-multiheader-kind-diag.h @@ -0,0 +1,14 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: not %clang -target x86_64-unknown-unknown -extract-api %t/first-header.h -x objective-c-header %t/second-header.h 2>&1 | FileCheck %s + +// CHECK: error: header file +// CHECK-SAME: input 'objective-c-header' does not match the type of prior input in api extraction; use '-x c-header' to override + +//--- first-header.h + +void dummy_function(void); + +//--- second-header.h + +void other_dummy_function(void); Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -28,6 +28,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" +#include "clang/Driver/Action.h" #include "clang/Driver/Distro.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/InputInfo.h" @@ -4387,8 +4388,9 @@ // CUDA/HIP compilation may have multiple inputs (source file + results of // device-side compilations). OpenMP device jobs also take the host IR as a // second input. Module precompilation accepts a list of header files to - // include as part of the module. All other jobs are expected to have exactly - // one input. + // include as part of the module. API extraction accepts a list of header + // files whose API information is emitted in the output. All other jobs are + // expected to have exactly one input. bool IsCuda = JA.isOffloading(Action::OFK_Cuda); bool IsCudaDevice = JA.isDeviceOffloading(Action::OFK_Cuda); bool IsHIP = JA.isOffloading(Action::OFK_HIP); @@ -4396,6 +4398,7 @@ bool IsOpenMPDevice = JA.isDeviceOffloading(Action::OFK_OpenMP); bool IsOpenMPHost = JA.isHostOffloading(Action::OFK_OpenMP); bool IsHeaderModulePrecompile = isa<HeaderModulePrecompileJobAction>(JA); + bool IsExtractAPI = isa<ExtractAPIJobAction>(JA); bool IsDeviceOffloadAction = !(JA.isDeviceOffloading(Action::OFK_None) || JA.isDeviceOffloading(Action::OFK_Host)); bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction); @@ -4409,10 +4412,21 @@ }(); InputInfo HeaderModuleInput(Inputs[0].getType(), ModuleName, ModuleName); - const InputInfo &Input = - IsHeaderModulePrecompile ? HeaderModuleInput : Inputs[0]; + // Extract API doesn't have a main input file, so invent a fake one as a + // placeholder. + InputInfo ExtractAPIPlaceholderInput(Inputs[0].getType(), "extract-api", + "extract-api"); + + const InputInfo &Input = [&]() -> const InputInfo & { + if (IsHeaderModulePrecompile) + return HeaderModuleInput; + if (IsExtractAPI) + return ExtractAPIPlaceholderInput; + return Inputs[0]; + }(); InputInfoList ModuleHeaderInputs; + InputInfoList ExtractAPIInputs; InputInfoList OpenMPHostInputs; const InputInfo *CudaDeviceInput = nullptr; const InputInfo *OpenMPDeviceInput = nullptr; @@ -4428,6 +4442,14 @@ << types::getTypeName(Expected); } ModuleHeaderInputs.push_back(I); + } else if (IsExtractAPI) { + auto ExpectedInputType = ExtractAPIPlaceholderInput.getType(); + if (I.getType() != ExpectedInputType) { + D.Diag(diag::err_drv_extract_api_wrong_kind) + << I.getFilename() << types::getTypeName(I.getType()) + << types::getTypeName(ExpectedInputType); + } + ExtractAPIInputs.push_back(I); } else if ((IsCuda || IsHIP) && !CudaDeviceInput) { CudaDeviceInput = &I; } else if (IsOpenMPDevice && !OpenMPDeviceInput) { @@ -4611,6 +4633,10 @@ CmdArgs.push_back("-emit-pch"); } else if (isa<VerifyPCHJobAction>(JA)) { CmdArgs.push_back("-verify-pch"); + } else if (isa<ExtractAPIJobAction>(JA)) { + assert(JA.getType() == types::TY_API_INFO && + "Extract API actions must generate a API information."); + CmdArgs.push_back("-extract-api"); } else { assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) && "Invalid action for clang tool."); @@ -4649,8 +4675,6 @@ } else if (JA.getType() == types::TY_RewrittenLegacyObjC) { CmdArgs.push_back("-rewrite-objc"); rewriteKind = RK_Fragile; - } else if (JA.getType() == types::TY_API_INFO) { - CmdArgs.push_back("-extract-api"); } else { assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!"); } @@ -7195,6 +7219,8 @@ ArrayRef<InputInfo> FrontendInputs = Input; if (IsHeaderModulePrecompile) FrontendInputs = ModuleHeaderInputs; + else if (IsExtractAPI) + FrontendInputs = ExtractAPIInputs; else if (Input.isNothing()) FrontendInputs = {}; Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -359,6 +359,7 @@ case Action::PrecompileJobClass: case Action::HeaderModulePrecompileJobClass: case Action::PreprocessJobClass: + case Action::ExtractAPIJobClass: case Action::AnalyzeJobClass: case Action::MigrateJobClass: case Action::VerifyPCHJobClass: Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -59,6 +59,7 @@ #include "clang/Driver/InputInfo.h" #include "clang/Driver/Job.h" #include "clang/Driver/Options.h" +#include "clang/Driver/Phases.h" #include "clang/Driver/SanitizerArgs.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -334,10 +335,10 @@ FinalPhase = phases::Preprocess; // --precompile only runs up to precompilation. - } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile))) { + } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) || + (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) { FinalPhase = phases::Precompile; - - // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. + // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler. } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) || (PhaseArg = DAL.getLastArg(options::OPT_print_supported_cpus)) || (PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) || @@ -346,8 +347,7 @@ (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || (PhaseArg = DAL.getLastArg(options::OPT__analyze)) || - (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) || - (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) { + (PhaseArg = DAL.getLastArg(options::OPT_emit_ast))) { FinalPhase = phases::Compile; // -S only runs up to the backend. @@ -3883,6 +3883,7 @@ // Construct the actions to perform. HeaderModulePrecompileJobAction *HeaderModuleAction = nullptr; + ExtractAPIJobAction *ExtractAPIAction = nullptr; ActionList LinkerInputs; ActionList MergerInputs; @@ -3943,6 +3944,12 @@ break; } + if (Phase == phases::Precompile && ExtractAPIAction) { + ExtractAPIAction->addHeaderInput(Current); + Current = nullptr; + break; + } + // Try to build the offloading actions and add the result as a dependency // to the host. if (Args.hasArg(options::OPT_fopenmp_new_driver)) @@ -3960,6 +3967,8 @@ if (auto *HMA = dyn_cast<HeaderModulePrecompileJobAction>(NewCurrent)) HeaderModuleAction = HMA; + else if (auto *EAA = dyn_cast<ExtractAPIJobAction>(NewCurrent)) + ExtractAPIAction = EAA; Current = NewCurrent; @@ -4203,6 +4212,10 @@ return C.MakeAction<PreprocessJobAction>(Input, OutputTy); } case phases::Precompile: { + // API extraction should not generate an actual precompilation action. + if (Args.hasArg(options::OPT_extract_api)) + return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO); + types::ID OutputTy = getPrecompiledType(Input->getType()); assert(OutputTy != types::TY_INVALID && "Cannot precompile this input type!"); @@ -4217,8 +4230,7 @@ OutputTy = types::TY_ModuleFile; } - if (Args.hasArg(options::OPT_fsyntax_only) || - Args.hasArg(options::OPT_extract_api)) { + if (Args.hasArg(options::OPT_fsyntax_only)) { // Syntax checks should not emit a PCH file OutputTy = types::TY_Nothing; } @@ -4247,7 +4259,7 @@ if (Args.hasArg(options::OPT_verify_pch)) return C.MakeAction<VerifyPCHJobAction>(Input, types::TY_Nothing); if (Args.hasArg(options::OPT_extract_api)) - return C.MakeAction<CompileJobAction>(Input, types::TY_API_INFO); + return C.MakeAction<ExtractAPIJobAction>(Input, types::TY_API_INFO); return C.MakeAction<CompileJobAction>(Input, types::TY_LLVM_BC); } case phases::Backend: { @@ -5778,7 +5790,8 @@ // And say "no" if this is not a kind of action clang understands. if (!isa<PreprocessJobAction>(JA) && !isa<PrecompileJobAction>(JA) && - !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA)) + !isa<CompileJobAction>(JA) && !isa<BackendJobAction>(JA) && + !isa<ExtractAPIJobAction>(JA)) return false; return true; Index: clang/lib/Driver/Action.cpp =================================================================== --- clang/lib/Driver/Action.cpp +++ clang/lib/Driver/Action.cpp @@ -26,6 +26,8 @@ case PreprocessJobClass: return "preprocessor"; case PrecompileJobClass: return "precompiler"; case HeaderModulePrecompileJobClass: return "header-module-precompiler"; + case ExtractAPIJobClass: + return "api-extractor"; case AnalyzeJobClass: return "analyzer"; case MigrateJobClass: return "migrator"; case CompileJobClass: return "compiler"; @@ -339,6 +341,11 @@ : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType), ModuleName(ModuleName) {} +void ExtractAPIJobAction::anchor() {} + +ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType) + : JobAction(ExtractAPIJobClass, Inputs, OutputType) {} + void AnalyzeJobAction::anchor() {} AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) Index: clang/include/clang/Driver/Types.def =================================================================== --- clang/include/clang/Driver/Types.def +++ clang/include/clang/Driver/Types.def @@ -100,5 +100,5 @@ TYPE("dependencies", Dependencies, INVALID, "d", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("cuda-fatbin", CUDA_FATBIN, INVALID, "fatbin", phases::Compile, phases::Backend, phases::Assemble, phases::Link) TYPE("hip-fatbin", HIP_FATBIN, INVALID, "hipfb", phases::Compile, phases::Backend, phases::Assemble, phases::Link) -TYPE("api-information", API_INFO, INVALID, "json", phases::Compile) +TYPE("api-information", API_INFO, INVALID, "json", phases::Precompile) TYPE("none", Nothing, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link) Index: clang/include/clang/Driver/Action.h =================================================================== --- clang/include/clang/Driver/Action.h +++ clang/include/clang/Driver/Action.h @@ -59,6 +59,7 @@ PreprocessJobClass, PrecompileJobClass, HeaderModulePrecompileJobClass, + ExtractAPIJobClass, AnalyzeJobClass, MigrateJobClass, CompileJobClass, @@ -443,6 +444,19 @@ const char *getModuleName() const { return ModuleName; } }; +class ExtractAPIJobAction : public JobAction { + void anchor() override; + +public: + ExtractAPIJobAction(Action *Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == ExtractAPIJobClass; + } + + void addHeaderInput(Action *Input) { getInputs().push_back(Input); } +}; + class AnalyzeJobAction : public JobAction { void anchor() override; Index: clang/include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticDriverKinds.td +++ clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -464,6 +464,10 @@ "-ftest-module-file-extension argument '%0' is not of the required form " "'blockname:major:minor:hashed:user info'">; +def err_drv_extract_api_wrong_kind : Error< + "header file '%0' input '%1' does not match the type of prior input " + "in api extraction; use '-x %2' to override">; + def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">, InGroup<DiagGroup<"slash-u-filename">>; def note_use_dashdash : Note<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits