r263836 - Fix printing of anonymous struct typedefs.

Steven Watanabe via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 18 14:35:59 PDT 2016


Author: steven_watanabe
Date: Fri Mar 18 16:35:59 2016
New Revision: 263836

URL: http://llvm.org/viewvc/llvm-project?rev=263836&view=rev
Log:
Fix printing of anonymous struct typedefs.

clang -cc1 -ast-print put the struct
definition in the wrong place, like this:

  struct {} typedef S;

The reason that this happens is that the printing code
first prints the struct definition, and then tells the next
declaration to leave out the type. This behavior
is correct for simple variable declarations, but fails for
typedefs (or extern, mutable, etc).

The patch address this problem by skipping the struct
declaration when we first see it, and then telling the first
subsequent declaration that it needs to print out the full
struct definition.

Differential Revision: http://reviews.llvm.org/D17285

Modified:
    cfe/trunk/include/clang/AST/PrettyPrinter.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/test/Sema/ast-print.c

Modified: cfe/trunk/include/clang/AST/PrettyPrinter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/PrettyPrinter.h?rev=263836&r1=263835&r2=263836&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/PrettyPrinter.h (original)
+++ cfe/trunk/include/clang/AST/PrettyPrinter.h Fri Mar 18 16:35:59 2016
@@ -36,7 +36,8 @@ struct PrintingPolicy {
   /// \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 @@ struct PrintingPolicy {
   /// \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;

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=263836&r1=263835&r2=263836&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Mar 18 16:35:59 2016
@@ -909,16 +909,19 @@ public:
   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 @@ public:
     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;

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=263836&r1=263835&r2=263836&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Fri Mar 18 16:35:59 2016
@@ -160,19 +160,17 @@ void Decl::printGroup(Decl** Begin, unsi
     ++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 @@ void DeclPrinter::printDeclType(QualType
     Pack = true;
     T = PET->getPattern();
   }
-  T.print(Out, Policy, (Pack ? "..." : "") + DeclName);
+  T.print(Out, Policy, (Pack ? "..." : "") + DeclName, Indentation);
 }
 
 void DeclPrinter::ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls) {
@@ -380,7 +378,8 @@ void DeclPrinter::VisitTypedefDecl(Typed
     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 @@ void DeclPrinter::VisitFieldDecl(FieldDe
     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 @@ void DeclPrinter::VisitVarDecl(VarDecl *
       }
       PrintingPolicy SubPolicy(Policy);
       SubPolicy.SuppressSpecifiers = false;
-      SubPolicy.SuppressTag = false;
+      SubPolicy.IncludeTagDefinition = false;
       Init->printPretty(Out, nullptr, SubPolicy, Indentation);
       if ((D->getInitStyle() == VarDecl::CallInit) && !isa<ParenListExpr>(Init))
         Out << ")";

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=263836&r1=263835&r2=263836&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Fri Mar 18 16:35:59 2016
@@ -81,12 +81,14 @@ namespace {
   
   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 @@ void TypePrinter::printMemberPointerBefo
     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::AppendScope(DeclContex
 }
 
 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::printInjectedClassName
 
 void TypePrinter::printElaboratedBefore(const ElaboratedType *T,
                                         raw_ostream &OS) {
-  if (Policy.SuppressTag && isa<TagType>(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 @@ std::string QualType::getAsString(const
 
 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,

Modified: cfe/trunk/test/Sema/ast-print.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ast-print.c?rev=263836&r1=263835&r2=263836&view=diff
==============================================================================
--- cfe/trunk/test/Sema/ast-print.c (original)
+++ cfe/trunk/test/Sema/ast-print.c Fri Mar 18 16:35:59 2016
@@ -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 @@ int rvarr(int n, int a[restrict static n
   return a[2];
 }
 
+// CHECK: typedef struct {
 typedef struct {
   int f;
 } T __attribute__ ((__aligned__));




More information about the cfe-commits mailing list