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,
Visibility,
WarnUnusedResult,
Weak,
- Blocks,
- Const,
- Pure,
- Cleanup,
- Nodebug,
- Noinline
+ WeakImport
};
private:
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) {}
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; }
};
"__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")
~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,
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
};
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;
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) {
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;
--- /dev/null
+// 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}}
+