From: Charles Davis Date: Tue, 16 Feb 2010 18:27:26 +0000 (+0000) Subject: dllimport and dllexport are declspec attributes, too. They're also X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f0122fe49329cb439d55a6712bfcaad9a6570428;p=clang dllimport and dllexport are declspec attributes, too. They're also Win32-specific. Also, fix a test to use FileCheck instead of grepping LLVM IR. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96364 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index cba1e9e1cd..02b2aa21b7 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -813,82 +813,6 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { 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(D)) { - D->addAttr(::new (S.Context) DLLImportAttr()); - return; - } - - FunctionDecl *FD = dyn_cast(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()) { - 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(D)) { - D->addAttr(::new (S.Context) DLLExportAttr()); - return; - } - - FunctionDecl *FD = dyn_cast(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. @@ -1786,6 +1710,11 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, }; } +static bool isKnownDeclSpecAttr(const AttributeList &Attr) { + return Attr.getKind() == AttributeList::AT_dllimport || + Attr.getKind() == AttributeList::AT_dllexport; +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -1796,8 +1725,8 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, /// 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; @@ -1820,8 +1749,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, 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; diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp index d45d0106ff..597a027696 100644 --- a/lib/Sema/TargetAttributesSema.cpp +++ b/lib/Sema/TargetAttributesSema.cpp @@ -97,12 +97,100 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D, 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(D)) { + D->addAttr(::new (S.Context) DLLImportAttr()); + return; + } + + FunctionDecl *FD = dyn_cast(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()) { + 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(D)) { + D->addAttr(::new (S.Context) DLLExportAttr()); + return; + } + + FunctionDecl *FD = dyn_cast(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; diff --git a/test/CodeGen/dllimport-dllexport.c b/test/CodeGen/dllimport-dllexport.c index c7c2420ea7..c187503c5c 100644 --- a/test/CodeGen/dllimport-dllexport.c +++ b/test/CodeGen/dllimport-dllexport.c @@ -1,7 +1,12 @@ -// 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(); diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c index 082929f6d8..0b2733e694 100644 --- a/test/Parser/MicrosoftExtensions.c +++ b/test/Parser/MicrosoftExtensions.c @@ -1,4 +1,4 @@ -// 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)(); diff --git a/test/Sema/dllimport-dllexport.c b/test/Sema/dllimport-dllexport.c index a1e7a18166..eea2f6fe96 100644 --- a/test/Sema/dllimport-dllexport.c +++ b/test/Sema/dllimport-dllexport.c @@ -1,4 +1,4 @@ -// 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}} @@ -16,3 +16,21 @@ typedef int __attribute__((dllimport)) type7; // expected-warning{{'dllimport' a 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}}