]> granicus.if.org Git - clang/commitdiff
Add Parse/Sema support for weak_import attribute.
authorDaniel Dunbar <daniel@zuster.org>
Fri, 6 Mar 2009 06:39:57 +0000 (06:39 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Fri, 6 Mar 2009 06:39:57 +0000 (06:39 +0000)
 - Also, diagnose weak applied to types.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66259 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Attr.h
include/clang/Basic/DiagnosticSemaKinds.def
include/clang/Parse/AttributeList.h
lib/Parse/AttributeList.cpp
lib/Sema/SemaDeclAttr.cpp
test/Sema/attr-weak.c [new file with mode: 0644]

index 0d6ed01e513f7b3009ad1998b3fb0deb2e8429b7..cd98ef1a8b0a76f8466bb9f29168d690a18f1369 100644 (file)
@@ -31,21 +31,27 @@ public:
     AlwaysInline,
     Annotate,
     AsmLabel, // Represent GCC asm label extension.
+    Blocks,
+    Cleanup,
+    Const,
     Constructor,
+    DLLExport,
+    DLLImport,
     Deprecated,
     Destructor,
-    DLLImport,
-    DLLExport,
     FastCall,    
     Format,
     IBOutletKind, // Clang-specific.  Use "Kind" suffix to not conflict with
-    NonNull,
     NoReturn,
     NoThrow,
-    ObjCNSObject,
+    Nodebug,
+    Noinline,
+    NonNull,
     ObjCException,
+    ObjCNSObject,
     Overloadable, // Clang-specific
     Packed,
+    Pure,
     Section,
     StdCall,
     TransparentUnion,
@@ -55,12 +61,7 @@ public:
     Visibility,
     WarnUnusedResult,
     Weak,
-    Blocks,
-    Const,
-    Pure,
-    Cleanup,
-    Nodebug,
-    Noinline
+    WeakImport
   };
     
 private:
@@ -298,6 +299,16 @@ public:
   static bool classof(const WeakAttr *A) { return true; }
 };
 
+class WeakImportAttr : public Attr {
+public:
+  WeakImportAttr() : Attr(WeakImport) {}
+
+  // Implement isa/cast/dyncast/etc.
+
+  static bool classof(const Attr *A) { return A->getKind() == WeakImport; }
+  static bool classof(const WeakImportAttr *A) { return true; }
+};
+
 class NoThrowAttr : public Attr {
 public:
   NoThrowAttr() : Attr(NoThrow) {}
@@ -520,7 +531,7 @@ public:
   WarnUnusedResultAttr() : Attr(WarnUnusedResult) {}
   
   // Implement isa/cast/dyncast/etc.
-  static bool classof(const Attr *A) { return A->getKind() == WarnUnusedResult;}  
+  static bool classof(const Attr *A) { return A->getKind() == WarnUnusedResult;}
   static bool classof(const WarnUnusedResultAttr *A) { return true; }
 };
 
index beefc02ef586c6a5d754e447657799093c2763e7..ef6f7eeb9c65b7fe3e81007ee9cabb9c5cc12d24 100644 (file)
@@ -376,6 +376,8 @@ DIAG(warn_attribute_weak_on_field, WARNING,
      "__weak attribute cannot be specified on a field declaration")
 DIAG(warn_attribute_weak_on_local, WARNING,
      "__weak attribute cannot be specified on an automatic variable")
+DIAG(warn_attribute_weak_import_invalid_on_definition, WARNING,
+    "'weak_import' attribute cannot be specified on a definition")
 DIAG(warn_attribute_wrong_decl_type, WARNING,
      "'%0' attribute only applies to %select{function|union|"
      "variable and function|function or method}1 types")
index bfa03571d6a647e2c635e259261e75433951b179..2f71e4d758cccfcb472e978cd346535b86b4e3a4 100644 (file)
@@ -44,29 +44,37 @@ public:
   ~AttributeList();
   
   enum Kind {              // Please keep this list alphabetized.
+    AT_IBOutlet,          // Clang-specific.
     AT_address_space,
     AT_alias,
     AT_aligned,
     AT_always_inline,
     AT_annotate,
+    AT_blocks,
+    AT_cleanup,
+    AT_const,
     AT_constructor,
     AT_deprecated,
     AT_destructor,
-    AT_dllimport,
     AT_dllexport,
+    AT_dllimport,
     AT_ext_vector_type,
     AT_fastcall,
     AT_format,
-    AT_IBOutlet,          // Clang-specific.
     AT_mode,
+    AT_nodebug,
     AT_noinline,
     AT_nonnull,
     AT_noreturn,
     AT_nothrow,
+    AT_nsobject,
+    AT_objc_exception,
+    AT_objc_gc,
     AT_overloadable,      // Clang-specific
     AT_packed,
     AT_pure,
     AT_section,
+    AT_sentinel,
     AT_stdcall,
     AT_transparent_union,
     AT_unavailable,
@@ -76,14 +84,7 @@ public:
     AT_visibility,
     AT_warn_unused_result,
     AT_weak,
-    AT_objc_gc,
-    AT_objc_exception,
-    AT_blocks,
-    AT_sentinel,
-    AT_const,
-    AT_nsobject,
-    AT_cleanup,
-    AT_nodebug,
+    AT_weak_import,
     IgnoredAttribute,
     UnknownAttribute
   };
index 6b58a001bca95fa684f3911efa671060b0de3ac3..9cee6abebbdfdf5a986ce96f22893aa0c51e5835 100644 (file)
@@ -105,6 +105,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
       return IgnoredAttribute; // FIXME: printf format string checking.
     break;
   case 11:
+    if (!memcmp(Str, "weak_import", 11)) return AT_weak_import;
     if (!memcmp(Str, "vector_size", 11)) return AT_vector_size;
     if (!memcmp(Str, "constructor", 11)) return AT_constructor;
     if (!memcmp(Str, "unavailable", 11)) return AT_unavailable;
index d97747c35b3d17c7cc0143f28720c81c7bac160b..57cd3d2bcb235f1fe1061073d6ca628569a3861b 100644 (file)
@@ -730,10 +730,47 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
     return;
   }
+
+  // TODO: could also be applied to methods?
+  if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+    << "weak" << 2 /*variable and function*/;
+    return;
+  }
   
   D->addAttr(::new (S.Context) WeakAttr());
 }
 
+static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
+  // check the attribute arguments.
+  if (Attr.getNumArgs() != 0) {
+    S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
+    return;
+  }  
+
+  // weak_import only applies to variable & function declarations.
+  bool isDef = false;
+  if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
+    isDef = (!VD->hasExternalStorage() || VD->getInit());
+  } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    isDef = FD->getBody();
+  } else {
+    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+    << "weak_import" << 2 /*variable and function*/;
+    return;
+  }
+
+  // Merge should handle any subsequent violations.
+  if (isDef) {
+    S.Diag(Attr.getLoc(), 
+           diag::warn_attribute_weak_import_invalid_on_definition)
+      << "weak_import" << 2 /*variable and function*/;
+    return;
+  }
+
+  D->addAttr(::new (S.Context) WeakImportAttr());
+}
+
 static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
   // check the attribute arguments.
   if (Attr.getNumArgs() != 0) {
@@ -1441,6 +1478,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) {
   case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S);
     break;
   case AttributeList::AT_weak:        HandleWeakAttr      (D, Attr, S); break;
+  case AttributeList::AT_weak_import: HandleWeakImportAttr(D, Attr, S); break;
   case AttributeList::AT_transparent_union:
     HandleTransparentUnionAttr(D, Attr, S);
     break;
diff --git a/test/Sema/attr-weak.c b/test/Sema/attr-weak.c
new file mode 100644 (file)
index 0000000..a58e61e
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: clang -verify -fsyntax-only %s
+
+extern int g0 __attribute__((weak));
+extern int g1 __attribute__((weak_import));
+int g2 __attribute__((weak));
+int g3 __attribute__((weak_import)); // expected-warning {{'weak_import' attribute cannot be specified on a definition}}
+int __attribute__((weak_import)) g4(void);
+int __attribute__((weak_import)) g5(void) { 
+}
+
+struct __attribute__((weak)) s0 {}; // expected-warning {{'weak' attribute only applies to variable and function types}}
+struct __attribute__((weak_import)) s1 {}; // expected-warning {{'weak_import' attribute only applies to variable and function types}}
+