500 lines
19 KiB
Diff
500 lines
19 KiB
Diff
|
|
From feb61342aaf3e5ef2bcc36b3d512eba600e03c9c Mon Sep 17 00:00:00 2001
|
||
|
|
From: cokeom <cokelin@hnu.edu.cn>
|
||
|
|
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<clang_replaced_options_Group>,
|
||
|
|
HelpText<"Generate big-endian/little-endian code">;
|
||
|
|
|
||
|
|
+def aux_info : Separate<["-"], "aux-info">,
|
||
|
|
+ Flags<[NoXarchOption, CoreOption, CC1Option]>,
|
||
|
|
+ Group<Action_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<"<clang internal options>">, 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<ASTConsumer> CreateASTDeclNodeLister();
|
||
|
|
// function declarations to stderr.
|
||
|
|
std::unique_ptr<ASTConsumer> CreateASTViewer();
|
||
|
|
|
||
|
|
+std::unique_ptr<ASTConsumer>
|
||
|
|
+CreateASTFunctionPrinter(std::unique_ptr<llvm::raw_fd_ostream> 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<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
|
||
|
|
+ StringRef InFile) override;
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
class GeneratePCHAction : public ASTFrontendAction {
|
||
|
|
protected:
|
||
|
|
std::unique_ptr<ASTConsumer> 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<FunctionDecl *>(dyn_cast<FunctionDecl>(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<ParenType>(Ty)) {
|
||
|
|
+ Proto = '(' + Proto + ')';
|
||
|
|
+ Ty = PT->getInnerType();
|
||
|
|
+ }
|
||
|
|
+ if (const FunctionType *AFT = Ty->getAs<FunctionType>()) {
|
||
|
|
+ const FunctionProtoType *FT = nullptr;
|
||
|
|
+ if (D->hasWrittenPrototype())
|
||
|
|
+ FT = dyn_cast<FunctionProtoType>(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<PrecompileJobAction>(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<CompileJobAction>(Input, types::TY_Nothing);
|
||
|
|
if (Args.hasArg(options::OPT_rewrite_objc))
|
||
|
|
return C.MakeAction<CompileJobAction>(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<ASTConsumer> clang::CreateASTViewer() {
|
||
|
|
return std::make_unique<ASTViewer>();
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+//===----------------------------------------------------------------------===//
|
||
|
|
+/// ASTFunctionPrototype - AST FunctionPrototype print
|
||
|
|
+namespace {
|
||
|
|
+ class ASTFunctionPrinter : public ASTConsumer {
|
||
|
|
+ private:
|
||
|
|
+ llvm::raw_fd_ostream &Out;
|
||
|
|
+ std::unique_ptr<llvm::raw_fd_ostream> OwnedOut;
|
||
|
|
+ public:
|
||
|
|
+ ASTFunctionPrinter(std::unique_ptr<llvm::raw_fd_ostream> 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<FunctionDecl>(D)) {
|
||
|
|
+ D->printDeclPrototype(Out);
|
||
|
|
+ Out << ";";
|
||
|
|
+ Out << '\n';
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+std::unique_ptr<ASTConsumer>
|
||
|
|
+clang::CreateASTFunctionPrinter(std::unique_ptr<llvm::raw_fd_ostream> Out) {
|
||
|
|
+ return std::make_unique<ASTFunctionPrinter>(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<ASTConsumer>
|
||
|
|
+ASTFunctionPrinterAction::CreateASTConsumer(CompilerInstance &CI,
|
||
|
|
+ StringRef InFile) {
|
||
|
|
+ StringRef OutputFileName = CI.getFrontendOpts().OutputFile;
|
||
|
|
+ std::unique_ptr<llvm::raw_fd_ostream> 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<ASTConsumer>
|
||
|
|
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<ASTDumpAction>();
|
||
|
|
case ASTPrint: return std::make_unique<ASTPrintAction>();
|
||
|
|
case ASTView: return std::make_unique<ASTViewAction>();
|
||
|
|
+ case ASTFunctionPrinter:
|
||
|
|
+ return std::make_unique<ASTFunctionPrinterAction>();
|
||
|
|
case DumpCompilerOptions:
|
||
|
|
return std::make_unique<DumpCompilerOptionsAction>();
|
||
|
|
case DumpRawTokens: return std::make_unique<DumpRawTokensAction>();
|
||
|
|
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
|
||
|
|
|