D->addAttr(::new (S.Context) WeakImportAttr());
}
-static void HandleDLLImportAttr(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;
- }
-
- // Attribute can be applied only to functions or variables.
- if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLImportAttr());
- return;
- }
-
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
-
- // Currently, the dllimport attribute is ignored for inlined functions.
- // Warning is emitted.
- if (FD->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
- return;
- }
-
- // The attribute is also overridden by a subsequent declaration as dllexport.
- // Warning is emitted.
- for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
- nextAttr = nextAttr->getNext()) {
- if (nextAttr->getKind() == AttributeList::AT_dllexport) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
- return;
- }
- }
-
- if (D->getAttr<DLLExportAttr>()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
- return;
- }
-
- D->addAttr(::new (S.Context) DLLImportAttr());
-}
-
-static void HandleDLLExportAttr(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;
- }
-
- // Attribute can be applied only to functions or variables.
- if (isa<VarDecl>(D)) {
- D->addAttr(::new (S.Context) DLLExportAttr());
- return;
- }
-
- FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
- if (!FD) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << Attr.getName() << 2 /*variable and function*/;
- return;
- }
-
- // Currently, the dllexport attribute is ignored for inlined functions, unless
- // the -fkeep-inline-functions flag has been used. Warning is emitted;
- if (FD->isInlineSpecified()) {
- // FIXME: ... unless the -fkeep-inline-functions flag has been used.
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
- return;
- }
-
- D->addAttr(::new (S.Context) DLLExportAttr());
-}
-
static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
Sema &S) {
// Attribute has 3 arguments.
};
}
+static bool isKnownDeclSpecAttr(const AttributeList &Attr) {
+ return Attr.getKind() == AttributeList::AT_dllimport ||
+ Attr.getKind() == AttributeList::AT_dllexport;
+}
+
//===----------------------------------------------------------------------===//
// Top Level Sema Entry Points
//===----------------------------------------------------------------------===//
/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4).
static void ProcessDeclAttribute(Scope *scope, Decl *D,
const AttributeList &Attr, Sema &S) {
- if (Attr.isDeclspecAttribute())
- // FIXME: Try to deal with __declspec attributes!
+ if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr))
+ // FIXME: Try to deal with other __declspec attributes!
return;
switch (Attr.getKind()) {
case AttributeList::AT_IBOutlet: HandleIBOutletAttr (D, Attr, S); break;
case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break;
case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break;
case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break;
- case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break;
- case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break;
case AttributeList::AT_ext_vector_type:
HandleExtVectorTypeAttr(scope, D, Attr, S);
break;
D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr());
}
+static void HandleDLLImportAttr(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;
+ }
+
+ // Attribute can be applied only to functions or variables.
+ if (isa<VarDecl>(D)) {
+ D->addAttr(::new (S.Context) DLLImportAttr());
+ return;
+ }
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ // Currently, the dllimport attribute is ignored for inlined functions.
+ // Warning is emitted.
+ if (FD->isInlineSpecified()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+
+ // The attribute is also overridden by a subsequent declaration as dllexport.
+ // Warning is emitted.
+ for (AttributeList *nextAttr = Attr.getNext(); nextAttr;
+ nextAttr = nextAttr->getNext()) {
+ if (nextAttr->getKind() == AttributeList::AT_dllexport) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+ }
+
+ if (D->getAttr<DLLExportAttr>()) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) DLLImportAttr());
+}
+
+static void HandleDLLExportAttr(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;
+ }
+
+ // Attribute can be applied only to functions or variables.
+ if (isa<VarDecl>(D)) {
+ D->addAttr(::new (S.Context) DLLExportAttr());
+ return;
+ }
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
+ if (!FD) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 2 /*variable and function*/;
+ return;
+ }
+
+ // Currently, the dllexport attribute is ignored for inlined functions, unless
+ // the -fkeep-inline-functions flag has been used. Warning is emitted;
+ if (FD->isInlineSpecified()) {
+ // FIXME: ... unless the -fkeep-inline-functions flag has been used.
+ S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport";
+ return;
+ }
+
+ D->addAttr(::new (S.Context) DLLExportAttr());
+}
+
namespace {
class X86AttributesSema : public TargetAttributesSema {
public:
X86AttributesSema() { }
bool ProcessDeclAttribute(Scope *scope, Decl *D,
const AttributeList &Attr, Sema &S) const {
+ const llvm::Triple &Triple(S.Context.Target.getTriple());
+ if (Triple.getOS() == llvm::Triple::Win32 ||
+ Triple.getOS() == llvm::Triple::MinGW32 ||
+ Triple.getOS() == llvm::Triple::MinGW64) {
+ switch (Attr.getKind()) {
+ case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S);
+ return true;
+ case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S);
+ return true;
+ default: break;
+ }
+ }
if (Attr.getName()->getName() == "force_align_arg_pointer") {
HandleX86ForceAlignArgPointerAttr(D, Attr, S);
return true;
-// RUN: %clang_cc1 -emit-llvm < %s -o %t
-// RUN: grep 'dllexport' %t | count 1
-// RUN: not grep 'dllimport' %t
+// RUN: %clang_cc1 -triple i386-mingw32 -emit-llvm < %s | FileCheck %s
void __attribute__((dllimport)) foo1();
void __attribute__((dllexport)) foo1(){}
+// CHECK: define dllexport void @foo1
void __attribute__((dllexport)) foo2();
+
+// PR6269
+__declspec(dllimport) void foo3();
+__declspec(dllexport) void foo3(){}
+// CHECK: define dllexport void @foo3
+__declspec(dllexport) void foo4();
-// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -x objective-c++ %s
+// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify -fms-extensions -x objective-c++ %s
__stdcall int func0();
int __stdcall func();
typedef int (__cdecl *tptr)();
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify %s
inline void __attribute__((dllexport)) foo1(){} // expected-warning{{dllexport attribute ignored}}
inline void __attribute__((dllimport)) foo2(){} // expected-warning{{dllimport attribute ignored}}
void __attribute__((dllimport)) foo6();
void foo6(){} // expected-warning {{'foo6' redeclared without dllimport attribute: previous dllimport ignored}}
+
+// PR6269
+inline void __declspec(dllexport) foo7(){} // expected-warning{{dllexport attribute ignored}}
+inline void __declspec(dllimport) foo8(){} // expected-warning{{dllimport attribute ignored}}
+
+void __declspec(dllimport) foo9(){} // expected-error{{dllimport attribute can be applied only to symbol declaration}}
+
+void __declspec(dllimport) __declspec(dllexport) foo10(); // expected-warning{{dllimport attribute ignored}}
+
+void __declspec(dllexport) foo11();
+void __declspec(dllimport) foo11(); // expected-warning{{dllimport attribute ignored}}
+
+typedef int __declspec(dllexport) type1; // expected-warning{{'dllexport' attribute only applies to variable and function types}}
+
+typedef int __declspec(dllimport) type2; // expected-warning{{'dllimport' attribute only applies to variable and function}}
+
+void __declspec(dllimport) foo12();
+void foo12(){} // expected-warning {{'foo12' redeclared without dllimport attribute: previous dllimport ignored}}