diff options
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 3 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/inline-functions.cpp | 15 |
3 files changed, 18 insertions, 2 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 932bc1cb86d..89e1d52c643 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7911,7 +7911,7 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, // Functions specified with extern and inline in -fms-compatibility mode // forcibly get emitted. While the body of the function cannot be later // replaced, the function definition cannot be discarded. - if (FD->getMostRecentDecl()->isMSExternInline()) + if (FD->isMSExternInline()) return GVA_StrongODR; return GVA_DiscardableODR; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index a7e879e04c8..e700cf85997 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2734,7 +2734,8 @@ bool FunctionDecl::isMSExternInline() const { if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>()) return false; - for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDecl()) + for (const FunctionDecl *FD = getMostRecentDecl(); FD; + FD = FD->getPreviousDecl()) if (FD->getStorageClass() == SC_Extern) return true; diff --git a/clang/test/CodeGenCXX/inline-functions.cpp b/clang/test/CodeGenCXX/inline-functions.cpp index 622cfa9536f..20da1f63180 100644 --- a/clang/test/CodeGenCXX/inline-functions.cpp +++ b/clang/test/CodeGenCXX/inline-functions.cpp @@ -121,3 +121,18 @@ struct TypeWithInlineMethods { // CHECK-NOT: _ZN21TypeWithInlineMethods12NonStaticFunEv void NonStaticFun() { StaticFun(); } }; + +namespace PR22959 { +template <typename> +struct S; + +S<int> Foo(); + +template <typename> +struct S { + friend S<int> Foo(); +}; + +__attribute__((used)) inline S<int> Foo() { return S<int>(); } +// CHECK-LABEL: define linkonce_odr void @_ZN7PR229593FooEv( +} |