diff options
-rw-r--r-- | clang/lib/Sema/Sema.h | 43 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 122 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 |
3 files changed, 103 insertions, 64 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 2e457156d1e..067c7a57df4 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -78,37 +78,6 @@ namespace clang { class BasePaths; class MemberLookupCriteria; -/// 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(unsigned A) : Alignment(A) {} - - 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); -}; - /// Sema - This implements semantic analysis and AST building for C. class Sema : public Action { Sema(const Sema&); // DO NOT IMPLEMENT @@ -134,7 +103,7 @@ public: /// PackContext - Manages the stack for #pragma pack. An alignment /// of 0 indicates default alignment. - PragmaPackStack PackContext; + void *PackContext; // Really a "PragmaPackStack*" /// LabelMap - This is a mapping from label identifiers to the LabelStmt for /// it (which acts like the label decl in some ways). Forward referenced @@ -231,6 +200,9 @@ public: llvm::DenseMap<Selector, ObjCMethodList> FactoryMethodPool; public: Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer); + ~Sema() { + if (PackContext) FreePackedContext(); + } const LangOptions &getLangOptions() const { return LangOpts; } Diagnostic &getDiagnostics() const { return Diags; } @@ -1706,6 +1678,13 @@ public: SourceLocation PragmaLoc, SourceLocation LParenLoc, SourceLocation RParenLoc); + + /// getPragmaPackAlignment() - Return the current alignment as specified by + /// the current #pragma pack directive, or 0 if none is currently active. + unsigned getPragmaPackAlignment() const; + + /// FreePackedContext - Deallocate and null out PackContext. + void FreePackedContext(); /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit /// cast. If there is already an implicit cast, merge into the existing one. diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index a3978ac32c3..bf1e10e5b0b 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/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 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 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 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 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 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, 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 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, } else { // Pop succeeded, set the new alignment if specified. if (Alignment) - PackContext.setAlignment(AlignmentVal); + Context->setAlignment(AlignmentVal); } break; @@ -84,27 +168,3 @@ void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, } } -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; -} diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 70990a87a32..7b8373ca390 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3276,7 +3276,7 @@ CreateNewDecl: // many points during the parsing of a struct declaration (because // the #pragma tokens are effectively skipped over during the // parsing of the struct). - if (unsigned Alignment = PackContext.getAlignment()) + if (unsigned Alignment = getPragmaPackAlignment()) New->addAttr(new PackedAttr(Alignment * 8)); } |