diff options
author | Ryan Flynn <pizza@parseerror.com> | 2009-07-30 03:15:39 +0000 |
---|---|---|
committer | Ryan Flynn <pizza@parseerror.com> | 2009-07-30 03:15:39 +0000 |
commit | e25ff83fb7eee9eeda89b6f2371bc33a37bf1028 (patch) | |
tree | 2a296454907206ac03076fb3f9d5547e11a259bc /lib/Sema/SemaDeclAttr.cpp | |
parent | 218e0b701cc02b4ca04a601a3836068f96210915 (diff) |
PR3679 - handle #pragma weak
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77573 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 69f6056883..a8efc2497a 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1818,10 +1818,57 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *Attr } } +/// DeclClonePragmaWeak - clone existing decl (maybe definition), +/// #pragma weak needs a non-definition decl and source may not have one +static NamedDecl * DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) +{ + NamedDecl *NewD = 0; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), + FD->getLocation(), DeclarationName(II), + FD->getType()); + } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { + NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), + VD->getLocation(), II, + VD->getType(), VD->getStorageClass()); + } + return NewD; +} + +/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak +/// applied to it, possibly with an alias. +void Sema::DeclApplyPragmaWeak(NamedDecl *ND, WeakInfo &W) { + assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND)); + if (!W.getUsed()) { // only do this once + W.setUsed(true); + if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) + IdentifierInfo *NDId = ND->getIdentifier(); + NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias()); + NewD->addAttr(::new (Context) AliasAttr(NDId->getName())); + NewD->addAttr(::new (Context) WeakAttr()); + ND->getDeclContext()->addDecl(NewD); + } else { // just add weak to existing + ND->addAttr(::new (Context) WeakAttr()); + } + } +} + /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in /// it, apply them to D. This is a bit tricky because PD can have attributes /// specified in many different places, and we need to find and apply them all. void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { + // Handle #pragma weak + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + if (ND->hasLinkage()) { + WeakInfo W = WeakUndeclaredIdentifiers.lookup(ND->getIdentifier()); + if (W != WeakInfo()) { + // Declaration referenced by #pragma weak before it was declared + DeclApplyPragmaWeak(ND, W); + WeakUndeclaredIdentifiers[ND->getIdentifier()] = W; + } + } + } + // Apply decl attributes from the DeclSpec if present. if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) ProcessDeclAttributeList(S, D, Attrs); |