aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/DeclPrinter.cpp
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2009-05-30 04:20:30 +0000
committerEli Friedman <eli.friedman@gmail.com>2009-05-30 04:20:30 +0000
commit42f42c0dd5cf71fbfc6fa282d03079a902f6e342 (patch)
tree0bf46b5d106a78443812a898b3e72e44d9120ead /lib/AST/DeclPrinter.cpp
parent4572baba9d18c275968ac113fd73b0e3c77cccb8 (diff)
Expose an API to print a group of decls (like "int a,b;").
Make StmtPrinter use DeclPrinter to print all declarations. Merge declarations in the limited case of an unnamed TagDecl followed by one or more declarations using that TagDecl directly. Change SuppressTypeSpecifiers to the more general SuppressSpecifiers, and use it to suppress stuff like "typedef" and "extern". Replace OwnedTag with SuppressTag, since it's more convenient to print declarations from DeclPrinter at the moment. improvements to declaration printing. Fix pretty-printing for K&R function definitions and __builtin_va_arg. We're now to the point where the pretty-printing output for non-trivial programs can actually be piped back into clang. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72608 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/DeclPrinter.cpp')
-rw-r--r--lib/AST/DeclPrinter.cpp143
1 files changed, 129 insertions, 14 deletions
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index b665e2e0e1..950dd9e223 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -32,6 +32,7 @@ namespace {
unsigned Indentation;
llvm::raw_ostream& Indent();
+ void ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls);
public:
DeclPrinter(llvm::raw_ostream &Out, ASTContext &Context,
@@ -79,6 +80,67 @@ void Decl::print(llvm::raw_ostream &Out, ASTContext &Context,
Printer.Visit(this);
}
+static QualType GetBaseType(QualType T) {
+ // FIXME: This should be on the Type class!
+ QualType BaseType = T;
+ while (!BaseType->isSpecifierType()) {
+ if (isa<TypedefType>(BaseType))
+ break;
+ else if (const PointerType* PTy = BaseType->getAsPointerType())
+ BaseType = PTy->getPointeeType();
+ else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
+ BaseType = ATy->getElementType();
+ else if (const FunctionType* FTy = BaseType->getAsFunctionType())
+ BaseType = FTy->getResultType();
+ else
+ assert(0 && "Unknown declarator!");
+ }
+ return BaseType;
+}
+
+static QualType getDeclType(Decl* D) {
+ if (TypedefDecl* TDD = dyn_cast<TypedefDecl>(D))
+ return TDD->getUnderlyingType();
+ if (ValueDecl* VD = dyn_cast<ValueDecl>(D))
+ return VD->getType();
+ return QualType();
+}
+
+void Decl::printGroup(Decl** Begin, unsigned NumDecls,
+ llvm::raw_ostream &Out, ASTContext &Context,
+ const PrintingPolicy &Policy,
+ unsigned Indentation) {
+ if (NumDecls == 1) {
+ (*Begin)->print(Out, Context, Policy, Indentation);
+ return;
+ }
+
+ Decl** End = Begin + NumDecls;
+ TagDecl* TD = dyn_cast<TagDecl>(*Begin);
+ if (TD)
+ ++Begin;
+
+ PrintingPolicy SubPolicy(Policy);
+ if (TD && TD->isDefinition()) {
+ TD->print(Out, Context, Policy, Indentation);
+ Out << " ";
+ SubPolicy.SuppressTag = true;
+ }
+
+ bool isFirst = true;
+ for ( ; Begin != End; ++Begin) {
+ if (isFirst) {
+ SubPolicy.SuppressSpecifiers = false;
+ isFirst = false;
+ } else {
+ if (!isFirst) Out << ", ";
+ SubPolicy.SuppressSpecifiers = true;
+ }
+
+ (*Begin)->print(Out, Context, SubPolicy, Indentation);
+ }
+}
+
void Decl::dump(ASTContext &Context) {
print(llvm::errs(), Context);
}
@@ -89,6 +151,15 @@ llvm::raw_ostream& DeclPrinter::Indent() {
return Out;
}
+void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) {
+ this->Indent();
+ Decl::printGroup(Decls.data(), Decls.size(), Out, Context,
+ Policy, Indentation);
+ Out << ";\n";
+ Decls.clear();
+
+}
+
//----------------------------------------------------------------------------
// Common C declarations
//----------------------------------------------------------------------------
@@ -97,9 +168,38 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
if (Indent)
Indentation += Policy.Indentation;
+ llvm::SmallVector<Decl*, 2> Decls;
for (DeclContext::decl_iterator D = DC->decls_begin(Context),
DEnd = DC->decls_end(Context);
D != DEnd; ++D) {
+ // The next bits of code handles stuff like "struct {int x;} a,b"; we're
+ // forced to merge the declarations because there's no other way to
+ // refer to the struct in question. This limited merging is safe without
+ // a bunch of other checks because it only merges declarations directly
+ // referring to the tag, not typedefs.
+ //
+ // Check whether the current declaration should be grouped with a previous
+ // unnamed struct.
+ QualType CurDeclType = getDeclType(*D);
+ if (!Decls.empty() && !CurDeclType.isNull()) {
+ QualType BaseType = GetBaseType(CurDeclType);
+ if (!BaseType.isNull() && isa<TagType>(BaseType) &&
+ cast<TagType>(BaseType)->getDecl() == Decls[0]) {
+ Decls.push_back(*D);
+ continue;
+ }
+ }
+
+ // If we have a merged group waiting to be handled, handle it now.
+ if (!Decls.empty())
+ ProcessDeclGroup(Decls);
+
+ // If the current declaration is an unnamed tag type, save it
+ // so we can merge it with the subsequent declaration(s) using it.
+ if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
+ Decls.push_back(*D);
+ continue;
+ }
this->Indent();
Visit(*D);
@@ -130,6 +230,9 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
Out << "\n";
}
+ if (!Decls.empty())
+ ProcessDeclGroup(Decls);
+
if (Indent)
Indentation -= Policy.Indentation;
}
@@ -141,7 +244,9 @@ void DeclPrinter::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) {
std::string S = D->getNameAsString();
D->getUnderlyingType().getAsStringInternal(S, Policy);
- Out << "typedef " << S;
+ if (!Policy.SuppressSpecifiers)
+ Out << "typedef ";
+ Out << S;
}
void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
@@ -153,8 +258,10 @@ void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
void DeclPrinter::VisitRecordDecl(RecordDecl *D) {
// print a free standing tag decl (e.g. "struct x;").
Out << D->getKindName();
- Out << " ";
- Out << D->getNameAsString();
+ if (D->getIdentifier()) {
+ Out << " ";
+ Out << D->getNameAsString();
+ }
if (D->isDefinition()) {
Out << " {\n";
@@ -172,15 +279,17 @@ void DeclPrinter::VisitEnumConstantDecl(EnumConstantDecl *D) {
}
void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
- switch (D->getStorageClass()) {
- case FunctionDecl::None: break;
- case FunctionDecl::Extern: Out << "extern "; break;
- case FunctionDecl::Static: Out << "static "; break;
- case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
- }
+ if (!Policy.SuppressSpecifiers) {
+ switch (D->getStorageClass()) {
+ case FunctionDecl::None: break;
+ case FunctionDecl::Extern: Out << "extern "; break;
+ case FunctionDecl::Static: Out << "static "; break;
+ case FunctionDecl::PrivateExtern: Out << "__private_extern__ "; break;
+ }
- if (D->isInline()) Out << "inline ";
- if (D->isVirtualAsWritten()) Out << "virtual ";
+ if (D->isInline()) Out << "inline ";
+ if (D->isVirtualAsWritten()) Out << "virtual ";
+ }
std::string Proto = D->getNameAsString();
if (isa<FunctionType>(D->getType().getTypePtr())) {
@@ -203,6 +312,12 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
if (D->getNumParams()) POut << ", ";
POut << "...";
}
+ } else if (D->isThisDeclarationADefinition() && !D->hasPrototype()) {
+ for (unsigned i = 0, e = D->getNumParams(); i != e; ++i) {
+ if (i)
+ Proto += ", ";
+ Proto += D->getParamDecl(i)->getNameAsString();
+ }
}
Proto += ")";
@@ -238,7 +353,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
}
void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
- if (D->isMutable())
+ if (!Policy.SuppressSpecifiers && D->isMutable())
Out << "mutable ";
std::string Name = D->getNameAsString();
@@ -252,10 +367,10 @@ void DeclPrinter::VisitFieldDecl(FieldDecl *D) {
}
void DeclPrinter::VisitVarDecl(VarDecl *D) {
- if (D->getStorageClass() != VarDecl::None)
+ if (!Policy.SuppressSpecifiers && D->getStorageClass() != VarDecl::None)
Out << VarDecl::getStorageClassSpecifierString(D->getStorageClass()) << " ";
- if (D->isThreadSpecified())
+ if (!Policy.SuppressSpecifiers && D->isThreadSpecified())
Out << "__thread ";
std::string Name = D->getNameAsString();