aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Flynn <pizza@parseerror.com>2009-07-30 03:15:39 +0000
committerRyan Flynn <pizza@parseerror.com>2009-07-30 03:15:39 +0000
commite25ff83fb7eee9eeda89b6f2371bc33a37bf1028 (patch)
tree2a296454907206ac03076fb3f9d5547e11a259bc
parent218e0b701cc02b4ca04a601a3836068f96210915 (diff)
PR3679 - handle #pragma weak
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77573 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--lib/Sema/Sema.cpp10
-rw-r--r--lib/Sema/Sema.h25
-rw-r--r--lib/Sema/SemaDecl.cpp23
-rw-r--r--lib/Sema/SemaDeclAttr.cpp47
-rw-r--r--test/Parser/pragma-weak.c2
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<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)
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<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;
/// 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<IdentifierInfo*,WeakInfo>
+ (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<AliasAttr>())
+ if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl))
+ DeclApplyPragmaWeak(ND, W);
+ } else {
+ (void)WeakUndeclaredIdentifiers.insert(
+ std::pair<IdentifierInfo*,WeakInfo>(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<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);
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