[clang] 8c98c88 - PR47176: Don't read from an inactive union member if a friend function
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 24 19:02:39 PDT 2020
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__(( )) {}
More information about the cfe-commits
mailing list