[clang] Fix new-expression with elaborated-type-specifier
Expressions like ``` struct A {}; ... new struct A {}; struct A* b = (1 == 1) ? new struct A : new struct A; ``` were parsed as redefinitions of `struct A` and failed, however as clarified by `CWG2141` new-expression cannot define a type, so both these examples should be considered as references to the previously declared `struct A`. The patch adds a "new" kind context for parsing declaration specifiers in addition to already existing declarator context in order to track that the parser is inside of a new expression. Fixes https://github.com/llvm/llvm-project/issues/34341 Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D153857
This commit is contained in:
parent
fc5a5794ab
commit
4a792e06e8
@ -563,6 +563,8 @@ Bug Fixes in This Version
|
|||||||
(`#60709 <https://github.com/llvm/llvm-project/issues/60709>`_).
|
(`#60709 <https://github.com/llvm/llvm-project/issues/60709>`_).
|
||||||
- Fixed a missed integer overflow warning with temporary values.
|
- Fixed a missed integer overflow warning with temporary values.
|
||||||
(`#63629 <https://github.com/llvm/llvm-project/issues/63629>`_)
|
(`#63629 <https://github.com/llvm/llvm-project/issues/63629>`_)
|
||||||
|
- Fixed parsing of elaborated type specifier inside of a new expression.
|
||||||
|
(`#34341 <https://github.com/llvm/llvm-project/issues/34341>`_)
|
||||||
|
|
||||||
Bug Fixes to Compiler Builtins
|
Bug Fixes to Compiler Builtins
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -2217,7 +2217,8 @@ private:
|
|||||||
DSC_objc_method_result, // ObjC method result context, enables
|
DSC_objc_method_result, // ObjC method result context, enables
|
||||||
// 'instancetype'
|
// 'instancetype'
|
||||||
DSC_condition, // condition declaration context
|
DSC_condition, // condition declaration context
|
||||||
DSC_association // A _Generic selection expression's type association
|
DSC_association, // A _Generic selection expression's type association
|
||||||
|
DSC_new, // C++ new expression
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Is this a context in which we are parsing just a type-specifier (or
|
/// Is this a context in which we are parsing just a type-specifier (or
|
||||||
@ -2239,6 +2240,7 @@ private:
|
|||||||
case DeclSpecContext::DSC_trailing:
|
case DeclSpecContext::DSC_trailing:
|
||||||
case DeclSpecContext::DSC_alias_declaration:
|
case DeclSpecContext::DSC_alias_declaration:
|
||||||
case DeclSpecContext::DSC_association:
|
case DeclSpecContext::DSC_association:
|
||||||
|
case DeclSpecContext::DSC_new:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Missing DeclSpecContext case");
|
llvm_unreachable("Missing DeclSpecContext case");
|
||||||
@ -2287,6 +2289,7 @@ private:
|
|||||||
case DeclSpecContext::DSC_trailing:
|
case DeclSpecContext::DSC_trailing:
|
||||||
case DeclSpecContext::DSC_conv_operator:
|
case DeclSpecContext::DSC_conv_operator:
|
||||||
case DeclSpecContext::DSC_template_arg:
|
case DeclSpecContext::DSC_template_arg:
|
||||||
|
case DeclSpecContext::DSC_new:
|
||||||
return AllowDefiningTypeSpec::No;
|
return AllowDefiningTypeSpec::No;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Missing DeclSpecContext case");
|
llvm_unreachable("Missing DeclSpecContext case");
|
||||||
@ -2310,6 +2313,7 @@ private:
|
|||||||
case DeclSpecContext::DSC_association:
|
case DeclSpecContext::DSC_association:
|
||||||
case DeclSpecContext::DSC_conv_operator:
|
case DeclSpecContext::DSC_conv_operator:
|
||||||
case DeclSpecContext::DSC_template_arg:
|
case DeclSpecContext::DSC_template_arg:
|
||||||
|
case DeclSpecContext::DSC_new:
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -2329,6 +2333,7 @@ private:
|
|||||||
case DeclSpecContext::DSC_type_specifier:
|
case DeclSpecContext::DSC_type_specifier:
|
||||||
case DeclSpecContext::DSC_association:
|
case DeclSpecContext::DSC_association:
|
||||||
case DeclSpecContext::DSC_conv_operator:
|
case DeclSpecContext::DSC_conv_operator:
|
||||||
|
case DeclSpecContext::DSC_new:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case DeclSpecContext::DSC_objc_method_result:
|
case DeclSpecContext::DSC_objc_method_result:
|
||||||
@ -2351,6 +2356,7 @@ private:
|
|||||||
case DeclSpecContext::DSC_trailing:
|
case DeclSpecContext::DSC_trailing:
|
||||||
case DeclSpecContext::DSC_alias_declaration:
|
case DeclSpecContext::DSC_alias_declaration:
|
||||||
case DeclSpecContext::DSC_template_param:
|
case DeclSpecContext::DSC_template_param:
|
||||||
|
case DeclSpecContext::DSC_new:
|
||||||
return ImplicitTypenameContext::Yes;
|
return ImplicitTypenameContext::Yes;
|
||||||
|
|
||||||
case DeclSpecContext::DSC_normal:
|
case DeclSpecContext::DSC_normal:
|
||||||
|
@ -2981,6 +2981,8 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
|
|||||||
return DeclSpecContext::DSC_condition;
|
return DeclSpecContext::DSC_condition;
|
||||||
case DeclaratorContext::ConversionId:
|
case DeclaratorContext::ConversionId:
|
||||||
return DeclSpecContext::DSC_conv_operator;
|
return DeclSpecContext::DSC_conv_operator;
|
||||||
|
case DeclaratorContext::CXXNew:
|
||||||
|
return DeclSpecContext::DSC_new;
|
||||||
case DeclaratorContext::Prototype:
|
case DeclaratorContext::Prototype:
|
||||||
case DeclaratorContext::ObjCResult:
|
case DeclaratorContext::ObjCResult:
|
||||||
case DeclaratorContext::ObjCParameter:
|
case DeclaratorContext::ObjCParameter:
|
||||||
@ -2989,7 +2991,6 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
|
|||||||
case DeclaratorContext::Block:
|
case DeclaratorContext::Block:
|
||||||
case DeclaratorContext::ForInit:
|
case DeclaratorContext::ForInit:
|
||||||
case DeclaratorContext::SelectionInit:
|
case DeclaratorContext::SelectionInit:
|
||||||
case DeclaratorContext::CXXNew:
|
|
||||||
case DeclaratorContext::CXXCatch:
|
case DeclaratorContext::CXXCatch:
|
||||||
case DeclaratorContext::ObjCCatch:
|
case DeclaratorContext::ObjCCatch:
|
||||||
case DeclaratorContext::BlockLiteral:
|
case DeclaratorContext::BlockLiteral:
|
||||||
|
@ -3231,7 +3231,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
|
|||||||
// A new-type-id is a simplified type-id, where essentially the
|
// A new-type-id is a simplified type-id, where essentially the
|
||||||
// direct-declarator is replaced by a direct-new-declarator.
|
// direct-declarator is replaced by a direct-new-declarator.
|
||||||
MaybeParseGNUAttributes(DeclaratorInfo);
|
MaybeParseGNUAttributes(DeclaratorInfo);
|
||||||
if (ParseCXXTypeSpecifierSeq(DS))
|
if (ParseCXXTypeSpecifierSeq(DS, DeclaratorContext::CXXNew))
|
||||||
DeclaratorInfo.setInvalidType(true);
|
DeclaratorInfo.setInvalidType(true);
|
||||||
else {
|
else {
|
||||||
DeclaratorInfo.SetSourceRange(DS.getSourceRange());
|
DeclaratorInfo.SetSourceRange(DS.getSourceRange());
|
||||||
|
@ -21,8 +21,8 @@ void f() {
|
|||||||
for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may not be defined in a for range declaration}}
|
for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may not be defined in a for range declaration}}
|
||||||
// expected-error@-1{{use of undeclared identifier 'Undeclared'}}
|
// expected-error@-1{{use of undeclared identifier 'Undeclared'}}
|
||||||
|
|
||||||
new struct T {}; // expected-error {{'T' cannot be defined in a type specifier}}
|
new struct T {}; // expected-error {{allocation of incomplete type 'struct T'}} //expected-note{{forward declaration of 'T'}}
|
||||||
new struct A {}; // expected-error {{'A' cannot be defined in a type specifier}}
|
new struct A {};
|
||||||
|
|
||||||
try {} catch (struct U {}) {} // expected-error {{'U' cannot be defined in a type specifier}}
|
try {} catch (struct U {}) {} // expected-error {{'U' cannot be defined in a type specifier}}
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ namespace dr1966 { // dr1966: 11
|
|||||||
enum E : int {1}; // expected-error {{expected identifier}} (not bit-field)
|
enum E : int {1}; // expected-error {{expected identifier}} (not bit-field)
|
||||||
};
|
};
|
||||||
auto *p1 = new enum E : int; // expected-error {{only permitted as a standalone declaration}}
|
auto *p1 = new enum E : int; // expected-error {{only permitted as a standalone declaration}}
|
||||||
auto *p2 = new enum F : int {}; // expected-error {{cannot be defined in a type specifier}}
|
auto *p2 = new enum F : int {}; // expected-error {{only permitted as a standalone declaration}}
|
||||||
auto *p3 = true ? new enum G : int {}; // expected-error {{forward reference}} expected-error {{incomplete}} expected-note {{declaration}}
|
auto *p3 = true ? new enum G : int {}; // expected-error {{forward reference}} expected-error {{incomplete}} expected-note {{declaration}}
|
||||||
auto h() -> enum E : int {}; // expected-error {{only permitted as a standalone declaration}}
|
auto h() -> enum E : int {}; // expected-error {{only permitted as a standalone declaration}}
|
||||||
|
|
||||||
|
@ -120,6 +120,31 @@ namespace dr2140 { // dr2140: 9
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace dr2141 { // dr2141: 17
|
||||||
|
struct A{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct B{};
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
struct A *b = (1 == 1) ? new struct A : new struct A;
|
||||||
|
struct S *a = (1 == 1) ? new struct S : new struct S; // expected-error 2{{allocation of incomplete type}} // expected-note 2{{forward}}
|
||||||
|
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
A *aa = new struct A{};
|
||||||
|
B<int> *bb = new struct B<int>{};
|
||||||
|
(void)new struct C{}; // expected-error {{allocation of incomplete type }} // expected-note {{forward}}
|
||||||
|
|
||||||
|
struct A *c = (1 == 1) ? new struct A {} : new struct A {};
|
||||||
|
|
||||||
|
alignof(struct D{}); // expected-error {{cannot be defined in a type specifier}}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sizeof(struct E{}); // expected-error {{cannot be defined in a type specifier}}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace dr2157 { // dr2157: 11
|
namespace dr2157 { // dr2157: 11
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
enum E : int;
|
enum E : int;
|
||||||
|
@ -1078,9 +1078,10 @@ namespace dr686 { // dr686: yes
|
|||||||
(void)const_cast<struct E{}*>(0); // expected-error {{cannot be defined in a type specifier}}
|
(void)const_cast<struct E{}*>(0); // expected-error {{cannot be defined in a type specifier}}
|
||||||
(void)sizeof(struct F*);
|
(void)sizeof(struct F*);
|
||||||
(void)sizeof(struct F{}*); // expected-error {{cannot be defined in a type specifier}}
|
(void)sizeof(struct F{}*); // expected-error {{cannot be defined in a type specifier}}
|
||||||
(void)new struct G*;
|
(void)new struct G*; // expected-note {{forward}}
|
||||||
(void)new struct G{}*; // expected-error {{cannot be defined in a type specifier}}
|
(void)new struct G{}*; // expected-error {{incomplete}}
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
|
// expected-error@-2 {{expected expression}}
|
||||||
(void)alignof(struct H*);
|
(void)alignof(struct H*);
|
||||||
(void)alignof(struct H{}*); // expected-error {{cannot be defined in a type specifier}}
|
(void)alignof(struct H{}*); // expected-error {{cannot be defined in a type specifier}}
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,10 +13,8 @@ void f() {
|
|||||||
} catch (constexpr int) { // expected-error{{type name does not allow constexpr}}
|
} catch (constexpr int) { // expected-error{{type name does not allow constexpr}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These parse as type definitions, not as type references with braced
|
(void) new struct S {};
|
||||||
// initializers. Sad but true...
|
(void) new enum E { e };
|
||||||
(void) new struct S {}; // expected-error{{'S' cannot be defined in a type specifier}}
|
|
||||||
(void) new enum E { e }; // expected-error{{'E' cannot be defined in a type specifier}}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// And for trailing-type-specifier-seq
|
// And for trailing-type-specifier-seq
|
||||||
|
@ -12653,7 +12653,7 @@ and <I>POD class</I></td>
|
|||||||
<td><a href="https://cplusplus.github.io/CWG/issues/2141.html">2141</a></td>
|
<td><a href="https://cplusplus.github.io/CWG/issues/2141.html">2141</a></td>
|
||||||
<td>CD4</td>
|
<td>CD4</td>
|
||||||
<td>Ambiguity in <I>new-expression</I> with <I>elaborated-type-specifier</I></td>
|
<td>Ambiguity in <I>new-expression</I> with <I>elaborated-type-specifier</I></td>
|
||||||
<td class="none" align="center">Unknown</td>
|
<td class="unreleased" align="center">Clang 17</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="2142">
|
<tr id="2142">
|
||||||
<td><a href="https://cplusplus.github.io/CWG/issues/2142.html">2142</a></td>
|
<td><a href="https://cplusplus.github.io/CWG/issues/2142.html">2142</a></td>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user