]> granicus.if.org Git - clang/commitdiff
PR3679 - handle #pragma weak
authorRyan Flynn <pizza@parseerror.com>
Thu, 30 Jul 2009 03:15:39 +0000 (03:15 +0000)
committerRyan Flynn <pizza@parseerror.com>
Thu, 30 Jul 2009 03:15:39 +0000 (03:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77573 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/Sema.cpp
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/Parser/pragma-weak.c

index 586be85cf61e1a304eb36a3d165b1a6595306c95..ab454d0e471315db1fce537d4344ec28c4913f1f 100644 (file)
@@ -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<
index 39662511f1ace6cedbbd659ad7f93173585628e9..f0aea4304773a49bae03ee4b9fc8e65a00b1985d 100644 (file)
@@ -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;
 
index 960ad879f9ab166942ea267cb6348718c4ef6eb3..f0fdce5aa3ecc3bb40b203ce4011c7a4aacacf42 100644 (file)
@@ -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,
index ce8fbb978374d0a1d269111a7d70868275597984..01875bbcdf2bade8ad1894c20b0f8093de282fcd 100644 (file)
@@ -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;
 }
index 69f60568837b2667cff192d5169b5a85e91312dc..a8efc2497ad5fd57bd14f1bfedda8e4d98745484 100644 (file)
@@ -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);
index 355a95487b97f706986dd4cec620b97898e1ae9b..dca0f8dd4c15a4cc73a20c4be0604141c127e89c 100644 (file)
@@ -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