From b3addea8f706e5418334ce15b1f971aad9df076f Mon Sep 17 00:00:00 2001 From: cokeom Date: Sat, 15 Oct 2022 12:45:14 +0800 Subject: [PATCH] add ignored options, replaced options and option -aux-info --- clang.spec | 13 +- support-ignored_and_replaced_opts.patch | 201 +++++++++ support-print-c-function-prototype.patch | 499 +++++++++++++++++++++++ 3 files changed, 711 insertions(+), 2 deletions(-) create mode 100644 support-ignored_and_replaced_opts.patch create mode 100644 support-print-c-function-prototype.patch diff --git a/clang.spec b/clang.spec index 89a4cde..03956ae 100644 --- a/clang.spec +++ b/clang.spec @@ -6,7 +6,7 @@ Name: clang Version: 12.0.1 -Release: 1 +Release: 3 License: GPL-2.0-only and Apache-2.0 and MIT Summary: An "LLVM native" C/C++/Objective-C compiler URL: http://llvm.org @@ -33,6 +33,9 @@ Recommends: compiler-rt = %{version} Conflicts: compiler-rt < %{version} Conflicts: compiler-rt > %{version} +Patch0: support-ignored_and_replaced_opts.patch +Patch1: support-print-c-function-prototype.patch + %description The Clang project provides a language front-end and tooling infrastructure for\ languages in the C language family (C, C++, Objective C/C++, OpenCL, CUDA, and\ @@ -94,7 +97,7 @@ clang-format integration for git. pathfix.py -i %{__python3} -pn \ clang-tidy/tool/*.py -%autosetup -n %{clang_srcdir} -p1 -Sgit +%autosetup -n %{clang_srcdir} -p1 pathfix.py -i %{__python3} -pn \ tools/clang-format/*.py \ tools/clang-format/git-clang-format \ @@ -266,6 +269,12 @@ ln -s clang++ %{buildroot}%{_bindir}/clang++-%{maj_ver} %{_bindir}/git-clang-format %changelog +* Thu Sep 22 2022 linguoxiong - 12.0.1-3 +- Implement the "-aux-info" option to print function prototype + +* Tue Aug 23 2022 linguoxiong - 12.0.1-2 +- Implement some options to ignore and replace + * Wed Dec 29 2021 panxiaohe - 12.0.1-1 - update to 12.0.1 - add clang-resource-filesystem sub-package diff --git a/support-ignored_and_replaced_opts.patch b/support-ignored_and_replaced_opts.patch new file mode 100644 index 0000000..2393489 --- /dev/null +++ b/support-ignored_and_replaced_opts.patch @@ -0,0 +1,201 @@ +From e6c1017c1bc412148662f64156a4d60315e59eb3 Mon Sep 17 00:00:00 2001 +From: cokeom +Date: Fri, 14 Oct 2022 18:20:15 +0800 +Subject: [PATCH] Implement ignored options and replaced options. + +--- + include/clang/Basic/DiagnosticDriverKinds.td | 6 +++ + include/clang/Driver/Options.td | 25 ++++++++++++ + lib/Driver/Driver.cpp | 41 ++++++++++++++++++++ + lib/Driver/ToolChains/Clang.cpp | 16 ++++++++ + test/Driver/ignored-and-replaced-options.c | 25 ++++++++++++ + test/Misc/warning-flags.c | 3 +- + 6 files changed, 115 insertions(+), 1 deletion(-) + create mode 100644 test/Driver/ignored-and-replaced-options.c + +diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td +index ad13f923..bd7225b5 100644 +--- a/include/clang/Basic/DiagnosticDriverKinds.td ++++ b/include/clang/Basic/DiagnosticDriverKinds.td +@@ -536,4 +536,10 @@ def err_drv_invalid_object_mode : Error<"OBJECT_MODE setting %0 is not recognize + + def err_aix_default_altivec_abi : Error< + "The default Altivec ABI on AIX is not yet supported, use '-mabi=vec-extabi' for the extended Altivec ABI">; ++ ++def warn_drv_ignore_options : Warning<"unsupported option '%0', ignore it.">, ++ InGroup; ++ ++def warn_drv_replace_options ++ : Warning<"unsupported option '%0', use '%1' instead.">; + } +diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td +index 81779892..04521197 100644 +--- a/include/clang/Driver/Options.td ++++ b/include/clang/Driver/Options.td +@@ -466,6 +466,31 @@ defvar std = !strconcat("LangStandard::getLangStandardForKind(", lang_std.KeyPat + // C++ => CXX + // . => _ + ++// Options to ignore and replace ++def clang_ignored_options_Group : OptionGroup<"">, ++ Group, ++ Flags<[Ignored]>; ++def ip : Flag<["-"], "ip">, ++ Group, ++ HelpText<"Enables additional interprocedural optimizations for " ++ "single-file compilation">; ++def assume : Separate<["-"], "assume">, ++ Group, ++ HelpText<"Determines whether units for the OPEN statement RECL " ++ "specifier (record length) value in unformatted files " ++ "are in bytes or longwords (four-byte units)">; ++def fdec : Flag<["-"], "fdec">, ++ Group, ++ HelpText<"Enables extensions and other features that mimic the " ++ "default behavior of older compilers (such as DEC)">; ++ ++def clang_replaced_options_Group ++ : OptionGroup<"">, ++ Group; ++def convert : Separate<["-"], "convert">, ++ Group, ++ HelpText<"Generate big-endian/little-endian code">; ++ + // Developer Driver Options + + def internal_Group : OptionGroup<"">, Flags<[HelpHidden]>; +diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp +index 418e1d3e..95c0e256 100644 +--- a/lib/Driver/Driver.cpp ++++ b/lib/Driver/Driver.cpp +@@ -996,6 +996,47 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { + CLOptions = std::make_unique( + ParseArgStrings(ArgList.slice(1), IsCLMode(), ContainsError)); + ++ // Compiler replacement option function. ++ for (auto *Opt : ++ CLOptions->filtered(options::OPT_clang_replaced_options_Group)) { ++ switch (Opt->getOption().getID()) { ++ default: ++ Diag(diag::err_drv_unsupported_opt) << Opt->getAsString(*CLOptions); ++ break; ++ case options::OPT_convert: ++ auto *OptLastArg = ++ CLOptions->getLastArg(options::OPT_mlittle_endian, ++ options::OPT_mbig_endian, options::OPT_convert); ++ if (OptLastArg->getOption().matches(options::OPT_convert)) { ++ StringRef OptionValue = OptLastArg->getValue(); ++ if (OptionValue.equals("big_endian")) { ++ Diag(diag::warn_drv_replace_options) ++ << OptLastArg->getAsString(*CLOptions) << "-mbig-endian"; ++ StringRef SpellingReplaced = StringRef("-mbig-endian"); ++ unsigned IndexReplaced = CLOptions->MakeIndex(SpellingReplaced); ++ Option OptReplaced = getOpts().getOption(options::OPT_mbig_endian); ++ Arg *ArgReplaced = ++ new Arg(OptReplaced, SpellingReplaced, IndexReplaced); ++ CLOptions->append(ArgReplaced); ++ } else if (OptionValue.equals("little_endian")) { ++ Diag(diag::warn_drv_replace_options) ++ << OptLastArg->getAsString(*CLOptions) << "-mlittle-endian"; ++ StringRef SpellingReplaced = StringRef("-mlittle-endian"); ++ unsigned IndexReplaced = CLOptions->MakeIndex(SpellingReplaced); ++ Option OptReplaced = getOpts().getOption(options::OPT_mlittle_endian); ++ Arg *ArgReplaced = ++ new Arg(OptReplaced, SpellingReplaced, IndexReplaced); ++ CLOptions->append(ArgReplaced); ++ } else { ++ Diag(diag::err_drv_unknown_argument) ++ << OptLastArg->getAsString(*CLOptions); ++ } ++ } ++ CLOptions->eraseArg(options::OPT_convert); ++ break; ++ } ++ } ++ + // Try parsing configuration file. + if (!ContainsError) + ContainsError = loadConfigFile(); +diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp +index 1976b48e..706d0431 100644 +--- a/lib/Driver/ToolChains/Clang.cpp ++++ b/lib/Driver/ToolChains/Clang.cpp +@@ -5178,6 +5178,22 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, + A->claim(); + } + ++ // Warn about ignored options to clang ++ for (const Arg *A : Args.filtered(options::OPT_clang_ignored_options_Group)) { ++ if (A->getOption().matches(options::OPT_assume)) { ++ StringRef OptionValue = A->getValue(); ++ if (OptionValue.equals("byterecl")) { ++ D.Diag(diag::warn_drv_ignore_options) << A->getAsString(Args); ++ } else { ++ D.Diag(diag::err_drv_unknown_argument) << A->getAsString(Args); ++ } ++ A->claim(); ++ continue; ++ } ++ D.Diag(diag::warn_drv_ignore_options) << A->getAsString(Args); ++ A->claim(); ++ } ++ + claimNoWarnArgs(Args); + + Args.AddAllArgs(CmdArgs, options::OPT_R_Group); +diff --git a/test/Driver/ignored-and-replaced-options.c b/test/Driver/ignored-and-replaced-options.c +new file mode 100644 +index 00000000..a13944db +--- /dev/null ++++ b/test/Driver/ignored-and-replaced-options.c +@@ -0,0 +1,25 @@ ++// Test that Some options are ignored and replaced. ++// ++// REQUIRES: clang-driver ++ ++// RUN: %clang -### -ip -c %s 2>&1 \ ++// RUN: | FileCheck --check-prefix=WARN %s ++// WARN: warning: unsupported option '-ip', ignore it. ++ ++// RUN: %clang -### -fdec -c %s 2>&1 \ ++// RUN: | FileCheck --check-prefix=WARN1 %s ++// WARN1: warning: unsupported option '-fdec', ignore it. ++ ++// RUN: %clang -### -assume byterecl -c %s 2>&1 \ ++// RUN: | FileCheck --check-prefix=WARN2 %s ++// WARN2: warning: unsupported option '-assume byterecl', ignore it. ++ ++// RUN: %clang -convert little_endian -c %s 2>&1 \ ++// RUN: | FileCheck --check-prefix=WARN3 %s ++// WARN3: warning: unsupported option '-convert little_endian', use ++// '-mlittle-endian' instead. ++ ++// RUN: %clang -convert big_endian -c %s 2>&1 \ ++// RUN: | FileCheck --check-prefix=WARN4 %s ++// WARN4: warning: unsupported option '-convert big_endian', use '-mbig-endian' ++// instead. +\ No newline at end of file +diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c +index 54e36e1e..1b9b779e 100644 +--- a/test/Misc/warning-flags.c ++++ b/test/Misc/warning-flags.c +@@ -18,7 +18,7 @@ This test serves two purposes: + + The list of warnings below should NEVER grow. It should gradually shrink to 0. + +-CHECK: Warnings without flags (68): ++CHECK: Warnings without flags (69): + + CHECK-NEXT: ext_expected_semi_decl_list + CHECK-NEXT: ext_explicit_specialization_storage_class +@@ -47,6 +47,7 @@ CHECK-NEXT: warn_double_const_requires_fp64 + CHECK-NEXT: warn_drv_assuming_mfloat_abi_is + CHECK-NEXT: warn_drv_clang_unsupported + CHECK-NEXT: warn_drv_pch_not_first_include ++CHECK-NEXT: warn_drv_replace_options + CHECK-NEXT: warn_dup_category_def + CHECK-NEXT: warn_enum_value_overflow + CHECK-NEXT: warn_expected_qualified_after_typename +-- +2.25.1 + diff --git a/support-print-c-function-prototype.patch b/support-print-c-function-prototype.patch new file mode 100644 index 0000000..cd94f14 --- /dev/null +++ b/support-print-c-function-prototype.patch @@ -0,0 +1,499 @@ +From feb61342aaf3e5ef2bcc36b3d512eba600e03c9c Mon Sep 17 00:00:00 2001 +From: cokeom +Date: Fri, 14 Oct 2022 18:30:00 +0800 +Subject: [PATCH] Implement -aux-info option. + +--- + include/clang/AST/DeclBase.h | 2 + + include/clang/AST/PrettyPrinter.h | 6 +- + include/clang/Driver/Options.td | 7 ++ + include/clang/Frontend/ASTConsumers.h | 3 + + include/clang/Frontend/FrontendActions.h | 6 ++ + include/clang/Frontend/FrontendOptions.h | 3 + + lib/AST/DeclPrinter.cpp | 96 +++++++++++++++++++ + lib/AST/TypePrinter.cpp | 23 +++-- + lib/Driver/Driver.cpp | 6 +- + lib/Driver/ToolChains/Clang.cpp | 7 ++ + lib/Frontend/ASTConsumers.cpp | 34 +++++++ + lib/Frontend/CompilerInvocation.cpp | 7 ++ + lib/Frontend/FrontendActions.cpp | 13 +++ + .../ExecuteCompilerInvocation.cpp | 2 + + test/Frontend/print-function-prototype.c | 28 ++++++ + 15 files changed, 230 insertions(+), 13 deletions(-) + create mode 100644 test/Frontend/print-function-prototype.c + +diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h +index 15eb29f7..a46b13e4 100644 +--- a/include/clang/AST/DeclBase.h ++++ b/include/clang/AST/DeclBase.h +@@ -1164,6 +1164,8 @@ public: + bool PrintInstantiation = false) const; + void print(raw_ostream &Out, const PrintingPolicy &Policy, + unsigned Indentation = 0, bool PrintInstantiation = false) const; ++ void printDeclPrototype(raw_ostream &Out, unsigned Indentation = 0, ++ bool PrintInstantiation = false) const; + static void printGroup(Decl** Begin, unsigned NumDecls, + raw_ostream &Out, const PrintingPolicy &Policy, + unsigned Indentation = 0); +diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h +index 3baf2b2b..f147fd87 100644 +--- a/include/clang/AST/PrettyPrinter.h ++++ b/include/clang/AST/PrettyPrinter.h +@@ -74,7 +74,8 @@ struct PrintingPolicy { + MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), + MSVCFormatting(false), ConstantsAsWritten(false), + SuppressImplicitBase(false), FullyQualifiedName(false), +- PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true) {} ++ PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true), ++ PrintRestrict(true) {} + + /// Adjust this printing policy for cases where it's known that we're + /// printing C++ code (for instance, if AST dumping reaches a C++-only +@@ -273,6 +274,9 @@ struct PrintingPolicy { + /// invalid C++ code. + unsigned PrintInjectedClassNameWithArguments : 1; + ++ /// Whether to print the keyword "restrict" in the function prototype. ++ unsigned PrintRestrict : 1; ++ + /// Callbacks to use to allow the behavior of printing to be customized. + const PrintingCallbacks *Callbacks = nullptr; + }; +diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td +index 04521197..2126f0df 100644 +--- a/include/clang/Driver/Options.td ++++ b/include/clang/Driver/Options.td +@@ -491,6 +491,13 @@ def convert : Separate<["-"], "convert">, + Group, + HelpText<"Generate big-endian/little-endian code">; + ++def aux_info : Separate<["-"], "aux-info">, ++ Flags<[NoXarchOption, CoreOption, CC1Option]>, ++ Group, ++ HelpText<"Output to the given filename prototyped declarations " ++ "for all functions declared and/or defined in a " ++ "translation unit, including those in header files">; ++ + // Developer Driver Options + + def internal_Group : OptionGroup<"">, Flags<[HelpHidden]>; +diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h +index 98cfc7ca..ecd3c268 100644 +--- a/include/clang/Frontend/ASTConsumers.h ++++ b/include/clang/Frontend/ASTConsumers.h +@@ -50,6 +50,9 @@ std::unique_ptr CreateASTDeclNodeLister(); + // function declarations to stderr. + std::unique_ptr CreateASTViewer(); + ++std::unique_ptr ++CreateASTFunctionPrinter(std::unique_ptr Out); ++ + } // end clang namespace + + #endif +diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h +index 25ca9598..d2b294a5 100644 +--- a/include/clang/Frontend/FrontendActions.h ++++ b/include/clang/Frontend/FrontendActions.h +@@ -74,6 +74,12 @@ protected: + StringRef InFile) override; + }; + ++class ASTFunctionPrinterAction : public ASTFrontendAction { ++protected: ++ std::unique_ptr CreateASTConsumer(CompilerInstance &CI, ++ StringRef InFile) override; ++}; ++ + class GeneratePCHAction : public ASTFrontendAction { + protected: + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, +diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h +index 223c1e05..3362a2fc 100644 +--- a/include/clang/Frontend/FrontendOptions.h ++++ b/include/clang/Frontend/FrontendOptions.h +@@ -44,6 +44,9 @@ enum ActionKind { + /// Parse ASTs and view them in Graphviz. + ASTView, + ++ /// Print function prototype. ++ ASTFunctionPrinter, ++ + /// Dump the compiler configuration. + DumpCompilerOptions, + +diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp +index ca64f8f6..a857466e 100644 +--- a/lib/AST/DeclPrinter.cpp ++++ b/lib/AST/DeclPrinter.cpp +@@ -115,6 +115,7 @@ namespace { + void prettyPrintAttributes(Decl *D); + void prettyPrintPragmas(Decl *D); + void printDeclType(QualType T, StringRef DeclName, bool Pack = false); ++ void printFunctionDeclPrototype(FunctionDecl *D); + }; + } + +@@ -135,6 +136,14 @@ void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, + print(Out, Context, Context.getPrintingPolicy(), OmitTemplateKW); + } + ++void Decl::printDeclPrototype(raw_ostream &Out, unsigned Indentation, ++ bool PrintInstantiation) const { ++ DeclPrinter Printer(Out, getASTContext().getPrintingPolicy(), getASTContext(), ++ Indentation, PrintInstantiation); ++ auto *FD = const_cast(dyn_cast(this)); ++ Printer.printFunctionDeclPrototype(FD); ++} ++ + void TemplateParameterList::print(raw_ostream &Out, const ASTContext &Context, + const PrintingPolicy &Policy, + bool OmitTemplateKW) const { +@@ -784,6 +793,93 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { + } + } + ++void DeclPrinter::printFunctionDeclPrototype(FunctionDecl *D) { ++ if (!Policy.SuppressSpecifiers) { ++ switch (D->getStorageClass()) { ++ case SC_None: ++ case SC_Extern: ++ case SC_PrivateExtern: ++ Out << "extern "; ++ break; ++ case SC_Static: ++ Out << "static "; ++ break; ++ case SC_Auto: ++ case SC_Register: ++ llvm_unreachable("invalid for functions"); ++ } ++ } ++ ++ PrintingPolicy SubPolicy(Policy); ++ SubPolicy.SuppressSpecifiers = false; ++ SubPolicy.PrintRestrict = false; ++ std::string Proto; ++ ++ /// Print the function name. ++ if (Policy.FullyQualifiedName) { ++ Proto += D->getQualifiedNameAsString(); ++ } else { ++ llvm::raw_string_ostream OS(Proto); ++ if (!Policy.SuppressScope) { ++ if (const NestedNameSpecifier *NS = D->getQualifier()) { ++ NS->print(OS, Policy); ++ } ++ } ++ D->getNameInfo().printName(OS, Policy); ++ } ++ ++ QualType Ty = D->getType(); ++ while (const ParenType *PT = dyn_cast(Ty)) { ++ Proto = '(' + Proto + ')'; ++ Ty = PT->getInnerType(); ++ } ++ if (const FunctionType *AFT = Ty->getAs()) { ++ const FunctionProtoType *FT = nullptr; ++ if (D->hasWrittenPrototype()) ++ FT = dyn_cast(AFT); ++ ++ Proto += "("; ++ ++ /// Print function parameters. ++ if (FT) { ++ llvm::raw_string_ostream POut(Proto); ++ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { ++ if (i) ++ POut << ", "; ++ ParmVarDecl *PVD = D->getParamDecl(i); ++ QualType T = PVD->getTypeSourceInfo() ++ ? PVD->getTypeSourceInfo()->getType() ++ : PVD->getASTContext().getUnqualifiedObjCPointerType( ++ PVD->getType()); ++ T.print(POut, SubPolicy, "", Indentation); ++ } ++ ++ if (FT->isVariadic()) { ++ if (D->getNumParams()) ++ POut << ", "; ++ POut << "..."; ++ } else if (!D->getNumParams()) { ++ POut << "void"; ++ } ++ } else if (D->doesThisDeclarationHaveABody() && !D->hasPrototype()) { ++ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { ++ if (i) ++ Proto += ", "; ++ Proto += D->getParamDecl(i)->getNameAsString(); ++ } ++ if (!D->getNumParams()) { ++ Proto += "void"; ++ } ++ } ++ Proto += ")"; ++ ++ /// Print the function return type. ++ AFT->getReturnType().print(Out, Policy, Proto); ++ } else { ++ Ty.print(Out, Policy, Proto); ++ } ++} ++ + void DeclPrinter::VisitFriendDecl(FriendDecl *D) { + if (TypeSourceInfo *TSI = D->getFriendType()) { + unsigned NumTPLists = D->getFriendTypeNumTemplateParameterLists(); +diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp +index 25d7874b..37d116ca 100644 +--- a/lib/AST/TypePrinter.cpp ++++ b/lib/AST/TypePrinter.cpp +@@ -139,7 +139,7 @@ namespace { + } // namespace + + static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, +- bool HasRestrictKeyword) { ++ bool HasRestrictKeyword, bool PrintRestrict) { + bool appendSpace = false; + if (TypeQuals & Qualifiers::Const) { + OS << "const"; +@@ -151,11 +151,13 @@ static void AppendTypeQualList(raw_ostream &OS, unsigned TypeQuals, + appendSpace = true; + } + if (TypeQuals & Qualifiers::Restrict) { +- if (appendSpace) OS << ' '; +- if (HasRestrictKeyword) { +- OS << "restrict"; +- } else { +- OS << "__restrict"; ++ if (PrintRestrict) { ++ if (appendSpace) OS << ' '; ++ if (HasRestrictKeyword) { ++ OS << "restrict"; ++ } else { ++ OS << "__restrict"; ++ } + } + } + } +@@ -506,8 +508,8 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T, + raw_ostream &OS) { + OS << '['; + if (T->getIndexTypeQualifiers().hasQualifiers()) { +- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), +- Policy.Restrict); ++ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict, ++ Policy.PrintRestrict); + OS << ' '; + } + +@@ -542,7 +544,8 @@ void TypePrinter::printVariableArrayAfter(const VariableArrayType *T, + raw_ostream &OS) { + OS << '['; + if (T->getIndexTypeQualifiers().hasQualifiers()) { +- AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict); ++ AppendTypeQualList(OS, T->getIndexTypeCVRQualifiers(), Policy.Restrict, ++ Policy.PrintRestrict); + OS << ' '; + } + +@@ -2149,7 +2152,7 @@ void Qualifiers::print(raw_ostream &OS, const PrintingPolicy& Policy, + + unsigned quals = getCVRQualifiers(); + if (quals) { +- AppendTypeQualList(OS, quals, Policy.Restrict); ++ AppendTypeQualList(OS, quals, Policy.Restrict, Policy.PrintRestrict); + addSpace = true; + } + if (hasUnaligned()) { +diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp +index 95c0e256..ce677965 100644 +--- a/lib/Driver/Driver.cpp ++++ b/lib/Driver/Driver.cpp +@@ -309,7 +309,8 @@ phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, + (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_emit_ast)) || ++ (PhaseArg = DAL.getLastArg(options::OPT_aux_info))) { + FinalPhase = phases::Compile; + + // -S only runs up to the backend. +@@ -3851,7 +3852,8 @@ Action *Driver::ConstructPhaseAction( + return C.MakeAction(Input, OutputTy); + } + case phases::Compile: { +- if (Args.hasArg(options::OPT_fsyntax_only)) ++ if (Args.hasArg(options::OPT_fsyntax_only) || ++ Args.hasArg(options::OPT_aux_info)) + return C.MakeAction(Input, types::TY_Nothing); + if (Args.hasArg(options::OPT_rewrite_objc)) + return C.MakeAction(Input, types::TY_RewrittenObjC); +diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp +index 706d0431..e7946529 100644 +--- a/lib/Driver/ToolChains/Clang.cpp ++++ b/lib/Driver/ToolChains/Clang.cpp +@@ -6258,6 +6258,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, + } + } + ++ if (Arg *A = Args.getLastArg(options::OPT_aux_info)) { ++ if (Input.getType() == types::TY_C) { ++ CmdArgs.push_back("-aux-info"); ++ CmdArgs.push_back(A->getValue()); ++ } ++ } ++ + // With -save-temps, we want to save the unoptimized bitcode output from the + // CompileJobAction, use -disable-llvm-passes to get pristine IR generated + // by the frontend. +diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp +index a73cc887..48f999ab 100644 +--- a/lib/Frontend/ASTConsumers.cpp ++++ b/lib/Frontend/ASTConsumers.cpp +@@ -212,3 +212,37 @@ void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { + std::unique_ptr clang::CreateASTViewer() { + return std::make_unique(); + } ++ ++//===----------------------------------------------------------------------===// ++/// ASTFunctionPrototype - AST FunctionPrototype print ++namespace { ++ class ASTFunctionPrinter : public ASTConsumer { ++ private: ++ llvm::raw_fd_ostream &Out; ++ std::unique_ptr OwnedOut; ++ public: ++ ASTFunctionPrinter(std::unique_ptr Out) ++ : Out(Out ? *Out : llvm::outs()), OwnedOut(std::move(Out)) {} ++ ++ bool HandleTopLevelDecl(DeclGroupRef D) override { ++ for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) ++ HandleTopLevelSingleDecl(*I); ++ return true; ++ } ++ ++ void HandleTopLevelSingleDecl(Decl *D); ++ }; ++} // namespace ++ ++void ASTFunctionPrinter::HandleTopLevelSingleDecl(Decl *D) { ++ if (isa(D)) { ++ D->printDeclPrototype(Out); ++ Out << ";"; ++ Out << '\n'; ++ } ++} ++ ++std::unique_ptr ++clang::CreateASTFunctionPrinter(std::unique_ptr Out) { ++ return std::make_unique(std::move(Out)); ++} +\ No newline at end of file +diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp +index 5c5cf461..9665b4ed 100644 +--- a/lib/Frontend/CompilerInvocation.cpp ++++ b/lib/Frontend/CompilerInvocation.cpp +@@ -1574,6 +1574,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, + Opts.ProgramAction = frontend::ASTPrint; break; + case OPT_ast_view: + Opts.ProgramAction = frontend::ASTView; break; ++ case OPT_aux_info: ++ Opts.ProgramAction = frontend::ASTFunctionPrinter; break; + case OPT_compiler_options_dump: + Opts.ProgramAction = frontend::DumpCompilerOptions; break; + case OPT_dump_raw_tokens: +@@ -2711,6 +2713,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { + case frontend::ASTDump: + case frontend::ASTPrint: + case frontend::ASTView: ++ case frontend::ASTFunctionPrinter: + case frontend::EmitAssembly: + case frontend::EmitBC: + case frontend::EmitHTML: +@@ -2971,6 +2974,10 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, + + FixupInvocation(Res, Diags, Args, DashX); + ++ if (Arg *A = Args.getLastArg(OPT_aux_info)) { ++ Res.getFrontendOpts().OutputFile = A->getValue(); ++ } ++ + return Success; + } + +diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp +index 060cec23..1d0044c8 100644 +--- a/lib/Frontend/FrontendActions.cpp ++++ b/lib/Frontend/FrontendActions.cpp +@@ -93,6 +93,19 @@ ASTViewAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + return CreateASTViewer(); + } + ++std::unique_ptr ++ASTFunctionPrinterAction::CreateASTConsumer(CompilerInstance &CI, ++ StringRef InFile) { ++ StringRef OutputFileName = CI.getFrontendOpts().OutputFile; ++ std::unique_ptr OutFile; ++ if (!OutputFileName.empty() && OutputFileName != "-") { ++ std::error_code EC; ++ OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC, ++ llvm::sys::fs::CD_CreateAlways)); ++ } ++ return CreateASTFunctionPrinter(std::move(OutFile)); ++} ++ + std::unique_ptr + GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + std::string Sysroot; +diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp +index ac64e170..63a6b403 100644 +--- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp ++++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp +@@ -46,6 +46,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) { + case ASTDump: return std::make_unique(); + case ASTPrint: return std::make_unique(); + case ASTView: return std::make_unique(); ++ case ASTFunctionPrinter: ++ return std::make_unique(); + case DumpCompilerOptions: + return std::make_unique(); + case DumpRawTokens: return std::make_unique(); +diff --git a/test/Frontend/print-function-prototype.c b/test/Frontend/print-function-prototype.c +new file mode 100644 +index 00000000..5abc7550 +--- /dev/null ++++ b/test/Frontend/print-function-prototype.c +@@ -0,0 +1,28 @@ ++// Test that -aux-info prints correct function prototypes. ++// RUN: %clang %s -aux-info %t 2>&1 \ ++// RUN: | FileCheck -input-file=%t %s ++// CHECK: extern void function1(int, const int, float); ++// CHECK: extern int function2(int, int); ++// CHECK: extern void function3(int, double, float); ++// CHECK: static void function4(void); ++// CHECK: extern int function5(volatile int *); ++// CHECK: extern int function6(int *); ++// CHECK: extern const int function7(void); ++// CHECK: extern volatile float function8(void); ++// CHECK: extern int main(void); ++// CHECK: extern void function1(int, const int, float); ++ ++void function1(int, const int, float); ++int function2(int a, int b) { return a + b; } ++void function3(int a, double b, float c) {} ++static void function4() {} ++inline int function5(volatile int *j); ++int function6(int *a) { return 0; } ++const int function7() { return 1; } ++volatile float function8() { return 0.; } ++int main() { ++ function1(1, 1, 0.0); ++ function2(1, 1); ++ return 0; ++} ++void function1(int a, const int b, float c) {} +\ No newline at end of file +-- +2.25.1 + -- Gitee