diff options
Diffstat (limited to 'gcc/c-pragma.c')
| -rw-r--r-- | gcc/c-pragma.c | 83 | 
1 files changed, 83 insertions, 0 deletions
| diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c index 563e2d7abdc..0bf2f1231bc 100644 --- a/gcc/c-pragma.c +++ b/gcc/c-pragma.c @@ -566,6 +566,86 @@ maybe_apply_renaming_pragma (tree decl, tree asmname)    return 0;  } + +#ifdef HANDLE_PRAGMA_VISIBILITY +static void handle_pragma_visibility (cpp_reader *); + +/* Sets the default visibility for symbols to something other than that +   specified on the command line.  */ +static void +handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED) +{ /* Form is #pragma GCC visibility push(hidden)|pop */ +  static int visstack [16], visidx; +  tree x; +  enum cpp_ttype token; +  enum { bad, push, pop } action = bad; +  +  token = c_lex (&x); +  if (token == CPP_NAME) +    { +      const char *op = IDENTIFIER_POINTER (x); +      if (!strcmp (op, "push")) +        action = push; +      else if (!strcmp (op, "pop")) +        action = pop; +    } +  if (bad == action) +    GCC_BAD ("#pragma GCC visibility must be followed by push or pop"); +  else +    { +      if (pop == action) +        { +          if (!visidx) +            { +              GCC_BAD ("No matching push for '#pragma GCC visibility pop'"); +            } +          else +            { +              default_visibility = visstack[--visidx]; +              visibility_options.inpragma = (visidx>0); +            } +        } +      else +        { +          if (c_lex (&x) != CPP_OPEN_PAREN) +            GCC_BAD ("missing '(' after '#pragma GCC visibility push' - ignored"); +          token = c_lex (&x); +          if (token != CPP_NAME) +            { +              GCC_BAD ("malformed #pragma GCC visibility push"); +            } +          else if (visidx >= 16) +            { +              GCC_BAD ("No more than sixteen #pragma GCC visibility pushes allowed at once"); +            } +          else +            { +              const char *str = IDENTIFIER_POINTER (x); +              visstack[visidx++] = default_visibility; +              if (!strcmp (str, "default")) +                default_visibility = VISIBILITY_DEFAULT; +              else if (!strcmp (str, "internal")) +                default_visibility = VISIBILITY_INTERNAL; +              else if (!strcmp (str, "hidden")) +                default_visibility = VISIBILITY_HIDDEN;   +              else if (!strcmp (str, "protected")) +                default_visibility = VISIBILITY_PROTECTED; +              else +                { +                  GCC_BAD ("#pragma GCC visibility push() must specify default, internal, hidden or protected"); +                } +              visibility_options.inpragma = 1; +            } +          if (c_lex (&x) != CPP_CLOSE_PAREN) +            GCC_BAD ("missing '(' after '#pragma GCC visibility push' - ignored"); +        } +    } +  if (c_lex (&x) != CPP_EOF) +    warning ("junk at end of '#pragma GCC visibility'"); +} + +#endif +  /* Front-end wrapper for pragma registration to avoid dragging     cpplib.h in almost everywhere.  */  void @@ -585,6 +665,9 @@ init_pragma (void)  #ifdef HANDLE_PRAGMA_WEAK    c_register_pragma (0, "weak", handle_pragma_weak);  #endif +#ifdef HANDLE_PRAGMA_VISIBILITY +  c_register_pragma ("GCC", "visibility", handle_pragma_visibility); +#endif    c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname);    c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix); | 

