diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -563,6 +563,8 @@ (`#60709 `_). - Fixed a missed integer overflow warning with temporary values. (`#63629 `_) +- Fixed parsing of elaborated type specifier inside of a new expression. + (`#34341 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2217,7 +2217,8 @@ DSC_objc_method_result, // ObjC method result context, enables // 'instancetype' 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 @@ -2239,6 +2240,7 @@ case DeclSpecContext::DSC_trailing: case DeclSpecContext::DSC_alias_declaration: case DeclSpecContext::DSC_association: + case DeclSpecContext::DSC_new: return true; } llvm_unreachable("Missing DeclSpecContext case"); @@ -2287,6 +2289,7 @@ case DeclSpecContext::DSC_trailing: case DeclSpecContext::DSC_conv_operator: case DeclSpecContext::DSC_template_arg: + case DeclSpecContext::DSC_new: return AllowDefiningTypeSpec::No; } llvm_unreachable("Missing DeclSpecContext case"); @@ -2310,6 +2313,7 @@ case DeclSpecContext::DSC_association: case DeclSpecContext::DSC_conv_operator: case DeclSpecContext::DSC_template_arg: + case DeclSpecContext::DSC_new: return false; } @@ -2329,6 +2333,7 @@ case DeclSpecContext::DSC_type_specifier: case DeclSpecContext::DSC_association: case DeclSpecContext::DSC_conv_operator: + case DeclSpecContext::DSC_new: return true; case DeclSpecContext::DSC_objc_method_result: @@ -2351,6 +2356,7 @@ case DeclSpecContext::DSC_trailing: case DeclSpecContext::DSC_alias_declaration: case DeclSpecContext::DSC_template_param: + case DeclSpecContext::DSC_new: return ImplicitTypenameContext::Yes; case DeclSpecContext::DSC_normal: diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -2981,6 +2981,8 @@ return DeclSpecContext::DSC_condition; case DeclaratorContext::ConversionId: return DeclSpecContext::DSC_conv_operator; + case DeclaratorContext::CXXNew: + return DeclSpecContext::DSC_new; case DeclaratorContext::Prototype: case DeclaratorContext::ObjCResult: case DeclaratorContext::ObjCParameter: @@ -2989,7 +2991,6 @@ case DeclaratorContext::Block: case DeclaratorContext::ForInit: case DeclaratorContext::SelectionInit: - case DeclaratorContext::CXXNew: case DeclaratorContext::CXXCatch: case DeclaratorContext::ObjCCatch: case DeclaratorContext::BlockLiteral: diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -3231,7 +3231,7 @@ // A new-type-id is a simplified type-id, where essentially the // direct-declarator is replaced by a direct-new-declarator. MaybeParseGNUAttributes(DeclaratorInfo); - if (ParseCXXTypeSpecifierSeq(DS)) + if (ParseCXXTypeSpecifierSeq(DS, DeclaratorContext::CXXNew)) DeclaratorInfo.setInvalidType(true); else { DeclaratorInfo.SetSourceRange(DS.getSourceRange()); diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp @@ -21,8 +21,8 @@ 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'}} - new struct T {}; // expected-error {{'T' cannot be defined in a type specifier}} - new struct A {}; // expected-error {{'A' 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 {}; try {} catch (struct U {}) {} // expected-error {{'U' cannot be defined in a type specifier}} diff --git a/clang/test/CXX/drs/dr19xx.cpp b/clang/test/CXX/drs/dr19xx.cpp --- a/clang/test/CXX/drs/dr19xx.cpp +++ b/clang/test/CXX/drs/dr19xx.cpp @@ -194,7 +194,7 @@ 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 *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 h() -> enum E : int {}; // expected-error {{only permitted as a standalone declaration}} diff --git a/clang/test/CXX/drs/dr21xx.cpp b/clang/test/CXX/drs/dr21xx.cpp --- a/clang/test/CXX/drs/dr21xx.cpp +++ b/clang/test/CXX/drs/dr21xx.cpp @@ -120,6 +120,31 @@ #endif } +namespace dr2141 { // dr2141: 17 +struct A{}; + +template +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 *bb = new struct B{}; + (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 #if __cplusplus >= 201103L enum E : int; diff --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp --- a/clang/test/CXX/drs/dr6xx.cpp +++ b/clang/test/CXX/drs/dr6xx.cpp @@ -1078,9 +1078,10 @@ (void)const_cast(0); // expected-error {{cannot be defined in a type specifier}} (void)sizeof(struct F*); (void)sizeof(struct F{}*); // expected-error {{cannot be defined in a type specifier}} - (void)new struct G*; - (void)new struct G{}*; // expected-error {{cannot be defined in a type specifier}} + (void)new struct G*; // expected-note {{forward}} + (void)new struct G{}*; // expected-error {{incomplete}} #if __cplusplus >= 201103L + // expected-error@-2 {{expected expression}} (void)alignof(struct H*); (void)alignof(struct H{}*); // expected-error {{cannot be defined in a type specifier}} #endif diff --git a/clang/test/Parser/cxx11-type-specifier.cpp b/clang/test/Parser/cxx11-type-specifier.cpp --- a/clang/test/Parser/cxx11-type-specifier.cpp +++ b/clang/test/Parser/cxx11-type-specifier.cpp @@ -13,10 +13,8 @@ } catch (constexpr int) { // expected-error{{type name does not allow constexpr}} } - // These parse as type definitions, not as type references with braced - // initializers. Sad but true... - (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}} + (void) new struct S {}; + (void) new enum E { e }; } // And for trailing-type-specifier-seq diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -12653,7 +12653,7 @@ 2141 CD4 Ambiguity in new-expression with elaborated-type-specifier - Unknown + Clang 17 2142