Xiangling_L updated this revision to Diff 308065.
Xiangling_L added a comment.

Adjusted the logic of operator == for class AlignPackInfo;
Removed mac68k sentinel;


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

https://reviews.llvm.org/D87702

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Sema/Sema.h
  clang/include/clang/Serialization/ASTReader.h
  clang/include/clang/Serialization/ASTWriter.h
  clang/lib/AST/RecordLayoutBuilder.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaAttr.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/Driver/aix-pragma-pack.c
  clang/test/Layout/aix-double-struct-member.cpp
  clang/test/Layout/aix-power-natural-interaction.cpp
  clang/test/PCH/aix-pragma-pack.c
  clang/test/Sema/aix-pragma-pack-and-align.c

Index: clang/test/Sema/aix-pragma-pack-and-align.c
===================================================================
--- /dev/null
+++ clang/test/Sema/aix-pragma-pack-and-align.c
@@ -0,0 +1,231 @@
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -faix-pragma-pack -verify -fsyntax-only -x c++ %s | \
+// RUN:   FileCheck %s
+
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -faix-pragma-pack -verify -fsyntax-only -x c++ %s | \
+// RUN:   FileCheck %s
+
+namespace test1 {
+#pragma align(natural)
+#pragma pack(4)
+#pragma pack(2)
+struct A {
+  int i;
+  double d;
+};
+
+int a = sizeof(A);
+#pragma pack()
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 4}}
+#pragma pack(pop)
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 8}}
+struct B {
+  int i;
+  double d;
+};
+#pragma align(reset)
+
+int b = sizeof(B);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test1::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=2, preferredalign=2,
+// CHECK-NEXT:            |  nvsize=12, nvalign=2, preferrednvalign=2]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test1::B
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          8 |   double d
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+} // namespace test1
+
+namespace test2 {
+#pragma align(natural)
+#pragma pack(2)
+struct A {
+  int i;
+  double d;
+};
+
+int a = sizeof(A);
+#pragma align(reset)
+
+struct B {
+  int i;
+  double d;
+};
+
+int b = sizeof(B);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test2::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=2, preferredalign=2,
+// CHECK-NEXT:            |  nvsize=12, nvalign=2, preferrednvalign=2]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test2::B
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+
+} // namespace test2
+
+namespace test3 {
+#pragma pack(2)
+#pragma align(natural)
+struct A {
+  double d;
+};
+#pragma align(reset)
+#pragma pack(pop)
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test3::A
+// CHECK-NEXT:          0 |   double d
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=8]
+
+} // namespace test3
+
+namespace test4 {
+#pragma pack(2)
+#pragma align(natural)
+#pragma pack(pop)
+
+struct A {
+  int i;
+  double d;
+} a;
+#pragma align(reset)
+#pragma pack(pop)
+
+int i = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test4::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          8 |   double d
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+} // namespace test4
+
+namespace test5 {
+#pragma align(power)
+#pragma align(natural)
+#pragma pack(2)
+#pragma align(reset)
+struct A {
+  int i;
+  double d;
+};
+#pragma align(reset)
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test5::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+
+} // namespace test5
+
+namespace test6 {
+#pragma align(natural)
+#pragma pack(0)    // expected-error {{expected #pragma pack parameter to be '1', '2', '4', '8', or '16'}}
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 8}}
+
+struct A {
+  int i;
+  double d;
+} a;
+#pragma align(reset)
+
+int i = sizeof(a);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test6::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          8 |   double d
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+} // namespace test6
+
+namespace test7 {
+#pragma align = natural // expected-warning {{missing '(' after '#pragma align' - ignoring}}
+#pragma align(reset)    // expected-warning {{#pragma options align=reset failed: stack empty}}
+} // namespace test7
+
+namespace test8 {
+#pragma align(packed)
+#pragma pack(2)
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 2}}
+struct A {
+  int i;
+  double d;
+};
+#pragma align(reset)
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test8::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=2, preferredalign=2,
+// CHECK-NEXT:            |  nvsize=12, nvalign=2, preferrednvalign=2]
+
+} // namespace test8
+
+namespace test9 {
+#pragma pack(push, r1, 2) // expected-warning {{specifying an identifier within pragma pack is not supported, identifier is ignored}}
+struct A {
+  int i;
+  double d;
+};
+#pragma pack(pop)
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test9::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=2, preferredalign=2,
+// CHECK-NEXT:            |  nvsize=12, nvalign=2, preferrednvalign=2]
+
+} // namespace test9
+
+namespace test10 {
+#pragma pack(2)
+#pragma align(reset)
+struct A {
+  int i;
+  double d;
+};
+
+int a = sizeof(A);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test10::A
+// CHECK-NEXT:          0 |   int i
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+
+} // namespace test10
+
+// expected-no-warning
Index: clang/test/PCH/aix-pragma-pack.c
===================================================================
--- /dev/null
+++ clang/test/PCH/aix-pragma-pack.c
@@ -0,0 +1,119 @@
+// Test this without pch.
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only -Wno-pragma-pack -DSET
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only -Wno-pragma-pack -DRESET
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only -Wno-pragma-pack -DPUSH
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only \
+// RUN:     -Wno-pragma-pack -DPUSH_POP
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -include %s -fsyntax-only -fdump-record-layouts \
+// RUN:     -Wno-pragma-pack -DALIGN_NATURAL | \
+// RUN:   FileCheck %s
+
+// Test with pch.
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DSET -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DSET -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DRESET -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DRESET -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH_POP -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH_POP -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DALIGN_NATURAL -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DALIGN_NATURAL \
+// RUN:     -fdump-record-layouts -include-pch %t | \
+// RUN:   FileCheck %s
+
+// Test this without pch.
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only -Wno-pragma-pack -DSET
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only -Wno-pragma-pack -DRESET
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only -Wno-pragma-pack -DPUSH
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -include %s -verify -fsyntax-only \
+// RUN:     -Wno-pragma-pack -DPUSH_POP
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -include %s -fsyntax-only -fdump-record-layouts \
+// RUN:     -Wno-pragma-pack -DALIGN_NATURAL
+
+// Test with pch.
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DSET -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DSET -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DRESET -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DRESET -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH_POP -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DPUSH_POP -verify -include-pch %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DALIGN_NATURAL -emit-pch -o %t
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -faix-pragma-pack %s -Wno-pragma-pack -DALIGN_NATURAL \
+// RUN:     -fdump-record-layouts -include-pch %t | \
+// RUN:   FileCheck %s
+
+#ifndef HEADER
+#define HEADER
+
+#ifdef SET
+#pragma pack(1)
+#endif
+
+#ifdef RESET
+#pragma pack(2)
+#pragma pack()
+#endif
+
+#ifdef PUSH
+#pragma pack(1)
+#pragma pack(push, 2)
+#endif
+
+#ifdef PUSH_POP
+#pragma pack(push, 4)
+#pragma pack(push, 2)
+#pragma pack(pop)
+#endif
+
+#ifdef ALIGN_NATURAL
+#pragma align(natural)
+#endif
+
+#else
+
+#ifdef SET
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 1}}
+#pragma pack(pop)
+#endif
+
+#ifdef RESET
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 8}}
+#pragma()
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 8}}
+#endif
+
+#ifdef PUSH
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 2}}
+#pragma pack(pop)
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 1}}
+#pragma pack()
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 8}}
+#pragma pack(pop)  // expected-warning {{#pragma pack(pop, ...) failed: stack empty}}
+#endif
+
+#ifdef PUSH_POP
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 4}}
+#pragma pack(pop)
+#pragma pack(show) // expected-warning {{value of #pragma pack(show) == 8}}
+#pragma pack(pop)  // expected-warning {{#pragma pack(pop, ...) failed: stack empty}}
+#endif
+
+#ifdef ALIGN_NATURAL
+struct D {
+  int i;
+  double d;
+} d;
+
+int s = sizeof(d);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK:          0 | struct D
+// CHECK:          0 |   int i
+// CHECK:          8 |   double d
+// CHECK:            | [sizeof=16, align=4, preferredalign=8]
+#endif
+
+#endif
Index: clang/test/Layout/aix-power-natural-interaction.cpp
===================================================================
--- /dev/null
+++ clang/test/Layout/aix-power-natural-interaction.cpp
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -faix-pragma-pack -fsyntax-only %s | \
+// RUN:   FileCheck %s
+
+// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
+// RUN:     -faix-pragma-pack -fsyntax-only %s | \
+// RUN:   FileCheck %s
+
+namespace test1 {
+#pragma align(natural)
+struct A {
+  int i1;
+};
+
+struct B {
+  double d1;
+};
+#pragma align(reset)
+
+struct C : A, B {
+  double d2;
+};
+
+int a = sizeof(C);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test1::A
+// CHECK-NEXT:          0 |   int i1
+// CHECK-NEXT:            | [sizeof=4, dsize=4, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=4, nvalign=4, preferrednvalign=4]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test1::B
+// CHECK-NEXT:          0 |   double d1
+// CHECK-NEXT:            | [sizeof=8, dsize=8, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=8, nvalign=4, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test1::C
+// CHECK-NEXT:          0 |   struct test1::A (base)
+// CHECK-NEXT:          0 |     int i1
+// CHECK-NEXT:          4 |   struct test1::B (base)
+// CHECK-NEXT:          4 |     double d1
+// CHECK-NEXT:         12 |   double d2
+// CHECK-NEXT:            | [sizeof=20, dsize=20, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=20, nvalign=4, preferrednvalign=4]
+
+} // namespace test1
+
+namespace test2 {
+struct A {
+  int i1;
+  double d;
+};
+
+#pragma align(natural)
+struct B : A {
+  int i2;
+};
+#pragma align(reset)
+
+int b = sizeof(B);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test2::A
+// CHECK-NEXT:          0 |   int i1
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test2::B
+// CHECK-NEXT:          0 |   struct test2::A (base)
+// CHECK-NEXT:          0 |     int i1
+// CHECK-NEXT:          4 |     double d
+// CHECK-NEXT:         12 |   int i2
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=4]
+
+} // namespace test2
+
+namespace test3 {
+#pragma align(natural)
+struct A {
+  int i1;
+  double d;
+};
+#pragma align(reset)
+
+struct B {
+  struct A a;
+  int i2;
+};
+
+int c = sizeof(B);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test3::A
+// CHECK-NEXT:          0 |   int i1
+// CHECK-NEXT:          8 |   double d
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=8]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test3::B
+// CHECK-NEXT:          0 |   struct test3::A a
+// CHECK-NEXT:          0 |     int i1
+// CHECK-NEXT:          8 |     double d
+// CHECK-NEXT:         16 |   int i2
+// CHECK-NEXT:            | [sizeof=24, dsize=24, align=4, preferredalign=8,
+// CHECK-NEXT:            |  nvsize=24, nvalign=4, preferrednvalign=8]
+
+} // namespace test3
+
+namespace test4 {
+struct A {
+  int i1;
+  double d;
+};
+
+#pragma align(natural)
+struct B {
+  int i2;
+  struct A a;
+};
+#pragma align(reset)
+
+int d = sizeof(B);
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test4::A
+// CHECK-NEXT:          0 |   int i1
+// CHECK-NEXT:          4 |   double d
+// CHECK-NEXT:            | [sizeof=12, dsize=12, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=12, nvalign=4, preferrednvalign=4]
+
+// CHECK:      *** Dumping AST Record Layout
+// CHECK-NEXT:          0 | struct test4::B
+// CHECK-NEXT:          0 |   int i2
+// CHECK-NEXT:          4 |   struct test4::A a
+// CHECK-NEXT:          4 |     int i1
+// CHECK-NEXT:          8 |     double d
+// CHECK-NEXT:            | [sizeof=16, dsize=16, align=4, preferredalign=4,
+// CHECK-NEXT:            |  nvsize=16, nvalign=4, preferrednvalign=4]
+
+} // namespace test4
Index: clang/test/Layout/aix-double-struct-member.cpp
===================================================================
--- clang/test/Layout/aix-double-struct-member.cpp
+++ clang/test/Layout/aix-double-struct-member.cpp
@@ -1,9 +1,9 @@
 // RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
-// RUN:     -fsyntax-only  %s | \
+// RUN:     -fsyntax-only -faix-pragma-pack %s | \
 // RUN:   FileCheck %s
 
 // RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
-// RUN:     -fsyntax-only %s | \
+// RUN:     -fsyntax-only -faix-pragma-pack %s | \
 // RUN:   FileCheck %s
 
 namespace test1 {
@@ -335,6 +335,7 @@
   short j;
   double k;
 };
+#pragma pack(pop)
 
 #pragma pack(2)
 struct D {
@@ -342,22 +343,26 @@
   short j;
   int i;
 };
+#pragma pack(pop)
 
 #pragma pack(8)
 struct E {
   double __attribute__((aligned(4))) d;
   short s;
 };
+#pragma pack(pop)
 
 #pragma pack(4)
 struct F : public D {
   double d;
 };
+#pragma pack(pop)
 
 #pragma pack(2)
 struct G : public E {
   int i;
 };
+#pragma pack(pop)
 
 int a = sizeof(A);
 int b = sizeof(B);
Index: clang/test/Driver/aix-pragma-pack.c
===================================================================
--- /dev/null
+++ clang/test/Driver/aix-pragma-pack.c
@@ -0,0 +1,4 @@
+// RUN: %clang -### -target powerpc-ibm-aix-xcoff -c %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: %clang -### -target powerpc64-ibm-aix-xcoff -c %s -o /dev/null 2>&1 | FileCheck %s
+
+// CHECK: "-faix-pragma-pack"
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -4159,11 +4159,11 @@
     return;
 
   RecordData Record;
-  Record.push_back(SemaRef.PackStack.CurrentValue);
+  AddAlignPackInfo(SemaRef.PackStack.CurrentValue, Record);
   AddSourceLocation(SemaRef.PackStack.CurrentPragmaLocation, Record);
   Record.push_back(SemaRef.PackStack.Stack.size());
   for (const auto &StackEntry : SemaRef.PackStack.Stack) {
-    Record.push_back(StackEntry.Value);
+    AddAlignPackInfo(StackEntry.Value, Record);
     AddSourceLocation(StackEntry.PragmaLocation, Record);
     AddSourceLocation(StackEntry.PragmaPushLocation, Record);
     AddString(StackEntry.StackSlotLabel, Record);
@@ -5107,6 +5107,12 @@
   }
 }
 
+void ASTWriter::AddAlignPackInfo(const Sema::AlignPackInfo &Info,
+                                 RecordDataImpl &Record) {
+  uint32_t Raw = Info.getRawEncoding(Info);
+  Record.push_back(Raw);
+}
+
 void ASTWriter::AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record) {
   uint32_t Raw = Loc.getRawEncoding();
   Record.push_back((Raw << 1) | (Raw >> 31));
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -3748,7 +3748,7 @@
         Error("invalid pragma pack record");
         return Failure;
       }
-      PragmaPackCurrentValue = Record[0];
+      PragmaPackCurrentValue = ReadAlignPackInfo(Record[0]);
       PragmaPackCurrentLocation = ReadSourceLocation(F, Record[1]);
       unsigned NumStackEntries = Record[2];
       unsigned Idx = 3;
@@ -3756,7 +3756,7 @@
       PragmaPackStack.clear();
       for (unsigned I = 0; I < NumStackEntries; ++I) {
         PragmaPackStackEntry Entry;
-        Entry.Value = Record[Idx++];
+        Entry.Value = ReadAlignPackInfo(Record[Idx++]);
         Entry.Location = ReadSourceLocation(F, Record[Idx++]);
         Entry.PushLocation = ReadSourceLocation(F, Record[Idx++]);
         PragmaPackStrings.push_back(ReadString(Record, Idx));
@@ -7891,12 +7891,13 @@
       DropFirst = true;
     }
     for (const auto &Entry :
-         llvm::makeArrayRef(PragmaPackStack).drop_front(DropFirst ? 1 : 0))
+         llvm::makeArrayRef(PragmaPackStack).drop_front(DropFirst ? 1 : 0)) {
       SemaObj->PackStack.Stack.emplace_back(Entry.SlotLabel, Entry.Value,
                                             Entry.Location, Entry.PushLocation);
+    }
     if (PragmaPackCurrentLocation.isInvalid()) {
       assert(*PragmaPackCurrentValue == SemaObj->PackStack.DefaultValue &&
-             "Expected a default alignment value");
+             "Expected a default align and pack value");
       // Keep the current values.
     } else {
       SemaObj->PackStack.CurrentValue = *PragmaPackCurrentValue;
Index: clang/lib/Sema/SemaAttr.cpp
===================================================================
--- clang/lib/Sema/SemaAttr.cpp
+++ clang/lib/Sema/SemaAttr.cpp
@@ -48,18 +48,28 @@
 }
 
 void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
-  // If there is no pack value, we don't need any attributes.
-  if (!PackStack.CurrentValue)
+  AlignPackInfo InfoVal = PackStack.CurrentValue;
+  AlignPackInfo::Mode M = InfoVal.getAlignMode();
+  bool IsPackSet = InfoVal.IsPackSet();
+  bool IsXLPragma = getLangOpts().XLPragmaPack;
+
+  // If we are not under mac68k/natural alignment mode and also there is no pack
+  // value, we don't need any attributes.
+  if (!IsPackSet && M != AlignPackInfo::Mac68k && M != AlignPackInfo::Natural)
     return;
 
-  // Otherwise, check to see if we need a max field alignment attribute.
-  if (unsigned Alignment = PackStack.CurrentValue) {
-    if (Alignment == Sema::kMac68kAlignmentSentinel)
-      RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
-    else
-      RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
-                                                        Alignment * 8));
+  if (M == AlignPackInfo::Mac68k && (IsXLPragma || InfoVal.IsAlignAttr())) {
+    RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
+  } else if (IsPackSet) {
+    // Check to see if we need a max field alignment attribute.
+    RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(
+        Context, InfoVal.getPackNumber() * 8));
+  }
+
+  if (IsXLPragma && M == AlignPackInfo::Natural) {
+    RD->addAttr(AlignNaturalAttr::CreateImplicit(Context));
   }
+
   if (PackIncludeStack.empty())
     return;
   // The #pragma pack affected a record in an included file,  so Clang should
@@ -205,23 +215,29 @@
 void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
                                    SourceLocation PragmaLoc) {
   PragmaMsStackAction Action = Sema::PSK_Reset;
-  unsigned Alignment = 0;
+  AlignPackInfo::Mode ModeVal = AlignPackInfo::Native;
+  bool IsAIX = getLangOpts().XLPragmaPack;
+
   switch (Kind) {
-    // For all targets we support native and natural are the same.
+    // For most of the platforms we support, native and natural are the same.
+    // On AIX, native is the same as power, natural means something else.
     //
     // FIXME: This is not true on Darwin/PPC.
   case POAK_Native:
   case POAK_Power:
+    Action = Sema::PSK_Push_Set;
+    break;
   case POAK_Natural:
     Action = Sema::PSK_Push_Set;
-    Alignment = 0;
+    if (IsAIX)
+      ModeVal = AlignPackInfo::Natural;
     break;
 
     // Note that '#pragma options align=packed' is not equivalent to attribute
     // packed, it has a different precedence relative to attribute aligned.
   case POAK_Packed:
     Action = Sema::PSK_Push_Set;
-    Alignment = 1;
+    ModeVal = AlignPackInfo::Packed;
     break;
 
   case POAK_Mac68k:
@@ -231,7 +247,7 @@
       return;
     }
     Action = Sema::PSK_Push_Set;
-    Alignment = Sema::kMac68kAlignmentSentinel;
+    ModeVal = AlignPackInfo::Mac68k;
     break;
 
   case POAK_Reset:
@@ -239,7 +255,8 @@
     // default.
     Action = Sema::PSK_Pop;
     if (PackStack.Stack.empty()) {
-      if (PackStack.CurrentValue) {
+      if (PackStack.CurrentValue.getAlignMode() != AlignPackInfo::Native ||
+          PackStack.CurrentValue.IsPackAttr()) {
         Action = Sema::PSK_Reset;
       } else {
         Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
@@ -250,7 +267,9 @@
     break;
   }
 
-  PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
+  AlignPackInfo Info(ModeVal, IsAIX);
+
+  PackStack.Act(PragmaLoc, Action, StringRef(), Info);
 }
 
 void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, PragmaClangSectionAction Action,
@@ -295,46 +314,71 @@
 
 void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
                            StringRef SlotLabel, Expr *alignment) {
+  bool IsXLPragma = getLangOpts().XLPragmaPack;
+  const AlignPackInfo CurVal = PackStack.CurrentValue;
   Expr *Alignment = static_cast<Expr *>(alignment);
 
   // If specified then alignment must be a "small" power of two.
   unsigned AlignmentVal = 0;
+  AlignPackInfo::Mode ModeVal = CurVal.getAlignMode();
+
   if (Alignment) {
     Optional<llvm::APSInt> Val;
+    Val = Alignment->getIntegerConstantExpr(Context);
 
     // pack(0) is like pack(), which just works out since that is what
     // we use 0 for in PackAttr.
-    if (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
-        !(Val = Alignment->getIntegerConstantExpr(Context)) ||
+    if (Alignment->isTypeDependent() || Alignment->isValueDependent() || !Val ||
         !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) {
       Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment);
       return; // Ignore
     }
 
+    if (IsXLPragma && *Val == 0) {
+      // pack(0) does not work out on AIX.
+      Diag(PragmaLoc, diag::err_pragma_pack_invalid_alignment);
+      return; // Ignore
+    }
+
     AlignmentVal = (unsigned)Val->getZExtValue();
   }
+
   if (Action == Sema::PSK_Show) {
     // Show the current alignment, making sure to show the right value
     // for the default.
     // FIXME: This should come from the target.
-    AlignmentVal = PackStack.CurrentValue;
-    if (AlignmentVal == 0)
+    AlignmentVal = CurVal.getPackNumber();
+    if (!CurVal.IsPackSet())
       AlignmentVal = 8;
-    if (AlignmentVal == Sema::kMac68kAlignmentSentinel)
+    if (ModeVal == AlignPackInfo::Mac68k &&
+        (IsXLPragma || CurVal.IsAlignAttr()))
       Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
     else
       Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
   }
+
   // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
   // "#pragma pack(pop, identifier, n) is undefined"
   if (Action & Sema::PSK_Pop) {
     if (Alignment && !SlotLabel.empty())
       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment);
-    if (PackStack.Stack.empty())
+    if (PackStack.Stack.empty()) {
+      assert(CurVal.getAlignMode() == AlignPackInfo::Native &&
+             "Empty pack stack can only be at Native alignment mode.");
       Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
+    }
   }
 
-  PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
+  AlignPackInfo Info(ModeVal, AlignmentVal, IsXLPragma);
+
+  // XL pragma pack does not support identifier syntax.
+  if (IsXLPragma && !SlotLabel.empty()) {
+    Diag(PragmaLoc, diag::warn_pragma_pack_identifer_not_supported);
+    PackStack.Act(PragmaLoc, Action, StringRef(), Info);
+    return;
+  }
+
+  PackStack.Act(PragmaLoc, Action, SlotLabel, Info);
 }
 
 void Sema::DiagnoseNonDefaultPragmaPack(PragmaPackDiagnoseKind Kind,
@@ -365,6 +409,8 @@
     Diag(PrevPackState.CurrentPragmaLocation, diag::note_pragma_pack_here);
   }
   // Warn about modified alignment after #includes.
+  // FIXME: PackStack may contain both #pragma align and #pragma pack
+  // information, we should warn about both modified align mode and alignment.
   if (PrevPackState.CurrentValue != PackStack.CurrentValue) {
     Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include);
     Diag(PackStack.CurrentPragmaLocation, diag::note_pragma_pack_here);
@@ -376,6 +422,8 @@
     return;
   bool IsInnermost = true;
   for (const auto &StackSlot : llvm::reverse(PackStack.Stack)) {
+    // FIXME: PackStack may contain both #pragma align and #pragma pack
+    // information, we should warn about both unterminated ones.
     Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof);
     // The user might have already reset the alignment, so suggest replacing
     // the reset with a pop.
@@ -481,6 +529,69 @@
   VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode);
 }
 
+template <>
+void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation,
+                                                 PragmaMsStackAction Action,
+                                                 llvm::StringRef StackSlotLabel,
+                                                 AlignPackInfo Value) {
+  if (Action == PSK_Reset) {
+    CurrentValue = DefaultValue;
+    CurrentPragmaLocation = PragmaLocation;
+    return;
+  }
+  if (Action & PSK_Push)
+    Stack.emplace_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation,
+                            PragmaLocation));
+  else if (Action & PSK_Pop) {
+    if (!StackSlotLabel.empty()) {
+      // If we've got a label, try to find it and jump there.
+      auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
+        return x.StackSlotLabel == StackSlotLabel;
+      });
+      // If we found the label so pop from there.
+      if (I != Stack.rend()) {
+        CurrentValue = I->Value;
+        CurrentPragmaLocation = I->PragmaLocation;
+        Stack.erase(std::prev(I.base()), Stack.end());
+      }
+    } else if (Value.IsAIXStack() && Value.IsAlignAttr() &&
+               CurrentValue.IsPackAttr()) {
+      // AIX '#pragma align(reset)' would pop the stack until
+      // a current in effect pragma align is popped.
+      auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) {
+        return x.Value.IsAlignAttr();
+      });
+      // If we found pragma align so pop from there.
+      if (I != Stack.rend()) {
+        Stack.erase(std::prev(I.base()), Stack.end());
+        if (Stack.empty()) {
+          CurrentValue = DefaultValue;
+          CurrentPragmaLocation = PragmaLocation;
+        } else {
+          CurrentValue = Stack.back().Value;
+          CurrentPragmaLocation = Stack.back().PragmaLocation;
+          Stack.pop_back();
+        }
+      }
+    } else if (!Stack.empty()) {
+      // AIX '#pragma align' sets the base line,
+      // and pragma pack cannot pop over the base line.
+      if (Value.IsAIXStack() && Value.IsPackAttr() &&
+          CurrentValue.IsAlignAttr())
+        return;
+
+      // We don't have a label, just pop the last entry.
+      CurrentValue = Stack.back().Value;
+      CurrentPragmaLocation = Stack.back().PragmaLocation;
+      Stack.pop_back();
+    }
+  }
+  if (Action & PSK_Set) {
+    CurrentValue = Value;
+    CurrentPragmaLocation = PragmaLocation;
+  }
+}
+
 bool Sema::UnifySection(StringRef SectionName,
                         int SectionFlags,
                         DeclaratorDecl *Decl) {
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -157,7 +157,8 @@
       OriginalLexicalContext(nullptr), MSStructPragmaOn(false),
       MSPointerToMemberRepresentationMethod(
           LangOpts.getMSPointerToMemberRepresentationMethod()),
-      VtorDispStack(LangOpts.getVtorDispMode()), PackStack(0),
+      VtorDispStack(LangOpts.getVtorDispMode()),
+      PackStack(AlignPackInfo(getLangOpts().XLPragmaPack)),
       DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
       CodeSegStack(nullptr), FpPragmaStack(FPOptionsOverride()),
       CurInitSeg(nullptr), VisContext(nullptr),
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -1736,9 +1736,10 @@
 
     // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
     // the push/pop stack.
-    // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
-    Action =
-        PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
+    // In Apple gcc/AIX, #pragma pack(4) is equivalent to #pragma pack(push, 4)
+    Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
+                 ? Sema::PSK_Push_Set
+                 : Sema::PSK_Set;
   } else if (Tok.is(tok::identifier)) {
     const IdentifierInfo *II = Tok.getIdentifierInfo();
     if (II->isStr("show")) {
@@ -1786,10 +1787,11 @@
         }
       }
     }
-  } else if (PP.getLangOpts().ApplePragmaPack) {
+  } else if (PP.getLangOpts().ApplePragmaPack ||
+             PP.getLangOpts().XLPragmaPack) {
     // In MSVC/gcc, #pragma pack() resets the alignment without affecting
     // the push/pop stack.
-    // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
+    // In Apple gcc and AIX, #pragma pack() is equivalent to #pragma pack(pop).
     Action = Sema::PSK_Pop;
   }
 
@@ -1918,6 +1920,7 @@
 
 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
+// #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
                              bool IsOptions) {
   Token Tok;
@@ -1932,7 +1935,12 @@
   }
 
   PP.Lex(Tok);
-  if (Tok.isNot(tok::equal)) {
+  if (PP.getLangOpts().XLPragmaPack) {
+    if (Tok.isNot(tok::l_paren)) {
+      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
+      return;
+    }
+  } else if (Tok.isNot(tok::equal)) {
     PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
       << IsOptions;
     return;
@@ -1965,6 +1973,14 @@
     return;
   }
 
+  if (PP.getLangOpts().XLPragmaPack) {
+    PP.Lex(Tok);
+    if (Tok.isNot(tok::r_paren)) {
+      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
+      return;
+    }
+  }
+
   SourceLocation EndLoc = Tok.getLocation();
   PP.Lex(Tok);
   if (Tok.isNot(tok::eod)) {
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -3087,6 +3087,7 @@
   Opts.DebuggerSupport = Args.hasArg(OPT_fdebugger_support);
   Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id);
   Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal);
+  Opts.XLPragmaPack = Args.hasArg(OPT_faix_pragma_pack);
   Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack);
   Opts.ModuleName = std::string(Args.getLastArgValue(OPT_fmodule_name_EQ));
   Opts.CurrentModule = Opts.ModuleName;
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6035,6 +6035,10 @@
                    options::OPT_fno_apple_pragma_pack, false))
     CmdArgs.push_back("-fapple-pragma-pack");
 
+  if (Args.hasFlag(options::OPT_faix_pragma_pack,
+                   options::OPT_fno_aix_pragma_pack, RawTriple.isOSAIX()))
+    CmdArgs.push_back("-faix-pragma-pack");
+
   // Remarks can be enabled with any of the `-f.*optimization-record.*` flags.
   if (willEmitRemarks(Args) && checkRemarksOptions(D, Args, Triple))
     renderRemarksOptions(Args, CmdArgs, Triple, Input, Output, JA);
Index: clang/lib/AST/RecordLayoutBuilder.cpp
===================================================================
--- clang/lib/AST/RecordLayoutBuilder.cpp
+++ clang/lib/AST/RecordLayoutBuilder.cpp
@@ -615,6 +615,8 @@
 
   unsigned IsMac68kAlign : 1;
 
+  unsigned IsNaturalAlign : 1;
+
   unsigned IsMsStruct : 1;
 
   /// UnfilledBitsInLastUnit - If the last field laid out was a bitfield,
@@ -693,7 +695,10 @@
         UnpackedAlignment(CharUnits::One()),
         UnadjustedAlignment(CharUnits::One()), UseExternalLayout(false),
         InferAlignment(false), Packed(false), IsUnion(false),
-        IsMac68kAlign(false), IsMsStruct(false), UnfilledBitsInLastUnit(0),
+        IsMac68kAlign(false),
+        IsNaturalAlign(!Context.getTargetInfo().getTriple().isOSAIX() ? true
+                                                                      : false),
+        IsMsStruct(false), UnfilledBitsInLastUnit(0),
         LastBitfieldStorageUnitSize(0), MaxFieldAlignment(CharUnits::Zero()),
         DataSize(0), NonVirtualSize(CharUnits::Zero()),
         NonVirtualAlignment(CharUnits::One()),
@@ -1243,7 +1248,7 @@
       // By handling a base class that is not empty, we're handling the
       // "first (inherited) member".
       HandledFirstNonOverlappingEmptyField = true;
-    } else {
+    } else if (!IsNaturalAlign) {
       UnpackedPreferredBaseAlign = UnpackedBaseAlign;
       PreferredBaseAlign = BaseAlign;
     }
@@ -1314,7 +1319,7 @@
 
   Packed = D->hasAttr<PackedAttr>();
   HandledFirstNonOverlappingEmptyField =
-      !Context.getTargetInfo().defaultsToAIXPowerAlignment();
+      !Context.getTargetInfo().defaultsToAIXPowerAlignment() || IsNaturalAlign;
 
   // Honor the default struct packing maximum alignment flag.
   if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) {
@@ -1326,11 +1331,17 @@
   // allude to additional (more complicated) semantics, especially with regard
   // to bit-fields, but gcc appears not to follow that.
   if (D->hasAttr<AlignMac68kAttr>()) {
+    assert(
+        !D->hasAttr<AlignNaturalAttr>() &&
+        "Having both mac68k and natural alignment on a decl is not allowed.");
     IsMac68kAlign = true;
     MaxFieldAlignment = CharUnits::fromQuantity(2);
     Alignment = CharUnits::fromQuantity(2);
     PreferredAlignment = CharUnits::fromQuantity(2);
   } else {
+    if (D->hasAttr<AlignNaturalAttr>())
+      IsNaturalAlign = true;
+
     if (const MaxFieldAlignmentAttr *MFAA = D->getAttr<MaxFieldAlignmentAttr>())
       MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment());
 
@@ -1921,7 +1932,7 @@
   // types marked `no_unique_address` are not considered to be prior members.
   CharUnits PreferredAlign = FieldAlign;
   if (DefaultsToAIXPowerAlignment && !AlignIsRequired &&
-      FoundFirstNonOverlappingEmptyFieldForAIX) {
+      (FoundFirstNonOverlappingEmptyFieldForAIX || IsNaturalAlign)) {
     auto performBuiltinTypeAlignmentUpgrade = [&](const BuiltinType *BTy) {
       if (BTy->getKind() == BuiltinType::Double ||
           BTy->getKind() == BuiltinType::LongDouble) {
Index: clang/include/clang/Serialization/ASTWriter.h
===================================================================
--- clang/include/clang/Serialization/ASTWriter.h
+++ clang/include/clang/Serialization/ASTWriter.h
@@ -19,6 +19,7 @@
 #include "clang/AST/Type.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaConsumer.h"
 #include "clang/Serialization/ASTBitCodes.h"
 #include "clang/Serialization/ASTDeserializationListener.h"
@@ -584,6 +585,10 @@
   /// Emit a token.
   void AddToken(const Token &Tok, RecordDataImpl &Record);
 
+  /// Emit a AlignPackInfo.
+  void AddAlignPackInfo(const Sema::AlignPackInfo &Info,
+                        RecordDataImpl &Record);
+
   /// Emit a source location.
   void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record);
 
Index: clang/include/clang/Serialization/ASTReader.h
===================================================================
--- clang/include/clang/Serialization/ASTReader.h
+++ clang/include/clang/Serialization/ASTReader.h
@@ -25,6 +25,7 @@
 #include "clang/Lex/PreprocessingRecord.h"
 #include "clang/Sema/ExternalSemaSource.h"
 #include "clang/Sema/IdentifierResolver.h"
+#include "clang/Sema/Sema.h"
 #include "clang/Serialization/ASTBitCodes.h"
 #include "clang/Serialization/ContinuousRangeMap.h"
 #include "clang/Serialization/ModuleFile.h"
@@ -870,10 +871,10 @@
   llvm::SmallVector<std::string, 2> FpPragmaStrings;
 
   /// The pragma pack state.
-  Optional<unsigned> PragmaPackCurrentValue;
+  Optional<Sema::AlignPackInfo> PragmaPackCurrentValue;
   SourceLocation PragmaPackCurrentLocation;
   struct PragmaPackStackEntry {
-    unsigned Value;
+    Sema::AlignPackInfo Value;
     SourceLocation Location;
     SourceLocation PushLocation;
     StringRef SlotLabel;
@@ -2117,6 +2118,11 @@
   /// Read the contents of a CXXCtorInitializer array.
   CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
 
+  /// Read a AlignPackInfo from raw form.
+  Sema::AlignPackInfo ReadAlignPackInfo(uint32_t Raw) const {
+    return Sema::AlignPackInfo::getFromRawEncoding(Raw);
+  }
+
   /// Read a source location from raw form and return it in its
   /// originating module file's source location space.
   SourceLocation ReadUntranslatedSourceLocation(uint32_t Raw) const {
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -477,6 +477,108 @@
     PSK_Pop_Set   = PSK_Pop | PSK_Set,  // #pragma (pop[, id], value)
   };
 
+  // #pragma pack and align.
+  class AlignPackInfo {
+  public:
+    // `Native` represents default align mode, which may vary based on the
+    // platform.
+    enum Mode : unsigned char { Native, Natural, Packed, Mac68k };
+
+    // #pragma pack info constructor
+    AlignPackInfo(AlignPackInfo::Mode M, int Num, bool IsAIX)
+        : PackAttr(true), AlignMode(M), PackNumber(Num), AIXStack(IsAIX) {
+      assert(Num == PackNumber && "Unexpected value.");
+    }
+
+    // #pragma align info constructor
+    AlignPackInfo(AlignPackInfo::Mode M, bool IsAIX)
+        : PackAttr(false), AlignMode(M),
+          PackNumber(M == Packed ? 1 : UninitPackVal), AIXStack(IsAIX) {}
+
+    AlignPackInfo(bool IsAIX) : AlignPackInfo(Native, IsAIX) {}
+
+    AlignPackInfo() : AlignPackInfo(Native, false) {}
+
+    // When a AlignPackInfo itself cannot be used, this returns an 32-bit
+    // integer encoding for it. This should only be passed to
+    // AlignPackInfo::getFromRawEncoding, it should not be inspected directly.
+    uint32_t getRawEncoding(const AlignPackInfo &Info) const {
+      std::uint32_t Encoding{};
+      if (Info.IsAIXStack())
+        Encoding |= IsAIXMask;
+
+      Encoding |= static_cast<uint32_t>(Info.getAlignMode()) << 1;
+
+      if (Info.IsPackAttr())
+        Encoding |= PackAttrMask;
+
+      Encoding |= static_cast<uint32_t>(Info.getPackNumber()) << 4;
+
+      return Encoding;
+    }
+
+    static AlignPackInfo getFromRawEncoding(unsigned Encoding) {
+      bool IsAIX = static_cast<bool>(Encoding & IsAIXMask);
+      AlignPackInfo::Mode M =
+          static_cast<AlignPackInfo::Mode>((Encoding & AlignModeMask) >> 1);
+      int PackNumber = (Encoding & PackNumMask) >> 4;
+
+      if (Encoding & PackAttrMask)
+        return AlignPackInfo(M, PackNumber, IsAIX);
+      else
+        return AlignPackInfo(M, IsAIX);
+    }
+
+    bool IsPackAttr() const { return PackAttr; }
+
+    bool IsAlignAttr() const { return !PackAttr; }
+
+    Mode getAlignMode() const { return AlignMode; }
+
+    unsigned char getPackNumber() const { return PackNumber; }
+
+    bool IsPackSet() const {
+      // #pragma align, #pragma pack(), and #pragma pack(0) do not set the pack
+      // attriute on a decl.
+      return PackNumber != UninitPackVal && PackNumber != 0;
+    }
+
+    bool IsAIXStack() const { return AIXStack; }
+
+    bool operator==(const AlignPackInfo &Info) const {
+      return std::tie(AlignMode, PackNumber, PackAttr, AIXStack) ==
+             std::tie(Info.AlignMode, Info.PackNumber, Info.PackAttr,
+                      Info.AIXStack);
+    }
+
+    bool operator!=(const AlignPackInfo &Info) const {
+      return !(*this == Info);
+    }
+
+  private:
+    /// \brief True if this is a pragma pack attribute,
+    ///         not a pragma align attribute.
+    bool PackAttr;
+
+    /// \brief The alignment mode that is in effect.
+    Mode AlignMode;
+
+    /// \brief The pack number of the stack.
+    unsigned char PackNumber;
+
+    /// \brief True if it is a AIX #pragma align/pack stack.
+    bool AIXStack;
+
+    /// \brief Uninitialized pack value.
+    static constexpr unsigned char UninitPackVal = -1;
+
+    // Masks to encode and decode an AlignPackInfo.
+    static constexpr uint32_t IsAIXMask{0x0000'0001};
+    static constexpr uint32_t AlignModeMask{0x0000'0006};
+    static constexpr uint32_t PackAttrMask{0x00000'0008};
+    static constexpr uint32_t PackNumMask{0x0000'01F0};
+  };
+
   template<typename ValueType>
   struct PragmaStack {
     struct Slot {
@@ -569,13 +671,10 @@
   /// 2: Always insert vtordisps to support RTTI on partially constructed
   ///    objects
   PragmaStack<MSVtorDispMode> VtorDispStack;
-  // #pragma pack.
-  // Sentinel to represent when the stack is set to mac68k alignment.
-  static const unsigned kMac68kAlignmentSentinel = ~0U;
-  PragmaStack<unsigned> PackStack;
+  PragmaStack<AlignPackInfo> PackStack;
   // The current #pragma pack values and locations at each #include.
   struct PackIncludeState {
-    unsigned CurrentValue;
+    AlignPackInfo CurrentValue;
     SourceLocation CurrentPragmaLocation;
     bool HasNonDefaultValue, ShouldWarnOnInclude;
   };
@@ -12768,6 +12867,13 @@
   /// The template function declaration to be late parsed.
   Decl *D;
 };
+
+template <>
+void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation,
+                                                 PragmaMsStackAction Action,
+                                                 llvm::StringRef StackSlotLabel,
+                                                 AlignPackInfo Value);
+
 } // end namespace clang
 
 namespace llvm {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -774,6 +774,8 @@
   HelpText<"Use Apple's kernel extensions ABI">;
 def fapple_pragma_pack : Flag<["-"], "fapple-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
+def faix_pragma_pack : Flag<["-"], "faix-pragma-pack">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Enable AIX #pragma pack handling">;
 def shared_libsan : Flag<["-"], "shared-libsan">,
   HelpText<"Dynamically link the sanitizer runtime">;
 def static_libsan : Flag<["-"], "static-libsan">,
@@ -1592,6 +1594,7 @@
 def fnested_functions : Flag<["-"], "fnested-functions">, Group<f_Group>;
 def fnext_runtime : Flag<["-"], "fnext-runtime">, Group<f_Group>;
 def fno_apple_pragma_pack : Flag<["-"], "fno-apple-pragma-pack">, Group<f_Group>;
+def fno_aix_pragma_pack : Flag<["-"], "fno-aix-pragma-pack">, Group<f_Group>;
 def fno_asm : Flag<["-"], "fno-asm">, Group<f_Group>;
 def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables">, Group<f_Group>;
 def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group<f_Group>,
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -352,6 +352,8 @@
 
 LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling")
 
+LANGOPT(XLPragmaPack, 1, 0, "AIX #pragma pack handling")
+
 LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST")
 
 LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan "
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -847,6 +847,8 @@
 def warn_pragma_pack_invalid_alignment : Warning<
   "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">,
   InGroup<IgnoredPragmas>;
+def err_pragma_pack_invalid_alignment : Error<
+  "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">;
 def warn_pragma_pack_non_default_at_include : Warning<
   "non-default #pragma pack value changes the alignment of struct or union "
   "members in the included file">, InGroup<PragmaPackSuspiciousInclude>,
@@ -880,6 +882,9 @@
   Warning<"ms_struct may not produce Microsoft-compatible layouts for classes "
           "with base classes or virtual functions">,
   DefaultError, InGroup<IncompatibleMSStruct>;
+def warn_pragma_pack_identifer_not_supported : Warning<
+  "specifying an identifier within pragma pack is not supported, identifier is ignored">,
+  InGroup<PragmaPack>;
 def err_section_conflict : Error<"%0 causes a section type conflict with %1">;
 def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">;
 def err_invalid_super_scope : Error<"invalid use of '__super', "
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -675,6 +675,13 @@
   let Documentation = [Undocumented];
 }
 
+def AlignNatural : InheritableAttr {
+  // This attribute has no spellings as it is only ever created implicitly.
+  let Spellings = [];
+  let SemaHandler = 0;
+  let Documentation = [Undocumented];
+}
+
 def AlwaysInline : InheritableAttr {
   let Spellings = [GCC<"always_inline">, Keyword<"__forceinline">];
   let Subjects = SubjectList<[Function]>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to