[clang] 4a792e0 - [clang] Fix new-expression with elaborated-type-specifier

Mariya Podchishchaeva via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 3 03:13:44 PDT 2023


Author: Mariya Podchishchaeva
Date: 2023-07-03T06:07:04-04:00
New Revision: 4a792e06e8e72f4c14e5a5251e71051d7a984820

URL: https://github.com/llvm/llvm-project/commit/4a792e06e8e72f4c14e5a5251e71051d7a984820
DIFF: https://github.com/llvm/llvm-project/commit/4a792e06e8e72f4c14e5a5251e71051d7a984820.diff

LOG: [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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Parse/Parser.h
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Parse/ParseExprCXX.cpp
    clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/p3-0x.cpp
    clang/test/CXX/drs/dr19xx.cpp
    clang/test/CXX/drs/dr21xx.cpp
    clang/test/CXX/drs/dr6xx.cpp
    clang/test/Parser/cxx11-type-specifier.cpp
    clang/www/cxx_dr_status.html

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index bea609cdc08695..94eddd5e3b89c7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -563,6 +563,8 @@ Bug Fixes in This Version
   (`#60709 <https://github.com/llvm/llvm-project/issues/60709>`_).
 - Fixed a missed integer overflow warning with temporary values.
   (`#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
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index c706482aec983f..210fbb183dc07e 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2217,7 +2217,8 @@ class Parser : public CodeCompletionHandler {
     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 @@ class Parser : public CodeCompletionHandler {
     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 @@ class Parser : public CodeCompletionHandler {
     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 @@ class Parser : public CodeCompletionHandler {
     case DeclSpecContext::DSC_association:
     case DeclSpecContext::DSC_conv_operator:
     case DeclSpecContext::DSC_template_arg:
+    case DeclSpecContext::DSC_new:
 
       return false;
     }
@@ -2329,6 +2333,7 @@ class Parser : public CodeCompletionHandler {
     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 @@ class Parser : public CodeCompletionHandler {
     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
index 32085461ff8b7e..43b2a32cce71ca 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2981,6 +2981,8 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
     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 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {
   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
index 981345a7d55ca1..b035bd9db9d5c8 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -3231,7 +3231,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
     // 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
index 447f7c5d6cf387..122295741a5b7e 100644
--- 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 @@ void f() {
   for (struct S { S(int) {} } s : Undeclared); // expected-error{{types may not be defined in a for range declaration}}
                                                // expected-error at -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
index 65a14da66f9745..b15be762ecd109 100644
--- a/clang/test/CXX/drs/dr19xx.cpp
+++ b/clang/test/CXX/drs/dr19xx.cpp
@@ -194,7 +194,7 @@ namespace dr1966 { // dr1966: 11
     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
index bd6f8b7cb6e684..a1b8fe3f2a9be9 100644
--- a/clang/test/CXX/drs/dr21xx.cpp
+++ b/clang/test/CXX/drs/dr21xx.cpp
@@ -120,6 +120,31 @@ namespace dr2140 { // dr2140: 9
 #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
 #if __cplusplus >= 201103L
   enum E : int;

diff  --git a/clang/test/CXX/drs/dr6xx.cpp b/clang/test/CXX/drs/dr6xx.cpp
index 557663f2ca6a99..c5cd478c5e3319 100644
--- a/clang/test/CXX/drs/dr6xx.cpp
+++ b/clang/test/CXX/drs/dr6xx.cpp
@@ -1078,9 +1078,10 @@ namespace dr686 { // dr686: yes
     (void)const_cast<struct E{}*>(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 at -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
index 1676623ef65b87..845e0d87c8ea28 100644
--- a/clang/test/Parser/cxx11-type-specifier.cpp
+++ b/clang/test/Parser/cxx11-type-specifier.cpp
@@ -13,10 +13,8 @@ void f() {
   } 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
index 77790bceea851d..13b230706b9e80 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -12653,7 +12653,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://cplusplus.github.io/CWG/issues/2141.html">2141</a></td>
     <td>CD4</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 id="2142">
     <td><a href="https://cplusplus.github.io/CWG/issues/2142.html">2142</a></td>


        


More information about the cfe-commits mailing list