diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2015-05-04 18:23:59 +0000 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2015-05-04 18:23:59 +0000 |
commit | d418722555c0d0b9a1aa1d7931d0856bc216f51c (patch) | |
tree | 6c33af0cd656c6451202c637523757a677b14ac2 | |
parent | b5bd437007c19841a8754db8c89c7a093d7c5e76 (diff) |
Merging r232786:
------------------------------------------------------------------------
r232786 | david.majnemer | 2015-03-19 20:02:27 -0400 (Thu, 19 Mar 2015) | 7 lines
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.
------------------------------------------------------------------------
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_36@236442 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/ASTContext.cpp | 2 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 3 | ||||
-rw-r--r-- | test/CodeGenCXX/inline-functions.cpp | 15 |
3 files changed, 18 insertions, 2 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 28755085d6..c9fb80ceaa 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -7874,7 +7874,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/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index e43c28af9b..dc08d23a24 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -2674,7 +2674,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/test/CodeGenCXX/inline-functions.cpp b/test/CodeGenCXX/inline-functions.cpp index 622cfa9536..20da1f6318 100644 --- a/test/CodeGenCXX/inline-functions.cpp +++ b/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( +} |