jdenny updated this revision to Diff 142687.
jdenny added a comment.

Rebased onto a more recent master.


https://reviews.llvm.org/D45465

Files:
  lib/AST/DeclPrinter.cpp
  test/Misc/ast-print-enum-decl.c
  test/Misc/ast-print-record-decl.c
  test/Sema/ast-print.c
  test/SemaCXX/ast-print.cpp

Index: test/SemaCXX/ast-print.cpp
===================================================================
--- test/SemaCXX/ast-print.cpp
+++ test/SemaCXX/ast-print.cpp
@@ -214,10 +214,13 @@
 struct [[gnu::visibility("hidden")]] S;
 }
 
-// CHECK: struct CXXFunctionalCastExprPrint fce = CXXFunctionalCastExprPrint{};
+// CHECK:      struct CXXFunctionalCastExprPrint {
+// CHECK-NEXT: } fce = CXXFunctionalCastExprPrint{};
 struct CXXFunctionalCastExprPrint {} fce = CXXFunctionalCastExprPrint{};
 
-// CHECK: struct CXXTemporaryObjectExprPrint toe = CXXTemporaryObjectExprPrint{};
+// CHECK:      struct CXXTemporaryObjectExprPrint {
+// CHECK-NEXT:   CXXTemporaryObjectExprPrint();
+// CHECK-NEXT: } toe = CXXTemporaryObjectExprPrint{};
 struct CXXTemporaryObjectExprPrint { CXXTemporaryObjectExprPrint(); } toe = CXXTemporaryObjectExprPrint{};
 
 namespace PR24872 {
Index: test/Sema/ast-print.c
===================================================================
--- test/Sema/ast-print.c
+++ test/Sema/ast-print.c
@@ -83,8 +83,7 @@
   EnumWithAttributesFoo __attribute__((deprecated)),
   // CHECK-NEXT: EnumWithAttributesBar __attribute__((unavailable(""))) = 50
   EnumWithAttributesBar __attribute__((unavailable)) = 50
-  // CHECK-NEXT: };
-  // CHECK-NEXT: enum EnumWithAttributes *EnumWithAttributesPtr;
+  // CHECK-NEXT: } *EnumWithAttributesPtr;
 } __attribute__((deprecated)) *EnumWithAttributesPtr; // expected-note {{'EnumWithAttributes' has been explicitly marked deprecated here}}
 
 // FIXME: If enum is forward-declared at file scope, attributes are lost.
Index: test/Misc/ast-print-record-decl.c
===================================================================
--- test/Misc/ast-print-record-decl.c
+++ test/Misc/ast-print-record-decl.c
@@ -6,8 +6,8 @@
 //   RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
 //
 //   RUN: %clang_cc1 -verify -ast-print -DKW=struct -DBASES= %s > %t.c
-//   RUN: FileCheck --check-prefixes=CHECK,PRINT -DKW=struct -DBASES= %s \
-//   RUN:           --input-file %t.c
+//   RUN: FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=struct -DBASES= \
+//   RUN:           %s --input-file %t.c
 //
 //   Now check compiling and printing of the printed file.
 //
@@ -18,7 +18,8 @@
 //   RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
 //
 //   RUN: %clang_cc1 -verify -ast-print %t.c \
-//   RUN: | FileCheck --check-prefixes=CHECK,PRINT -DKW=struct -DBASES= %s
+//   RUN: | FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=struct \
+//   RUN:             -DBASES= %s
 
 // Repeat for union:
 //
@@ -28,8 +29,8 @@
 //   RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
 //
 //   RUN: %clang_cc1 -verify -ast-print -DKW=union -DBASES= %s > %t.c
-//   RUN: FileCheck --check-prefixes=CHECK,PRINT -DKW=union -DBASES= %s \
-//   RUN:           --input-file %t.c
+//   RUN: FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=union -DBASES= \
+//   RUN:           %s --input-file %t.c
 //
 //   Now check compiling and printing of the printed file.
 //
@@ -40,7 +41,8 @@
 //   RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
 //
 //   RUN: %clang_cc1 -verify -ast-print %t.c \
-//   RUN: | FileCheck --check-prefixes=CHECK,PRINT -DKW=union -DBASES= %s
+//   RUN: | FileCheck --check-prefixes=CHECK,PRINT,PRINT-C -DKW=union \
+//   RUN:             -DBASES= %s
 
 // Repeat for C++ (BASES helps ensure we're printing as C++ not as C):
 //
@@ -52,7 +54,7 @@
 //
 //   RUN: %clang_cc1 -verify -ast-print -DKW=struct -DBASES=' : B' -xc++ %s \
 //   RUN: > %t.cpp
-//   RUN: FileCheck --check-prefixes=CHECK,PRINT,CXX -DKW=struct \
+//   RUN: FileCheck --check-prefixes=CHECK,PRINT,PRINT-CXX -DKW=struct \
 //   RUN:           -DBASES=' : B' %s --input-file %t.cpp
 //
 //   Now check compiling and printing of the printed file.
@@ -64,7 +66,7 @@
 //   RUN: | FileCheck --check-prefixes=CHECK,LLVM %s
 //
 //   RUN: %clang_cc1 -verify -ast-print %t.cpp \
-//   RUN: | FileCheck --check-prefixes=CHECK,PRINT,CXX -DKW=struct \
+//   RUN: | FileCheck --check-prefixes=CHECK,PRINT,PRINT-CXX -DKW=struct \
 //   RUN:             -DBASES=' : B' %s
 
 // END.
@@ -161,29 +163,41 @@
   // expected-note@+1 2 {{'T' has been explicitly marked deprecated here}}
   KW __attribute__((deprecated(""))) T *p0;
 
-  // PRINT-NEXT: [[KW]]
-  // PRINT-DAG:  __attribute__((deprecated("")))
-  // PRINT-DAG:  __attribute__((aligned(16)))
-  // PRINT-NOT:  __attribute__
-  // PRINT-SAME: T[[BASES]] {
-  // PRINT-NEXT:   int i;
-  // PRINT-NEXT:   [[KW]] T *p2;
-  // PRINT-NEXT: } *p1;
-  KW __attribute__((aligned(16))) T BASES { // expected-warning {{'T' is deprecated}}
+  // PRINT-NEXT:  [[KW]]
+  // PRINT-DAG:   __attribute__((deprecated("")))
+  // PRINT-DAG:   __attribute__((aligned(64)))
+  // PRINT-NOT:   __attribute__
+  // PRINT-SAME:  T[[BASES]] {
+  // PRINT-NEXT:    int i;
+  // PRINT-NEXT:    [[KW]] T *p2;
+  // PRINT-NEXT:    [[KW]]
+  // PRINT-C-DAG:   __attribute__((deprecated("")))
+  // PRINT-C-DAG:   __attribute__((aligned(64)))
+  // PRINT-DAG:     __attribute__((may_alias))
+  // PRINT-NOT:     __attribute__
+  // PRINT-SAME:    T *p3, *p4;
+  // PRINT-NEXT:  } *p1;
+  KW __attribute__((aligned(64))) T BASES { // expected-warning {{'T' is deprecated}}
     int i;
     KW T *p2;
+    // FIXME: For C++, T at p3 loses aligned and deprecated, perhaps because
+    // that RecordDecl isn't in the same redecl list.  Perhaps the redecl lists
+    // are split here but not in C due to the different scoping rules in C++
+    // classes.
+    KW __attribute__((may_alias)) T *p3;
+    KW T *p4;
   } *p1;
 
-  // LLVM: store i64 16
+  // LLVM: store i64 64
   long s0 = sizeof *p0;
-  // LLVM-NEXT: store i64 16
+  // LLVM-NEXT: store i64 64
   long s1 = sizeof *p1;
-  // LLVM-NEXT: store i64 16
+  // LLVM-NEXT: store i64 64
   long s2 = sizeof *p0->p2;
-  // LLVM-NEXT: store i64 16
-  long s3 = sizeof *p1->p2;
-  // LLVM-NEXT: store i64 16
-  long s4 = sizeof *p1->p2->p2;
+  // LLVM-NEXT: store i64 64
+  long s3 = sizeof *p1->p3;
+  // LLVM-NEXT: store i64 64
+  long s4 = sizeof *p1->p4->p2;
 }
 
 // CHECK-LABEL: declsOnly
@@ -238,14 +252,41 @@
 }
 
 #ifdef __cplusplus
-// CXX-LABEL: inMemberPtr
+// PRINT-CXX-LABEL: inMemberPtr
 void inMemberPtr() {
-  // CXX-NEXT: [[KW]] T1 {
-  // CXX-NEXT:   int i;
-  // CXX-NEXT: };
+  // PRINT-CXX-NEXT: [[KW]] T1 {
+  // PRINT-CXX-NEXT:   int i;
+  // PRINT-CXX-NEXT: };
   KW T1 { int i; };
-  // CXX-NEXT: [[KW]] T2 {
-  // CXX-NEXT: } T1::*p;
+  // PRINT-CXX-NEXT: [[KW]] T2 {
+  // PRINT-CXX-NEXT: } T1::*p;
   KW T2 {} T1::*p;
 }
 #endif
+
+// Check that tag decl groups stay together in decl contexts.
+
+// PRINT-LABEL: DeclGroupAtFileScope {
+// PRINT-NEXT:    int i;
+// PRINT-NEXT:  } *DeclGroupAtFileScopePtr;
+KW DeclGroupAtFileScope { int i; } *DeclGroupAtFileScopePtr;
+
+// PRINT-LABEL: DeclGroupInMemberList {
+KW DeclGroupInMemberList {
+  // PRINT-NEXT:  struct  T1 {
+  // PRINT-NEXT:    int i;
+  // PRINT-NEXT:  } t1;
+  struct T1 { int i; } t1;
+  // PRINT-NEXT:  union T2 {
+  // PRINT-NEXT:    int i;
+  // PRINT-NEXT:  } *t20, t21[2];
+  union T2 { int i; } *t20, t21[2];
+  // PRINT-NEXT:  enum T3 {
+  // PRINT-NEXT:    T30
+  // PRINT-NEXT:  } t30;
+  enum T3 { T30 } t30;
+  // PRINT-NEXT: };
+};
+
+// A tag decl group in the tag decl's own member list is exercised in
+// defSelfRef above.
Index: test/Misc/ast-print-enum-decl.c
===================================================================
--- test/Misc/ast-print-enum-decl.c
+++ test/Misc/ast-print-enum-decl.c
@@ -89,3 +89,23 @@
   // PRINT-NEXT: enum T *p4;
   enum T *p4;
 }
+
+// Check that tag decl groups stay together in decl contexts.
+
+// PRINT-LABEL: enum DeclGroupAtFileScope {
+// PRINT-NEXT:    DeclGroupAtFileScope0
+// PRINT-NEXT:  } *DeclGroupAtFileScopePtr;
+enum DeclGroupAtFileScope { DeclGroupAtFileScope0 } *DeclGroupAtFileScopePtr;
+
+// PRINT-LABEL: struct DeclGroupInMemberList
+struct DeclGroupInMemberList {
+  // PRINT-NEXT:  enum T1 {
+  // PRINT-NEXT:    T10
+  // PRINT-NEXT:  } *p0;
+  enum T1 { T10 } *p0;
+  // PRINT-NEXT:  enum T2 {
+  // PRINT-NEXT:    T20
+  // PRINT-NEXT:  } *p1, *p2;
+  enum T2 { T20 } *p1, *p2;
+  // PRINT-NEXT: };
+};
Index: lib/AST/DeclPrinter.cpp
===================================================================
--- lib/AST/DeclPrinter.cpp
+++ lib/AST/DeclPrinter.cpp
@@ -373,21 +373,26 @@
           !isa<ClassTemplateSpecializationDecl>(DC))
         continue;
 
-    // The next bits of code handles stuff like "struct {int x;} a,b"; we're
+    // The next bits of code handle 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.
+    // refer to the struct in question.  When that struct is named instead, we
+    // also need to merge to avoid splitting off a stand-alone struct
+    // declaration that produces the warning ext_no_declarators in some
+    // contexts.
+    //
+    // 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.
+    // non-free-standing tag declaration.
     QualType CurDeclType = getDeclType(*D);
     if (!Decls.empty() && !CurDeclType.isNull()) {
       QualType BaseType = GetBaseType(CurDeclType);
       if (!BaseType.isNull() && isa<ElaboratedType>(BaseType))
         BaseType = cast<ElaboratedType>(BaseType)->getNamedType();
       if (!BaseType.isNull() && isa<TagType>(BaseType) &&
-          cast<TagType>(BaseType)->getDecl() == Decls[0]) {
+          cast<TagType>(BaseType) ==
+              cast<TagDecl>(Decls[0])->getTypeForDecl()) {
         Decls.push_back(*D);
         continue;
       }
@@ -397,9 +402,9 @@
     if (!Decls.empty())
       ProcessDeclGroup(Decls);
 
-    // If the current declaration is an unnamed tag type, save it
+    // If the current declaration is not a free standing declaration, save it
     // so we can merge it with the subsequent declaration(s) using it.
-    if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->getIdentifier()) {
+    if (isa<TagDecl>(*D) && !cast<TagDecl>(*D)->isFreeStanding()) {
       Decls.push_back(*D);
       continue;
     }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D45465: [... Joel E. Denny via Phabricator via cfe-commits

Reply via email to