From aa5ab26ed93382b812147f532dcbf4afb5494040 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 23 Feb 2012 23:47:16 +0000 Subject: [PATCH] Handle "#pragma GCC visibility" in a few more places. Switch over "#pragma pack" to use the same handling that gcc does. Fixes and . (Hopefully, common usage of these pragmas isn't irregular enough to break our current handling. Doug has ideas for a more crazy approach if necessary.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151307 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/TokenKinds.def | 5 ++++ include/clang/Parse/Parser.h | 4 +++ lib/Parse/ParseDeclCXX.cpp | 10 ++++++++ lib/Parse/ParsePragma.cpp | 34 +++++++++++++++++++++++-- lib/Parse/ParseStmt.cpp | 8 ++++++ lib/Parse/Parser.cpp | 3 +++ test/Sema/pragma-pack-2.c | 40 +++++++++++++++++++----------- test/SemaCXX/pragma-visibility.cpp | 11 ++++++++ test/SemaObjC/pragma-pack.m | 16 ++++++++++++ 9 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 test/SemaObjC/pragma-pack.m diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 014e111033..300db4d886 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -574,6 +574,11 @@ ANNOTATION(pragma_unused) // handles them. ANNOTATION(pragma_vis) +// Annotation for #pragma pack... +// The lexer produces these so that they only take effect when the parser +// handles them. +ANNOTATION(pragma_pack) + #undef ANNOTATION #undef TESTING_KEYWORD #undef OBJC2_AT_KEYWORD diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 079a93fb5b..64736118e1 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -410,6 +410,10 @@ private: /// #pragma GCC visibility... void HandlePragmaVisibility(); + /// \brief Handle the annotation token produced for + /// #pragma pack... + void HandlePragmaPack(); + /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) /// returns the token after Tok, etc. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index cc8c0c45d2..c2bf54db2c 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2251,6 +2251,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, continue; } + if (Tok.is(tok::annot_pragma_vis)) { + HandlePragmaVisibility(); + continue; + } + + if (Tok.is(tok::annot_pragma_pack)) { + HandlePragmaPack(); + continue; + } + AccessSpecifier AS = getAccessSpecifierIfPresent(); if (AS != AS_none) { // Current token is a C++ access specifier. diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 433c76b83b..96a4f3af76 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -37,6 +37,24 @@ void Parser::HandlePragmaVisibility() { Actions.ActOnPragmaVisibility(VisType, VisLoc); } +struct PragmaPackInfo { + Sema::PragmaPackKind Kind; + IdentifierInfo *Name; + Expr *Alignment; + SourceLocation LParenLoc; + SourceLocation RParenLoc; +}; + +void Parser::HandlePragmaPack() { + assert(Tok.is(tok::annot_pragma_pack)); + PragmaPackInfo *Info = + static_cast(Tok.getAnnotationValue()); + SourceLocation PragmaLoc = ConsumeToken(); + Actions.ActOnPragmaPack(Info->Kind, Info->Name, Info->Alignment, PragmaLoc, + Info->LParenLoc, Info->RParenLoc); + delete Info; +} + // #pragma GCC visibility comes in two variants: // 'push' '(' [visibility] ')' // 'pop' @@ -196,8 +214,20 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, return; } - Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc, - LParenLoc, RParenLoc); + PragmaPackInfo *Info = new PragmaPackInfo; + Info->Kind = Kind; + Info->Name = Name; + Info->Alignment = Alignment.release(); + Info->LParenLoc = LParenLoc; + Info->RParenLoc = RParenLoc; + + Token *Toks = new Token[1]; + Toks[0].startToken(); + Toks[0].setKind(tok::annot_pragma_pack); + Toks[0].setLocation(PackLoc); + Toks[0].setAnnotationValue(static_cast(Info)); + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/true); } // #pragma ms_struct on diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 3537768eed..0ce73cbeb2 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -280,6 +280,14 @@ Retry: case tok::kw___try: return ParseSEHTryBlock(attrs); + + case tok::annot_pragma_vis: + HandlePragmaVisibility(); + return StmtEmpty(); + + case tok::annot_pragma_pack: + HandlePragmaPack(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4c5df4d2ff..6927c50b8f 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -549,6 +549,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_vis: HandlePragmaVisibility(); return DeclGroupPtrTy(); + case tok::annot_pragma_pack: + HandlePragmaPack(); + return DeclGroupPtrTy(); case tok::semi: Diag(Tok, getLang().CPlusPlus0x ? diag::warn_cxx98_compat_top_level_semi : diag::ext_top_level_semi) diff --git a/test/Sema/pragma-pack-2.c b/test/Sema/pragma-pack-2.c index 3e6234c57f..10968fa8bd 100644 --- a/test/Sema/pragma-pack-2.c +++ b/test/Sema/pragma-pack-2.c @@ -22,32 +22,32 @@ extern int a1[offsetof(struct s1, f1) == 2 ? 1 : -1]; // Test scope of definition #pragma pack(push, 2) -struct s2_0 { -#pragma pack(pop) +struct s2_0 { // expected-error {{expected ';'}} +#pragma pack(pop) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}} char f0; int f1; }; extern int a2_0[offsetof(struct s2_0, f1) == 2 ? 1 : -1]; struct s2_1 { - char f0; -#pragma pack(push, 2) - int f1; -#pragma pack(pop) + char f0; // expected-error {{expected ';'}} +#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}} + int f1; // expected-error {{expected ';'}} +#pragma pack(pop) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}} }; extern int a2_1[offsetof(struct s2_1, f1) == 4 ? 1 : -1]; struct s2_2 { char f0; - int f1; -#pragma pack(push, 2) + int f1; // expected-error {{expected ';'}} +#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}} }; #pragma pack(pop) extern int a2_2[offsetof(struct s2_2, f1) == 4 ? 1 : -1]; struct s2_3 { - char f0; -#pragma pack(push, 2) + char f0; // expected-error {{expected ';'}} +#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}} struct s2_3_0 { #pragma pack(pop) int f0; @@ -58,10 +58,10 @@ extern int a2_3[offsetof(struct s2_3, f1) == 2 ? 1 : -1]; struct s2_4 { char f0; struct s2_4_0 { - int f0; -#pragma pack(push, 2) - } f1; -#pragma pack(pop) + int f0; // expected-error {{expected ';'}} +#pragma pack(push, 2) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}} + } f1; // expected-error {{expected ';'}} +#pragma pack(pop) // expected-error {{type name}} expected-error {{member name}} expected-warning {{type specifier}} }; extern int a2_4[offsetof(struct s2_4, f1) == 4 ? 1 : -1]; @@ -91,3 +91,15 @@ struct s4_1 { }; extern int a4_0[offsetof(struct s4_0, f1) == 1 ? 1 : -1]; extern int a4_1[offsetof(struct s4_1, f1) == 4 ? 1 : -1]; + +void f() { + #pragma pack(push, 2) + struct s5_0 { + char f0; + struct s2_4_0 { + int f0; + } f1; + }; + #pragma pack(pop) + extern int s5_0[offsetof(struct s5_0, f1) == 2 ? 1 : -1]; +} diff --git a/test/SemaCXX/pragma-visibility.cpp b/test/SemaCXX/pragma-visibility.cpp index d63f19c693..e3ef97a744 100644 --- a/test/SemaCXX/pragma-visibility.cpp +++ b/test/SemaCXX/pragma-visibility.cpp @@ -10,3 +10,14 @@ namespace test2 __attribute__((visibility("hidden"))) { } // expected-note{{surrounding namespace with visibility attribute ends here}} #pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}} + +// +struct A { + #pragma GCC visibility push(protected) + #pragma GCC visibility pop +}; + +void f() { + #pragma GCC visibility push(protected) + #pragma GCC visibility pop +} diff --git a/test/SemaObjC/pragma-pack.m b/test/SemaObjC/pragma-pack.m new file mode 100644 index 0000000000..e0ee5609d7 --- /dev/null +++ b/test/SemaObjC/pragma-pack.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple i686-apple-darwin9 -fsyntax-only -verify %s + +// Make sure pragma pack works inside ObjC methods. +@interface X +@end +@implementation X +- (void)Y { +#pragma pack(push, 1) + struct x { + char a; + int b; + }; +#pragma pack(pop) + typedef char check_[sizeof (struct x) == 5 ? 1 : -1]; +} +@end -- 2.40.0