From: Rafael Espindola Date: Thu, 26 Jan 2012 02:02:57 +0000 (+0000) Subject: Fix our handling of #pragma GCC visibility. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=426fc94ed3bce15b55c43692537e3833388f0352;p=clang Fix our handling of #pragma GCC visibility. 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 --- diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index cac0733730..5c9708bc71 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -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 diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 07f39603f0..ca71047fe4 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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. diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 2fe2f3bdf3..f47b32f513 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -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(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(static_cast(VisType))); + PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true, + /*OwnsTokens=*/true); } // #pragma pack(...) comes in the following delicious flavors: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 45b4a74583..7f7fdf7c44 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -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 index 0000000000..05221acc84 --- /dev/null +++ b/test/CodeGenCXX/pr11797.cpp @@ -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() diff --git a/test/CodeGenCXX/pragma-visibility.cpp b/test/CodeGenCXX/pragma-visibility.cpp index 2dc8bcc74f..97f8cc8bb8 100644 --- a/test/CodeGenCXX/pragma-visibility.cpp +++ b/test/CodeGenCXX/pragma-visibility.cpp @@ -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