зеркало из https://github.com/microsoft/clang-1.git
PR3679 - handle #pragma weak
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77573 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
218e0b701c
Коммит
e25ff83fb7
|
@ -545,6 +545,8 @@ def warn_attribute_weak_on_field : Warning<
|
||||||
"__weak attribute cannot be specified on a field declaration">;
|
"__weak attribute cannot be specified on a field declaration">;
|
||||||
def warn_attribute_weak_on_local : Warning<
|
def warn_attribute_weak_on_local : Warning<
|
||||||
"__weak attribute cannot be specified on an automatic variable">;
|
"__weak attribute cannot be specified on an automatic variable">;
|
||||||
|
def warn_weak_identifier_undeclared : Warning<
|
||||||
|
"weak identifier %0 never declared">;
|
||||||
def err_attribute_weak_static : Error<
|
def err_attribute_weak_static : Error<
|
||||||
"weak declaration of '%0' must be public">;
|
"weak declaration of '%0' must be public">;
|
||||||
def warn_attribute_weak_import_invalid_on_definition : Warning<
|
def warn_attribute_weak_import_invalid_on_definition : Warning<
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "Sema.h"
|
#include "Sema.h"
|
||||||
|
#include "llvm/ADT/DenseMap.h"
|
||||||
#include "clang/AST/ASTConsumer.h"
|
#include "clang/AST/ASTConsumer.h"
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/AST/DeclObjC.h"
|
#include "clang/AST/DeclObjC.h"
|
||||||
|
@ -242,6 +243,15 @@ void Sema::ActOnEndOfTranslationUnit() {
|
||||||
// template instantiations earlier.
|
// template instantiations earlier.
|
||||||
PerformPendingImplicitInstantiations();
|
PerformPendingImplicitInstantiations();
|
||||||
|
|
||||||
|
// check for #pragma weak identifiers that were never declared
|
||||||
|
for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
|
||||||
|
I = WeakUndeclaredIdentifiers.begin(),
|
||||||
|
E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
|
||||||
|
if (!I->second.getUsed())
|
||||||
|
Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
|
||||||
|
<< I->first;
|
||||||
|
}
|
||||||
|
|
||||||
if (!CompleteTranslationUnit)
|
if (!CompleteTranslationUnit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -231,6 +231,29 @@ public:
|
||||||
/// a given variable will be recorded here.
|
/// a given variable will be recorded here.
|
||||||
llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions;
|
llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions;
|
||||||
|
|
||||||
|
/// WeakUndeclaredIdentifiers - Identifiers contained in
|
||||||
|
/// #pragma weak before declared. rare. may alias another
|
||||||
|
/// identifier, declared or undeclared
|
||||||
|
class WeakInfo {
|
||||||
|
IdentifierInfo *alias; // alias (optional)
|
||||||
|
SourceLocation loc; // for diagnostics
|
||||||
|
bool used; // identifier later declared?
|
||||||
|
public:
|
||||||
|
WeakInfo()
|
||||||
|
: alias(0), loc(SourceLocation()), used(false) {}
|
||||||
|
WeakInfo(IdentifierInfo *Alias, SourceLocation Loc)
|
||||||
|
: alias(Alias), loc(Loc), used(false) {}
|
||||||
|
inline IdentifierInfo * getAlias() const { return alias; }
|
||||||
|
inline SourceLocation getLocation() const { return loc; }
|
||||||
|
void setUsed(bool Used=true) { used = Used; }
|
||||||
|
inline bool getUsed() { return used; }
|
||||||
|
bool operator==(WeakInfo RHS) const {
|
||||||
|
return alias == RHS.getAlias() && loc == RHS.getLocation();
|
||||||
|
}
|
||||||
|
bool operator!=(WeakInfo RHS) const { return !(*this == RHS); }
|
||||||
|
};
|
||||||
|
llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers;
|
||||||
|
|
||||||
IdentifierResolver IdResolver;
|
IdentifierResolver IdResolver;
|
||||||
|
|
||||||
/// Translation Unit Scope - useful to Objective-C actions that need
|
/// Translation Unit Scope - useful to Objective-C actions that need
|
||||||
|
@ -2921,6 +2944,8 @@ public:
|
||||||
SourceLocation LParenLoc,
|
SourceLocation LParenLoc,
|
||||||
SourceLocation RParenLoc);
|
SourceLocation RParenLoc);
|
||||||
|
|
||||||
|
void DeclApplyPragmaWeak(NamedDecl *D, WeakInfo &W);
|
||||||
|
|
||||||
/// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
|
/// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
|
||||||
virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
|
virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
|
||||||
SourceLocation PragmaLoc,
|
SourceLocation PragmaLoc,
|
||||||
|
|
|
@ -5198,13 +5198,13 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
|
||||||
SourceLocation NameLoc) {
|
SourceLocation NameLoc) {
|
||||||
Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName);
|
Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName);
|
||||||
|
|
||||||
// FIXME: This implementation is an ugly hack!
|
|
||||||
if (PrevDecl) {
|
if (PrevDecl) {
|
||||||
PrevDecl->addAttr(::new (Context) WeakAttr());
|
PrevDecl->addAttr(::new (Context) WeakAttr());
|
||||||
return;
|
} else {
|
||||||
|
(void)WeakUndeclaredIdentifiers.insert(
|
||||||
|
std::pair<IdentifierInfo*,WeakInfo>
|
||||||
|
(Name, WeakInfo((IdentifierInfo*)0, NameLoc)));
|
||||||
}
|
}
|
||||||
Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
|
void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
|
||||||
|
@ -5212,14 +5212,15 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
|
||||||
SourceLocation PragmaLoc,
|
SourceLocation PragmaLoc,
|
||||||
SourceLocation NameLoc,
|
SourceLocation NameLoc,
|
||||||
SourceLocation AliasNameLoc) {
|
SourceLocation AliasNameLoc) {
|
||||||
Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName);
|
Decl *PrevDecl = LookupName(TUScope, AliasName, LookupOrdinaryName);
|
||||||
|
WeakInfo W = WeakInfo(Name, NameLoc);
|
||||||
|
|
||||||
// FIXME: This implementation is an ugly hack!
|
|
||||||
if (PrevDecl) {
|
if (PrevDecl) {
|
||||||
PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName()));
|
if (!PrevDecl->hasAttr<AliasAttr>())
|
||||||
PrevDecl->addAttr(::new (Context) WeakAttr());
|
if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
|
||||||
return;
|
DeclApplyPragmaWeak(ND, W);
|
||||||
|
} else {
|
||||||
|
(void)WeakUndeclaredIdentifiers.insert(
|
||||||
|
std::pair<IdentifierInfo*,WeakInfo>(AliasName, W));
|
||||||
}
|
}
|
||||||
Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in
|
||||||
/// it, apply them to D. This is a bit tricky because PD can have attributes
|
/// 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.
|
/// specified in many different places, and we need to find and apply them all.
|
||||||
void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) {
|
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.
|
// Apply decl attributes from the DeclSpec if present.
|
||||||
if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
|
if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes())
|
||||||
ProcessDeclAttributeList(S, D, Attrs);
|
ProcessDeclAttributeList(S, D, Attrs);
|
||||||
|
|
|
@ -10,7 +10,7 @@ int x;
|
||||||
extern int z;
|
extern int z;
|
||||||
/* expected-warning {{expected identifier in '#pragma weak'}}*/ #pragma weak z = =
|
/* expected-warning {{expected identifier in '#pragma weak'}}*/ #pragma weak z = =
|
||||||
/* expected-warning {{expected identifier in '#pragma weak'}}*/ #pragma weak z =
|
/* expected-warning {{expected identifier in '#pragma weak'}}*/ #pragma weak z =
|
||||||
#pragma weak z = y
|
/* expected-warning {{weak identifier 'y' never declared}} */ #pragma weak z = y
|
||||||
|
|
||||||
extern int a;
|
extern int a;
|
||||||
/* expected-warning {{extra tokens at end of '#pragma weak'}}*/ #pragma weak a b
|
/* expected-warning {{extra tokens at end of '#pragma weak'}}*/ #pragma weak a b
|
||||||
|
|
Загрузка…
Ссылка в новой задаче