From 73768709f2627080f1635aef7573766257f2ec59 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 20 Mar 2015 00:02:27 +0000 Subject: [PATCH] Don't crash-on-valid when an inline function is friend of class template We assumed that the most recent declaration of an inline function would also be inline. However, a more recent declaration can come from a friend declaration in a class template that is instantiated at the definition of the function. llvm-svn: 232786 --- clang/lib/AST/ASTContext.cpp | 2 +- clang/lib/AST/Decl.cpp | 3 ++- 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 932bc1c..89e1d52 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 a7e879e..e700cf8 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()) 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 622cfa9..20da1f6 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 +struct S; + +S Foo(); + +template +struct S { + friend S Foo(); +}; + +__attribute__((used)) inline S Foo() { return S(); } +// CHECK-LABEL: define linkonce_odr void @_ZN7PR229593FooEv( +} -- 2.7.4