diff options
-rw-r--r-- | include/clang/AST/DeclBase.h | 4 | ||||
-rw-r--r-- | include/clang/AST/PrettyPrinter.h | 39 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 143 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 191 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 7 |
5 files changed, 161 insertions, 223 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index c25f467715..c061b85706 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -314,6 +314,10 @@ public: unsigned Indentation = 0); void print(llvm::raw_ostream &Out, ASTContext &Context, const PrintingPolicy &Policy, unsigned Indentation = 0); + static void printGroup(Decl** Begin, unsigned NumDecls, + llvm::raw_ostream &Out, ASTContext &Context, + const PrintingPolicy &Policy, + unsigned Indentation = 0); void dump(ASTContext &Context); private: diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index dcbb823056..385602b1fb 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -34,8 +34,8 @@ public: struct PrintingPolicy { /// \brief Create a default printing policy for C. PrintingPolicy() - : Indentation(2), CPlusPlus(false), SuppressTypeSpecifiers(false), - SuppressTagKind(false), Dump(false), OwnedTag(0) { } + : Indentation(2), CPlusPlus(false), SuppressSpecifiers(false), + SuppressTag(false), SuppressTagKind(false), Dump(false) { } /// \brief The number of spaces to use to indent each line. unsigned Indentation : 8; @@ -44,8 +44,8 @@ struct PrintingPolicy { /// printing C code). bool CPlusPlus : 1; - /// \brief Whether we should suppress printing of the actual type - /// specifiers within the type that we are printing. + /// \brief Whether we should suppress printing of the actual specifiers for + /// the given type or declaration. /// /// This flag is only used when we are printing declarators beyond /// the first declarator within a declaration group. For example, given: @@ -54,11 +54,21 @@ struct PrintingPolicy { /// const int *x, *y; /// \endcode /// - /// SuppressTypeSpecifiers will be false when printing the + /// SuppressSpecifiers will be false when printing the /// declaration for "x", so that we will print "int *x"; it will be /// \c true when we print "y", so that we suppress printing the /// "const int" type specifier and instead only print the "*y". - bool SuppressTypeSpecifiers : 1; + bool SuppressSpecifiers : 1; + + /// \brief Whether type printing should skip printing the actual tag type. + /// + /// This is used when the caller needs to print a tag definition in front + /// of the type, as in constructs like the following: + /// + /// \code + /// typedef struct { int x, y; } Point; + /// \endcode + bool SuppressTag : 1; /// \brief If we are printing a tag type, suppresses printing of the /// kind of tag, e.g., "struct", "union", "enum". @@ -69,23 +79,6 @@ struct PrintingPolicy { /// and pretty-printing involves printing something similar to /// source code. bool Dump : 1; - - /// \brief If we are printing a type where the tag type (e.g., a - /// class or enum type) was declared or defined within the type - /// itself, OwnedTag will point at the declaration node owned by - /// this type. - /// - /// Owned tags occur when a tag type is defined as part of the - /// declaration specifiers of another declarator, e.g., - /// - /// \code - /// typedef struct { int x, y; } Point; - /// \endcode - /// - /// Here, the anonymous struct definition is owned by the type of - /// Point. The actual representation uses a DeclGroup to store both - /// the RecordDecl and the TypedefDecl. - TagDecl *OwnedTag; }; } // end namespace clang 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(); diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 113cbb48dd..a698688e6c 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -57,14 +57,9 @@ 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); @@ -116,190 +111,18 @@ 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<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; -} - -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<TypedefDecl>(ND)) { - Ty = TDD->getUnderlyingType(); - } else if (ValueDecl* VD = dyn_cast<ValueDecl>(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. - if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) { - OS << "typedef " << localType->getUnderlyingType().getAsString(); - OS << " " << localType->getNameAsString(); - } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { - // Emit storage class for vardecls. - if (VarDecl *V = dyn_cast<VarDecl>(VD)) { - if (V->getStorageClass() != VarDecl::None) - OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass()) - << ' '; - } - - std::string Name = VD->getNameAsString(); - VD->getType().getAsStringInternal(Name, Policy); - OS << Name; - - // If this is a vardecl with an initializer, emit it. - if (VarDecl *V = dyn_cast<VarDecl>(VD)) { - if (V->getInit()) { - OS << " = "; - PrintExpr(V->getInit()); - } - } - } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - // print a free standing tag decl (e.g. "struct x;"). - OS << TD->getKindName(); - OS << " "; - if (const IdentifierInfo *II = TD->getIdentifier()) - OS << II->getName(); - if (TD->isDefinition()) { - if (RecordDecl *RD = dyn_cast<RecordDecl>(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<EnumDecl>(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 { - assert(0 && "Unexpected decl"); - } -} - -void StmtPrinter::PrintFieldDecl(FieldDecl *FD) { - 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"; + D->print(OS, *(ASTContext*)0, Policy, IndentLevel); } void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) { DeclStmt::decl_iterator Begin = S->decl_begin(), End = S->decl_end(); + llvm::SmallVector<Decl*, 2> Decls; + for ( ; Begin != End; ++Begin) + Decls.push_back(*Begin); - TagDecl* TD = dyn_cast<TagDecl>(*Begin); - if (TD) - ++Begin; - - if (Begin == End) { - PrintRawDecl(TD); - return; - } - - if (isa<TypedefDecl>(*Begin)) - OS << "typedef "; - else if (VarDecl *V = dyn_cast<VarDecl>(*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<FunctionDecl>(*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<ValueDecl>(*Begin)) { - BaseType = VD->getType(); - } else { - BaseType = cast<TypedefDecl>(*Begin)->getUnderlyingType(); - } - BaseType = GetBaseType(BaseType); - PrintBaseType(BaseType, TD); - - bool isFirst = true; - for ( ; Begin != End; ++Begin) { - if (!isFirst) OS << ", "; - else isFirst = false; - - PrintDeclIdentifier(cast<NamedDecl>(*Begin)); - } + Decl::printGroup(Decls.data(), Decls.size(), OS, *(ASTContext*)0, Policy, + IndentLevel); } void StmtPrinter::VisitNullStmt(NullStmt *Node) { @@ -1042,7 +865,7 @@ void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) { } void StmtPrinter::VisitVAArgExpr(VAArgExpr *Node) { - OS << "va_arg("; + OS << "__builtin_va_arg("; PrintExpr(Node->getSubExpr()); OS << ", "; OS << Node->getType().getAsString(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index f7eb41c28b..b2ee58f3f3 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1168,7 +1168,7 @@ QualType::getAsStringInternal(std::string &S, return; } - if (Policy.SuppressTypeSpecifiers && getTypePtr()->isSpecifierType()) + if (Policy.SuppressSpecifiers && getTypePtr()->isSpecifierType()) return; // Print qualifiers as appropriate. @@ -1398,7 +1398,7 @@ void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy S += "("; std::string Tmp; PrintingPolicy ParamPolicy(Policy); - ParamPolicy.SuppressTypeSpecifiers = false; + ParamPolicy.SuppressSpecifiers = false; for (unsigned i = 0, e = getNumArgs(); i != e; ++i) { if (i) S += ", "; getArgType(i).getAsStringInternal(Tmp, ParamPolicy); @@ -1592,6 +1592,9 @@ void ObjCQualifiedIdType::getAsStringInternal(std::string &InnerString, const Pr } void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { + if (Policy.SuppressTag) + return; + if (!InnerString.empty()) // Prefix the basic type, e.g. 'typedefname X'. InnerString = ' ' + InnerString; |