summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/Attr.h33
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.def2
-rw-r--r--clang/include/clang/Parse/AttributeList.h21
-rw-r--r--clang/lib/Parse/AttributeList.cpp1
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp38
-rw-r--r--clang/test/Sema/attr-weak.c13
6 files changed, 87 insertions, 21 deletions
diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h
index 0d6ed01e513..cd98ef1a8b0 100644
--- a/clang/include/clang/AST/Attr.h
+++ b/clang/include/clang/AST/Attr.h
@@ -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; }
};
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.def b/clang/include/clang/Basic/DiagnosticSemaKinds.def
index beefc02ef58..ef6f7eeb9c6 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.def
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.def
@@ -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")
diff --git a/clang/include/clang/Parse/AttributeList.h b/clang/include/clang/Parse/AttributeList.h
index bfa03571d6a..2f71e4d758c 100644
--- a/clang/include/clang/Parse/AttributeList.h
+++ b/clang/include/clang/Parse/AttributeList.h
@@ -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
};
diff --git a/clang/lib/Parse/AttributeList.cpp b/clang/lib/Parse/AttributeList.cpp
index 6b58a001bca..9cee6abebbd 100644
--- a/clang/lib/Parse/AttributeList.cpp
+++ b/clang/lib/Parse/AttributeList.cpp
@@ -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;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index d97747c35b3..57cd3d2bcb2 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -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/clang/test/Sema/attr-weak.c b/clang/test/Sema/attr-weak.c
new file mode 100644
index 00000000000..a58e61e627a
--- /dev/null
+++ b/clang/test/Sema/attr-weak.c
@@ -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}}
+
OpenPOWER on IntegriCloud