diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2012-01-26 02:02:57 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2012-01-26 02:02:57 +0000 |
commit | 273fd772ab7f5a85d0ec314da504d9bbee2844cb (patch) | |
tree | 0c8d2505f0667043a8d03ba162995c3503232908 | |
parent | 5bfde1aa42a70f6f96807c7d40a7286eb5a3ded7 (diff) | |
download | bcm5719-llvm-273fd772ab7f5a85d0ec314da504d9bbee2844cb.tar.gz bcm5719-llvm-273fd772ab7f5a85d0ec314da504d9bbee2844cb.zip |
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.
llvm-svn: 149014
-rw-r--r-- | clang/include/clang/Basic/TokenKinds.def | 5 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 4 | ||||
-rw-r--r-- | clang/lib/Parse/ParsePragma.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 3 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/pr11797.cpp | 8 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/pragma-visibility.cpp | 4 |
6 files changed, 36 insertions, 5 deletions
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index cac07337305..5c9708bc712 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/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/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 07f39603f00..ca71047fe44 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/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/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index 2fe2f3bdf3c..f47b32f513b 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/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<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: diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index 45b4a745838..7f7fdf7c448 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/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/clang/test/CodeGenCXX/pr11797.cpp b/clang/test/CodeGenCXX/pr11797.cpp new file mode 100644 index 00000000000..05221acc84f --- /dev/null +++ b/clang/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/clang/test/CodeGenCXX/pragma-visibility.cpp b/clang/test/CodeGenCXX/pragma-visibility.cpp index 2dc8bcc74fa..97f8cc8bb85 100644 --- a/clang/test/CodeGenCXX/pragma-visibility.cpp +++ b/clang/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 |