]> granicus.if.org Git - clang/commitdiff
Sema: Fix a bug with #pragma options align=reset, reset against an empty stack
authorDaniel Dunbar <daniel@zuster.org>
Fri, 16 Jul 2010 04:54:16 +0000 (04:54 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Fri, 16 Jul 2010 04:54:16 +0000 (04:54 +0000)
is well defined, it resets to the default alignment.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108508 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaAttr.cpp
test/Sema/pragma-align-packed.c

index 69f27b0ada7da7196a3763ec35728b2f039a61a0..540ee7a2af123cdf45ff7e2dc506284c85169aeb 100644 (file)
@@ -62,18 +62,30 @@ namespace {
     /// alignment to the previous value. If \arg Name is non-zero then
     /// the first such named record is popped, otherwise the top record
     /// is popped. Returns true if the pop succeeded.
-    bool pop(IdentifierInfo *Name);
+    bool pop(IdentifierInfo *Name, bool IsReset);
   };
 }  // end anonymous namespace.
 
-bool PragmaPackStack::pop(IdentifierInfo *Name) {
-  if (Stack.empty())
-    return false;
-
+bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
   // If name is empty just pop top.
   if (!Name) {
-    Alignment = Stack.back().Alignment;
-    Stack.pop_back();
+    // An empty stack is a special case...
+    if (Stack.empty()) {
+      // If this isn't a reset, it is always an error.
+      if (!IsReset)
+        return false;
+
+      // Otherwise, it is an error only if some alignment has been set.
+      if (!Alignment)
+        return false;
+
+      // Otherwise, reset to the default alignment.
+      Alignment = 0;
+    } else {
+      Alignment = Stack.back().Alignment;
+      Stack.pop_back();
+    }
+
     return true;
   }
 
@@ -122,13 +134,10 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
 
   PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
 
-  // Reset just pops the top of the stack.
+  // Reset just pops the top of the stack, or resets the current alignment to
+  // default.
   if (Kind == Action::POAK_Reset) {
-    // Do the pop.
-    if (!Context->pop(0)) {
-      // If a name was specified then failure indicates the name
-      // wasn't found. Otherwise failure indicates the stack was
-      // empty.
+    if (!Context->pop(0, /*IsReset=*/true)) {
       Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
         << "stack empty";
     }
@@ -232,7 +241,7 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);
 
     // Do the pop.
-    if (!Context->pop(Name)) {
+    if (!Context->pop(Name, /*IsReset=*/false)) {
       // If a name was specified then failure indicates the name
       // wasn't found. Otherwise failure indicates the stack was
       // empty.
index 30b87bf99695fe5d26792894ff1bad91f2191cc4..74fbd13d162bf40699393c9153d57b1bb3802c54 100644 (file)
@@ -21,3 +21,10 @@ struct s2 {
 };
 extern int a[sizeof(struct s2) == 5 ? 1 : -1];
 #pragma options align=reset
+
+#pragma pack(1)
+struct s3_0 { unsigned char f0; unsigned int f1; };
+int t3_0[sizeof(struct s3_0) == 5 ? 1 : -1];
+#pragma options align=reset
+struct s3_1 { unsigned char f0; unsigned int f1; };
+int t3_1[sizeof(struct s3_1) == 8 ? 1 : -1];