[cfe-commits] r149559 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaAttr.cpp lib/Sema/SemaDeclCXX.cpp test/CodeGenCXX/pragma-visibility.cpp test/SemaCXX/pragma-visibility.cpp

Rafael Espindola rafael.espindola at gmail.com
Wed Feb 1 15:24:59 PST 2012


Author: rafael
Date: Wed Feb  1 17:24:59 2012
New Revision: 149559

URL: http://llvm.org/viewvc/llvm-project?rev=149559&view=rev
Log:
Reject mismatched "#pragma GCC visibility push" and "#pragma GCC visibility pop".

Added:
    cfe/trunk/test/SemaCXX/pragma-visibility.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaAttr.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CodeGenCXX/pragma-visibility.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=149559&r1=149558&r2=149559&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Feb  1 17:24:59 2012
@@ -372,6 +372,14 @@
   "only variables can be arguments to '#pragma unused'">;
 def err_unsupported_pragma_weak : Error<
   "using '#pragma weak' to refer to an undeclared identifier is not yet supported">;
+def err_pragma_push_visibility_mismatch : Error<
+  "#pragma visibility push with no matching #pragma visibility pop">;
+def note_surrounding_namespace_ends_here : Note<
+  "surrounding namespace with visibility attribute ends here">;
+def err_pragma_pop_visibility_mismatch : Error<
+  "#pragma visibility pop with no matching #pragma visibility push">;
+def note_surrounding_namespace_starts_here : Note<
+  "surrounding namespace with visibility attribute starts here">;
 
 /// Objective-C parser diagnostics
 def err_duplicate_class_def : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=149559&r1=149558&r2=149559&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb  1 17:24:59 2012
@@ -5625,7 +5625,8 @@
 
   /// PushNamespaceVisibilityAttr - Note that we've entered a
   /// namespace with a visibility attribute.
-  void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr);
+  void PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
+                                   SourceLocation Loc);
 
   /// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used,
   /// add an appropriate visibility attribute.
@@ -5633,7 +5634,7 @@
 
   /// PopPragmaVisibility - Pop the top element of the visibility stack; used
   /// for '#pragma GCC visibility' and visibility attributes on namespaces.
-  void PopPragmaVisibility();
+  void PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc);
 
   /// FreeVisContext - Deallocate and null out VisContext.
   void FreeVisContext();

Modified: cfe/trunk/lib/Sema/SemaAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaAttr.cpp?rev=149559&r1=149558&r2=149559&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaAttr.cpp Wed Feb  1 17:24:59 2012
@@ -365,7 +365,7 @@
     }
     PushPragmaVisibility(*this, type, PragmaLoc);
   } else {
-    PopPragmaVisibility();
+    PopPragmaVisibility(false, PragmaLoc);
   }
 }
 
@@ -383,23 +383,44 @@
   }
 }
 
-void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) {
+void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr,
+                                       SourceLocation Loc) {
   // Visibility calculations will consider the namespace's visibility.
   // Here we just want to note that we're in a visibility context
   // which overrides any enclosing #pragma context, but doesn't itself
   // contribute visibility.
-  PushPragmaVisibility(*this, NoVisibility, SourceLocation());
+  PushPragmaVisibility(*this, NoVisibility, Loc);
 }
 
-void Sema::PopPragmaVisibility() {
-  // Pop visibility from stack, if there is one on the stack.
-  if (VisContext) {
-    VisStack *Stack = static_cast<VisStack*>(VisContext);
-
-    Stack->pop_back();
-    // To simplify the implementation, never keep around an empty stack.
-    if (Stack->empty())
-      FreeVisContext();
+void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
+  if (!VisContext) {
+    Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
+    return;
   }
-  // FIXME: Add diag for pop without push.
+
+  // Pop visibility from stack
+  VisStack *Stack = static_cast<VisStack*>(VisContext);
+
+  const std::pair<unsigned, SourceLocation> *Back = &Stack->back();
+  bool StartsWithPragma = Back->first != NoVisibility;
+  if (StartsWithPragma && IsNamespaceEnd) {
+    Diag(Back->second, diag::err_pragma_push_visibility_mismatch);
+    Diag(EndLoc, diag::note_surrounding_namespace_ends_here);
+
+    // For better error recovery, eat all pushes inside the namespace.
+    do {
+      Stack->pop_back();
+      Back = &Stack->back();
+      StartsWithPragma = Back->first != NoVisibility;
+    } while (StartsWithPragma);
+  } else if (!StartsWithPragma && !IsNamespaceEnd) {
+    Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch);
+    Diag(Back->second, diag::note_surrounding_namespace_starts_here);
+    return;
+  }
+
+  Stack->pop_back();
+  // To simplify the implementation, never keep around an empty stack.
+  if (Stack->empty())
+    FreeVisContext();
 }

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=149559&r1=149558&r2=149559&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb  1 17:24:59 2012
@@ -5683,7 +5683,7 @@
 
   // FIXME: Should we be merging attributes?
   if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
-    PushNamespaceVisibilityAttr(Attr);
+    PushNamespaceVisibilityAttr(Attr, Loc);
 
   if (IsStd)
     StdNamespace = Namespc;
@@ -5758,7 +5758,7 @@
   Namespc->setRBraceLoc(RBrace);
   PopDeclContext();
   if (Namespc->hasAttr<VisibilityAttr>())
-    PopPragmaVisibility();
+    PopPragmaVisibility(true, RBrace);
 }
 
 CXXRecordDecl *Sema::getStdBadAlloc() const {

Modified: cfe/trunk/test/CodeGenCXX/pragma-visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pragma-visibility.cpp?rev=149559&r1=149558&r2=149559&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/pragma-visibility.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/pragma-visibility.cpp Wed Feb  1 17:24:59 2012
@@ -60,11 +60,3 @@
   // CHECK: define hidden void @_ZN1n1gEv
 #pragma GCC visibility pop
 }
-
-// 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"))) {
-  #pragma GCC visibility pop
-  void h() {}
-  // CHECK disabled: define void @_ZN1n1hEv
-}

Added: cfe/trunk/test/SemaCXX/pragma-visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/pragma-visibility.cpp?rev=149559&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/pragma-visibility.cpp (added)
+++ cfe/trunk/test/SemaCXX/pragma-visibility.cpp Wed Feb  1 17:24:59 2012
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace test1 __attribute__((visibility("hidden"))) { // expected-note{{surrounding namespace with visibility attribute starts here}}
+#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}}
+}
+
+// GCC 4.6 accepts this, but the "hidden" leaks past the namespace end.
+namespace test2 __attribute__((visibility("hidden"))) {
+#pragma GCC visibility push(protected) // expected-error{{#pragma visibility push with no matching #pragma visibility pop}}
+} // expected-note{{surrounding namespace with visibility attribute ends here}}
+
+#pragma GCC visibility pop // expected-error{{#pragma visibility pop with no matching #pragma visibility push}}





More information about the cfe-commits mailing list