[cfe-commits] [PATCH] Implement '#pragma GCC visibility' (WIP)

Eli Friedman eli.friedman at gmail.com
Sun Jul 18 09:36:15 PDT 2010


On Sun, Jul 18, 2010 at 5:08 AM, Douglas Gregor <dgregor at apple.com> wrote:
>
> On Jul 17, 2010, at 9:09 PM, Eli Friedman wrote:
>
>> Attached.  Review comments welcome.  This doesn't interact quite
>> correctly with classes and namespaces; any guidance on how to
>> implement the correct rules there would be appreciated.
>
> Thanks for working on this! A few comments:
>
> Index: lib/Sema/SemaDeclAttr.cpp
> ===================================================================
> --- lib/Sema/SemaDeclAttr.cpp   (revision 108632)
> +++ lib/Sema/SemaDeclAttr.cpp   (working copy)
> @@ -678,7 +678,7 @@
>   else if (TypeStr == "protected")
>     type = VisibilityAttr::ProtectedVisibility;
>   else {
> -    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
> +    S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << Str;
>     return;
>   }
>
> @@ -2172,6 +2172,9 @@
>   // Finally, apply any attributes on the decl itself.
>   if (const AttributeList *Attrs = PD.getAttributes())
>     ProcessDeclAttributeList(S, D, Attrs);
> +
> +  // Tack on a visibility attribute from '#pragma GCC visibility', if necessary.
> +  AddPushedVisibilityAttribute(D);
>  }
>
> Since this isn't supposed to apply to class members, function-local variables, instance members, etc.,, the AddPushedVisibilityAttribute call should only occur when the declaration has external linkage and !D->getDeclContext()->isRecord().

Ah, I guess that'll cover the issue's I've spotted with class members.

> It would be interesting to put a "#pragma GCC visibility push(hidden)" at the top of some non-trivial source file and then look at which declarations get tagged with the visibility attribute;.
>
> Index: lib/Sema/SemaAttr.cpp
> ===================================================================
> --- lib/Sema/SemaAttr.cpp       (revision 108632)
> +++ lib/Sema/SemaAttr.cpp       (working copy)
> @@ -289,3 +289,62 @@
>     VD->addAttr(::new (Context) UnusedAttr());
>   }
>  }
> +
> +typedef std::vector<VisibilityAttr::VisibilityTypes> VisStack;
>
> llvm::SmallVector?

Sure.

> Index: lib/Sema/Sema.cpp
> ===================================================================
> --- lib/Sema/Sema.cpp   (revision 108632)
> +++ lib/Sema/Sema.cpp   (working copy)
> @@ -123,7 +123,7 @@
>     LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
>     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
>     ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
> -    PackContext(0), TopFunctionScope(0), ParsingDeclDepth(0),
> +    PackContext(0), VisContext(0), TopFunctionScope(0), ParsingDeclDepth(0),
>     IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0),
>     GlobalNewDeleteDeclared(false),
>     CompleteTranslationUnit(CompleteTranslationUnit),
> @@ -145,6 +145,7 @@
>
>  Sema::~Sema() {
>   if (PackContext) FreePackedContext();
> +  if (VisContext) FreeVisContext();
>   delete TheTargetAttributesSema;
>   while (!FunctionScopes.empty())
>     PopFunctionOrBlockScope();
>
> Should we warn about  an unpopped visibility push(blah) in Sema::ActOnEndOfTranslationUnit()?

I don't think so... gcc doesn't warn, and Firefox uses a pattern that
would warn if we checked this.

> Index: lib/Parse/ParsePragma.cpp
> ===================================================================
> --- lib/Parse/ParsePragma.cpp   (revision 108632)
> +++ lib/Parse/ParsePragma.cpp   (working copy)
> @@ -18,6 +18,59 @@
>  #include "clang/Parse/Parser.h"
>  using namespace clang;
>
> +
> +// #pragma GCC visibility comes in two variants:
> +//   'push' '(' [visibility] ')'
> +//   'pop'
> +void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, Token &VisTok) {
> +  SourceLocation VisLoc = VisTok.getLocation();
> +
> +  Token Tok;
> +  PP.Lex(Tok);
> +
> +  const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
> +
> +  bool IsPush;
> +  const IdentifierInfo *VisType;
> +  if (PushPop && PushPop->isStr("pop")) {
> +    IsPush = false;
> +    VisType = 0;
> +  } else if (PushPop && PushPop->isStr("push")) {
> +    IsPush = true;
> +    PP.Lex(Tok);
> +    if (Tok.isNot(tok::l_paren)) {
> +      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
> +        << "visibility";
> +      return;
> +    }
> +    PP.Lex(Tok);
> +    VisType = Tok.getIdentifierInfo();
> +    if (!VisType) {
> +      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
> +        << "visibility";
> +      return;
> +    }
> +    PP.Lex(Tok);
> +    if (Tok.isNot(tok::r_paren)) {
> +      PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
> +        << "visibility";
> +      return;
> +    }
> +  } else {
> +    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
> +      << "visibility";
> +    return;
> +  }
>
> We should produce a more-helpful diagnostic in this case, e.g., "expected visibility 'push' or 'pop' ".

OK.

-Eli




More information about the cfe-commits mailing list