diff options
Diffstat (limited to 'clang/lib/Sema/SemaAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 189 |
1 files changed, 37 insertions, 152 deletions
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index c22c7c620c9..7387b66c0cc 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -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::~PragmaStackSentinelRAII() { } } -/// 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(RecordDecl *RD) { 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(PragmaOptionsAlignKind Kind, 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(PragmaOptionsAlignKind Kind, 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(PragmaPackKind Kind, IdentifierInfo *Name, 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) { |