Skip to content

Commit 9df9e9f

Browse files
committed
[Clang] Skip deleted function body on error
1 parent 99c8dd1 commit 9df9e9f

File tree

5 files changed

+32
-0
lines changed

5 files changed

+32
-0
lines changed

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,7 @@ class Parser : public CodeCompletionHandler {
16011601
const VirtSpecifiers &VS,
16021602
SourceLocation PureSpecLoc);
16031603
StringLiteral *ParseCXXDeletedFunctionMessage();
1604+
void SkipDeletedFunctionBody();
16041605
void ParseCXXNonStaticMemberInitializer(Decl *VarD);
16051606
void ParseLexedAttributes(ParsingClass &Class);
16061607
void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D,

clang/lib/Parse/ParseCXXInlineMethods.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@ StringLiteral *Parser::ParseCXXDeletedFunctionMessage() {
4242
return Message;
4343
}
4444

45+
/// If we've encountered '= delete' in a context where it is ill-formed, such
46+
/// as in the declaration of a non-function, also skip the ("message") part if
47+
/// it is present to avoid issuing further diagnostics.
48+
void Parser::SkipDeletedFunctionBody() {
49+
if (!Tok.is(tok::l_paren))
50+
return;
51+
52+
BalancedDelimiterTracker BT{*this, tok::l_paren};
53+
BT.consumeOpen();
54+
55+
// Just skip to the end of the current declaration.
56+
SkipUntil(tok::r_paren, tok::comma, StopAtSemi | StopBeforeMatch);
57+
if (Tok.is(tok::r_paren))
58+
BT.consumeClose();
59+
}
60+
4561
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
4662
/// Declarator is a well formed C++ inline method definition. Now lex its body
4763
/// and store its tokens for parsing after the C++ class is complete.

clang/lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,6 +2676,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
26762676
<< 1 /* delete */;
26772677
else
26782678
Diag(ConsumeToken(), diag::err_deleted_non_function);
2679+
SkipDeletedFunctionBody();
26792680
} else if (Tok.is(tok::kw_default)) {
26802681
if (D.isFunctionDeclarator())
26812682
Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3397,6 +3397,7 @@ ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,
33973397
<< 1 /* delete */;
33983398
else
33993399
Diag(ConsumeToken(), diag::err_deleted_non_function);
3400+
SkipDeletedFunctionBody();
34003401
return ExprError();
34013402
}
34023403
} else if (Tok.is(tok::kw_default)) {

clang/test/Parser/cxx2c-delete-with-message.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,16 @@ void c() = delete(); // expected-error {{expected string literal}}
3333
void d() = delete(42); // expected-error {{expected string literal}}
3434
void e() = delete("foo"[0]); // expected-error {{expected ')'}} expected-note {{to match this '('}} // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}}
3535
void f() = delete("foo"); // pre26-warning {{'= delete' with a message is a C++2c extension}} compat-warning {{'= delete' with a message is incompatible with C++ standards before C++2c}}
36+
37+
namespace CWG2876 {
38+
using T = void ();
39+
using U = int;
40+
41+
T a = delete ("hello"); // expected-error {{only functions can have deleted definitions}}
42+
U b = delete ("hello"), c, d = delete ("hello"); // expected-error 2 {{only functions can have deleted definitions}}
43+
44+
struct C {
45+
T e = delete ("hello"); // expected-error {{'= delete' is a function definition and must occur in a standalone declaration}}
46+
U f = delete ("hello"); // expected-error {{cannot delete expression of type 'const char[6]'}}
47+
};
48+
}

0 commit comments

Comments
 (0)