parent
ef7c0ffe40
commit
570024a8d9
|
@ -540,12 +540,15 @@ public:
|
|||
};
|
||||
private:
|
||||
VisibilityTypes VisibilityType;
|
||||
bool FromPragma;
|
||||
public:
|
||||
VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility),
|
||||
VisibilityType(v) {}
|
||||
VisibilityAttr(VisibilityTypes v, bool fp) : Attr(attr::Visibility),
|
||||
VisibilityType(v), FromPragma(fp) {}
|
||||
|
||||
VisibilityTypes getVisibility() const { return VisibilityType; }
|
||||
|
||||
bool isFromPragma() const { return FromPragma; }
|
||||
|
||||
virtual Attr *clone(ASTContext &C) const;
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
|
|
|
@ -988,7 +988,7 @@ def warn_transparent_union_attribute_zero_fields : Warning<
|
|||
"transparent_union attribute ignored">;
|
||||
def warn_attribute_type_not_supported : Warning<
|
||||
"'%0' attribute argument not supported: %1">;
|
||||
def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">;
|
||||
def warn_attribute_unknown_visibility : Warning<"unknown visibility '%0'">;
|
||||
def err_unknown_machine_mode : Error<"unknown machine mode %0">;
|
||||
def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
|
||||
def err_mode_not_primitive : Error<
|
||||
|
|
|
@ -2734,6 +2734,14 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... .
|
||||
virtual void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
|
||||
SourceLocation PragmaLoc) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
|
||||
virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
|
||||
SourceLocation PragmaLoc,
|
||||
|
|
|
@ -110,6 +110,7 @@ class Parser {
|
|||
IdentifierInfo *Ident_pixel;
|
||||
|
||||
llvm::OwningPtr<PragmaHandler> AlignHandler;
|
||||
llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler;
|
||||
llvm::OwningPtr<PragmaHandler> OptionsHandler;
|
||||
llvm::OwningPtr<PragmaHandler> PackHandler;
|
||||
llvm::OwningPtr<PragmaHandler> UnusedHandler;
|
||||
|
|
|
@ -213,7 +213,7 @@ Attr *SentinelAttr::clone(ASTContext &C) const {
|
|||
}
|
||||
|
||||
Attr *VisibilityAttr::clone(ASTContext &C) const {
|
||||
return ::new (C) VisibilityAttr(VisibilityType);
|
||||
return ::new (C) VisibilityAttr(VisibilityType, FromPragma);
|
||||
}
|
||||
|
||||
Attr *OverloadableAttr::clone(ASTContext &C) const {
|
||||
|
|
|
@ -190,8 +190,10 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
|
|||
return LangOptions::Hidden;
|
||||
}
|
||||
|
||||
// This decl should have the same visibility as its parent.
|
||||
// If this decl is contained in a class, it should have the same visibility
|
||||
// as the parent class.
|
||||
if (const DeclContext *DC = D->getDeclContext())
|
||||
if (DC->isRecord())
|
||||
return getDeclVisibilityMode(cast<Decl>(DC));
|
||||
|
||||
return getLangOptions().getVisibilityMode();
|
||||
|
|
|
@ -1292,7 +1292,8 @@ Attr *PCHReader::ReadAttributes(llvm::BitstreamCursor &DeclsCursor) {
|
|||
|
||||
case attr::Visibility:
|
||||
New = ::new (*Context) VisibilityAttr(
|
||||
(VisibilityAttr::VisibilityTypes)Record[Idx++]);
|
||||
(VisibilityAttr::VisibilityTypes)Record[Idx++],
|
||||
(bool)Record[Idx++]);
|
||||
break;
|
||||
|
||||
SIMPLE_ATTR(WarnUnusedResult);
|
||||
|
|
|
@ -2106,6 +2106,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
|
|||
case attr::Visibility:
|
||||
// FIXME: stable encoding
|
||||
Record.push_back(cast<VisibilityAttr>(Attr)->getVisibility());
|
||||
Record.push_back(cast<VisibilityAttr>(Attr)->isFromPragma());
|
||||
break;
|
||||
|
||||
case attr::WarnUnusedResult:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
PP.Lex(Tok);
|
||||
if (Tok.isNot(tok::eom)) {
|
||||
PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
|
||||
<< "visibility";
|
||||
return;
|
||||
}
|
||||
|
||||
Actions.ActOnPragmaVisibility(IsPush, VisType, VisLoc);
|
||||
}
|
||||
|
||||
// #pragma pack(...) comes in the following delicious flavors:
|
||||
// pack '(' [integer] ')'
|
||||
// pack '(' 'show' ')'
|
||||
|
|
|
@ -28,6 +28,15 @@ public:
|
|||
virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
|
||||
};
|
||||
|
||||
class PragmaGCCVisibilityHandler : public PragmaHandler {
|
||||
Action &Actions;
|
||||
public:
|
||||
explicit PragmaGCCVisibilityHandler(Action &A) : PragmaHandler("visibility"),
|
||||
Actions(A) {}
|
||||
|
||||
virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
|
||||
};
|
||||
|
||||
class PragmaOptionsHandler : public PragmaHandler {
|
||||
Action &Actions;
|
||||
public:
|
||||
|
|
|
@ -36,6 +36,9 @@ Parser::Parser(Preprocessor &pp, Action &actions)
|
|||
AlignHandler.reset(new PragmaAlignHandler(actions));
|
||||
PP.AddPragmaHandler(AlignHandler.get());
|
||||
|
||||
GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler(actions));
|
||||
PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
|
||||
|
||||
OptionsHandler.reset(new PragmaOptionsHandler(actions));
|
||||
PP.AddPragmaHandler(OptionsHandler.get());
|
||||
|
||||
|
@ -303,6 +306,8 @@ Parser::~Parser() {
|
|||
// Remove the pragma handlers we installed.
|
||||
PP.RemovePragmaHandler(AlignHandler.get());
|
||||
AlignHandler.reset();
|
||||
PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
|
||||
GCCVisibilityHandler.reset();
|
||||
PP.RemovePragmaHandler(OptionsHandler.get());
|
||||
OptionsHandler.reset();
|
||||
PP.RemovePragmaHandler(PackHandler.get());
|
||||
|
|
|
@ -126,7 +126,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
|||
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()), GlobalNewDeleteDeclared(false),
|
||||
CompleteTranslationUnit(CompleteTranslationUnit),
|
||||
NumSFINAEErrors(0), SuppressAccessChecking(false),
|
||||
|
@ -147,6 +147,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
|||
|
||||
Sema::~Sema() {
|
||||
if (PackContext) FreePackedContext();
|
||||
if (VisContext) FreeVisContext();
|
||||
delete TheTargetAttributesSema;
|
||||
while (!FunctionScopes.empty())
|
||||
PopFunctionOrBlockScope();
|
||||
|
|
|
@ -285,6 +285,9 @@ public:
|
|||
/// of 0 indicates default alignment.
|
||||
void *PackContext; // Really a "PragmaPackStack*"
|
||||
|
||||
/// VisContext - Manages the stack for #pragma GCC visibility.
|
||||
void *VisContext; // Really a "PragmaVisStack*"
|
||||
|
||||
/// \brief Stack containing information about each of the nested function,
|
||||
/// block, and method scopes that are currently active.
|
||||
llvm::SmallVector<FunctionScopeInfo *, 4> FunctionScopes;
|
||||
|
@ -4199,6 +4202,10 @@ public:
|
|||
SourceLocation LParenLoc,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
/// ActOnPragmaVisibility - Called on well formed #pragma GCC visibility... .
|
||||
virtual void ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType,
|
||||
SourceLocation PragmaLoc);
|
||||
|
||||
NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II);
|
||||
void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W);
|
||||
|
||||
|
@ -4221,6 +4228,21 @@ public:
|
|||
/// FreePackedContext - Deallocate and null out PackContext.
|
||||
void FreePackedContext();
|
||||
|
||||
/// AddPushedVisibilityAttribute - If '#pragma GCC visibility' was used,
|
||||
/// add an appropriate visibility attribute.
|
||||
void AddPushedVisibilityAttribute(Decl *RD);
|
||||
|
||||
/// PushPragmaVisibility - Push the top element of the visibility stack; used
|
||||
/// for '#pragma GCC visibility' and visibility attributes on namespaces.
|
||||
void PushPragmaVisibility(VisibilityAttr::VisibilityTypes type);
|
||||
|
||||
/// PopPragmaVisibility - Pop the top element of the visibility stack; used
|
||||
/// for '#pragma GCC visibility' and visibility attributes on namespaces.
|
||||
void PopPragmaVisibility();
|
||||
|
||||
/// FreeVisContext - Deallocate and null out VisContext.
|
||||
void FreeVisContext();
|
||||
|
||||
/// AddAlignedAttr - Adds an aligned attribute to a particular declaration.
|
||||
void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E);
|
||||
|
||||
|
|
|
@ -288,3 +288,70 @@ void Sema::ActOnPragmaUnused(const Token *Identifiers, unsigned NumIdentifiers,
|
|||
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.
|
||||
}
|
||||
|
|
|
@ -2680,6 +2680,11 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
!NewVD->isInvalidDecl())
|
||||
RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
|
||||
|
||||
// If there's a #pragma GCC visibility in scope, and this isn't a class
|
||||
// member, set the visibility of this variable.
|
||||
if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord())
|
||||
AddPushedVisibilityAttribute(NewVD);
|
||||
|
||||
return NewVD;
|
||||
}
|
||||
|
||||
|
@ -3529,6 +3534,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
NewFD->addAttr(::new (Context) OverloadableAttr());
|
||||
}
|
||||
|
||||
// If there's a #pragma GCC visibility in scope, and this isn't a class
|
||||
// member, set the visibility of this function.
|
||||
if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord())
|
||||
AddPushedVisibilityAttribute(NewFD);
|
||||
|
||||
// If this is a locally-scoped extern C function, update the
|
||||
// map of such names.
|
||||
if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
|
||||
|
@ -6367,6 +6377,11 @@ void Sema::ActOnFields(Scope* S,
|
|||
|
||||
if (Attr)
|
||||
ProcessDeclAttributeList(S, Record, Attr);
|
||||
|
||||
// If there's a #pragma GCC visibility in scope, and this isn't a subclass,
|
||||
// set the visibility of this record.
|
||||
if (Record && !Record->getDeclContext()->isRecord())
|
||||
AddPushedVisibilityAttribute(Record);
|
||||
}
|
||||
|
||||
/// \brief Determine whether the given integral value is representable within
|
||||
|
|
|
@ -847,7 +847,7 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) {
|
|||
return;
|
||||
}
|
||||
|
||||
d->addAttr(::new (S.Context) VisibilityAttr(type));
|
||||
d->addAttr(::new (S.Context) VisibilityAttr(type, false));
|
||||
}
|
||||
|
||||
static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr,
|
||||
|
|
|
@ -3179,6 +3179,9 @@ Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
|
|||
|
||||
ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
|
||||
|
||||
if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>())
|
||||
PushPragmaVisibility(attr->getVisibility());
|
||||
|
||||
if (II) {
|
||||
// C++ [namespace.def]p2:
|
||||
// The identifier in an original-namespace-definition shall not have been
|
||||
|
@ -3310,6 +3313,8 @@ void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) {
|
|||
assert(Namespc && "Invalid parameter, expected NamespaceDecl");
|
||||
Namespc->setRBracLoc(RBrace);
|
||||
PopDeclContext();
|
||||
if (Namespc->hasAttr<VisibilityAttr>())
|
||||
PopPragmaVisibility();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the special "std" namespace, which may require us to
|
||||
|
|
Loading…
Reference in New Issue