From: Eli Friedman Date: Sat, 30 May 2009 00:19:54 +0000 (+0000) Subject: Some enhancements to DeclStmt printing. Some of this should X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=db23b154bb62e95e63c6412965835a510c7771d1;p=clang Some enhancements to DeclStmt printing. Some of this should move to DeclPrinter.cpp, but I haven't quite worked out how best to do that. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72599 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index fc9fdf975d..7fe1524c58 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -56,11 +56,15 @@ namespace { } IndentLevel -= SubIndent; } - + + QualType GetBaseType(QualType T); + void PrintBaseType(QualType T, TagDecl* TD); + void PrintDeclIdentifier(NamedDecl* ND); void PrintRawCompoundStmt(CompoundStmt *S); void PrintRawDecl(Decl *D); void PrintRawDeclStmt(DeclStmt *S); void PrintFieldDecl(FieldDecl *FD); + void PrintEnumConstantDecl(EnumConstantDecl *ECD); void PrintRawIfStmt(IfStmt *If); void PrintRawCXXCatchStmt(CXXCatchStmt *Catch); @@ -112,6 +116,57 @@ void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) { Indent() << "}"; } +QualType StmtPrinter::GetBaseType(QualType T) { + // FIXME: This should be on the Type class! + QualType BaseType = T; + while (!BaseType->isSpecifierType()) { + if (isa(BaseType)) + break; + else if (const PointerType* PTy = BaseType->getAsPointerType()) + BaseType = PTy->getPointeeType(); + else if (const ArrayType* ATy = dyn_cast(BaseType)) + BaseType = ATy->getElementType(); + else if (const FunctionType* FTy = BaseType->getAsFunctionType()) + BaseType = FTy->getResultType(); + else + assert(0 && "Unknown declarator!"); + } + return BaseType; +} + +void StmtPrinter::PrintBaseType(QualType BaseType, TagDecl* TD) { + std::string BaseString; + if (TD && TD->isDefinition()) { + // FIXME: This is an ugly hack; perhaps we can expose something better + // from Type.h? + if (BaseType.isConstQualified()) + OS << "const "; + PrintRawDecl(TD); + OS << " "; + } else { + BaseType.getAsStringInternal(BaseString, Policy); + OS << BaseString << " "; + } +} + +void StmtPrinter::PrintDeclIdentifier(NamedDecl* ND) { + std::string Name = ND->getNameAsString(); + + QualType Ty; + if (TypedefDecl* TDD = dyn_cast(ND)) { + Ty = TDD->getUnderlyingType(); + } else if (ValueDecl* VD = dyn_cast(ND)) { + Ty = VD->getType(); + } else { + assert(0 && "Unexpected decl"); + } + + PrintingPolicy SubPolicy(Policy); + SubPolicy.SuppressTypeSpecifiers = true; + Ty.getAsStringInternal(Name, SubPolicy); + OS << Name; +} + void StmtPrinter::PrintRawDecl(Decl *D) { // FIXME: Need to complete/beautify this... this code simply shows the // nodes are where they need to be. @@ -143,16 +198,28 @@ void StmtPrinter::PrintRawDecl(Decl *D) { OS << " "; if (const IdentifierInfo *II = TD->getIdentifier()) OS << II->getName(); - if (RecordDecl *RD = dyn_cast(TD)) { - OS << "{\n"; - IndentLevel += 1; - // FIXME: The context passed to field_begin/field_end should - // never be NULL! - ASTContext *Context = 0; - for (RecordDecl::field_iterator i = RD->field_begin(*Context); - i != RD->field_end(*Context); ++i) { - PrintFieldDecl(*i); - IndentLevel -= 1; + if (TD->isDefinition()) { + if (RecordDecl *RD = dyn_cast(TD)) { + OS << "{\n"; + IndentLevel += 1; + // FIXME: The context passed to field_begin/field_end should + // never be NULL! + ASTContext *Context = 0; + for (RecordDecl::field_iterator i = RD->field_begin(*Context); + i != RD->field_end(*Context); ++i) + PrintFieldDecl(*i); + IndentLevel -= 1; + Indent() << "}"; + } else if (EnumDecl *ED = dyn_cast(TD)) { + OS << "{\n"; + IndentLevel += 1; + // FIXME: The context shouldn't be NULL! + ASTContext *Context = 0; + for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Context); + i != ED->enumerator_end(*Context); ++i) + PrintEnumConstantDecl(*i); + IndentLevel -= 1; + Indent() << "}"; } } } else { @@ -161,19 +228,72 @@ void StmtPrinter::PrintRawDecl(Decl *D) { } void StmtPrinter::PrintFieldDecl(FieldDecl *FD) { - Indent() << FD->getNameAsString() << "\n"; + Indent(); + QualType BaseType = GetBaseType(FD->getType()); + PrintBaseType(BaseType, 0); + PrintDeclIdentifier(FD); + if (FD->isBitField()) { + OS << " : "; + PrintExpr(FD->getBitWidth()); + } + OS << ";\n"; +} + +void StmtPrinter::PrintEnumConstantDecl(EnumConstantDecl *ECD) { + Indent() << ECD->getNameAsString(); + if (ECD->getInitExpr()) { + OS << " = "; + PrintExpr(ECD->getInitExpr()); + } + OS << ",\n"; } void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) { + DeclStmt::decl_iterator Begin = S->decl_begin(), End = S->decl_end(); + + TagDecl* TD = dyn_cast(*Begin); + if (TD) + ++Begin; + + if (isa(*Begin)) + OS << "typedef "; + else if (VarDecl *V = dyn_cast(*Begin)) { + switch (V->getStorageClass()) { + default: assert(0 && "Unknown storage class!"); + case VarDecl::None: break; + case VarDecl::Auto: OS << "auto "; break; + case VarDecl::Register: OS << "register "; break; + case VarDecl::Extern: OS << "extern "; break; + case VarDecl::Static: OS << "static "; break; + case VarDecl::PrivateExtern: OS << "__private_extern__ "; break; + } + } else if (FunctionDecl *V = dyn_cast(*Begin)) { + switch (V->getStorageClass()) { + default: assert(0 && "Unknown storage class!"); + case FunctionDecl::None: break; + case FunctionDecl::Extern: OS << "extern "; break; + case FunctionDecl::Static: OS << "static "; break; + case FunctionDecl::PrivateExtern: OS << "__private_extern__ "; break; + } + } else { + assert(0 && "Unhandled decl"); + } + + QualType BaseType; + if (ValueDecl* VD = dyn_cast(*Begin)) { + BaseType = VD->getType(); + } else { + BaseType = cast(*Begin)->getUnderlyingType(); + } + BaseType = GetBaseType(BaseType); + PrintBaseType(BaseType, TD); + bool isFirst = true; - - for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); - I != E; ++I) { - + for ( ; Begin != End; ++Begin) { if (!isFirst) OS << ", "; else isFirst = false; - - PrintRawDecl(*I); + + PrintDeclIdentifier(cast(*Begin)); } } @@ -182,12 +302,9 @@ void StmtPrinter::VisitNullStmt(NullStmt *Node) { } void StmtPrinter::VisitDeclStmt(DeclStmt *Node) { - for (DeclStmt::decl_iterator I = Node->decl_begin(), E = Node->decl_end(); - I!=E; ++I) { - Indent(); - PrintRawDecl(*I); - OS << ";\n"; - } + Indent(); + PrintRawDeclStmt(Node); + OS << ";\n"; } void StmtPrinter::VisitCompoundStmt(CompoundStmt *Node) {