summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2012-01-26 02:02:57 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2012-01-26 02:02:57 +0000
commit273fd772ab7f5a85d0ec314da504d9bbee2844cb (patch)
tree0c8d2505f0667043a8d03ba162995c3503232908
parent5bfde1aa42a70f6f96807c7d40a7286eb5a3ded7 (diff)
downloadbcm5719-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.def5
-rw-r--r--clang/include/clang/Parse/Parser.h4
-rw-r--r--clang/lib/Parse/ParsePragma.cpp17
-rw-r--r--clang/lib/Parse/Parser.cpp3
-rw-r--r--clang/test/CodeGenCXX/pr11797.cpp8
-rw-r--r--clang/test/CodeGenCXX/pragma-visibility.cpp4
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
OpenPOWER on IntegriCloud