Print enum constant values using the original source formatting

if possible when creating "Declaration" nodes in XML comments

rdar://14765746

llvm-svn: 311085
This commit is contained in:
Alex Lorenz 2017-08-17 13:41:55 +00:00
parent 032e7f2cad
commit 36070ed8d2
6 changed files with 93 additions and 21 deletions

View File

@ -50,7 +50,8 @@ struct PrintingPolicy {
UseVoidForZeroParams(!LO.CPlusPlus), UseVoidForZeroParams(!LO.CPlusPlus),
TerseOutput(false), PolishForDeclaration(false), TerseOutput(false), PolishForDeclaration(false),
Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), 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 /// \brief Adjust this printing policy for cases where it's known that
/// we're printing C++ code (for instance, if AST dumping reaches a /// 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 /// prints anonymous namespaces as `anonymous namespace' and does not insert
/// spaces after template arguments. /// spaces after template arguments.
bool MSVCFormatting : 1; 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 } // end namespace clang

View File

@ -389,8 +389,8 @@ public:
/// back to its original source language syntax. /// back to its original source language syntax.
void dumpPretty(const ASTContext &Context) const; void dumpPretty(const ASTContext &Context) const;
void printPretty(raw_ostream &OS, PrinterHelper *Helper, void printPretty(raw_ostream &OS, PrinterHelper *Helper,
const PrintingPolicy &Policy, const PrintingPolicy &Policy, unsigned Indentation = 0,
unsigned Indentation = 0) const; const ASTContext *Context = nullptr) const;
/// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only
/// works on systems with GraphViz (Mac OS X) or dot+gv installed. /// works on systems with GraphViz (Mac OS X) or dot+gv installed.

View File

@ -28,6 +28,7 @@ namespace {
class DeclPrinter : public DeclVisitor<DeclPrinter> { class DeclPrinter : public DeclVisitor<DeclPrinter> {
raw_ostream &Out; raw_ostream &Out;
PrintingPolicy Policy; PrintingPolicy Policy;
const ASTContext &Context;
unsigned Indentation; unsigned Indentation;
bool PrintInstantiation; bool PrintInstantiation;
@ -48,9 +49,10 @@ namespace {
public: public:
DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy, DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation = 0, bool PrintInstantiation = false) const ASTContext &Context, unsigned Indentation = 0,
: Out(Out), Policy(Policy), Indentation(Indentation), bool PrintInstantiation = false)
PrintInstantiation(PrintInstantiation) { } : Out(Out), Policy(Policy), Context(Context), Indentation(Indentation),
PrintInstantiation(PrintInstantiation) {}
void VisitDeclContext(DeclContext *DC, bool Indent = true); 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, void Decl::print(raw_ostream &Out, const PrintingPolicy &Policy,
unsigned Indentation, bool PrintInstantiation) const { unsigned Indentation, bool PrintInstantiation) const {
DeclPrinter Printer(Out, Policy, Indentation, PrintInstantiation); DeclPrinter Printer(Out, Policy, getASTContext(), Indentation,
PrintInstantiation);
Printer.Visit(const_cast<Decl*>(this)); Printer.Visit(const_cast<Decl*>(this));
} }
@ -192,7 +195,7 @@ LLVM_DUMP_METHOD void DeclContext::dumpDeclContext() const {
DC = DC->getParent(); DC = DC->getParent();
ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext(); ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), 0); DeclPrinter Printer(llvm::errs(), Ctx.getPrintingPolicy(), Ctx, 0);
Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false); Printer.VisitDeclContext(const_cast<DeclContext *>(this), /*Indent=*/false);
} }
@ -467,7 +470,7 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
prettyPrintAttributes(D); prettyPrintAttributes(D);
if (Expr *Init = D->getInitExpr()) { if (Expr *Init = D->getInitExpr()) {
Out << " = "; 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(); Proto = GuideDecl->getDeducedTemplate()->getDeclName().getAsString();
if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) { if (const TemplateArgumentList *TArgs = D->getTemplateSpecializationArgs()) {
llvm::raw_string_ostream POut(Proto); llvm::raw_string_ostream POut(Proto);
DeclPrinter TArgPrinter(POut, SubPolicy, Indentation); DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
TArgPrinter.printTemplateArguments(*TArgs); TArgPrinter.printTemplateArguments(*TArgs);
} }
@ -539,7 +542,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
Proto += "("; Proto += "(";
if (FT) { if (FT) {
llvm::raw_string_ostream POut(Proto); 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) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
if (i) POut << ", "; if (i) POut << ", ";
ParamPrinter.VisitParmVarDecl(D->getParamDecl(i)); 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 // This is a K&R function definition, so we need to print the
// parameters. // parameters.
Out << '\n'; Out << '\n';
DeclPrinter ParamPrinter(Out, SubPolicy, Indentation); DeclPrinter ParamPrinter(Out, SubPolicy, Context, Indentation);
Indentation += Policy.Indentation; Indentation += Policy.Indentation;
for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) { for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
Indent(); Indent();

View File

@ -24,6 +24,7 @@
#include "clang/AST/PrettyPrinter.h" #include "clang/AST/PrettyPrinter.h"
#include "clang/AST/StmtVisitor.h" #include "clang/AST/StmtVisitor.h"
#include "clang/Basic/CharInfo.h" #include "clang/Basic/CharInfo.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/Support/Format.h" #include "llvm/Support/Format.h"
using namespace clang; using namespace clang;
@ -38,12 +39,14 @@ namespace {
unsigned IndentLevel; unsigned IndentLevel;
clang::PrinterHelper* Helper; clang::PrinterHelper* Helper;
PrintingPolicy Policy; PrintingPolicy Policy;
const ASTContext *Context;
public: public:
StmtPrinter(raw_ostream &os, PrinterHelper* helper, StmtPrinter(raw_ostream &os, PrinterHelper *helper,
const PrintingPolicy &Policy, const PrintingPolicy &Policy, unsigned Indentation = 0,
unsigned Indentation = 0) const ASTContext *Context = nullptr)
: OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy) {} : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
Context(Context) {}
void PrintStmt(Stmt *S) { void PrintStmt(Stmt *S) {
PrintStmt(S, Policy.Indentation); 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) { void StmtPrinter::VisitIntegerLiteral(IntegerLiteral *Node) {
if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
return;
bool isSigned = Node->getType()->isSignedIntegerType(); bool isSigned = Node->getType()->isSignedIntegerType();
OS << Node->getValue().toString(10, isSigned); OS << Node->getValue().toString(10, isSigned);
@ -1485,6 +1507,8 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
} }
void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) { void StmtPrinter::VisitFloatingLiteral(FloatingLiteral *Node) {
if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
return;
PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true); PrintFloatingLiteral(OS, Node, /*PrintSuffix=*/true);
} }
@ -2696,11 +2720,10 @@ void Stmt::dumpPretty(const ASTContext &Context) const {
printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts())); printPretty(llvm::errs(), nullptr, PrintingPolicy(Context.getLangOpts()));
} }
void Stmt::printPretty(raw_ostream &OS, void Stmt::printPretty(raw_ostream &OS, PrinterHelper *Helper,
PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation,
const PrintingPolicy &Policy, const ASTContext *Context) const {
unsigned Indentation) const { StmtPrinter P(OS, Helper, Policy, Indentation, Context);
StmtPrinter P(OS, Helper, Policy, Indentation);
P.Visit(const_cast<Stmt*>(this)); P.Visit(const_cast<Stmt*>(this));
} }

View File

@ -579,6 +579,7 @@ void getSourceTextOfDeclaration(const DeclInfo *ThisDecl,
PrintingPolicy PPolicy(LangOpts); PrintingPolicy PPolicy(LangOpts);
PPolicy.PolishForDeclaration = true; PPolicy.PolishForDeclaration = true;
PPolicy.TerseOutput = true; PPolicy.TerseOutput = true;
PPolicy.ConstantsAsWritten = true;
ThisDecl->CurrentDecl->print(OS, PPolicy, ThisDecl->CurrentDecl->print(OS, PPolicy,
/*Indentation*/0, /*PrintInstantiation*/false); /*Indentation*/0, /*PrintInstantiation*/false);
} }

View File

@ -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: <Declaration>hexadecimal = 0x10</Declaration>
, withSuffix = 1u + 010 //!< b
// CHECK: <Declaration>withSuffix = 1u + 010</Declaration>
#define ARG(x) x
, macroArg = ARG(0x1) //!< c
// CHECK: <Declaration>macroArg = ARG(0x1)</Declaration>
#define MACROCONCAT(x, y) 22##x##y
, macroConcat = MACROCONCAT(3, 2) //!< d
// CHECK: <Declaration>macroConcat = MACROCONCAT(3, 2)</Declaration>
#define MACRO(a,n) = 0x##a##n
, weirdMacros MACRO(2,1) //!< e
// CHECK: <Declaration>weirdMacros = 33</Declaration>
, floatLiteral = value(0.25e3) //!< f
// CHECK: <Declaration>floatLiteral = value(0.25e3)</Declaration>
};