Make PragmaPackStack be a private class in SemaAttr and make its
instance in Sema be a pimpl.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64718 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index a3978ac..bf1e10e 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -7,7 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 //
-//  This file implements semantic analysis for non-trivial attributes.
+// This file implements semantic analysis for non-trivial attributes and
+// pragmas.
 //
 //===----------------------------------------------------------------------===//
 
@@ -15,6 +16,83 @@
 #include "clang/AST/Expr.h"
 using namespace clang;
 
+//===----------------------------------------------------------------------===//
+// Pragma Packed
+//===----------------------------------------------------------------------===//
+
+namespace {
+  /// PragmaPackStack - Simple class to wrap the stack used by #pragma
+  /// pack.
+  class PragmaPackStack {
+    typedef std::vector< std::pair<unsigned, IdentifierInfo*> > stack_ty;
+
+    /// Alignment - The current user specified alignment.
+    unsigned Alignment;
+
+    /// Stack - Entries in the #pragma pack stack, consisting of saved
+    /// alignments and optional names.
+    stack_ty Stack;
+    
+  public:  
+    PragmaPackStack() : Alignment(0) {}
+
+    void setAlignment(unsigned A) { Alignment = A; }
+    unsigned getAlignment() { return Alignment; }
+
+    /// push - Push the current alignment onto the stack, optionally
+    /// using the given \arg Name for the record, if non-zero.
+    void push(IdentifierInfo *Name) {
+      Stack.push_back(std::make_pair(Alignment, Name));
+    }
+
+    /// pop - Pop a record from the stack and restore the current
+    /// 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);
+  };
+}  // end anonymous namespace.
+
+bool PragmaPackStack::pop(IdentifierInfo *Name) {
+  if (Stack.empty())
+    return false;
+  
+  // If name is empty just pop top.
+  if (!Name) {
+    Alignment = Stack.back().first;
+    Stack.pop_back();
+    return true;
+  } 
+  
+  // Otherwise, find the named record.
+  for (unsigned i = Stack.size(); i != 0; ) {
+    --i;
+    if (Stack[i].second == Name) {
+      // Found it, pop up to and including this record.
+      Alignment = Stack[i].first;
+      Stack.erase(Stack.begin() + i, Stack.end());
+      return true;
+    }
+  }
+  
+  return false;
+}
+
+
+/// FreePackedContext - Deallocate and null out PackContext.
+void Sema::FreePackedContext() {
+  delete static_cast<PragmaPackStack*>(PackContext);
+  PackContext = 0;
+}
+
+/// getPragmaPackAlignment() - Return the current alignment as specified by
+/// the current #pragma pack directive, or 0 if none is currently active.
+unsigned Sema::getPragmaPackAlignment() const {
+  if (PackContext)
+    return static_cast<PragmaPackStack*>(PackContext)->getAlignment();
+  return 0;
+}
+
 void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 
                            ExprTy *alignment, SourceLocation PragmaLoc, 
                            SourceLocation LParenLoc, SourceLocation RParenLoc) {
@@ -34,16 +112,22 @@
 
     AlignmentVal = (unsigned) Val.getZExtValue();
   }
+  
+  if (PackContext == 0)
+    PackContext = new PragmaPackStack();
 
+  
+  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
+  
   switch (Kind) {
   case Action::PPK_Default: // pack([n])
-    PackContext.setAlignment(AlignmentVal);
+    Context->setAlignment(AlignmentVal);
     break;
 
   case Action::PPK_Show: // pack(show)
     // Show the current alignment, making sure to show the right value
     // for the default.
-    AlignmentVal = PackContext.getAlignment();
+    AlignmentVal = Context->getAlignment();
     // FIXME: This should come from the target.
     if (AlignmentVal == 0)
       AlignmentVal = 8;
@@ -51,10 +135,10 @@
     break;
 
   case Action::PPK_Push: // pack(push [, id] [, [n])
-    PackContext.push(Name);
+    Context->push(Name);
     // Set the new alignment if specified.
     if (Alignment)
-      PackContext.setAlignment(AlignmentVal);    
+      Context->setAlignment(AlignmentVal);    
     break;
 
   case Action::PPK_Pop: // pack(pop [, id] [,  n])
@@ -64,7 +148,7 @@
       Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment);    
     
     // Do the pop.
-    if (!PackContext.pop(Name)) {
+    if (!Context->pop(Name)) {
       // If a name was specified then failure indicates the name
       // wasn't found. Otherwise failure indicates the stack was
       // empty.
@@ -75,7 +159,7 @@
     } else {
       // Pop succeeded, set the new alignment if specified.
       if (Alignment)
-        PackContext.setAlignment(AlignmentVal);
+        Context->setAlignment(AlignmentVal);
     }
     break;
 
@@ -84,27 +168,3 @@
   }
 }
 
-bool PragmaPackStack::pop(IdentifierInfo *Name) {
-  if (Stack.empty())
-    return false;
-
-  // If name is empty just pop top.
-  if (!Name) {
-    Alignment = Stack.back().first;
-    Stack.pop_back();
-    return true;
-  } 
-
-  // Otherwise, find the named record.
-  for (unsigned i = Stack.size(); i != 0; ) {
-    --i;
-    if (Stack[i].second == Name) {
-      // Found it, pop up to and including this record.
-      Alignment = Stack[i].first;
-      Stack.erase(Stack.begin() + i, Stack.end());
-      return true;
-    }
-  }
-
-  return false;
-}