static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { // Put visibility on stack. if (!S.VisContext) S.VisContext = new VisStack; VisStack *Stack = static_cast<VisStack*>(S.VisContext); Stack->push_back(std::make_pair(type, 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(); } // FIXME: Add diag for pop without push. }
void Sema::AddPushedVisibilityAttribute(Decl *D) { if (!VisContext) return; if (D->hasAttr<VisibilityAttr>()) return; VisStack *Stack = static_cast<VisStack*>(VisContext); unsigned rawType = Stack->back().first; if (rawType == NoVisibility) return; VisibilityAttr::VisibilityType type = (VisibilityAttr::VisibilityType) rawType; SourceLocation loc = Stack->back().second; D->addAttr(::new (Context) VisibilityAttr(loc, Context, type)); }
void Sema::AddPushedVisibilityAttribute(Decl *D) { if (!VisContext) return; NamedDecl *ND = dyn_cast<NamedDecl>(D); if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue)) return; VisStack *Stack = static_cast<VisStack*>(VisContext); unsigned rawType = Stack->back().first; if (rawType == NoVisibility) return; VisibilityAttr::VisibilityType type = (VisibilityAttr::VisibilityType) rawType; SourceLocation loc = Stack->back().second; D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc)); }
void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { if (!VisContext) { Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); return; } // 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(); }