r268085 - [MS] Make #pragma pack use PragmaStack<> class.

Denis Zobnin via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 29 11:17:40 PDT 2016


Author: dzobnin
Date: Fri Apr 29 13:17:40 2016
New Revision: 268085

URL: http://llvm.org/viewvc/llvm-project?rev=268085&view=rev
Log:
[MS] Make #pragma pack use PragmaStack<> class.

Make implementation of #pragma pack consistent with other "stack" pragmas.
Use PragmaStack<> class instead of old representation of internal stack.
Don't change compiler's behavior.

TODO:
  1. Introduce diagnostics on popping named slots from pragma stacks.

Reviewer: rnk

Differential revision: http://reviews.llvm.org/D19727

Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Parse/ParsePragma.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaAttr.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=268085&r1=268084&r2=268085&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Apr 29 13:17:40 2016
@@ -317,10 +317,6 @@ public:
   /// This is used as part of a hack to omit that class from ADL results.
   DeclarationName VAListTagName;
 
-  /// PackContext - Manages the stack for \#pragma pack. An alignment
-  /// of 0 indicates default alignment.
-  void *PackContext; // Really a "PragmaPackStack*"
-
   bool MSStructPragmaOn; // True when \#pragma ms_struct on
 
   /// \brief Controls member pointer representation format under the MS ABI.
@@ -338,6 +334,7 @@ public:
     PSK_Set       = 0x1,                // #pragma (value)
     PSK_Push      = 0x2,                // #pragma (push[, id])
     PSK_Pop       = 0x4,                // #pragma (pop[, id])
+    PSK_Show      = 0x8,                // #pragma (show) -- only for "pack"!
     PSK_Push_Set  = PSK_Push | PSK_Set, // #pragma (push[, id], value)
     PSK_Pop_Set   = PSK_Pop | PSK_Set,  // #pragma (pop[, id], value)
   };
@@ -400,11 +397,15 @@ public:
   /// 2: Always insert vtordisps to support RTTI on partially constructed
   ///    objects
   PragmaStack<MSVtorDispAttr::Mode> VtorDispStack;
+  // #pragma pack.
+  // Sentinel to represent when the stack is set to mac68k alignment.
+  static const unsigned kMac68kAlignmentSentinel = ~0U;
+  PragmaStack<unsigned> PackStack;
+  // Segment #pragmas.
   PragmaStack<StringLiteral *> DataSegStack;
   PragmaStack<StringLiteral *> BSSSegStack;
   PragmaStack<StringLiteral *> ConstSegStack;
   PragmaStack<StringLiteral *> CodeSegStack;
-  // TODO: Change implementation of #pragma pack to use PragmaStack<> approach.
 
   // RAII object to push / pop sentinel slots for all MS #pragma stacks.
   // Actions should be performed only if we enter / exit a C++ method body.
@@ -7658,20 +7659,9 @@ public:
   void ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
                                SourceLocation PragmaLoc);
 
-  enum PragmaPackKind {
-    PPK_Default, // #pragma pack([n])
-    PPK_Show,    // #pragma pack(show), only supported by MSVC.
-    PPK_Push,    // #pragma pack(push, [identifier], [n])
-    PPK_Pop      // #pragma pack(pop, [identifier], [n])
-  };
-
   /// ActOnPragmaPack - Called on well formed \#pragma pack(...).
-  void ActOnPragmaPack(PragmaPackKind Kind,
-                       IdentifierInfo *Name,
-                       Expr *Alignment,
-                       SourceLocation PragmaLoc,
-                       SourceLocation LParenLoc,
-                       SourceLocation RParenLoc);
+  void ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
+                       StringRef SlotLabel, Expr *Alignment);
 
   /// ActOnPragmaMSStruct - Called on well formed \#pragma ms_struct [on|off].
   void ActOnPragmaMSStruct(PragmaMSStructKind Kind);

Modified: cfe/trunk/lib/Parse/ParsePragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=268085&r1=268084&r2=268085&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.cpp (original)
+++ cfe/trunk/lib/Parse/ParsePragma.cpp Fri Apr 29 13:17:40 2016
@@ -337,11 +337,9 @@ void Parser::HandlePragmaVisibility() {
 
 namespace {
 struct PragmaPackInfo {
-  Sema::PragmaPackKind Kind;
-  IdentifierInfo *Name;
+  Sema::PragmaMsStackAction Action;
+  StringRef SlotLabel;
   Token Alignment;
-  SourceLocation LParenLoc;
-  SourceLocation RParenLoc;
 };
 } // end anonymous namespace
 
@@ -356,8 +354,8 @@ void Parser::HandlePragmaPack() {
     if (Alignment.isInvalid())
       return;
   }
-  Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
-                          Info->LParenLoc, Info->RParenLoc);
+  Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
+                          Alignment.get());
 }
 
 void Parser::HandlePragmaMSStruct() {
@@ -962,11 +960,10 @@ void PragmaPackHandler::HandlePragma(Pre
     return;
   }
 
-  Sema::PragmaPackKind Kind = Sema::PPK_Default;
-  IdentifierInfo *Name = nullptr;
+  Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
+  StringRef SlotLabel;
   Token Alignment;
   Alignment.startToken();
-  SourceLocation LParenLoc = Tok.getLocation();
   PP.Lex(Tok);
   if (Tok.is(tok::numeric_constant)) {
     Alignment = Tok;
@@ -976,18 +973,18 @@ void PragmaPackHandler::HandlePragma(Pre
     // 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)
-    if (PP.getLangOpts().ApplePragmaPack)
-      Kind = Sema::PPK_Push;
+    Action =
+        PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
   } else if (Tok.is(tok::identifier)) {
     const IdentifierInfo *II = Tok.getIdentifierInfo();
     if (II->isStr("show")) {
-      Kind = Sema::PPK_Show;
+      Action = Sema::PSK_Show;
       PP.Lex(Tok);
     } else {
       if (II->isStr("push")) {
-        Kind = Sema::PPK_Push;
+        Action = Sema::PSK_Push;
       } else if (II->isStr("pop")) {
-        Kind = Sema::PPK_Pop;
+        Action = Sema::PSK_Pop;
       } else {
         PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
         return;
@@ -998,11 +995,12 @@ void PragmaPackHandler::HandlePragma(Pre
         PP.Lex(Tok);
 
         if (Tok.is(tok::numeric_constant)) {
+          Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
           Alignment = Tok;
 
           PP.Lex(Tok);
         } else if (Tok.is(tok::identifier)) {
-          Name = Tok.getIdentifierInfo();
+          SlotLabel = Tok.getIdentifierInfo()->getName();
           PP.Lex(Tok);
 
           if (Tok.is(tok::comma)) {
@@ -1013,6 +1011,7 @@ void PragmaPackHandler::HandlePragma(Pre
               return;
             }
 
+            Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
             Alignment = Tok;
 
             PP.Lex(Tok);
@@ -1027,7 +1026,7 @@ void PragmaPackHandler::HandlePragma(Pre
     // 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).
-    Kind = Sema::PPK_Pop;
+    Action = Sema::PSK_Pop;
   }
 
   if (Tok.isNot(tok::r_paren)) {
@@ -1044,11 +1043,9 @@ void PragmaPackHandler::HandlePragma(Pre
 
   PragmaPackInfo *Info =
       PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
-  Info->Kind = Kind;
-  Info->Name = Name;
+  Info->Action = Action;
+  Info->SlotLabel = SlotLabel;
   Info->Alignment = Alignment;
-  Info->LParenLoc = LParenLoc;
-  Info->RParenLoc = RParenLoc;
 
   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
                               1);

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=268085&r1=268084&r2=268085&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Apr 29 13:17:40 2016
@@ -79,12 +79,13 @@ Sema::Sema(Preprocessor &pp, ASTContext
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
     CollectStats(false), CodeCompleter(CodeCompleter),
     CurContext(nullptr), OriginalLexicalContext(nullptr),
-    PackContext(nullptr), MSStructPragmaOn(false),
+    MSStructPragmaOn(false),
     MSPointerToMemberRepresentationMethod(
         LangOpts.getMSPointerToMemberRepresentationMethod()),
     VtorDispStack(MSVtorDispAttr::Mode(LangOpts.VtorDispMode)),
-    DataSegStack(nullptr), BSSSegStack(nullptr), ConstSegStack(nullptr),
-    CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr),
+    PackStack(0), DataSegStack(nullptr), BSSSegStack(nullptr),
+    ConstSegStack(nullptr), CodeSegStack(nullptr), CurInitSeg(nullptr),
+    VisContext(nullptr),
     IsBuildingRecoveryCallExpr(false),
     ExprNeedsCleanups(false), LateTemplateParser(nullptr),
     LateTemplateParserCleanup(nullptr),
@@ -252,7 +253,6 @@ void Sema::Initialize() {
 
 Sema::~Sema() {
   llvm::DeleteContainerSeconds(LateParsedTemplateMap);
-  if (PackContext) FreePackedContext();
   if (VisContext) FreeVisContext();
   // Kill all the active scopes.
   for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)

Modified: cfe/trunk/lib/Sema/SemaAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAttr.cpp?rev=268085&r1=268084&r2=268085&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAttr.cpp Fri Apr 29 13:17:40 2016
@@ -25,86 +25,6 @@ using namespace clang;
 // Pragma 'pack' and 'options align'
 //===----------------------------------------------------------------------===//
 
-namespace {
-  struct PackStackEntry {
-    // We just use a sentinel to represent when the stack is set to mac68k
-    // alignment.
-    static const unsigned kMac68kAlignmentSentinel = ~0U;
-
-    unsigned Alignment;
-    IdentifierInfo *Name;
-  };
-
-  /// PragmaPackStack - Simple class to wrap the stack used by #pragma
-  /// pack.
-  class PragmaPackStack {
-    typedef std::vector<PackStackEntry> 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) {
-      PackStackEntry PSE = { Alignment, Name };
-      Stack.push_back(PSE);
-    }
-
-    /// 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, bool IsReset);
-  };
-}  // end anonymous namespace.
-
-bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) {
-  // If name is empty just pop top.
-  if (!Name) {
-    // 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;
-  }
-
-  // Otherwise, find the named record.
-  for (unsigned i = Stack.size(); i != 0; ) {
-    --i;
-    if (Stack[i].Name == Name) {
-      // Found it, pop up to and including this record.
-      Alignment = Stack[i].Alignment;
-      Stack.erase(Stack.begin() + i, Stack.end());
-      return true;
-    }
-  }
-
-  return false;
-}
-
 Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S,
                                                        StringRef SlotLabel,
                                                        bool ShouldAct)
@@ -128,22 +48,14 @@ Sema::PragmaStackSentinelRAII::~PragmaSt
   }
 }
 
-/// FreePackedContext - Deallocate and null out PackContext.
-void Sema::FreePackedContext() {
-  delete static_cast<PragmaPackStack*>(PackContext);
-  PackContext = nullptr;
-}
-
 void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) {
-  // If there is no pack context, we don't need any attributes.
-  if (!PackContext)
+  // If there is no pack value, we don't need any attributes.
+  if (!PackStack.CurrentValue)
     return;
 
-  PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext);
-
   // Otherwise, check to see if we need a max field alignment attribute.
-  if (unsigned Alignment = Stack->getAlignment()) {
-    if (Alignment == PackStackEntry::kMac68kAlignmentSentinel)
+  if (unsigned Alignment = PackStack.CurrentValue) {
+    if (Alignment == Sema::kMac68kAlignmentSentinel)
       RD->addAttr(AlignMac68kAttr::CreateImplicit(Context));
     else
       RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit(Context,
@@ -165,11 +77,8 @@ void Sema::AddMsStructLayoutForRecord(Re
 
 void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind,
                                    SourceLocation PragmaLoc) {
-  if (!PackContext)
-    PackContext = new PragmaPackStack();
-
-  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
-
+  PragmaMsStackAction Action = Sema::PSK_Reset;
+  unsigned Alignment;
   switch (Kind) {
     // For all targets we support native and natural are the same.
     //
@@ -177,15 +86,15 @@ void Sema::ActOnPragmaOptionsAlign(Pragm
   case POAK_Native:
   case POAK_Power:
   case POAK_Natural:
-    Context->push(nullptr);
-    Context->setAlignment(0);
+    Action = Sema::PSK_Push_Set;
+    Alignment = 0;
     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:
-    Context->push(nullptr);
-    Context->setAlignment(1);
+    Action = Sema::PSK_Push_Set;
+    Alignment = 1;
     break;
 
   case POAK_Mac68k:
@@ -194,24 +103,31 @@ void Sema::ActOnPragmaOptionsAlign(Pragm
       Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported);
       return;
     }
-    Context->push(nullptr);
-    Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel);
+    Action = Sema::PSK_Push_Set;
+    Alignment = Sema::kMac68kAlignmentSentinel;
     break;
 
   case POAK_Reset:
     // Reset just pops the top of the stack, or resets the current alignment to
     // default.
-    if (!Context->pop(nullptr, /*IsReset=*/true)) {
-      Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
-        << "stack empty";
+    Action = Sema::PSK_Pop;
+    if (PackStack.Stack.empty()) {
+      if (PackStack.CurrentValue) {
+        Action = Sema::PSK_Reset;
+      } else {
+        Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed)
+            << "stack empty";
+        return;
+      }
     }
     break;
   }
+
+  PackStack.Act(PragmaLoc, Action, StringRef(), Alignment);
 }
 
-void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name,
-                           Expr *alignment, SourceLocation PragmaLoc,
-                           SourceLocation LParenLoc, SourceLocation RParenLoc) {
+void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action,
+                           StringRef SlotLabel, Expr *alignment) {
   Expr *Alignment = static_cast<Expr *>(alignment);
 
   // If specified then alignment must be a "small" power of two.
@@ -232,59 +148,28 @@ void Sema::ActOnPragmaPack(PragmaPackKin
 
     AlignmentVal = (unsigned) Val.getZExtValue();
   }
-
-  if (!PackContext)
-    PackContext = new PragmaPackStack();
-
-  PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext);
-
-  switch (Kind) {
-  case Sema::PPK_Default: // pack([n])
-    Context->setAlignment(AlignmentVal);
-    break;
-
-  case Sema::PPK_Show: // pack(show)
+  if (Action == Sema::PSK_Show) {
     // Show the current alignment, making sure to show the right value
     // for the default.
-    AlignmentVal = Context->getAlignment();
     // FIXME: This should come from the target.
+    AlignmentVal = PackStack.CurrentValue;
     if (AlignmentVal == 0)
       AlignmentVal = 8;
-    if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel)
+    if (AlignmentVal == Sema::kMac68kAlignmentSentinel)
       Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k";
     else
       Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal;
-    break;
-
-  case Sema::PPK_Push: // pack(push [, id] [, [n])
-    Context->push(Name);
-    // Set the new alignment if specified.
-    if (Alignment)
-      Context->setAlignment(AlignmentVal);
-    break;
-
-  case Sema::PPK_Pop: // pack(pop [, id] [,  n])
-    // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack:
-    // "#pragma pack(pop, identifier, n) is undefined"
-    if (Alignment && Name)
+  }
+  // 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_identifer_and_alignment);
-
-    // Do the pop.
-    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.
-      Diag(PragmaLoc, diag::warn_pragma_pop_failed)
-          << "pack" << (Name ? "no record matching name" : "stack empty");
-
-      // FIXME: Warn about popping named records as MSVC does.
-    } else {
-      // Pop succeeded, set the new alignment if specified.
-      if (Alignment)
-        Context->setAlignment(AlignmentVal);
-    }
-    break;
+    if (PackStack.Stack.empty())
+      Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty";
   }
+
+  PackStack.Act(PragmaLoc, Action, SlotLabel, AlignmentVal);
 }
 
 void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { 




More information about the cfe-commits mailing list