Merged in r311105.
On Mon, Aug 14, 2017 at 10:07 AM, Hans Wennborg <h...@chromium.org> wrote: > Sounds good to me. Let's give it another day and see how it goes. > > On Fri, Aug 11, 2017 at 6:48 PM, Richard Smith <rich...@metafoo.co.uk> wrote: >> Hi Hans, >> >> I'd like to get this into Clang 5, but it's not entirely risk-free. Perhaps >> we could leave it in the tree for a little while and then merge if it seems >> OK? >> >> On 11 August 2017 at 18:46, Richard Smith via cfe-commits >> <cfe-commits@lists.llvm.org> wrote: >>> >>> Author: rsmith >>> Date: Fri Aug 11 18:46:03 2017 >>> New Revision: 310776 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=310776&view=rev >>> Log: >>> PR34163: Don't cache an incorrect key function for a class if queried >>> between >>> the class becoming complete and its inline methods being parsed. >>> >>> This replaces the hack of using the "late parsed template" flag to track >>> member >>> functions with bodies we've not parsed yet; instead we now use the "will >>> have >>> body" flag, which carries the desired implication that the function >>> declaration >>> *is* a definition, and that we've just not parsed its body yet. >>> >>> Added: >>> cfe/trunk/test/CodeGenCXX/pr34163.cpp >>> Modified: >>> cfe/trunk/include/clang/AST/Decl.h >>> cfe/trunk/lib/AST/DeclCXX.cpp >>> cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp >>> cfe/trunk/lib/Sema/SemaDecl.cpp >>> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp >>> cfe/trunk/test/SemaCUDA/function-overload.cu >>> cfe/trunk/test/SemaCUDA/no-destructor-overload.cu >>> >>> Modified: cfe/trunk/include/clang/AST/Decl.h >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=310776&r1=310775&r2=310776&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/include/clang/AST/Decl.h (original) >>> +++ cfe/trunk/include/clang/AST/Decl.h Fri Aug 11 18:46:03 2017 >>> @@ -1666,8 +1666,7 @@ private: >>> unsigned HasSkippedBody : 1; >>> >>> /// Indicates if the function declaration will have a body, once we're >>> done >>> - /// parsing it. (We don't set it to false when we're done parsing, in >>> the >>> - /// hopes this is simpler.) >>> + /// parsing it. >>> unsigned WillHaveBody : 1; >>> >>> /// \brief End part of this FunctionDecl's source range. >>> >>> Modified: cfe/trunk/lib/AST/DeclCXX.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=310776&r1=310775&r2=310776&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/AST/DeclCXX.cpp (original) >>> +++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Aug 11 18:46:03 2017 >>> @@ -1837,9 +1837,10 @@ bool CXXMethodDecl::hasInlineBody() cons >>> const FunctionDecl *CheckFn = getTemplateInstantiationPattern(); >>> if (!CheckFn) >>> CheckFn = this; >>> - >>> + >>> const FunctionDecl *fn; >>> - return CheckFn->hasBody(fn) && !fn->isOutOfLine(); >>> + return CheckFn->isDefined(fn) && !fn->isOutOfLine() && >>> + (fn->doesThisDeclarationHaveABody() || fn->willHaveBody()); >>> } >>> >>> bool CXXMethodDecl::isLambdaStaticInvoker() const { >>> >>> Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=310776&r1=310775&r2=310776&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original) >>> +++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Fri Aug 11 18:46:03 2017 >>> @@ -166,20 +166,11 @@ NamedDecl *Parser::ParseCXXInlineMethodD >>> } >>> >>> if (FnD) { >>> - // If this is a friend function, mark that it's late-parsed so that >>> - // it's still known to be a definition even before we attach the >>> - // parsed body. Sema needs to treat friend function definitions >>> - // differently during template instantiation, and it's possible for >>> - // the containing class to be instantiated before all its member >>> - // function definitions are parsed. >>> - // >>> - // If you remove this, you can remove the code that clears the flag >>> - // after parsing the member. >>> - if (D.getDeclSpec().isFriendSpecified()) { >>> - FunctionDecl *FD = FnD->getAsFunction(); >>> - Actions.CheckForFunctionRedefinition(FD); >>> - FD->setLateTemplateParsed(true); >>> - } >>> + FunctionDecl *FD = FnD->getAsFunction(); >>> + // Track that this function will eventually have a body; Sema needs >>> + // to know this. >>> + Actions.CheckForFunctionRedefinition(FD); >>> + FD->setWillHaveBody(true); >>> } else { >>> // If semantic analysis could not build a function declaration, >>> // just throw away the late-parsed declaration. >>> @@ -559,10 +550,6 @@ void Parser::ParseLexedMethodDef(LexedMe >>> >>> ParseFunctionStatementBody(LM.D, FnScope); >>> >>> - // Clear the late-template-parsed bit if we set it before. >>> - if (LM.D) >>> - LM.D->getAsFunction()->setLateTemplateParsed(false); >>> - >>> while (Tok.isNot(tok::eof)) >>> ConsumeAnyToken(); >>> >>> >>> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=310776&r1=310775&r2=310776&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) >>> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Aug 11 18:46:03 2017 >>> @@ -12090,8 +12090,9 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop >>> FD->setInvalidDecl(); >>> } >>> >>> - // See if this is a redefinition. >>> - if (!FD->isLateTemplateParsed()) { >>> + // See if this is a redefinition. If 'will have body' is already set, >>> then >>> + // these checks were already performed when it was set. >>> + if (!FD->willHaveBody() && !FD->isLateTemplateParsed()) { >>> CheckForFunctionRedefinition(FD, nullptr, SkipBody); >>> >>> // If we're skipping the body, we're done. Don't enter the scope. >>> >>> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=310776&r1=310775&r2=310776&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) >>> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Aug 11 18:46:03 >>> 2017 >>> @@ -3771,6 +3771,8 @@ void Sema::InstantiateFunctionDefinition >>> if (PatternDef) { >>> Pattern = PatternDef->getBody(PatternDef); >>> PatternDecl = PatternDef; >>> + if (PatternDef->willHaveBody()) >>> + PatternDef = nullptr; >>> } >>> >>> // FIXME: We need to track the instantiation stack in order to know >>> which >>> >>> Added: cfe/trunk/test/CodeGenCXX/pr34163.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pr34163.cpp?rev=310776&view=auto >>> >>> ============================================================================== >>> --- cfe/trunk/test/CodeGenCXX/pr34163.cpp (added) >>> +++ cfe/trunk/test/CodeGenCXX/pr34163.cpp Fri Aug 11 18:46:03 2017 >>> @@ -0,0 +1,13 @@ >>> +// RUN: %clang_cc1 -emit-llvm -debug-info-kind=standalone -triple >>> x86_64-linux-gnu -o - -x c++ %s | FileCheck %s >>> + >>> +void f(struct X *) {} >>> + >>> +// CHECK: @_ZTV1X = >>> +struct X { >>> + void a() { delete this; } >>> + virtual ~X() {} >>> + virtual void key_function(); >>> +}; >>> + >>> +// CHECK: define {{.*}} @_ZN1X12key_functionEv( >>> +void X::key_function() {} >>> >>> Modified: cfe/trunk/test/SemaCUDA/function-overload.cu >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/function-overload.cu?rev=310776&r1=310775&r2=310776&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCUDA/function-overload.cu (original) >>> +++ cfe/trunk/test/SemaCUDA/function-overload.cu Fri Aug 11 18:46:03 2017 >>> @@ -222,7 +222,7 @@ GlobalFnPtr fp_g = g; >>> // Test overloading of destructors >>> // Can't mix H and unattributed destructors >>> struct d_h { >>> - ~d_h() {} // expected-note {{previous declaration is here}} >>> + ~d_h() {} // expected-note {{previous definition is here}} >>> __host__ ~d_h() {} // expected-error {{destructor cannot be >>> redeclared}} >>> }; >>> >>> >>> Modified: cfe/trunk/test/SemaCUDA/no-destructor-overload.cu >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCUDA/no-destructor-overload.cu?rev=310776&r1=310775&r2=310776&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCUDA/no-destructor-overload.cu (original) >>> +++ cfe/trunk/test/SemaCUDA/no-destructor-overload.cu Fri Aug 11 18:46:03 >>> 2017 >>> @@ -7,27 +7,27 @@ >>> // giant change to clang, and the use cases seem quite limited. >>> >>> struct A { >>> - ~A() {} // expected-note {{previous declaration is here}} >>> + ~A() {} // expected-note {{previous definition is here}} >>> __device__ ~A() {} // expected-error {{destructor cannot be >>> redeclared}} >>> }; >>> >>> struct B { >>> - __host__ ~B() {} // expected-note {{previous declaration is here}} >>> + __host__ ~B() {} // expected-note {{previous definition is here}} >>> __host__ __device__ ~B() {} // expected-error {{destructor cannot be >>> redeclared}} >>> }; >>> >>> struct C { >>> - __host__ __device__ ~C() {} // expected-note {{previous declaration is >>> here}} >>> + __host__ __device__ ~C() {} // expected-note {{previous definition is >>> here}} >>> __host__ ~C() {} // expected-error {{destructor cannot be redeclared}} >>> }; >>> >>> struct D { >>> - __device__ ~D() {} // expected-note {{previous declaration is here}} >>> + __device__ ~D() {} // expected-note {{previous definition is here}} >>> __host__ __device__ ~D() {} // expected-error {{destructor cannot be >>> redeclared}} >>> }; >>> >>> struct E { >>> - __host__ __device__ ~E() {} // expected-note {{previous declaration is >>> here}} >>> + __host__ __device__ ~E() {} // expected-note {{previous definition is >>> here}} >>> __device__ ~E() {} // expected-error {{destructor cannot be >>> redeclared}} >>> }; >>> >>> >>> >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits@lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> >> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits