[cfe-commits] r96992 - in /cfe/trunk: include/clang/AST/Attr.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Parse/AttributeList.h lib/AST/AttrImpl.cpp lib/CodeGen/CodeGenModule.cpp lib/Frontend/PCHReaderDecl.cpp lib/Frontend/PCHWriter.cpp lib/Parse/AttributeList.cpp lib/Sema/SemaDeclAttr.cpp test/CodeGen/attributes.c test/SemaCXX/attr-weakref.cpp

Rafael Espindola rafael.espindola at gmail.com
Tue Feb 23 14:00:30 PST 2010


Author: rafael
Date: Tue Feb 23 16:00:30 2010
New Revision: 96992

URL: http://llvm.org/viewvc/llvm-project?rev=96992&view=rev
Log:
Add support for the weakref attribute. We still produce "alias weak" as llvm-gcc does, but are more strict on what uses of weakref we accept.


Added:
    cfe/trunk/test/SemaCXX/attr-weakref.cpp
Modified:
    cfe/trunk/include/clang/AST/Attr.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/AttributeList.h
    cfe/trunk/lib/AST/AttrImpl.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Parse/AttributeList.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/test/CodeGen/attributes.c

Modified: cfe/trunk/include/clang/AST/Attr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Attr.h?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Attr.h (original)
+++ cfe/trunk/include/clang/AST/Attr.h Tue Feb 23 16:00:30 2010
@@ -94,6 +94,7 @@
     WarnUnusedResult,
     Weak,
     WeakImport,
+    WeakRef,
 
     FIRST_TARGET_ATTRIBUTE,
     DLLExport,
@@ -357,6 +358,7 @@
 DEF_SIMPLE_ATTR(Used);
 DEF_SIMPLE_ATTR(Weak);
 DEF_SIMPLE_ATTR(WeakImport);
+DEF_SIMPLE_ATTR(WeakRef);
 DEF_SIMPLE_ATTR(NoThrow);
 DEF_SIMPLE_ATTR(Const);
 DEF_SIMPLE_ATTR(Pure);

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 23 16:00:30 2010
@@ -747,6 +747,12 @@
   "weak declaration of '%0' must be public">;
 def warn_attribute_weak_import_invalid_on_definition : Warning<
   "'weak_import' attribute cannot be specified on a definition">;
+def err_attribute_weakref_not_static : Error<
+  "weakref declaration of '%0' must be static">;
+def err_attribute_weakref_not_global_context : Error<
+  "weakref declaration of '%0' must be in a global context">;
+def err_attribute_weakref_without_alias : Error<
+  "weakref declaration of '%0' must also have an alias attribute">;
 def warn_attribute_wrong_decl_type : Warning<
   "%0 attribute only applies to %select{function|union|"
   "variable and function|function or method|parameter|"

Modified: cfe/trunk/include/clang/Parse/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/AttributeList.h?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/AttributeList.h (original)
+++ cfe/trunk/include/clang/Parse/AttributeList.h Tue Feb 23 16:00:30 2010
@@ -109,6 +109,7 @@
     AT_visibility,
     AT_warn_unused_result,
     AT_weak,
+    AT_weakref,
     AT_weak_import,
     AT_reqd_wg_size,
     IgnoredAttribute,

Modified: cfe/trunk/lib/AST/AttrImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/AttrImpl.cpp?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/lib/AST/AttrImpl.cpp (original)
+++ cfe/trunk/lib/AST/AttrImpl.cpp Tue Feb 23 16:00:30 2010
@@ -107,6 +107,7 @@
 DEF_SIMPLE_ATTR_CLONE(WarnUnusedResult)
 DEF_SIMPLE_ATTR_CLONE(Weak)
 DEF_SIMPLE_ATTR_CLONE(WeakImport)
+DEF_SIMPLE_ATTR_CLONE(WeakRef)
 DEF_SIMPLE_ATTR_CLONE(X86ForceAlignArgPointer)
 
 Attr* PragmaPackAttr::clone(ASTContext &C) const {
@@ -196,5 +197,3 @@
 Attr *MSP430InterruptAttr::clone(ASTContext &C) const {
   return ::new (C) MSP430InterruptAttr(Number);
 }
-
-

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Feb 23 16:00:30 2010
@@ -1327,6 +1327,7 @@
       GA->setLinkage(llvm::Function::DLLExportLinkage);
     }
   } else if (D->hasAttr<WeakAttr>() ||
+             D->hasAttr<WeakRefAttr>() ||
              D->hasAttr<WeakImportAttr>()) {
     GA->setLinkage(llvm::Function::WeakAnyLinkage);
   }

Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Tue Feb 23 16:00:30 2010
@@ -586,6 +586,7 @@
 
     SIMPLE_ATTR(WarnUnusedResult);
     SIMPLE_ATTR(Weak);
+    SIMPLE_ATTR(WeakRef);
     SIMPLE_ATTR(WeakImport);
     }
 

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Feb 23 16:00:30 2010
@@ -1916,6 +1916,7 @@
 
     case Attr::WarnUnusedResult:
     case Attr::Weak:
+    case Attr::WeakRef:
     case Attr::WeakImport:
       break;
     }
@@ -2335,4 +2336,3 @@
     break;
   }
 }
-

Modified: cfe/trunk/lib/Parse/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/AttributeList.cpp?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/AttributeList.cpp (original)
+++ cfe/trunk/lib/Parse/AttributeList.cpp Tue Feb 23 16:00:30 2010
@@ -57,6 +57,7 @@
   // FIXME: Hand generating this is neither smart nor efficient.
   return llvm::StringSwitch<AttributeList::Kind>(AttrName)
     .Case("weak", AT_weak)
+    .Case("weakref", AT_weakref)
     .Case("pure", AT_pure)
     .Case("mode", AT_mode)
     .Case("used", AT_used)

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Feb 23 16:00:30 2010
@@ -329,6 +329,86 @@
   d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size));
 }
 
+static bool isStaticVarOrStaticFunciton(Decl *D) {
+  if (VarDecl *VD = dyn_cast<VarDecl>(D))
+    return VD->getStorageClass() == VarDecl::Static;
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    return FD->getStorageClass() == FunctionDecl::Static;
+  return false;
+}
+
+static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) {
+  // Check the attribute arguments.
+  if (Attr.getNumArgs() > 1) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+    return;
+  }
+
+  // gcc rejects
+  // class c {
+  //   static int a __attribute__((weakref ("v2")));
+  //   static int b() __attribute__((weakref ("f3")));
+  // };
+  // and ignores the attributes of
+  // void f(void) {
+  //   static int a __attribute__((weakref ("v2")));
+  // }
+  // we reject them
+  if (const DeclContext *Ctx = d->getDeclContext()) {
+    Ctx = Ctx->getLookupContext();
+    if (!isa<TranslationUnitDecl>(Ctx) && !isa<NamespaceDecl>(Ctx) ) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) <<
+	dyn_cast<NamedDecl>(d)->getNameAsString();
+      return;
+    }
+  }
+
+  // The GCC manual says
+  //
+  // At present, a declaration to which `weakref' is attached can only
+  // be `static'.
+  //
+  // It also says
+  //
+  // Without a TARGET,
+  // given as an argument to `weakref' or to `alias', `weakref' is
+  // equivalent to `weak'.
+  //
+  // gcc 4.4.1 will accept
+  // int a7 __attribute__((weakref));
+  // as
+  // int a7 __attribute__((weak));
+  // This looks like a bug in gcc. We reject that for now. We should revisit
+  // it if this behaviour is actually used.
+
+  if (!isStaticVarOrStaticFunciton(d)) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static) <<
+      dyn_cast<NamedDecl>(d)->getNameAsString();
+    return;
+  }
+
+  // GCC rejects
+  // static ((alias ("y"), weakref)).
+  // Should we? How to check that weakref is before or after alias?
+
+  if (Attr.getNumArgs() == 1) {
+    Expr *Arg = static_cast<Expr*>(Attr.getArg(0));
+    Arg = Arg->IgnoreParenCasts();
+    StringLiteral *Str = dyn_cast<StringLiteral>(Arg);
+
+    if (Str == 0 || Str->isWide()) {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string)
+          << "weakref" << 1;
+      return;
+    }
+    // GCC will accept anything as the argument of weakref. Should we
+    // check for an existing decl?
+    d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString()));
+  }
+
+  d->addAttr(::new (S.Context) WeakRefAttr());
+}
+
 static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) {
   // check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
@@ -777,13 +857,7 @@
   }
 
   /* weak only applies to non-static declarations */
-  bool isStatic = false;
-  if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
-    isStatic = VD->getStorageClass() == VarDecl::Static;
-  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
-    isStatic = FD->getStorageClass() == FunctionDecl::Static;
-  }
-  if (isStatic) {
+  if (isStaticVarOrStaticFunciton(D)) {
     S.Diag(Attr.getLoc(), diag::err_attribute_weak_static) <<
       dyn_cast<NamedDecl>(D)->getNameAsString();
     return;
@@ -1809,6 +1883,7 @@
   case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
     break;
   case AttributeList::AT_weak:        HandleWeakAttr        (D, Attr, S); break;
+  case AttributeList::AT_weakref:     HandleWeakRefAttr     (D, Attr, S); break;
   case AttributeList::AT_weak_import: HandleWeakImportAttr  (D, Attr, S); break;
   case AttributeList::AT_transparent_union:
     HandleTransparentUnionAttr(D, Attr, S);
@@ -1847,9 +1922,17 @@
 /// ProcessDeclAttributeList - Apply all the decl attributes in the specified
 /// attribute list to the specified decl, ignoring any type attributes.
 void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) {
-  while (AttrList) {
-    ProcessDeclAttribute(S, D, *AttrList, *this);
-    AttrList = AttrList->getNext();
+  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+    ProcessDeclAttribute(S, D, *l, *this);
+  }
+
+  // GCC accepts
+  // static int a9 __attribute__((weakref));
+  // but that looks really pointless. We reject it.
+  if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) {
+    Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) <<
+	dyn_cast<NamedDecl>(D)->getNameAsString();
+    return;
   }
 }
 

Modified: cfe/trunk/test/CodeGen/attributes.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attributes.c?rev=96992&r1=96991&r2=96992&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attributes.c (original)
+++ cfe/trunk/test/CodeGen/attributes.c Tue Feb 23 16:00:30 2010
@@ -30,6 +30,12 @@
 void __t8() {}
 void t9() __attribute__((weak, alias("__t8")));
 
+static void t22(void) __attribute__((weakref("t8")));
+// CHECK: @t22 = alias weak void ()* @t8
+
+static void t23(void) __attribute__((weakref, alias("t8")));
+// CHECK: @t23 = alias weak void ()* @t8
+
 // CHECK: declare extern_weak i32 @t15()
 int __attribute__((weak_import)) t15(void);
 int t17() {

Added: cfe/trunk/test/SemaCXX/attr-weakref.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-weakref.cpp?rev=96992&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-weakref.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-weakref.cpp Tue Feb 23 16:00:30 2010
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// GCC will accept anything as the argument of weakref. Should we
+// check for an existing decl?
+static int a1() __attribute__((weakref ("foo")));
+static int a2() __attribute__((weakref, alias ("foo")));
+
+static int a3 __attribute__((weakref ("foo")));
+static int a4 __attribute__((weakref, alias ("foo")));
+
+// gcc rejects, clang accepts
+static int a5 __attribute__((alias ("foo"), weakref));
+
+// this is pointless, but accepted by gcc. We reject it.
+static int a6 __attribute__((weakref)); //expected-error {{weakref declaration of 'a6' must also have an alias attribute}}
+
+// gcc warns, clang rejects
+void f(void) {
+  static int a __attribute__((weakref ("v2"))); // expected-error {{declaration of 'a' must be in a global context}}
+}
+
+// both gcc and clang reject
+class c {
+  static int a __attribute__((weakref ("v2"))); // expected-error {{declaration of 'a' must be in a global context}}
+  static int b() __attribute__((weakref ("f3"))); // expected-error {{declaration of 'b' must be in a global context}}
+};
+int a7() __attribute__((weakref ("f1"))); // expected-error {{declaration of 'a7' must be static}}
+int a8 __attribute__((weakref ("v1"))); // expected-error {{declaration of 'a8' must be static}}
+
+// gcc accepts this
+int a9 __attribute__((weakref)); // expected-error {{declaration of 'a9' must be static}}





More information about the cfe-commits mailing list