mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-03 11:23:58 +00:00
[Clang] Support label at end of compound statement
Implements paper P2324R2 https://wg21.link/p2324r2 https://github.com/cplusplus/papers/issues/1006 Reviewed By: cor3ntin Differential Revision: https://reviews.llvm.org/D133887
This commit is contained in:
parent
133b6d7db9
commit
510383626f
@ -269,6 +269,9 @@ C2x Feature Support
|
||||
so the [[maybe_unused]] attribute may be applied to a label to silence an
|
||||
``-Wunused-label`` warning.
|
||||
|
||||
- Implemented `WG14 N508 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf>`_,
|
||||
so labels can placed everywhere inside a compound statement.
|
||||
|
||||
C++ Language Changes in Clang
|
||||
-----------------------------
|
||||
- Implemented DR692, DR1395 and DR1432. Use the ``-fclang-abi-compat=15`` option
|
||||
@ -313,6 +316,8 @@ C++20 Feature Support
|
||||
C++2b Feature Support
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Support label at end of compound statement (`P2324 <https://wg21.link/p2324r2>`_).
|
||||
|
||||
CUDA/HIP Language Changes in Clang
|
||||
----------------------------------
|
||||
|
||||
|
@ -295,8 +295,20 @@ def note_missing_selector_name : Note<
|
||||
def note_force_empty_selector_name : Note<
|
||||
"or insert whitespace before ':' to use %0 as parameter name "
|
||||
"and have an empty entry in the selector">;
|
||||
def err_label_end_of_compound_statement : Error<
|
||||
"label at end of compound statement: expected statement">;
|
||||
def err_switch_label_end_of_compound_statement : Error<
|
||||
"label at end of switch compound statement: expected statement">;
|
||||
def ext_c_label_end_of_compound_statement : ExtWarn<
|
||||
"label at end of compound statement is a C2x extension">,
|
||||
InGroup<C2x>;
|
||||
def ext_cxx_label_end_of_compound_statement : ExtWarn<
|
||||
"label at end of compound statement is a C++2b extension">,
|
||||
InGroup<CXX2b>;
|
||||
def warn_c2x_compat_label_end_of_compound_statement : Warning<
|
||||
"label at end of compound statement is incompatible with C standards before C2x">,
|
||||
InGroup<CPre2xCompat>, DefaultIgnore;
|
||||
def warn_cxx20_compat_label_end_of_compound_statement : Warning<
|
||||
"label at end of compound statement is incompatible with C++ standards before C++2b">,
|
||||
InGroup<CXXPre2bCompat>, DefaultIgnore;
|
||||
def err_address_of_label_outside_fn : Error<
|
||||
"use of address-of-label extension outside of a function body">;
|
||||
def err_asm_operand_wide_string_literal : Error<
|
||||
|
@ -679,9 +679,12 @@ StmtResult Parser::ParseSEHLeaveStatement() {
|
||||
|
||||
/// ParseLabeledStatement - We have an identifier and a ':' after it.
|
||||
///
|
||||
/// label:
|
||||
/// identifier ':'
|
||||
/// [GNU] identifier ':' attributes[opt]
|
||||
///
|
||||
/// labeled-statement:
|
||||
/// identifier ':' statement
|
||||
/// [GNU] identifier ':' attributes[opt] statement
|
||||
/// label statement
|
||||
///
|
||||
StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
|
||||
ParsedStmtContext StmtCtx) {
|
||||
@ -725,6 +728,20 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
|
||||
}
|
||||
}
|
||||
|
||||
// The label may have no statement following it
|
||||
if (SubStmt.isUnset() && Tok.is(tok::r_brace)) {
|
||||
if (getLangOpts().CPlusPlus) {
|
||||
Diag(Tok, getLangOpts().CPlusPlus2b
|
||||
? diag::warn_cxx20_compat_label_end_of_compound_statement
|
||||
: diag::ext_cxx_label_end_of_compound_statement);
|
||||
} else {
|
||||
Diag(Tok, getLangOpts().C2x
|
||||
? diag::warn_c2x_compat_label_end_of_compound_statement
|
||||
: diag::ext_c_label_end_of_compound_statement);
|
||||
}
|
||||
SubStmt = Actions.ActOnNullStmt(ColonLoc);
|
||||
}
|
||||
|
||||
// If we've not parsed a statement yet, parse one now.
|
||||
if (!SubStmt.isInvalid() && !SubStmt.isUsable())
|
||||
SubStmt = ParseStatement(nullptr, StmtCtx);
|
||||
@ -873,8 +890,8 @@ StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
|
||||
// another parsing error, so avoid producing extra diagnostics.
|
||||
if (ColonLoc.isValid()) {
|
||||
SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
|
||||
Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
|
||||
<< FixItHint::CreateInsertion(AfterColonLoc, " ;");
|
||||
Diag(AfterColonLoc, diag::err_switch_label_end_of_compound_statement)
|
||||
<< FixItHint::CreateInsertion(AfterColonLoc, " ;");
|
||||
}
|
||||
SubStmt = StmtError();
|
||||
}
|
||||
@ -928,8 +945,8 @@ StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
|
||||
// Diagnose the common error "switch (X) {... default: }", which is
|
||||
// not valid.
|
||||
SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
|
||||
Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
|
||||
<< FixItHint::CreateInsertion(AfterColonLoc, " ;");
|
||||
Diag(AfterColonLoc, diag::err_switch_label_end_of_compound_statement)
|
||||
<< FixItHint::CreateInsertion(AfterColonLoc, " ;");
|
||||
SubStmt = true;
|
||||
}
|
||||
|
||||
@ -1096,10 +1113,10 @@ StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
|
||||
return Actions.ActOnExprStmt(E, /*DiscardedValue=*/!IsStmtExprResult);
|
||||
}
|
||||
|
||||
/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
|
||||
/// ActOnCompoundStmt action. This expects the '{' to be the current token, and
|
||||
/// consume the '}' at the end of the block. It does not manipulate the scope
|
||||
/// stack.
|
||||
/// ParseCompoundStatementBody - Parse a sequence of statements optionally
|
||||
/// followed by a label and invoke the ActOnCompoundStmt action. This expects
|
||||
/// the '{' to be the current token, and consume the '}' at the end of the
|
||||
/// block. It does not manipulate the scope stack.
|
||||
StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
||||
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
|
||||
Tok.getLocation(),
|
||||
|
@ -161,6 +161,10 @@ label2:
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: ImplicitCastExpr
|
||||
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:9> 'void *' lvalue Var 0x{{[^ ]*}} 'ptr' 'void *'
|
||||
|
||||
label3:
|
||||
// CHECK-NEXT: LabelStmt 0x{{[^ ]*}} <line:[[@LINE-1]]:1, col:7> 'label3'
|
||||
// CHECK-NEXT: NullStmt 0x{{[^ ]*}} <col:7>
|
||||
}
|
||||
|
||||
void TestSwitch(int i) {
|
||||
|
10
clang/test/Parser/c2x-label.c
Normal file
10
clang/test/Parser/c2x-label.c
Normal file
@ -0,0 +1,10 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
|
||||
|
||||
void foo() {
|
||||
int x;
|
||||
label1:
|
||||
x = 1;
|
||||
label2: label3: label4:
|
||||
} // c17-warning {{label at end of compound statement is a C2x extension}} \
|
||||
c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
|
11
clang/test/Parser/cxx2b-label.cpp
Normal file
11
clang/test/Parser/cxx2b-label.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
|
||||
|
||||
void foo() {
|
||||
label1:
|
||||
int x;
|
||||
label2:
|
||||
x = 1;
|
||||
label3: label4: label5:
|
||||
} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
|
||||
cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
|
@ -160,14 +160,14 @@ void test12(int x) {
|
||||
void missing_statement_case(int x) {
|
||||
switch (x) {
|
||||
case 1:
|
||||
case 0: // expected-error {{label at end of compound statement: expected statement}}
|
||||
case 0: // expected-error {{label at end of switch compound statement: expected statement}}
|
||||
}
|
||||
}
|
||||
|
||||
void missing_statement_default(int x) {
|
||||
switch (x) {
|
||||
case 0:
|
||||
default: // expected-error {{label at end of compound statement: expected statement}}
|
||||
default: // expected-error {{label at end of switch compound statement: expected statement}}
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ void pr19022_1() {
|
||||
void pr19022_1a(int x) {
|
||||
switch(x) {
|
||||
case 1 // expected-error{{expected ':' after 'case'}} \
|
||||
// expected-error{{label at end of compound statement: expected statement}}
|
||||
// expected-error{{label at end of switch compound statement: expected statement}}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -763,7 +763,7 @@ conformance.</p>
|
||||
<tr>
|
||||
<td>Free positioning of labels inside compound statements</td>
|
||||
<td><a href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf">N2508</a></td>
|
||||
<td class="none" align="center">No</td>
|
||||
<td class="unreleased" align="center">Clang 16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Clarification request for C17 example of undefined behavior</td>
|
||||
|
@ -1456,7 +1456,7 @@ C++20, informally referred to as C++2b.</p>
|
||||
<tr>
|
||||
<td>Labels at the end of compound statements</td>
|
||||
<td><a href="https://wg21.link/P2324R2">P2324R2</a></td>
|
||||
<td class="none" align="center">No</td>
|
||||
<td class="unreleased" align="center">Clang 16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Delimited escape sequences</td>
|
||||
|
Loading…
Reference in New Issue
Block a user