]> granicus.if.org Git - clang/commitdiff
Fix our handling of #pragma GCC visibility.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 26 Jan 2012 02:02:57 +0000 (02:02 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 26 Jan 2012 02:02:57 +0000 (02:02 +0000)
Now the lexer just produces a token and the parser is the one responsible for
activating it.
This fixes problem like the one pr11797 where the lexer and the parser were not
in sync. This also let us be more strict on where in the file we accept
these pragmas.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149014 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/TokenKinds.def
include/clang/Parse/Parser.h
lib/Parse/ParsePragma.cpp
lib/Parse/Parser.cpp
test/CodeGenCXX/pr11797.cpp [new file with mode: 0644]
test/CodeGenCXX/pragma-visibility.cpp

index cac07337305d84fb008eadb9a7b7d7a89519242d..5c9708bc7121c32f500b1293e0fc63013d2aba89 100644 (file)
@@ -568,6 +568,11 @@ ANNOTATION(decltype)     // annotation for a decltype expression,
 // one 'pragma_unused' annotation token followed by the argument token.
 ANNOTATION(pragma_unused)
 
+// Annotation for #pragma GCC visibility...
+// The lexer produces these so that they only take effect when the parser
+// handles them.
+ANNOTATION(pragma_vis)
+
 #undef ANNOTATION
 #undef TESTING_KEYWORD
 #undef OBJC2_AT_KEYWORD
index 07f39603f00648d7995e8b803c17370f8ff62026..ca71047fe44f38141e1c089126cc985180d4534f 100644 (file)
@@ -410,6 +410,10 @@ private:
   /// \brief Handle the annotation token produced for #pragma unused(...)
   void HandlePragmaUnused();
 
+  /// \brief Handle the annotation token produced for
+  /// #pragma GCC visibility...
+  void HandlePragmaVisibility();
+
   /// 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 2fe2f3bdf3caa3a1dfcec10ed56906a453fc3baa..f47b32f513b35f844373caa8de83d34aaa2a51c5 100644 (file)
@@ -29,6 +29,14 @@ void Parser::HandlePragmaUnused() {
   ConsumeToken(); // The argument token.
 }
 
+void Parser::HandlePragmaVisibility() {
+  assert(Tok.is(tok::annot_pragma_vis));
+  const IdentifierInfo *VisType =
+    static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
+  SourceLocation VisLoc = ConsumeToken();
+  Actions.ActOnPragmaVisibility(VisType, VisLoc);
+}
+
 // #pragma GCC visibility comes in two variants:
 //   'push' '(' [visibility] ')'
 //   'pop'
@@ -77,7 +85,14 @@ void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
     return;
   }
 
-  Actions.ActOnPragmaVisibility(VisType, VisLoc);
+  Token *Toks = new Token[1];
+  Toks[0].startToken();
+  Toks[0].setKind(tok::annot_pragma_vis);
+  Toks[0].setLocation(VisLoc);
+  Toks[0].setAnnotationValue(
+                          const_cast<void*>(static_cast<const void*>(VisType)));
+  PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
+                      /*OwnsTokens=*/true);
 }
 
 // #pragma pack(...) comes in the following delicious flavors:
index 45b4a745838568ee07c7863ea16cb36cf26a0a57..7f7fdf7c448b503d3d419eadef495f250db72a03 100644 (file)
@@ -543,6 +543,9 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs,
 
   Decl *SingleDecl = 0;
   switch (Tok.getKind()) {
+  case tok::annot_pragma_vis:
+    HandlePragmaVisibility();
+    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/CodeGenCXX/pr11797.cpp b/test/CodeGenCXX/pr11797.cpp
new file mode 100644 (file)
index 0000000..05221ac
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 %s -fvisibility hidden -emit-llvm -o - | FileCheck %s
+
+namespace std __attribute__ ((__visibility__ ("default"))) {}
+#pragma GCC visibility push(default)
+void foo() {
+}
+#pragma GCC visibility pop
+// CHECK: define void @_Z3foov()
index 2dc8bcc74fac42884853f047fe14f32eb51cf80f..97f8cc8bb85b5a7db3a5152ab7c97ebd763c2930 100644 (file)
@@ -55,8 +55,6 @@ namespace n __attribute((visibility("default"))) {
 #pragma GCC visibility pop
 
 namespace n __attribute((visibility("default")))  {
-  extern int foofoo; // FIXME: Shouldn't be necessary, but otherwise the pragma
-                     //        gets to Sema before the namespace!
 #pragma GCC visibility push(hidden)
   void g() {}
   // CHECK: define hidden void @_ZN1n1gEv
@@ -66,8 +64,6 @@ namespace n __attribute((visibility("default")))  {
 // We used to test this, but it's insane, so unless it happens in
 // headers, we should not support it.
 namespace n __attribute((visibility("hidden"))) {
-  extern int foofoo; // FIXME: Shouldn't be necessary, but otherwise the pragma
-                     //        gets to Sema before the namespace!
   #pragma GCC visibility pop
   void h() {}
   // CHECK disabled: define void @_ZN1n1hEv