]> granicus.if.org Git - clang/commitdiff
Handle "#pragma GCC visibility" in a few more places. Switch over "#pragma pack...
authorEli Friedman <eli.friedman@gmail.com>
Thu, 23 Feb 2012 23:47:16 +0000 (23:47 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Thu, 23 Feb 2012 23:47:16 +0000 (23:47 +0000)
(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
include/clang/Parse/Parser.h
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParsePragma.cpp
lib/Parse/ParseStmt.cpp
lib/Parse/Parser.cpp
test/Sema/pragma-pack-2.c
test/SemaCXX/pragma-visibility.cpp
test/SemaObjC/pragma-pack.m [new file with mode: 0644]

index 014e111033fca0afe9f001d853df90f640a0dc4b..300db4d8862fc0bc2e96ba53de2772d8754cdb2c 100644 (file)
@@ -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
index 079a93fb5b8dc0ed2f693c9860ebed0fc5df7cd1..64736118e17b2760c8c2b40fedd200b1e2bb9eb0 100644 (file)
@@ -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.
index cc8c0c45d255849dc7da5f2914edba74f816197a..c2bf54db2cdfec31c9b2a194032c81621aa9279d 100644 (file)
@@ -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.
index 433c76b83bcf391c271e17de2703609975c0db37..96a4f3af76ca69908d62b51b3b71183dca759f2a 100644 (file)
@@ -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<PragmaPackInfo *>(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<void*>(Info));
+  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
+                      /*OwnsTokens=*/true);
 }
 
 // #pragma ms_struct on
index 3537768eed15133d639aec1c8914608e7260c3fa..0ce73cbeb2b9bd9f323ccb01747e7d99827ad330 100644 (file)
@@ -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.
index 4c5df4d2fff612a6f5e2b79a4a7c8dfbee12b567..6927c50b8f7f5bc5252fd4d2c3771f1c14315b0f 100644 (file)
@@ -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)
index 3e6234c57f0eea46e0af19e5e78b5aef3dbcec8b..10968fa8bd2329eaaaa9ecb9d606029e256ea24b 100644 (file)
@@ -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];
+}
index d63f19c693726485bde71a1d6e0effb3e647f11c..e3ef97a744472f356022a11b61ade9ae25ec411f 100644 (file)
@@ -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}}
+
+// <rdar://problem/10871094>
+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 (file)
index 0000000..e0ee560
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple i686-apple-darwin9 -fsyntax-only -verify %s
+
+// Make sure pragma pack works inside ObjC methods.  <rdar://problem/10893316>
+@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