r205197 - Sema: Check dll attributes on redeclarations
Nico Rieck
nico.rieck at gmail.com
Mon Mar 31 07:56:16 PDT 2014
Author: nrieck
Date: Mon Mar 31 09:56:15 2014
New Revision: 205197
URL: http://llvm.org/viewvc/llvm-project?rev=205197&view=rev
Log:
Sema: Check dll attributes on redeclarations
A redeclaration may not add dllimport or dllexport attributes. dllexport is
sticky and can be omitted on redeclarations while dllimport cannot.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/Sema/dllexport.c
cfe/trunk/test/Sema/dllimport.c
cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
cfe/trunk/test/SemaCXX/dllexport.cpp
cfe/trunk/test/SemaCXX/dllimport.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=205197&r1=205196&r2=205197&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Mar 31 09:56:15 2014
@@ -2077,6 +2077,8 @@ def err_attribute_selectany_non_extern_d
def warn_attribute_invalid_on_definition : Warning<
"'%0' attribute cannot be specified on a definition">,
InGroup<IgnoredAttributes>;
+def err_attribute_dll_redeclaration : Error<
+ "redeclaration of %q0 cannot add %q1 attribute">;
def err_attribute_dllimport_data_definition : Error<
"definition of dllimport data">;
def err_attribute_weakref_not_static : Error<
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=205197&r1=205196&r2=205197&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Mar 31 09:56:15 2014
@@ -4845,6 +4845,56 @@ static void checkAttributesAfterMerging(
}
}
+static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl,
+ NamedDecl *NewDecl,
+ bool IsSpecialization) {
+ if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl))
+ OldDecl = OldTD->getTemplatedDecl();
+ if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl))
+ NewDecl = NewTD->getTemplatedDecl();
+
+ if (!OldDecl || !NewDecl)
+ return;
+
+ const DLLImportAttr *OldImportAttr = OldDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *OldExportAttr = OldDecl->getAttr<DLLExportAttr>();
+ const DLLImportAttr *NewImportAttr = NewDecl->getAttr<DLLImportAttr>();
+ const DLLExportAttr *NewExportAttr = NewDecl->getAttr<DLLExportAttr>();
+
+ // dllimport and dllexport are inheritable attributes so we have to exclude
+ // inherited attribute instances.
+ bool HasNewAttr = (NewImportAttr && !NewImportAttr->isInherited()) ||
+ (NewExportAttr && !NewExportAttr->isInherited());
+
+ // A redeclaration is not allowed to add a dllimport or dllexport attribute,
+ // the only exception being explicit specializations.
+ // Implicitly generated declarations are also excluded for now because there
+ // is no other way to switch these to use dllimport or dllexport.
+ bool AddsAttr = !(OldImportAttr || OldExportAttr) && HasNewAttr;
+ if (AddsAttr && !IsSpecialization && !OldDecl->isImplicit()) {
+ S.Diag(NewDecl->getLocation(), diag::err_attribute_dll_redeclaration)
+ << NewDecl
+ << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr);
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ NewDecl->setInvalidDecl();
+ return;
+ }
+
+ // A redeclaration is not allowed to drop a dllimport attribute, the only
+ // exception being inline function definitions.
+ // FIXME: Handle inline functions.
+ // NB: MSVC converts such a declaration to dllexport.
+ if (OldImportAttr && !HasNewAttr) {
+ S.Diag(NewDecl->getLocation(),
+ diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
+ << NewDecl << OldImportAttr;
+ S.Diag(OldDecl->getLocation(), diag::note_previous_declaration);
+ S.Diag(OldImportAttr->getLocation(), diag::note_previous_attribute);
+ OldDecl->dropAttr<DLLImportAttr>();
+ NewDecl->dropAttr<DLLImportAttr>();
+ }
+}
+
/// Given that we are within the definition of the given function,
/// will that definition behave like C99's 'inline', where the
/// definition is discarded except for optimization purposes?
@@ -5497,6 +5547,12 @@ Sema::ActOnVariableDeclarator(Scope *S,
}
}
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewVD,
+ IsExplicitSpecialization);
+ }
+
if (NewTemplate) {
if (NewVD->isInvalidDecl())
NewTemplate->setInvalidDecl();
@@ -7318,6 +7374,12 @@ Sema::ActOnFunctionDeclarator(Scope *S,
// Set this FunctionDecl's range up to the right paren.
NewFD->setRangeEnd(D.getSourceRange().getEnd());
+ if (D.isRedeclaration() && !Previous.empty()) {
+ checkDLLAttributeRedeclaration(
+ *this, dyn_cast<NamedDecl>(Previous.getRepresentativeDecl()), NewFD,
+ isExplicitSpecialization || isFunctionTemplateSpecialization);
+ }
+
if (getLangOpts().CPlusPlus) {
if (FunctionTemplate) {
if (NewFD->isInvalidDecl())
@@ -9679,17 +9741,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop
FD->setInvalidDecl();
return D;
}
-
- // Visual C++ appears to not think this is an issue, so only issue
- // a warning when Microsoft extensions are disabled.
- if (!LangOpts.MicrosoftExt) {
- // If a symbol previously declared dllimport is later defined, the
- // attribute is ignored in subsequent references, and a warning is
- // emitted.
- Diag(FD->getLocation(),
- diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
- << FD << DA;
- }
}
// We want to attach documentation to original Decl (which might be
// a function template).
Modified: cfe/trunk/test/Sema/dllexport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllexport.c?rev=205197&r1=205196&r2=205197&view=diff
==============================================================================
--- cfe/trunk/test/Sema/dllexport.c (original)
+++ cfe/trunk/test/Sema/dllexport.c Mon Mar 31 09:56:15 2014
@@ -31,6 +31,16 @@ int __declspec(dllexport) GlobalInit2 =
__declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;
+// Redeclarations
+__declspec(dllexport) extern int GlobalRedecl1;
+__declspec(dllexport) int GlobalRedecl1;
+
+__declspec(dllexport) extern int GlobalRedecl2;
+ int GlobalRedecl2;
+
+ extern int GlobalRedecl3; // expected-note{{previous declaration is here}}
+__declspec(dllexport) extern int GlobalRedecl3; // expected-error{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}}
+
// Export in local scope.
void functionScope() {
__declspec(dllexport) extern int ExternLocalVarDecl;
@@ -69,6 +79,9 @@ __declspec(dllexport) void redecl2();
__declspec(dllexport) void redecl3();
void redecl3() {}
+ void redecl4(); // expected-note{{previous declaration is here}}
+__declspec(dllexport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}}
+
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/test/Sema/dllimport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllimport.c?rev=205197&r1=205196&r2=205197&view=diff
==============================================================================
--- cfe/trunk/test/Sema/dllimport.c (original)
+++ cfe/trunk/test/Sema/dllimport.c Mon Mar 31 09:56:15 2014
@@ -31,17 +31,17 @@ __declspec(dllimport) int GlobalInit1 =
int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
// Declare, then reject definition.
-__declspec(dllimport) extern int ExternGlobalDeclInit;
-int ExternGlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-__declspec(dllimport) int GlobalDeclInit;
-int GlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int *__attribute__((dllimport)) GlobalDeclChunkAttrInit;
-int *GlobalDeclChunkAttrInit = 0; // expected-error{{definition of dllimport data}}
+int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int GlobalDeclAttrInit __attribute__((dllimport));
-int GlobalDeclAttrInit = 1; // expected-error{{definition of dllimport data}}
+int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
// Redeclarations
__declspec(dllimport) extern int GlobalRedecl1;
@@ -56,6 +56,14 @@ int *__attribute__((dllimport)) GlobalRe
int GlobalRedecl2c __attribute__((dllimport));
int GlobalRedecl2c __attribute__((dllimport));
+// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+ extern int GlobalRedecl4; // expected-note{{previous declaration is here}}
+__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}}
+
// Import in local scope.
__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
@@ -95,5 +103,13 @@ inline void __attribute__((dllimport)) i
__declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1();
-__declspec(dllimport) void redecl3();
+// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+ void redecl4(); // expected-note{{previous declaration is here}}
+__declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}}
Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=205197&r1=205196&r2=205197&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Mon Mar 31 09:56:15 2014
@@ -119,10 +119,11 @@ enum : long long { // expected-warning{
class AAA {
__declspec(dllimport) void f(void) { }
-void f2(void);
+void f2(void); // expected-note{{previous declaration is here}}
};
-__declspec(dllimport) void AAA::f2(void) { // expected-error {{'dllimport' attribute can be applied only to symbol}}
+__declspec(dllimport) void AAA::f2(void) { // expected-error{{'dllimport' attribute can be applied only to symbol}}
+ // expected-error at -1{{redeclaration of 'AAA::f2' cannot add 'dllimport' attribute}}
}
Modified: cfe/trunk/test/SemaCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=205197&r1=205196&r2=205197&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllexport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllexport.cpp Mon Mar 31 09:56:15 2014
@@ -43,6 +43,16 @@ int __declspec(dllexport) GlobalInit2 =
__declspec(dllexport) extern int GlobalDeclInit;
int GlobalDeclInit = 1;
+// Redeclarations
+__declspec(dllexport) extern int GlobalRedecl1;
+__declspec(dllexport) int GlobalRedecl1;
+
+__declspec(dllexport) extern int GlobalRedecl2;
+ int GlobalRedecl2;
+
+ extern int GlobalRedecl3; // expected-note{{previous declaration is here}}
+__declspec(dllexport) extern int GlobalRedecl3; // expected-error{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}}
+
// Export in local scope.
void functionScope() {
__declspec(dllexport) extern int ExternLocalVarDecl;
@@ -84,6 +94,22 @@ __declspec(dllexport) void redecl1() {}
__declspec(dllexport) void redecl2();
void redecl2() {}
+ void redecl3(); // expected-note{{previous declaration is here}}
+__declspec(dllexport) void redecl3(); // expected-error{{redeclaration of 'redecl3' cannot add 'dllexport' attribute}}
+
+// Friend functions
+struct FuncFriend {
+ friend __declspec(dllexport) void friend1();
+ friend __declspec(dllexport) void friend2();
+ friend void friend3(); // expected-note{{previous declaration is here}}
+};
+__declspec(dllexport) void friend1() {}
+ void friend2() {}
+__declspec(dllexport) void friend3() {} // expected-error{{redeclaration of 'friend3' cannot add 'dllexport' attribute}}
+
+// Implicit declarations can be redeclared with dllexport.
+__declspec(dllexport) void* operator new(__SIZE_TYPE__ n);
+
//===----------------------------------------------------------------------===//
@@ -104,8 +130,18 @@ template<typename T> __declspec(dllexpor
template<typename T> __declspec(dllexport) void funcTmplRedecl2();
template<typename T> void funcTmplRedecl2() {}
-template<typename T> __declspec(dllexport) void funcTmplRedecl3();
-template<typename T> void funcTmplRedecl3() {}
+template<typename T> void funcTmplRedecl3(); // expected-note{{previous declaration is here}}
+template<typename T> __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}}
+
+// Function template friends
+struct FuncTmplFriend {
+ template<typename T> friend __declspec(dllexport) void funcTmplFriend1();
+ template<typename T> friend __declspec(dllexport) void funcTmplFriend2();
+ template<typename T> friend void funcTmplFriend3(); // expected-note{{previous declaration is here}}
+};
+template<typename T> __declspec(dllexport) void funcTmplFriend1() {}
+template<typename T> void funcTmplFriend2() {}
+template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}}
template<typename T> void funcTmpl() {}
Modified: cfe/trunk/test/SemaCXX/dllimport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=205197&r1=205196&r2=205197&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllimport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllimport.cpp Mon Mar 31 09:56:15 2014
@@ -43,17 +43,17 @@ __declspec(dllimport) int GlobalInit1 =
int __declspec(dllimport) GlobalInit2 = 1; // expected-error{{definition of dllimport data}}
// Declare, then reject definition.
-__declspec(dllimport) extern int ExternGlobalDeclInit;
-int ExternGlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) extern int ExternGlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int ExternGlobalDeclInit = 1; // expected-warning{{'ExternGlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-__declspec(dllimport) int GlobalDeclInit;
-int GlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+__declspec(dllimport) int GlobalDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclInit = 1; // expected-warning{{'GlobalDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int *__attribute__((dllimport)) GlobalDeclChunkAttrInit;
-int *GlobalDeclChunkAttrInit = 0; // expected-error{{definition of dllimport data}}
+int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-int GlobalDeclAttrInit __attribute__((dllimport));
-int GlobalDeclAttrInit = 1; // expected-error{{definition of dllimport data}}
+int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
// Redeclarations
__declspec(dllimport) extern int GlobalRedecl1;
@@ -68,6 +68,14 @@ int *__attribute__((dllimport)) GlobalRe
int GlobalRedecl2c __attribute__((dllimport));
int GlobalRedecl2c __attribute__((dllimport));
+// NB: MSVC issues a warning and makes GlobalRedecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+ extern int GlobalRedecl4; // expected-note{{previous declaration is here}}
+__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}}
+
// Import in local scope.
__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
@@ -110,9 +118,32 @@ inline void __attribute__((dllimport)) i
__declspec(dllimport) void redecl1();
__declspec(dllimport) void redecl1();
-__declspec(dllimport) void redecl3();
+// NB: MSVC issues a warning and makes redecl2/redecl3 dllexport. We follow GCC
+// and drop the dllimport with a warning.
+__declspec(dllimport) void redecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ void redecl2(); // expected-warning{{'redecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+__declspec(dllimport) void redecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+ void redecl4(); // expected-note{{previous declaration is here}}
+__declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}}
+
+// Friend functions
+struct FuncFriend {
+ friend __declspec(dllimport) void friend1();
+ friend __declspec(dllimport) void friend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ friend __declspec(dllimport) void friend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ friend void friend4(); // expected-note{{previous declaration is here}}
+};
+__declspec(dllimport) void friend1();
+ void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+ void friend3() {} // expected-warning{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+__declspec(dllimport) void friend4(); // expected-error{{redeclaration of 'friend4' cannot add 'dllimport' attribute}}
+
+// Implicit declarations can be redeclared with dllimport.
+__declspec(dllimport) void* operator new(__SIZE_TYPE__ n);
+
//===----------------------------------------------------------------------===//
@@ -127,12 +158,27 @@ template<typename T> void __declspec(dll
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
template<typename T> __declspec(dllimport) void funcTmplRedecl1();
-template<typename T> __declspec(dllimport) void funcTmplRedecl2();
-template<typename T> void funcTmplRedecl2();
+template<typename T> __declspec(dllimport) void funcTmplRedecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+template<typename T> void funcTmplRedecl2(); // expected-warning{{'funcTmplRedecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T> __declspec(dllimport) void funcTmplRedecl3();
+template<typename T> __declspec(dllimport) void funcTmplRedecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
template<typename T> void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}}
+template<typename T> __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}}
+
+// Function template friends
+struct FuncTmplFriend {
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend1();
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ template<typename T> friend __declspec(dllimport) void funcTmplFriend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+ template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}}
+};
+template<typename T> __declspec(dllimport) void funcTmplFriend1();
+template<typename T> void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}}
+
template<typename T> void funcTmpl() {}
template<typename T> __declspec(dllimport) void importedFuncTmpl();
More information about the cfe-commits
mailing list