mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-02 23:50:19 +00:00
Add support for pretty-printing attributes, from Richard Membarth!
llvm-svn: 145002
This commit is contained in:
parent
9f39a765e2
commit
49ccfaa938
@ -23,6 +23,7 @@
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
@ -103,6 +104,9 @@ public:
|
||||
// Clone this attribute.
|
||||
virtual Attr* clone(ASTContext &C) const = 0;
|
||||
|
||||
// Pretty print this attribute.
|
||||
virtual void printPretty(llvm::raw_ostream &OS, ASTContext &C) const = 0;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Attr *) { return true; }
|
||||
};
|
||||
|
@ -85,6 +85,7 @@ namespace {
|
||||
|
||||
void PrintTemplateParameters(const TemplateParameterList *Params,
|
||||
const TemplateArgumentList *Args);
|
||||
void prettyPrintAttributes(Decl *D);
|
||||
};
|
||||
}
|
||||
|
||||
@ -182,6 +183,16 @@ raw_ostream& DeclPrinter::Indent(unsigned Indentation) {
|
||||
return Out;
|
||||
}
|
||||
|
||||
void DeclPrinter::prettyPrintAttributes(Decl *D) {
|
||||
if (D->hasAttrs()) {
|
||||
AttrVec &Attrs = D->getAttrs();
|
||||
for (AttrVec::const_iterator i=Attrs.begin(), e=Attrs.end(); i!=e; ++i) {
|
||||
Attr *A = *i;
|
||||
A->printPretty(Out, Context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
|
||||
this->Indent();
|
||||
Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation);
|
||||
@ -320,6 +331,7 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
|
||||
Out << "__module_private__ ";
|
||||
}
|
||||
Out << S;
|
||||
prettyPrintAttributes(D);
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) {
|
||||
@ -350,6 +362,7 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
|
||||
VisitDeclContext(D);
|
||||
Indent() << "}";
|
||||
}
|
||||
prettyPrintAttributes(D);
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
|
||||
@ -466,12 +479,6 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
}
|
||||
}
|
||||
|
||||
if (D->hasAttr<NoReturnAttr>())
|
||||
Proto += " __attribute((noreturn))";
|
||||
|
||||
if (D->hasAttr<ReturnsTwiceAttr>())
|
||||
Proto += " __attribute((returns_twice))";
|
||||
|
||||
if (CXXConstructorDecl *CDecl = dyn_cast<CXXConstructorDecl>(D)) {
|
||||
bool HasInitializerList = false;
|
||||
for (CXXConstructorDecl::init_const_iterator B = CDecl->init_begin(),
|
||||
@ -542,6 +549,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
||||
}
|
||||
|
||||
Out << Proto;
|
||||
prettyPrintAttributes(D);
|
||||
|
||||
if (D->isPure())
|
||||
Out << " = 0";
|
||||
@ -588,6 +596,7 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
|
||||
Out << " = ";
|
||||
Init->printPretty(Out, Context, 0, Policy, Indentation);
|
||||
}
|
||||
prettyPrintAttributes(D);
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitLabelDecl(LabelDecl *D) {
|
||||
@ -624,6 +633,7 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) {
|
||||
if (D->hasCXXDirectInitializer())
|
||||
Out << ")";
|
||||
}
|
||||
prettyPrintAttributes(D);
|
||||
}
|
||||
|
||||
void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
|
||||
|
@ -98,6 +98,7 @@ namespace {
|
||||
virtual void writePCHReadArgs(raw_ostream &OS) const = 0;
|
||||
virtual void writePCHReadDecls(raw_ostream &OS) const = 0;
|
||||
virtual void writePCHWrite(raw_ostream &OS) const = 0;
|
||||
virtual void writeValue(raw_ostream &OS) const = 0;
|
||||
};
|
||||
|
||||
class SimpleArgument : public Argument {
|
||||
@ -136,6 +137,19 @@ namespace {
|
||||
OS << " " << WritePCHRecord(type, "SA->get" +
|
||||
std::string(getUpperName()) + "()");
|
||||
}
|
||||
void writeValue(raw_ostream &OS) const {
|
||||
if (type == "FunctionDecl *") {
|
||||
OS << "\" << get" << getUpperName() << "()->getNameInfo().getAsString() << \"";
|
||||
} else if (type == "IdentifierInfo *") {
|
||||
OS << "\" << get" << getUpperName() << "()->getName() << \"";
|
||||
} else if (type == "QualType") {
|
||||
OS << "\" << get" << getUpperName() << "().getAsString() << \"";
|
||||
} else if (type == "SourceLocation") {
|
||||
OS << "\" << get" << getUpperName() << "().getRawEncoding() << \"";
|
||||
} else {
|
||||
OS << "\" << get" << getUpperName() << "() << \"";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class StringArgument : public Argument {
|
||||
@ -190,6 +204,9 @@ namespace {
|
||||
void writePCHWrite(raw_ostream &OS) const {
|
||||
OS << " AddString(SA->get" << getUpperName() << "(), Record);\n";
|
||||
}
|
||||
void writeValue(raw_ostream &OS) const {
|
||||
OS << "\\\"\" << get" << getUpperName() << "() << \"\\\"";
|
||||
}
|
||||
};
|
||||
|
||||
class AlignedArgument : public Argument {
|
||||
@ -293,6 +310,9 @@ namespace {
|
||||
OS << " AddTypeSourceInfo(SA->get" << getUpperName()
|
||||
<< "Type(), Record);\n";
|
||||
}
|
||||
void writeValue(raw_ostream &OS) const {
|
||||
OS << "\" << get" << getUpperName() << "(Ctx) << \"";
|
||||
}
|
||||
};
|
||||
|
||||
class VariadicArgument : public Argument {
|
||||
@ -362,6 +382,18 @@ namespace {
|
||||
<< getLowerName() << "_end(); i != e; ++i)\n";
|
||||
OS << " " << WritePCHRecord(type, "(*i)");
|
||||
}
|
||||
void writeValue(raw_ostream &OS) const {
|
||||
OS << "\";\n";
|
||||
OS << " bool isFirst = true;\n"
|
||||
<< " for (" << getAttrName() << "Attr::" << getLowerName()
|
||||
<< "_iterator i = " << getLowerName() << "_begin(), e = "
|
||||
<< getLowerName() << "_end(); i != e; ++i) {\n"
|
||||
<< " if (isFirst) isFirst = false;\n"
|
||||
<< " else OS << \", \";\n"
|
||||
<< " OS << *i;\n"
|
||||
<< " }\n";
|
||||
OS << " OS << \"";
|
||||
}
|
||||
};
|
||||
|
||||
class EnumArgument : public Argument {
|
||||
@ -422,6 +454,9 @@ namespace {
|
||||
void writePCHWrite(raw_ostream &OS) const {
|
||||
OS << "Record.push_back(SA->get" << getUpperName() << "());\n";
|
||||
}
|
||||
void writeValue(raw_ostream &OS) const {
|
||||
OS << "\" << get" << getUpperName() << "() << \"";
|
||||
}
|
||||
};
|
||||
|
||||
class VersionArgument : public Argument {
|
||||
@ -463,6 +498,9 @@ namespace {
|
||||
void writePCHWrite(raw_ostream &OS) const {
|
||||
OS << " AddVersionTuple(SA->get" << getUpperName() << "(), Record);\n";
|
||||
}
|
||||
void writeValue(raw_ostream &OS) const {
|
||||
OS << getLowerName() << "=\" << get" << getUpperName() << "() << \"";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -511,6 +549,15 @@ static Argument *createArgument(Record &Arg, StringRef Attr,
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
static void writeAvailabilityValue(raw_ostream &OS) {
|
||||
OS << "\" << getPlatform()->getName();\n"
|
||||
<< " if (!getIntroduced().empty()) OS << \", introduced=\" << getIntroduced();\n"
|
||||
<< " if (!getDeprecated().empty()) OS << \", deprecated=\" << getDeprecated();\n"
|
||||
<< " if (!getObsoleted().empty()) OS << \", obsoleted=\" << getObsoleted();\n"
|
||||
<< " if (getUnavailable()) OS << \", unavailable\";\n"
|
||||
<< " OS << \"";
|
||||
}
|
||||
|
||||
void ClangAttrClassEmitter::run(raw_ostream &OS) {
|
||||
OS << "// This file is generated by TableGen. Do not edit.\n\n";
|
||||
OS << "#ifndef LLVM_CLANG_ATTR_CLASSES_INC\n";
|
||||
@ -571,6 +618,7 @@ void ClangAttrClassEmitter::run(raw_ostream &OS) {
|
||||
OS << " }\n\n";
|
||||
|
||||
OS << " virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
|
||||
OS << " virtual void printPretty(llvm::raw_ostream &OS, ASTContext &Ctx) const;\n";
|
||||
|
||||
for (ai = Args.begin(); ai != ae; ++ai) {
|
||||
(*ai)->writeAccessors(OS);
|
||||
@ -600,6 +648,7 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) {
|
||||
for (; i != e; ++i) {
|
||||
Record &R = **i;
|
||||
std::vector<Record*> ArgRecords = R.getValueAsListOfDefs("Args");
|
||||
std::vector<StringRef> Spellings = getValueAsListOfStrings(R, "Spellings");
|
||||
std::vector<Argument*> Args;
|
||||
for (ri = ArgRecords.begin(), re = ArgRecords.end(); ri != re; ++ri)
|
||||
Args.push_back(createArgument(**ri, R.getName()));
|
||||
@ -615,6 +664,24 @@ void ClangAttrImplEmitter::run(raw_ostream &OS) {
|
||||
(*ai)->writeCloneArgs(OS);
|
||||
}
|
||||
OS << ");\n}\n\n";
|
||||
|
||||
OS << "void " << R.getName() << "Attr::printPretty("
|
||||
<< "llvm::raw_ostream &OS, ASTContext &Ctx) const {\n";
|
||||
if (Spellings.begin() != Spellings.end()) {
|
||||
OS << " OS << \" __attribute__((" << *Spellings.begin();
|
||||
if (Args.size()) OS << "(";
|
||||
if (*Spellings.begin()=="availability") {
|
||||
writeAvailabilityValue(OS);
|
||||
} else {
|
||||
for (ai = Args.begin(); ai != ae; ++ai) {
|
||||
if (ai!=Args.begin()) OS <<", ";
|
||||
(*ai)->writeValue(OS);
|
||||
}
|
||||
}
|
||||
if (Args.size()) OS << ")";
|
||||
OS << "))\";\n";
|
||||
}
|
||||
OS << "}\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user