Skip to content

Commit 8c98c88

Browse files
committed
PR47176: Don't read from an inactive union member if a friend function
has default arguments and an exception specification.
1 parent 960535d commit 8c98c88

File tree

4 files changed

+19
-7
lines changed

4 files changed

+19
-7
lines changed

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1367,7 +1367,7 @@ class Parser : public CodeCompletionHandler {
13671367

13681368
void ParseLexedMethodDeclarations() override;
13691369

1370-
Parser* Self;
1370+
Parser *Self;
13711371

13721372
/// Method - The method declaration.
13731373
Decl *Method;

clang/lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6486,6 +6486,10 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
64866486
InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope);
64876487

64886488
// Parse exception-specification[opt].
6489+
// FIXME: Per [class.mem]p6, all exception-specifications at class scope
6490+
// should be delayed, including those for non-members (eg, friend
6491+
// declarations). But only applying this to member declarations is
6492+
// consistent with what other implementations do.
64896493
bool Delayed = D.isFirstDeclarationOfMember() &&
64906494
D.isFunctionDeclaratorAFunctionDeclaration();
64916495
if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) &&

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,17 +2186,20 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
21862186
auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
21872187
getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
21882188

2189-
// Stash the exception-specification tokens in the late-pased method.
2190-
LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
2191-
FTI.ExceptionSpecTokens = nullptr;
2192-
2193-
// Push tokens for each parameter. Those that do not have
2194-
// defaults will be NULL.
2189+
// Push tokens for each parameter. Those that do not have defaults will be
2190+
// NULL. We need to track all the parameters so that we can push them into
2191+
// scope for later parameters and perhaps for the exception specification.
21952192
LateMethod->DefaultArgs.reserve(FTI.NumParams);
21962193
for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)
21972194
LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(
21982195
FTI.Params[ParamIdx].Param,
21992196
std::move(FTI.Params[ParamIdx].DefaultArgTokens)));
2197+
2198+
// Stash the exception-specification tokens in the late-pased method.
2199+
if (FTI.getExceptionSpecType() == EST_Unparsed) {
2200+
LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
2201+
FTI.ExceptionSpecTokens = nullptr;
2202+
}
22002203
}
22012204
}
22022205

clang/test/Parser/cxx0x-decl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ namespace AliasDeclEndLocation {
199199
B something_else;
200200
}
201201

202+
class PR47176 {
203+
friend void f(PR47176, int = 0) noexcept(true) {}
204+
};
205+
static_assert(noexcept(f(PR47176())), "");
206+
202207
struct Base { virtual void f() = 0; virtual void g() = 0; virtual void h() = 0; };
203208
struct MemberComponentOrder : Base {
204209
void f() override __asm__("foobar") __attribute__(( )) {}

0 commit comments

Comments
 (0)