Author: Richard Smith Date: 2020-09-24T19:02:27-07:00 New Revision: 8c98c8803430804010da06a07cfb291dab59067c
URL: https://github.com/llvm/llvm-project/commit/8c98c8803430804010da06a07cfb291dab59067c DIFF: https://github.com/llvm/llvm-project/commit/8c98c8803430804010da06a07cfb291dab59067c.diff LOG: PR47176: Don't read from an inactive union member if a friend function has default arguments and an exception specification. Added: Modified: clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/ParseDeclCXX.cpp clang/test/Parser/cxx0x-decl.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 570f60fb9479..ee08cfc589e1 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1367,7 +1367,7 @@ class Parser : public CodeCompletionHandler { void ParseLexedMethodDeclarations() override; - Parser* Self; + Parser *Self; /// Method - The method declaration. Decl *Method; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index d6b2eb8a9877..79628cfed1b2 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6486,6 +6486,10 @@ void Parser::ParseFunctionDeclarator(Declarator &D, InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope); // Parse exception-specification[opt]. + // FIXME: Per [class.mem]p6, all exception-specifications at class scope + // should be delayed, including those for non-members (eg, friend + // declarations). But only applying this to member declarations is + // consistent with what other implementations do. bool Delayed = D.isFirstDeclarationOfMember() && D.isFunctionDeclaratorAFunctionDeclaration(); if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) && diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 290b3c5df959..059d875d683d 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2186,17 +2186,20 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl); getCurrentClass().LateParsedDeclarations.push_back(LateMethod); - // Stash the exception-specification tokens in the late-pased method. - LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; - FTI.ExceptionSpecTokens = nullptr; - - // Push tokens for each parameter. Those that do not have - // defaults will be NULL. + // Push tokens for each parameter. Those that do not have defaults will be + // NULL. We need to track all the parameters so that we can push them into + // scope for later parameters and perhaps for the exception specification. LateMethod->DefaultArgs.reserve(FTI.NumParams); for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument( FTI.Params[ParamIdx].Param, std::move(FTI.Params[ParamIdx].DefaultArgTokens))); + + // Stash the exception-specification tokens in the late-pased method. + if (FTI.getExceptionSpecType() == EST_Unparsed) { + LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; + FTI.ExceptionSpecTokens = nullptr; + } } } diff --git a/clang/test/Parser/cxx0x-decl.cpp b/clang/test/Parser/cxx0x-decl.cpp index 4ddcb8ccfd0f..8be98d6ef299 100644 --- a/clang/test/Parser/cxx0x-decl.cpp +++ b/clang/test/Parser/cxx0x-decl.cpp @@ -199,6 +199,11 @@ namespace AliasDeclEndLocation { B something_else; } +class PR47176 { + friend void f(PR47176, int = 0) noexcept(true) {} +}; +static_assert(noexcept(f(PR47176())), ""); + struct Base { virtual void f() = 0; virtual void g() = 0; virtual void h() = 0; }; struct MemberComponentOrder : Base { void f() override __asm__("foobar") __attribute__(( )) {} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits