Implement #pragma GCC visibility.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110315 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 13a0c59..d1e5fe6 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -288,3 +288,70 @@
VD->addAttr(::new (Context) UnusedAttr());
}
}
+
+typedef std::vector<VisibilityAttr::VisibilityTypes> VisStack;
+
+void Sema::AddPushedVisibilityAttribute(Decl *D) {
+ if (!VisContext)
+ return;
+
+ if (D->hasAttr<VisibilityAttr>())
+ return;
+
+ VisStack *Stack = static_cast<VisStack*>(VisContext);
+ VisibilityAttr::VisibilityTypes type = Stack->back();
+
+ D->addAttr(::new (Context) VisibilityAttr(type, true));
+}
+
+/// FreeVisContext - Deallocate and null out VisContext.
+void Sema::FreeVisContext() {
+ delete static_cast<VisStack*>(VisContext);
+ VisContext = 0;
+}
+
+void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
+ SourceLocation PragmaLoc) {
+ if (IsPush) {
+ // Compute visibility to use.
+ VisibilityAttr::VisibilityTypes type;
+ if (VisType->isStr("default"))
+ type = VisibilityAttr::DefaultVisibility;
+ else if (VisType->isStr("hidden"))
+ type = VisibilityAttr::HiddenVisibility;
+ else if (VisType->isStr("internal"))
+ type = VisibilityAttr::HiddenVisibility; // FIXME
+ else if (VisType->isStr("protected"))
+ type = VisibilityAttr::ProtectedVisibility;
+ else {
+ Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) <<
+ VisType->getName();
+ return;
+ }
+ PushPragmaVisibility(type);
+ } else {
+ PopPragmaVisibility();
+ }
+}
+
+void Sema::PushPragmaVisibility(VisibilityAttr::VisibilityTypes type) {
+ // Put visibility on stack.
+ if (!VisContext)
+ VisContext = new VisStack;
+
+ VisStack *Stack = static_cast<VisStack*>(VisContext);
+ Stack->push_back(type);
+}
+
+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();
+ }
+ // FIXME: Add diag for pop without push.
+}