From e25ff83fb7eee9eeda89b6f2371bc33a37bf1028 Mon Sep 17 00:00:00 2001 From: Ryan Flynn Date: Thu, 30 Jul 2009 03:15:39 +0000 Subject: [PATCH] PR3679 - handle #pragma weak git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77573 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 + lib/Sema/Sema.cpp | 10 +++++ lib/Sema/Sema.h | 25 ++++++++++++ lib/Sema/SemaDecl.cpp | 23 ++++++----- lib/Sema/SemaDeclAttr.cpp | 47 ++++++++++++++++++++++ test/Parser/pragma-weak.c | 2 +- 6 files changed, 97 insertions(+), 12 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 586be85cf6..ab454d0e47 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -545,6 +545,8 @@ def warn_attribute_weak_on_field : Warning< "__weak attribute cannot be specified on a field declaration">; def warn_attribute_weak_on_local : Warning< "__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< "weak declaration of '%0' must be public">; def warn_attribute_weak_import_invalid_on_definition : Warning< diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 39662511f1..f0aea43047 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "Sema.h" +#include "llvm/ADT/DenseMap.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -242,6 +243,15 @@ void Sema::ActOnEndOfTranslationUnit() { // template instantiations earlier. PerformPendingImplicitInstantiations(); + // check for #pragma weak identifiers that were never declared + for (llvm::DenseMap::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) return; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 960ad879f9..f0fdce5aa3 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -231,6 +231,29 @@ public: /// a given variable will be recorded here. llvm::DenseMap 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 WeakUndeclaredIdentifiers; + IdentifierResolver IdResolver; /// Translation Unit Scope - useful to Objective-C actions that need @@ -2921,6 +2944,8 @@ public: SourceLocation LParenLoc, SourceLocation RParenLoc); + void DeclApplyPragmaWeak(NamedDecl *D, WeakInfo &W); + /// ActOnPragmaWeakID - Called on well formed #pragma weak ident. virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName, SourceLocation PragmaLoc, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ce8fbb9783..01875bbcdf 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5198,13 +5198,13 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, SourceLocation NameLoc) { Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName); - // FIXME: This implementation is an ugly hack! if (PrevDecl) { PrevDecl->addAttr(::new (Context) WeakAttr()); - return; + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair + (Name, WeakInfo((IdentifierInfo*)0, NameLoc))); } - Diag(PragmaLoc, diag::err_unsupported_pragma_weak); - return; } void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, @@ -5212,14 +5212,15 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, SourceLocation PragmaLoc, SourceLocation NameLoc, 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) { - PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName())); - PrevDecl->addAttr(::new (Context) WeakAttr()); - return; + if (!PrevDecl->hasAttr()) + if (NamedDecl *ND = dyn_cast(PrevDecl)) + DeclApplyPragmaWeak(ND, W); + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair(AliasName, W)); } - Diag(PragmaLoc, diag::err_unsupported_pragma_weak); - return; } 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(ND)) { + NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), + FD->getLocation(), DeclarationName(II), + FD->getType()); + } else if (VarDecl *VD = dyn_cast(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(ND) || isa(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(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); diff --git a/test/Parser/pragma-weak.c b/test/Parser/pragma-weak.c index 355a95487b..dca0f8dd4c 100644 --- a/test/Parser/pragma-weak.c +++ b/test/Parser/pragma-weak.c @@ -10,7 +10,7 @@ int x; extern int 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; /* expected-warning {{extra tokens at end of '#pragma weak'}}*/ #pragma weak a b -- 2.40.0