From ddc6ff6b9aff656504c1e84ee7dc9f617a20f866 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Fri, 16 Jul 2010 04:54:16 +0000 Subject: [PATCH] Sema: Fix a bug with #pragma options align=reset, reset against an empty stack 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 | 37 ++++++++++++++++++++------------- test/Sema/pragma-align-packed.c | 7 +++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 69f27b0ada..540ee7a2af 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -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(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. diff --git a/test/Sema/pragma-align-packed.c b/test/Sema/pragma-align-packed.c index 30b87bf996..74fbd13d16 100644 --- a/test/Sema/pragma-align-packed.c +++ b/test/Sema/pragma-align-packed.c @@ -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]; -- 2.40.0