From 36070ed8d261c231cf1bde460aec9ffde16f9ff7 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 17 Aug 2017 13:41:55 +0000 Subject: [PATCH] Print enum constant values using the original source formatting if possible when creating "Declaration" nodes in XML comments rdar://14765746 llvm-svn: 311085 --- clang/include/clang/AST/PrettyPrinter.h | 21 +++++++++- clang/include/clang/AST/Stmt.h | 4 +- clang/lib/AST/DeclPrinter.cpp | 21 ++++++---- clang/lib/AST/StmtPrinter.cpp | 41 +++++++++++++++---- clang/lib/Index/CommentToXML.cpp | 1 + ...-xml-conversion-with-original-literals.cpp | 26 ++++++++++++ 6 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 clang/test/Index/comment-to-html-xml-conversion-with-original-literals.cpp diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h index 274df220e160..54fe39833713 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -50,7 +50,8 @@ struct PrintingPolicy { UseVoidForZeroParams(!LO.CPlusPlus), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), - IncludeNewlines(true), MSVCFormatting(false) { } + IncludeNewlines(true), MSVCFormatting(false), + ConstantsAsWritten(false) { } /// \brief Adjust this printing policy for cases where it's known that /// we're printing C++ code (for instance, if AST dumping reaches a @@ -200,6 +201,24 @@ struct PrintingPolicy { /// prints anonymous namespaces as `anonymous namespace' and does not insert /// spaces after template arguments. bool MSVCFormatting : 1; + + /// \brief Whether we should print the constant expressions as written in the + /// sources. + /// + /// This flag determines whether constants expressions like + /// + /// \code + /// 0x10 + /// 2.5e3 + /// \endcode + /// + /// will be printed as written or as follows: + /// + /// \code + /// 0x10 + /// 2.5e3 + /// \endcode + bool ConstantsAsWritten; }; } // end namespace clang diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index c210bd1cec2e..795f4d6e71b2 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -389,8 +389,8 @@ public: /// back to its original source language syntax. void dumpPretty(const ASTContext &Context) const; void printPretty(raw_ostream &OS, PrinterHelper *Helper, - const PrintingPolicy &Policy, - unsigned Indentation = 0) const; + const PrintingPolicy &Policy, unsigned Indentation = 0, + const ASTContext *Context = nullptr) const; /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// works on systems with GraphViz (Mac OS X) or dot+gv installed. diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 6eeba88e4033..00db026ebb49 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -28,6 +28,7 @@ namespace { class DeclPrinter : public DeclVisitor { raw_ostream &Out; PrintingPolicy Policy; + const ASTContext &Context; unsigned Indentation; bool PrintInstantiation; @@ -48,9 +49,10 @@ namespace { public: DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, - unsigned Indentation = 0, bool PrintInstantiation = false) - : Out(Out), Policy(Policy), Indentation(Indentation), - PrintInstantiation(PrintInstantiation) { } + const ASTContext &Context, unsigned Indentation = 0, + bool PrintInstantiation = false) + : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation), + PrintInstantiation(PrintInstantiation) {} void VisitDeclContext(DeclContext *DC, bool Indent = true); @@ -115,7 +117,8 @@ void Decl::print(raw_ostream &Out, unsigned Indentation, void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation, bool PrintInstantiation) const { - DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation); + DeclPrinter Printer(Out, Policy, getASTContext(), Indentation, + PrintInstantiation); Printer.Visit(const_cast(this)); } @@ -192,7 +195,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const { DC = DC->getParent(); ASTContext &Ctx = cast(DC)->getASTContext(); - DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0); + DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0); Printer.VisitDeclContext(const_cast(this), /*Indent=*/false); } @@ -467,7 +470,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) { prettyPrintAttributes(D); if (Expr *Init = D->getInitExpr()) { Out << " = "; - Init->printPretty(Out, nullptr, Policy, Indentation); + Init->printPretty(Out, nullptr, Policy, Indentation, &Context); } } @@ -521,7 +524,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString(); if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { llvm::raw_string_ostream POut(Proto); - DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); + DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation); TArgPrinter.printTemplateArguments(*TArgs); } @@ -539,7 +542,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { Proto += "("; if (FT) { llvm::raw_string_ostream POut(Proto); - DeclPrinter ParamPrinter(POut, SubPolicy, Indentation); + DeclPrinter ParamPrinter(POut, SubPolicy, Context, Indentation); for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { if (i) POut << ", "; ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); @@ -695,7 +698,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { // This is a K&R function definition, so we need to print the // parameters. Out << '\n'; - DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); + DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation); Indentation += Policy.Indentation; for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { Indent(); diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index e3b96284bd1c..950d0e29979a 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -24,6 +24,7 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/CharInfo.h" +#include "clang/Lex/Lexer.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Format.h" using namespace clang; @@ -38,12 +39,14 @@ namespace { unsigned IndentLevel; clang::PrinterHelper* Helper; PrintingPolicy Policy; + const ASTContext *Context; public: - StmtPrinter(raw_ostream &os, PrinterHelper* helper, - const PrintingPolicy &Policy, - unsigned Indentation = 0) - : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy) {} + StmtPrinter(raw_ostream &os, PrinterHelper *helper, + const PrintingPolicy &Policy, unsigned Indentation = 0, + const ASTContext *Context = nullptr) + : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy), + Context(Context) {} void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); @@ -1441,7 +1444,26 @@ void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) { } } +/// Prints the given expression using the original source text. Returns true on +/// success, false otherwise. +static bool printExprAsWritten(raw_ostream &OS, Expr *E, + const ASTContext *Context) { + if (!Context) + return false; + bool Invalid = false; + StringRef Source = Lexer::getSourceText( + CharSourceRange::getTokenRange(E->getSourceRange()), + Context->getSourceManager(), Context->getLangOpts(), &Invalid); + if (!Invalid) { + OS << Source; + return true; + } + return false; +} + void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) { + if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context)) + return; bool isSigned = Node->getType()->isSignedIntegerType(); OS << Node->getValue().toString(10, isSigned); @@ -1485,6 +1507,8 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node, } void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) { + if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context)) + return; PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true); } @@ -2696,11 +2720,10 @@ void Stmt::dumpPretty(const ASTContext &Context) const { printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts())); } -void Stmt::printPretty(raw_ostream &OS, - PrinterHelper *Helper, - const PrintingPolicy &Policy, - unsigned Indentation) const { - StmtPrinter P(OS, Helper, Policy, Indentation); +void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper, + const PrintingPolicy &Policy, unsigned Indentation, + const ASTContext *Context) const { + StmtPrinter P(OS, Helper, Policy, Indentation, Context); P.Visit(const_cast(this)); } diff --git a/clang/lib/Index/CommentToXML.cpp b/clang/lib/Index/CommentToXML.cpp index e568c838b7b0..918068a2405f 100644 --- a/clang/lib/Index/CommentToXML.cpp +++ b/clang/lib/Index/CommentToXML.cpp @@ -579,6 +579,7 @@ void getSourceTextOfDeclaration(const DeclInfo *ThisDecl, PrintingPolicy PPolicy(LangOpts); PPolicy.PolishForDeclaration = true; PPolicy.TerseOutput = true; + PPolicy.ConstantsAsWritten = true; ThisDecl->CurrentDecl->print(OS, PPolicy, /*Indentation*/0, /*PrintInstantiation*/false); } diff --git a/clang/test/Index/comment-to-html-xml-conversion-with-original-literals.cpp b/clang/test/Index/comment-to-html-xml-conversion-with-original-literals.cpp new file mode 100644 index 000000000000..26ca2238834e --- /dev/null +++ b/clang/test/Index/comment-to-html-xml-conversion-with-original-literals.cpp @@ -0,0 +1,26 @@ +// RUN: c-index-test -test-load-source all -comments-xml-schema=%S/../../bindings/xml/comment-xml-schema.rng %s -std=c++11 | FileCheck %s + +constexpr int value(float f) { return int(f); } + +enum MyEnum { +hexadecimal = 0x10 //!< a +// CHECK: hexadecimal = 0x10 + +, withSuffix = 1u + 010 //!< b +// CHECK: withSuffix = 1u + 010 + +#define ARG(x) x +, macroArg = ARG(0x1) //!< c +// CHECK: macroArg = ARG(0x1) + +#define MACROCONCAT(x, y) 22##x##y +, macroConcat = MACROCONCAT(3, 2) //!< d +// CHECK: macroConcat = MACROCONCAT(3, 2) + +#define MACRO(a,n) = 0x##a##n +, weirdMacros MACRO(2,1) //!< e +// CHECK: weirdMacros = 33 + +, floatLiteral = value(0.25e3) //!< f +// CHECK: floatLiteral = value(0.25e3) +};