r330722 - [Attr] Print enum attributes at correct position

Joel E. Denny via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 24 07:50:23 PDT 2018


Author: jdenny
Date: Tue Apr 24 07:50:23 2018
New Revision: 330722

URL: http://llvm.org/viewvc/llvm-project?rev=330722&view=rev
Log:
[Attr] Print enum attributes at correct position

For example, given:

  void fn() {
    enum __attribute__((deprecated)) T *p;
  }

-ast-print produced:

  void fn() {
    enum T __attribute__((deprecated(""))) *p;
  }

-ast-print on that produced:

  void fn() {
    enum T *p __attribute__((deprecated("")));
  }

The attribute is on enum T in the first case, but it's on p in the
other cases.

Details:

Within enum declarations, enum attributes were always printed after
the tag and any member list.  When no member list was present but the
enum was a type specifier in a variable declaration, the attribute
then applied to the variable not the enum, changing the semantics.

This patch fixes that by always printing attributes between the enum's
keyword and tag, as clang already does for structs, unions, and
classes.

Reviewed By: rsmith

Differential Revision: https://reviews.llvm.org/D45456

Modified:
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/test/Sema/ast-print.c

Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=330722&r1=330721&r2=330722&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Tue Apr 24 07:50:23 2018
@@ -496,14 +496,17 @@ void DeclPrinter::VisitTypeAliasDecl(Typ
 void DeclPrinter::VisitEnumDecl(EnumDecl *D) {
   if (!Policy.SuppressSpecifiers && D->isModulePrivate())
     Out << "__module_private__ ";
-  Out << "enum ";
+  Out << "enum";
   if (D->isScoped()) {
     if (D->isScopedUsingClassTag())
-      Out << "class ";
+      Out << " class";
     else
-      Out << "struct ";
+      Out << " struct";
   }
-  Out << *D;
+
+  prettyPrintAttributes(D);
+
+  Out << ' ' << *D;
 
   if (D->isFixed() && D->getASTContext().getLangOpts().CPlusPlus11)
     Out << " : " << D->getIntegerType().stream(Policy);
@@ -513,7 +516,6 @@ void DeclPrinter::VisitEnumDecl(EnumDecl
     VisitDeclContext(D);
     Indent() << "}";
   }
-  prettyPrintAttributes(D);
 }
 
 void DeclPrinter::VisitRecordDecl(RecordDecl *D) {

Modified: cfe/trunk/test/Sema/ast-print.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/ast-print.c?rev=330722&r1=330721&r2=330722&view=diff
==============================================================================
--- cfe/trunk/test/Sema/ast-print.c (original)
+++ cfe/trunk/test/Sema/ast-print.c Tue Apr 24 07:50:23 2018
@@ -1,5 +1,12 @@
-// RUN: %clang_cc1 %s -ast-print | FileCheck %s
-// RUN: %clang_cc1 %s -ast-print | %clang_cc1 -fsyntax-only -
+// RUN: %clang_cc1 %s -ast-print -verify > %t.c
+// RUN: FileCheck %s --input-file %t.c
+//
+// RUN: echo >> %t.c "// expected""-warning@* {{use of GNU old-style field designator extension}}"
+// RUN: echo >> %t.c "// expected""-warning@* {{'EnumWithAttributes' is deprecated}}"
+// RUN: echo >> %t.c "// expected""-note@* {{'EnumWithAttributes' has been explicitly marked deprecated here}}"
+// RUN: echo >> %t.c "// expected""-warning@* {{'EnumWithAttributes3' is deprecated}}"
+// RUN: echo >> %t.c "// expected""-note@* {{'EnumWithAttributes3' has been explicitly marked deprecated here}}"
+// RUN: %clang_cc1 -fsyntax-only %t.c -verify
 
 typedef void func_typedef();
 func_typedef xxx;
@@ -58,7 +65,7 @@ struct pair_t {
 };
 
 // CHECK: struct pair_t p = {a: 3, .b = 4};
-struct pair_t p = {a: 3, .b = 4};
+struct pair_t p = {a: 3, .b = 4}; // expected-warning {{use of GNU old-style field designator extension}}
 
 void initializers() {
   // CHECK: int *x = ((void *)0), *y = ((void *)0);
@@ -70,11 +77,30 @@ void initializers() {
   } z = {(struct Z){}};
 }
 
-// CHECK-LABEL: enum EnumWithAttributes {
-enum EnumWithAttributes {
+// CHECK-LABEL: enum __attribute__((deprecated(""))) EnumWithAttributes {
+enum EnumWithAttributes { // expected-warning {{'EnumWithAttributes' is deprecated}}
   // CHECK-NEXT: EnumWithAttributesFoo __attribute__((deprecated(""))),
   EnumWithAttributesFoo __attribute__((deprecated)),
   // CHECK-NEXT: EnumWithAttributesBar __attribute__((unavailable(""))) = 50
   EnumWithAttributesBar __attribute__((unavailable)) = 50
-  // CHECK-NEXT: } __attribute__((deprecated("")))
-} __attribute__((deprecated));
+  // CHECK-NEXT: };
+  // CHECK-NEXT: enum EnumWithAttributes *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.
+// CHECK-LABEL: enum EnumWithAttributes2 *EnumWithAttributes2Ptr;
+// expected-warning at +2 {{'EnumWithAttributes2' is deprecated}}
+// expected-note at +1 {{'EnumWithAttributes2' has been explicitly marked deprecated here}}
+enum __attribute__((deprecated)) EnumWithAttributes2 *EnumWithAttributes2Ptr;
+
+// CHECK-LABEL: EnumWithAttributes3Fn
+void EnumWithAttributes3Fn() {
+  // CHECK-NEXT: enum __attribute__((deprecated(""))) EnumWithAttributes3 *EnumWithAttributes3Ptr;
+  // expected-warning at +2 {{'EnumWithAttributes3' is deprecated}}
+  // expected-note at +1 {{'EnumWithAttributes3' has been explicitly marked deprecated here}}
+  enum __attribute__((deprecated)) EnumWithAttributes3 *EnumWithAttributes3Ptr;
+  // Printing must not put the attribute after the tag where it would apply to
+  // the variable instead of the type, and then our deprecation warning would
+  // move to this use of the variable.
+  void *p = EnumWithAttributes3Ptr;
+}




More information about the cfe-commits mailing list