[cfe-commits] r77573 - in /cfe/trunk: 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

Ryan Flynn pizza at parseerror.com
Wed Jul 29 20:15:46 PDT 2009


Author: pizza
Date: Wed Jul 29 22:15:39 2009
New Revision: 77573

URL: http://llvm.org/viewvc/llvm-project?rev=77573&view=rev
Log:
PR3679 - handle #pragma weak

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

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=77573&r1=77572&r2=77573&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jul 29 22:15:39 2009
@@ -545,6 +545,8 @@
   "__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<

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=77573&r1=77572&r2=77573&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Jul 29 22:15:39 2009
@@ -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 @@
   // 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;
 

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=77573&r1=77572&r2=77573&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jul 29 22:15:39 2009
@@ -231,6 +231,29 @@
   /// 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 @@
                                  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,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=77573&r1=77572&r2=77573&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jul 29 22:15:39 2009
@@ -5198,13 +5198,13 @@
                              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 @@
                                 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;
 }

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=77573&r1=77572&r2=77573&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Jul 29 22:15:39 2009
@@ -1818,10 +1818,57 @@
   }
 }
 
+/// 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);

Modified: cfe/trunk/test/Parser/pragma-weak.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/pragma-weak.c?rev=77573&r1=77572&r2=77573&view=diff

==============================================================================
--- cfe/trunk/test/Parser/pragma-weak.c (original)
+++ cfe/trunk/test/Parser/pragma-weak.c Wed Jul 29 22:15:39 2009
@@ -10,7 +10,7 @@
 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





More information about the cfe-commits mailing list