i'll commit-after-approval, in that unlikely event.

this is a fairly ugly hack to address this bug:

http://llvm.org/bugs/show_bug.cgi?id=3679

it has the upside of getting FreeBSD's libc and others closer to compiling.

it has the downside that it is fairly ugly and also introduces an
issue whereby we don't error on incompatible declarations with weak
attributes, an example is given in the test file.

constructive criticism appreciated.
Index: test/Sema/pragma-weak.c
===================================================================
--- test/Sema/pragma-weak.c	(revision 0)
+++ test/Sema/pragma-weak.c	(revision 0)
@@ -0,0 +1,68 @@
+// RUN: clang-cc -emit-llvm < %s | grep " weak" | count 8
+// FIXME: get bad_pass case and reduce above count by one
+
+// FIXME: following not caught because it has a weak attribute
+int __attribute__((weak)) bad_pass;
+void bad_pass(); // expected-error {{redefinition of 'bad_pass' as different kind of symbol}}
+
+// #pragma weak on undeclared variable/function works...
+#pragma weak v0
+#pragma weak v0
+int v0;
+#pragma weak v0
+#pragma weak v0
+#pragma weak v0
+
+// excerpts from the FreeBSD7 libc
+// http://fxr.watson.org/fxr/source/gen/dlfcn.c?v=FREEBSD7-LIBC
+
+// some dependencies
+static const char sorry[] = "Service unavailable";
+#define NULL 0
+
+#pragma weak _rtld_error
+void
+_rtld_error(const char *fmt, ...)
+{
+}
+
+#pragma weak dlerror
+const char *
+dlerror(void)
+{
+        return sorry;
+}
+
+#pragma weak dlclose
+int
+dlclose(void *handle)
+{
+        _rtld_error(sorry);
+        return -1;
+}
+
+#pragma weak dlopen
+void *
+dlopen(const char *name, int mode)
+{
+        _rtld_error(sorry);
+        return NULL;
+}
+
+#pragma weak dlsym
+void *
+dlsym(void * __restrict handle, const char * __restrict name)
+{
+        _rtld_error(sorry);
+        return NULL;
+}
+
+#pragma weak dlvsym
+void *
+dlvsym(void * __restrict handle, const char * __restrict name,
+    const char * __restrict version)
+{
+        _rtld_error(sorry);
+        return NULL;
+}
+
Index: include/clang/Parse/Action.h
===================================================================
--- include/clang/Parse/Action.h	(revision 76698)
+++ include/clang/Parse/Action.h	(working copy)
@@ -1884,6 +1884,7 @@
 
   /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
   virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+                                 const Token &WeakTok,
                                  SourceLocation PragmaLoc,
                                  SourceLocation WeakNameLoc) {
     return;
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp	(revision 76721)
+++ lib/Sema/SemaDecl.cpp	(working copy)
@@ -661,6 +661,12 @@
   else 
     Old = dyn_cast<FunctionDecl>(OldD);
   if (!Old) {
+    // FIXME: ActOnPragmaWeakID HACK
+    if (OldD->hasAttrs() && OldD->getAttrs()->getKind() == Attr::Weak) {
+      // OldD is a placeholder (Var)Decl, merge attrs only
+      MergeAttributes(New, OldD, Context);
+      return false;
+    }
     Diag(New->getLocation(), diag::err_redefinition_different_kind)
       << New->getDeclName();
     Diag(OldD->getLocation(), diag::note_previous_definition);
@@ -954,6 +960,11 @@
     MergedT = Context.mergeTypes(New->getType(), Old->getType());
   }
   if (MergedT.isNull()) {
+    // FIXME: ActOnPragmaWeakID HACK
+    if (OldD->hasAttrs() && OldD->getAttrs()->getKind() == Attr::Weak){
+      MergedT = New->getType();
+      return;
+    }
     Diag(New->getLocation(), diag::err_redefinition_different_type) 
       << New->getDeclName();
     Diag(Old->getLocation(), diag::note_previous_definition);
@@ -2560,6 +2571,9 @@
       if (MergeFunctionDecl(NewFD, OldDecl))
         return NewFD->setInvalidDecl();
 
+      if (dyn_cast<VarDecl>(OldDecl))
+        return; // FIXME: pragma weak hack: avoid storing previous definition
+
       if (FunctionTemplateDecl *OldTemplateDecl
             = dyn_cast<FunctionTemplateDecl>(OldDecl))
         NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
@@ -4626,6 +4640,7 @@
 }
 
 void Sema::ActOnPragmaWeakID(IdentifierInfo* Name,
+                             const Token &WeakTok,
                              SourceLocation PragmaLoc,
                              SourceLocation NameLoc) {
   Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName);
@@ -4634,9 +4649,23 @@
   if (PrevDecl) {
     PrevDecl->addAttr(::new (Context) WeakAttr());
     return;
+  } else {
+    // FIXME: hack on top of a hack
+    // create a dummy declaration with "weak" attribute, subsequent decl/def
+    // inherits attribute and discards thr rest. is not a "previous declaration"
+    DeclSpec DS;
+    const char *PrevSpec = 0;
+    // set TSW to something other than "unspecified" so that !!DS.hasTypeSpecifier()
+    DS.SetTypeSpecWidth(DeclSpec::TSW_long, NameLoc, PrevSpec);
+    // extern linkage prevents us from being ignored by later decls
+    DS.SetStorageClassSpec(DeclSpec::SCS_extern, NameLoc, PrevSpec);
+    DS.SetRangeStart(NameLoc);
+    DS.AddAttributes(new AttributeList(WeakTok.getIdentifierInfo(),
+                      WeakTok.getLocation(), 0, NameLoc, 0, 0, 0));
+    Declarator D(DS, Declarator::FileContext);
+    D.SetIdentifier(Name, NameLoc);
+    (void)HandleDeclarator(TUScope, D, MultiTemplateParamsArg(*this), false);
   }
-  Diag(PragmaLoc, diag::err_unsupported_pragma_weak);
-  return;
 }
 
 void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name,
Index: lib/Sema/Sema.h
===================================================================
--- lib/Sema/Sema.h	(revision 76698)
+++ lib/Sema/Sema.h	(working copy)
@@ -2890,6 +2890,7 @@
 
   /// ActOnPragmaWeakID - Called on well formed #pragma weak ident.
   virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName,
+                                 const Token &WeakTok,
                                  SourceLocation PragmaLoc,
                                  SourceLocation WeakNameLoc);
 
Index: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp	(revision 76698)
+++ lib/Parse/ParsePragma.cpp	(working copy)
@@ -232,6 +232,6 @@
     Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
                                  AliasNameLoc);
   } else {
-    Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
+    Actions.ActOnPragmaWeakID(WeakName, WeakTok, WeakLoc, WeakNameLoc);
   }
 }
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to