Index: cfe/trunk/include/clang/AST/PrettyPrinter.h =================================================================== --- cfe/trunk/include/clang/AST/PrettyPrinter.h +++ cfe/trunk/include/clang/AST/PrettyPrinter.h @@ -36,7 +36,8 @@ /// \brief Create a default printing policy for C. PrintingPolicy(const LangOptions &LO) : LangOpts(LO), Indentation(2), SuppressSpecifiers(false), - SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), + SuppressTagKeyword(false), + IncludeTagDefinition(false), SuppressScope(false), SuppressUnwrittenScope(false), SuppressInitializers(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), @@ -77,15 +78,15 @@ /// \endcode bool SuppressTagKeyword : 1; - /// \brief Whether type printing should skip printing the actual tag type. + /// \brief When true, include the body of a tag definition. /// - /// This is used when the caller needs to print a tag definition in front - /// of the type, as in constructs like the following: + /// This is used to place the definition of a struct + /// in the middle of another declaration as with: /// /// \code /// typedef struct { int x, y; } Point; /// \endcode - bool SuppressTag : 1; + bool IncludeTagDefinition : 1; /// \brief Suppresses printing of scope specifiers. bool SuppressScope : 1; Index: cfe/trunk/include/clang/AST/Type.h =================================================================== --- cfe/trunk/include/clang/AST/Type.h +++ cfe/trunk/include/clang/AST/Type.h @@ -909,16 +909,19 @@ std::string getAsString(const PrintingPolicy &Policy) const; void print(raw_ostream &OS, const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine()) const { - print(split(), OS, Policy, PlaceHolder); + const Twine &PlaceHolder = Twine(), + unsigned Indentation = 0) const { + print(split(), OS, Policy, PlaceHolder, Indentation); } static void print(SplitQualType split, raw_ostream &OS, - const PrintingPolicy &policy, const Twine &PlaceHolder) { - return print(split.Ty, split.Quals, OS, policy, PlaceHolder); + const PrintingPolicy &policy, const Twine &PlaceHolder, + unsigned Indentation = 0) { + return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); } static void print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder); + const Twine &PlaceHolder, + unsigned Indentation = 0); void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const { @@ -936,21 +939,24 @@ const QualType &T; const PrintingPolicy &Policy; const Twine &PlaceHolder; + unsigned Indentation; public: StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, - const Twine &PlaceHolder) - : T(T), Policy(Policy), PlaceHolder(PlaceHolder) { } + const Twine &PlaceHolder, unsigned Indentation) + : T(T), Policy(Policy), PlaceHolder(PlaceHolder), + Indentation(Indentation) { } friend raw_ostream &operator<<(raw_ostream &OS, const StreamedQualTypeHelper &SQT) { - SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder); + SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder, SQT.Indentation); return OS; } }; StreamedQualTypeHelper stream(const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine()) const { - return StreamedQualTypeHelper(*this, Policy, PlaceHolder); + const Twine &PlaceHolder = Twine(), + unsigned Indentation = 0) const { + return StreamedQualTypeHelper(*this, Policy, PlaceHolder, Indentation); } void dump(const char *s) const; Index: cfe/trunk/lib/AST/DeclPrinter.cpp =================================================================== --- cfe/trunk/lib/AST/DeclPrinter.cpp +++ cfe/trunk/lib/AST/DeclPrinter.cpp @@ -160,19 +160,17 @@ ++Begin; PrintingPolicy SubPolicy(Policy); - if (TD && TD->isCompleteDefinition()) { - TD->print(Out, Policy, Indentation); - Out << " "; - SubPolicy.SuppressTag = true; - } bool isFirst = true; for ( ; Begin != End; ++Begin) { if (isFirst) { + if(TD) + SubPolicy.IncludeTagDefinition = true; SubPolicy.SuppressSpecifiers = false; isFirst = false; } else { if (!isFirst) Out << ", "; + SubPolicy.IncludeTagDefinition = false; SubPolicy.SuppressSpecifiers = true; } @@ -246,7 +244,7 @@ Pack = true; T = PET->getPattern(); } - T.print(Out, Policy, (Pack ? "..." : "") + DeclName); + T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation); } void DeclPrinter::ProcessDeclGroup(SmallVectorImpl& Decls) { @@ -380,7 +378,8 @@ if (D->isModulePrivate()) Out << "__module_private__ "; } - D->getTypeSourceInfo()->getType().print(Out, Policy, D->getName()); + QualType Ty = D->getTypeSourceInfo()->getType(); + Ty.print(Out, Policy, D->getName(), Indentation); prettyPrintAttributes(D); } @@ -685,7 +684,7 @@ Out << "__module_private__ "; Out << D->getASTContext().getUnqualifiedObjCPointerType(D->getType()). - stream(Policy, D->getName()); + stream(Policy, D->getName(), Indentation); if (D->isBitField()) { Out << " : "; @@ -755,7 +754,7 @@ } PrintingPolicy SubPolicy(Policy); SubPolicy.SuppressSpecifiers = false; - SubPolicy.SuppressTag = false; + SubPolicy.IncludeTagDefinition = false; Init->printPretty(Out, nullptr, SubPolicy, Indentation); if ((D->getInitStyle() == VarDecl::CallInit) && !isa(Init)) Out << ")"; Index: cfe/trunk/lib/AST/TypePrinter.cpp =================================================================== --- cfe/trunk/lib/AST/TypePrinter.cpp +++ cfe/trunk/lib/AST/TypePrinter.cpp @@ -81,12 +81,14 @@ class TypePrinter { PrintingPolicy Policy; + unsigned Indentation; bool HasEmptyPlaceHolder; bool InsideCCAttribute; public: - explicit TypePrinter(const PrintingPolicy &Policy) - : Policy(Policy), HasEmptyPlaceHolder(false), InsideCCAttribute(false) { } + explicit TypePrinter(const PrintingPolicy &Policy, unsigned Indentation = 0) + : Policy(Policy), Indentation(Indentation), + HasEmptyPlaceHolder(false), InsideCCAttribute(false) { } void print(const Type *ty, Qualifiers qs, raw_ostream &OS, StringRef PlaceHolder); @@ -411,7 +413,7 @@ OS << '('; PrintingPolicy InnerPolicy(Policy); - InnerPolicy.SuppressTag = false; + InnerPolicy.IncludeTagDefinition = false; TypePrinter(InnerPolicy).print(QualType(T->getClass(), 0), OS, StringRef()); OS << "::*"; @@ -934,8 +936,13 @@ } void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) { - if (Policy.SuppressTag) + if (Policy.IncludeTagDefinition) { + PrintingPolicy SubPolicy = Policy; + SubPolicy.IncludeTagDefinition = false; + D->print(OS, SubPolicy, Indentation); + spaceBeforePlaceHolder(OS); return; + } bool HasKindDecoration = false; @@ -1090,14 +1097,16 @@ void TypePrinter::printElaboratedBefore(const ElaboratedType *T, raw_ostream &OS) { - if (Policy.SuppressTag && isa(T->getNamedType())) - return; - OS << TypeWithKeyword::getKeywordName(T->getKeyword()); - if (T->getKeyword() != ETK_None) - OS << " "; - NestedNameSpecifier* Qualifier = T->getQualifier(); - if (Qualifier) - Qualifier->print(OS, Policy); + // The tag definition will take care of these. + if (!Policy.IncludeTagDefinition) + { + OS << TypeWithKeyword::getKeywordName(T->getKeyword()); + if (T->getKeyword() != ETK_None) + OS << " "; + NestedNameSpecifier* Qualifier = T->getQualifier(); + if (Qualifier) + Qualifier->print(OS, Policy); + } ElaboratedTypePolicyRAII PolicyRAII(Policy); printBefore(T->getNamedType(), OS); @@ -1654,11 +1663,11 @@ void QualType::print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder) { + const Twine &PlaceHolder, unsigned Indentation) { SmallString<128> PHBuf; StringRef PH = PlaceHolder.toStringRef(PHBuf); - TypePrinter(policy).print(ty, qs, OS, PH); + TypePrinter(policy, Indentation).print(ty, qs, OS, PH); } void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, Index: cfe/trunk/test/Sema/ast-print.c =================================================================== --- cfe/trunk/test/Sema/ast-print.c +++ cfe/trunk/test/Sema/ast-print.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -ast-print | FileCheck %s +// RUN: %clang_cc1 %s -ast-print | %clang_cc1 -fsyntax-only - typedef void func_typedef(); func_typedef xxx; @@ -39,6 +40,7 @@ return a[2]; } +// CHECK: typedef struct { typedef struct { int f; } T __attribute__ ((__aligned__));