giulianobelinassi updated this revision to Diff 501835.
giulianobelinassi edited the summary of this revision.
giulianobelinassi added a comment.

Update to dump attributes right after the type specification, also
fixing the __declspec case.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141714/new/

https://reviews.llvm.org/D141714

Files:
  clang/lib/AST/DeclPrinter.cpp
  clang/test/AST/ast-print-attr-knr.c
  clang/test/AST/ast-print-attr.c
  clang/test/AST/ast-print-pragmas.cpp
  clang/test/Analysis/blocks.mm
  clang/test/Sema/attr-print.c
  clang/test/SemaCXX/attr-print.cpp
  clang/test/SemaCXX/cxx11-attr-print.cpp

Index: clang/test/SemaCXX/cxx11-attr-print.cpp
===================================================================
--- clang/test/SemaCXX/cxx11-attr-print.cpp
+++ clang/test/SemaCXX/cxx11-attr-print.cpp
@@ -1,29 +1,28 @@
 // RUN: %clang_cc1 -std=c++11 -ast-print -fms-extensions %s | FileCheck %s
 //
-// CHECK: int x __attribute__((aligned(4)));
-int x __attribute__((aligned(4)));
+// CHECK: int __attribute__((aligned(4))) x;
+int __attribute__((aligned(4))) x;
 
-// FIXME: Print this at a valid location for a __declspec attr.
-// CHECK: int y __declspec(align(4));
-__declspec(align(4)) int y;
+// CHECK: int __declspec(align(4)) y;
+int __declspec(align(4)) y;
 
 // CHECK: int z {{\[}}[gnu::aligned(4)]];
 int z [[gnu::aligned(4)]];
 
-// CHECK: __attribute__((deprecated("warning")));
-int a __attribute__((deprecated("warning")));
+// CHECK: int __attribute__((deprecated("warning"))) a;
+int __attribute__((deprecated("warning"))) a;
 
 // CHECK: int b {{\[}}[gnu::deprecated("warning")]];
 int b [[gnu::deprecated("warning")]];
 
-// CHECK: __declspec(deprecated("warning"))
-__declspec(deprecated("warning")) int c;
+// CHECK: int __declspec(deprecated("warning")) c;
+int __declspec(deprecated("warning")) c;
 
 // CHECK: int d {{\[}}[deprecated("warning")]];
 int d [[deprecated("warning")]];
 
-// CHECK: __attribute__((deprecated("warning", "fixit")));
-int e __attribute__((deprecated("warning", "fixit")));
+// CHECK: int __attribute__((deprecated("warning", "fixit"))) e;
+int __attribute__((deprecated("warning", "fixit"))) e;
 
 // CHECK: int cxx11_alignas alignas(4);
 alignas(4) int cxx11_alignas;
@@ -63,12 +62,12 @@
 // CHECK: __attribute__((format(printf, 2, 3)));
 void f8 (void *, const char *, ...) __attribute__ ((format (printf, 2, 3)));
 
-// CHECK: int m __attribute__((aligned(4
+// CHECK: int m __attribute__((aligned(4)))
 // CHECK: int n alignas(4
 // CHECK: static int f() __attribute__((pure))
 // CHECK: static int g() {{\[}}[gnu::pure]]
 template <typename T> struct S {
-  __attribute__((aligned(4))) int m;
+  int __attribute__((aligned(4))) m;
   alignas(4) int n;
   __attribute__((pure)) static int f() {
     return 0;
@@ -78,7 +77,7 @@
   }
 };
 
-// CHECK: int m __attribute__((aligned(4
+// CHECK: int m __attribute__((aligned(4)))
 // CHECK: int n alignas(4
 // CHECK: static int f() __attribute__((pure))
 // CHECK: static int g() {{\[}}[gnu::pure]]
Index: clang/test/SemaCXX/attr-print.cpp
===================================================================
--- clang/test/SemaCXX/attr-print.cpp
+++ clang/test/SemaCXX/attr-print.cpp
@@ -1,11 +1,11 @@
 // RUN: %clang_cc1 %s -ast-print -fms-extensions | FileCheck %s
 
-// CHECK: int x __attribute__((aligned(4)));
-int x __attribute__((aligned(4)));
+// CHECK: int __attribute__((aligned(4))) x;
+int __attribute__((aligned(4))) x;
 
 // FIXME: Print this at a valid location for a __declspec attr.
-// CHECK: int y __declspec(align(4));
-__declspec(align(4)) int y;
+// CHECK: int __declspec(align(4)) y;
+int __declspec(align(4)) y;
 
 // CHECK: void foo() __attribute__((const));
 void foo() __attribute__((const));
@@ -20,11 +20,11 @@
 // CHECK: typedef int Small1 __attribute__((mode(byte)));
 typedef int Small1 __attribute__((mode(byte)));
 
-// CHECK: int small __attribute__((mode(byte)));
-int small __attribute__((mode(byte)));
+// CHECK: int __attribute__((mode(byte))) small;
+int __attribute__((mode(byte))) small;
 
-// CHECK: int v __attribute__((visibility("hidden")));
-int v __attribute__((visibility("hidden")));
+// CHECK: int __attribute__((visibility("hidden"))) v;
+int __attribute__((visibility("hidden"))) v;
 
 // CHECK: char *PR24565() __attribute__((malloc))
 char *PR24565() __attribute__((__malloc__));
Index: clang/test/Sema/attr-print.c
===================================================================
--- clang/test/Sema/attr-print.c
+++ clang/test/Sema/attr-print.c
@@ -1,14 +1,14 @@
 // RUN: %clang_cc1 %s -ast-print -fms-extensions | FileCheck %s
 
-// CHECK: int x __attribute__((aligned(4)));
-int x __attribute__((aligned(4)));
+// CHECK: int __attribute__((aligned(4))) x;
+int __attribute__((aligned(4))) x;
 
 // FIXME: Print this at a valid location for a __declspec attr.
-// CHECK: int y __declspec(align(4));
-__declspec(align(4)) int y;
+// CHECK: int __declspec(align(4)) y;
+int __declspec(align(4)) y;
 
-// CHECK: short arr[3] __attribute__((aligned));
-short arr[3] __attribute__((aligned));
+// CHECK: short __attribute__((aligned)) arr[3];
+short __attribute__((aligned)) arr[3];
 
 // CHECK: void foo(void) __attribute__((const));
 void foo(void) __attribute__((const));
Index: clang/test/Analysis/blocks.mm
===================================================================
--- clang/test/Analysis/blocks.mm
+++ clang/test/Analysis/blocks.mm
@@ -70,6 +70,8 @@
   });
 }
 
+// FIXME: C++ issues a ignore warning on this __attribute__ output.
+
 // CHECK-LABEL:void testBlockWithCaptureByReference()
 // CHECK-NEXT: [B2 (ENTRY)]
 // CHECK-NEXT:   Succs (1): B1
@@ -78,7 +80,7 @@
 // CHECK-NEXT:   1: 5
 // WARNINGS-NEXT:   2: [B1.1] (CXXConstructExpr, StructWithCopyConstructor)
 // ANALYZER-NEXT:   2: [B1.1] (CXXConstructExpr, [B1.3], StructWithCopyConstructor)
-// CHECK-NEXT:   3: StructWithCopyConstructor s(5) __attribute__((blocks("byref")));
+// CHECK-NEXT:   3: StructWithCopyConstructor __attribute__((blocks("byref"))) s(5);
 // CHECK-NEXT:   4: ^{ }
 // CHECK-NEXT:   5: (void)([B1.4]) (CStyleCastExpr, ToVoid, void)
 // CHECK-NEXT:   Preds (1): B2
Index: clang/test/AST/ast-print-pragmas.cpp
===================================================================
--- clang/test/AST/ast-print-pragmas.cpp
+++ clang/test/AST/ast-print-pragmas.cpp
@@ -93,7 +93,7 @@
 #ifdef MS_EXT
 #pragma init_seg(compiler)
 // MS-EXT: #pragma init_seg (.CRT$XCC){{$}}
-// MS-EXT-NEXT: int x = 3 __declspec(thread);
+// MS-EXT-NEXT: int __declspec(thread) x = 3;
 int __declspec(thread) x = 3;
 #endif //MS_EXT
 
Index: clang/test/AST/ast-print-attr.c
===================================================================
--- clang/test/AST/ast-print-attr.c
+++ clang/test/AST/ast-print-attr.c
@@ -32,3 +32,9 @@
 
 // CHECK: void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
 void fun_holds(int *a) __attribute__((ownership_holds(fun_holds, 1)));
+
+// CHECK: int fun_var_unused() {
+// CHECK-NEXT: int __attribute__((unused)) x = 0;
+// CHECK-NEXT: return x;
+// CHECK-NEXT: }
+int fun_var_unused() { int __attribute__((unused)) x = 0; return x; }
Index: clang/test/AST/ast-print-attr-knr.c
===================================================================
--- /dev/null
+++ clang/test/AST/ast-print-attr-knr.c
@@ -0,0 +1,10 @@
+// This file contain tests for attribute arguments on K&R functions.
+
+// RUN: %clang_cc1 -ast-print -x c -std=c89 -fms-extensions %s -o - | FileCheck %s
+
+// CHECK: int knr(i)
+// CHECK-NEXT: int __attribute__((unused)) i;
+// CHECK-NEXT: {
+// CHECK-NEXT: return 0;
+// CHECK-NEXT: }
+int knr(i) int __attribute__((unused)) i; { return 0; }
Index: clang/lib/AST/DeclPrinter.cpp
===================================================================
--- clang/lib/AST/DeclPrinter.cpp
+++ clang/lib/AST/DeclPrinter.cpp
@@ -49,6 +49,17 @@
 
     void PrintObjCTypeParams(ObjCTypeParamList *Params);
 
+    enum AttrPrintLoc {
+      SIDE_NONE = 0,
+      SIDE_LEFT = 1,
+      SIDE_MIDDLE = 2,
+      SIDE_RIGHT = 4,
+      SIDE_ANY = SIDE_LEFT | SIDE_MIDDLE | SIDE_RIGHT,
+    };
+
+    void prettyPrintAttributes(Decl *D, raw_ostream &out,
+                               AttrPrintLoc loc = SIDE_ANY);
+
   public:
     DeclPrinter(raw_ostream &Out, const PrintingPolicy &Policy,
                 const ASTContext &Context, unsigned Indentation = 0,
@@ -117,7 +128,11 @@
                                 const TemplateParameterList *Params);
     void printTemplateArguments(llvm::ArrayRef<TemplateArgumentLoc> Args,
                                 const TemplateParameterList *Params);
-    void prettyPrintAttributes(Decl *D);
+
+    inline void prettyPrintAttributes(Decl *D) {
+      prettyPrintAttributes(D, Out);
+    }
+
     void prettyPrintPragmas(Decl *D);
     void printDeclType(QualType T, StringRef DeclName, bool Pack = false);
   };
@@ -234,7 +249,8 @@
   return Out;
 }
 
-void DeclPrinter::prettyPrintAttributes(Decl *D) {
+void DeclPrinter::prettyPrintAttributes(Decl *D, llvm::raw_ostream &out,
+                                        AttrPrintLoc loc) {
   if (Policy.PolishForDeclaration)
     return;
 
@@ -243,14 +259,28 @@
     for (auto *A : Attrs) {
       if (A->isInherited() || A->isImplicit())
         continue;
-      switch (A->getKind()) {
-#define ATTR(X)
-#define PRAGMA_SPELLING_ATTR(X) case attr::X:
-#include "clang/Basic/AttrList.inc"
-        break;
-      default:
-        A->printPretty(Out, Policy);
-        break;
+
+      // We will try to classify the attr::Kind into three disjoint sets:
+      // 1- should be print on the left side of a decl.
+      // 2- should be print on the middle of a decl right after the type.
+      // 3- should be print on the right side of a decl.
+      AttrPrintLoc attrloc = SIDE_MIDDLE; // We default to middle.
+      attr::Kind kind = A->getKind();
+
+      // FIXME: Find a way to use the AttrList.inc. We use if-else statements
+      // to classify each of them.
+      if (A->isCXX11Attribute()) {
+        // C++11 onwards attributes can not be placed on middle. Output on
+        // right to mimic old clang behaviour.
+        attrloc = SIDE_RIGHT;
+      } else if (kind == attr::AsmLabel) {
+        // AsmLabels can not be placed on the middle nor left.
+        attrloc = SIDE_RIGHT;
+      }
+
+      // Only print the side matches the user requested.
+      if ((loc & attrloc) != SIDE_NONE) {
+        A->printPretty(out, Policy);
       }
     }
   }
@@ -887,10 +917,29 @@
     }
   }
 
-  printDeclType(T, (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
-                    D->getIdentifier())
-                       ? D->getIdentifier()->deuglifiedName()
-                       : D->getName());
+  std::string Name;
+  llvm::raw_string_ostream NameStream(Name);
+
+  // Print the middle attributes into a string so we can concatenate with the
+  // name.
+  prettyPrintAttributes(D, NameStream, SIDE_MIDDLE);
+
+  // prettyPrintAttributes print a space on left side of the attribute.
+  if (Name[0] == ' ') {
+    // Skip the space prettyPrintAttributes generated.
+    Name.erase(0, Name.find_first_not_of(' '));
+
+    // Add a single space between the attribute and the Decl name.
+    NameStream << ' ';
+  }
+
+  Name += (isa<ParmVarDecl>(D) && Policy.CleanUglifiedParameters &&
+           D->getIdentifier())
+              ? D->getIdentifier()->deuglifiedName().str()
+              : D->getName().str();
+
+  printDeclType(T, StringRef(Name));
+
   Expr *Init = D->getInit();
   if (!Policy.SuppressInitializers && Init) {
     bool ImplicitInit = false;
@@ -919,7 +968,10 @@
         Out << ")";
     }
   }
-  prettyPrintAttributes(D);
+
+  // Print the attributes that should be placed right before the end of the
+  // decl.
+  prettyPrintAttributes(D, Out, SIDE_RIGHT);
 }
 
 void DeclPrinter::VisitParmVarDecl(ParmVarDecl *D) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to