diff options
| author | Hans Wennborg <hans@hanshq.net> | 2017-02-01 18:52:53 +0000 |
|---|---|---|
| committer | Hans Wennborg <hans@hanshq.net> | 2017-02-01 18:52:53 +0000 |
| commit | 9d17df8b463428c8e3a239accb316cec9bbd8bc0 (patch) | |
| tree | 3958b18fae4b42bdf73c13ff8ba92f01b12bc725 /clang/lib/Sema/SemaDecl.cpp | |
| parent | 6849f20d8524c570ece1c24e0af4c0d6889763f4 (diff) | |
| download | bcm5719-llvm-9d17df8b463428c8e3a239accb316cec9bbd8bc0.tar.gz bcm5719-llvm-9d17df8b463428c8e3a239accb316cec9bbd8bc0.zip | |
Drop 'dllimport' when redeclaring inline function template without the attribute (PR31695)
For non-template dllimport functions, MSVC allows providing an inline
definition without spelling out the attribute again. In the example below, f
remains a dllimport function.
__declspec(dllimport) int f();
inline int f() { return 42; }
int useit() {
return f();
}
However, for a function template, not putting dllimport on the redeclaration
causes it to be dropped. In the example below, f is not dllimport.
template <typename> __declspec(dllimport) int f();
template <typename> inline int f() { return 42; }
int useit() {
return f<int>();
}
This patch makes Clang match MSVC for the second example.
MSVC does not warn about the attribute being dropped in the example above, but
I think we should. (MSVC does warn if the inline keyword isn't used.)
Differential Revision: https://reviews.llvm.org/D29152
llvm-svn: 293800
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 60daae056b3..32663121f88 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5702,13 +5702,17 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, if (OldDecl->isInvalidDecl()) return; + bool IsTemplate = false; if (TemplateDecl *OldTD = dyn_cast<TemplateDecl>(OldDecl)) { OldDecl = OldTD->getTemplatedDecl(); + IsTemplate = true; if (!IsSpecialization) IsDefinition = false; } - if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl)) + if (TemplateDecl *NewTD = dyn_cast<TemplateDecl>(NewDecl)) { NewDecl = NewTD->getTemplatedDecl(); + IsTemplate = true; + } if (!OldDecl || !NewDecl) return; @@ -5761,9 +5765,10 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, } // A redeclaration is not allowed to drop a dllimport attribute, the only - // exceptions being inline function definitions, local extern declarations, - // qualified friend declarations or special MSVC extension: in the last case, - // the declaration is treated as if it were marked dllexport. + // exceptions being inline function definitions (except for function + // templates), local extern declarations, qualified friend declarations or + // special MSVC extension: in the last case, the declaration is treated as if + // it were marked dllexport. bool IsInline = false, IsStaticDataMember = false, IsQualifiedFriend = false; bool IsMicrosoft = S.Context.getTargetInfo().getCXXABI().isMicrosoft(); if (const auto *VD = dyn_cast<VarDecl>(NewDecl)) { @@ -5778,7 +5783,8 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, FD->getFriendObjectKind() == Decl::FOK_Declared; } - if (OldImportAttr && !HasNewAttr && !IsInline && !IsStaticDataMember && + if (OldImportAttr && !HasNewAttr && + (!IsInline || (IsMicrosoft && IsTemplate)) && !IsStaticDataMember && !NewDecl->isLocalExternDecl() && !IsQualifiedFriend) { if (IsMicrosoft && IsDefinition) { S.Diag(NewDecl->getLocation(), |

