hokein created this revision.
hokein added a reviewer: sammccall.
Herald added a project: All.
hokein requested review of this revision.
Herald added a subscriber: alextsao1999.
Herald added a project: clang-tools-extra.

The motivation is to eliminate a false ambiguous parse of
tempalte-arugment-list, see test file for details.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134302

Files:
  clang-tools-extra/pseudo/lib/cxx/CXX.cpp
  clang-tools-extra/pseudo/lib/cxx/cxx.bnf
  clang-tools-extra/pseudo/test/cxx/ellipsis-in-abstractor-declarator.cpp


Index: clang-tools-extra/pseudo/test/cxx/ellipsis-in-abstractor-declarator.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/test/cxx/ellipsis-in-abstractor-declarator.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-pseudo -grammar=cxx -source=%s --print-forest | FileCheck %s
+
+// Verify that we don't misparse T... as a complete type-id template argument
+Foo<T...> abc;
+// CHECK-NOT:  template-argument-list := <ambiguous>
+// CHECK: template-argument-list := template-argument ...
Index: clang-tools-extra/pseudo/lib/cxx/cxx.bnf
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/cxx.bnf
+++ clang-tools-extra/pseudo/lib/cxx/cxx.bnf
@@ -681,7 +681,7 @@
 template-argument-list := template-argument ..._opt
 template-argument-list := template-argument-list , template-argument ..._opt
 template-argument := constant-expression
-template-argument := type-id
+template-argument := type-id [guard]
 template-argument := id-expression
 constraint-expression := logical-or-expression
 deduction-guide := explicit-specifier_opt template-name ( 
parameter-declaration-list_opt ) -> simple-template-id ;
Index: clang-tools-extra/pseudo/lib/cxx/CXX.cpp
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/CXX.cpp
+++ clang-tools-extra/pseudo/lib/cxx/CXX.cpp
@@ -182,6 +182,22 @@
   return true;
 }
 
+bool guardEllipsisInAbstractDeclarator(const GuardParams& P) {
+  const auto* TypeID = P.RHS[0];
+  assert(TypeID->symbol() == Symbol::type_id);
+  if (TypeID->kind() == ForestNode::Sequence &&
+      TypeID->rule() == 
rule::type_id::type_specifier_seq__abstract_declarator) {
+    const auto* AbstractDeclarator = TypeID->elements()[1];
+    for (auto &Child : AbstractDeclarator->descendants()) {
+      if (Child.kind() == ForestNode::Terminal)
+        if (symbolToToken(Child.symbol()) == clang::tok::ellipsis)
+          return false;
+    }
+    return true;
+  }
+  return true;
+}
+
 // Whether this e.g. decl-specifier contains an "exclusive" type such as a 
class
 // name, and thus can't combine with a second exclusive type.
 //
@@ -353,6 +369,16 @@
            
decl_specifier_seq__L_SQUARE__identifier_list__R_SQUARE__initializer__SEMI,
        specifiesStructuredBinding},
 
+      // Per C++ [dcl.fct#25] -- A declarator-id or abstract-declarator 
containing
+      // an ellipsis shall only be used in a parameter-declaration.
+      //
+      // We should not misparse the `int...` in `vector<int...> abc;` as a
+      // type-id template argument (... is an abstractor-declarator).
+      {
+        rule::template_argument::type_id,
+        guardEllipsisInAbstractDeclarator
+      },
+
       // The grammar distinguishes (only) user-defined vs plain string 
literals,
       // where the clang lexer distinguishes (only) encoding types.
       {rule::user_defined_string_literal_chunk::STRING_LITERAL,


Index: clang-tools-extra/pseudo/test/cxx/ellipsis-in-abstractor-declarator.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/pseudo/test/cxx/ellipsis-in-abstractor-declarator.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-pseudo -grammar=cxx -source=%s --print-forest | FileCheck %s
+
+// Verify that we don't misparse T... as a complete type-id template argument
+Foo<T...> abc;
+// CHECK-NOT:  template-argument-list := <ambiguous>
+// CHECK: template-argument-list := template-argument ...
Index: clang-tools-extra/pseudo/lib/cxx/cxx.bnf
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/cxx.bnf
+++ clang-tools-extra/pseudo/lib/cxx/cxx.bnf
@@ -681,7 +681,7 @@
 template-argument-list := template-argument ..._opt
 template-argument-list := template-argument-list , template-argument ..._opt
 template-argument := constant-expression
-template-argument := type-id
+template-argument := type-id [guard]
 template-argument := id-expression
 constraint-expression := logical-or-expression
 deduction-guide := explicit-specifier_opt template-name ( parameter-declaration-list_opt ) -> simple-template-id ;
Index: clang-tools-extra/pseudo/lib/cxx/CXX.cpp
===================================================================
--- clang-tools-extra/pseudo/lib/cxx/CXX.cpp
+++ clang-tools-extra/pseudo/lib/cxx/CXX.cpp
@@ -182,6 +182,22 @@
   return true;
 }
 
+bool guardEllipsisInAbstractDeclarator(const GuardParams& P) {
+  const auto* TypeID = P.RHS[0];
+  assert(TypeID->symbol() == Symbol::type_id);
+  if (TypeID->kind() == ForestNode::Sequence &&
+      TypeID->rule() == rule::type_id::type_specifier_seq__abstract_declarator) {
+    const auto* AbstractDeclarator = TypeID->elements()[1];
+    for (auto &Child : AbstractDeclarator->descendants()) {
+      if (Child.kind() == ForestNode::Terminal)
+        if (symbolToToken(Child.symbol()) == clang::tok::ellipsis)
+          return false;
+    }
+    return true;
+  }
+  return true;
+}
+
 // Whether this e.g. decl-specifier contains an "exclusive" type such as a class
 // name, and thus can't combine with a second exclusive type.
 //
@@ -353,6 +369,16 @@
            decl_specifier_seq__L_SQUARE__identifier_list__R_SQUARE__initializer__SEMI,
        specifiesStructuredBinding},
 
+      // Per C++ [dcl.fct#25] -- A declarator-id or abstract-declarator containing
+      // an ellipsis shall only be used in a parameter-declaration.
+      //
+      // We should not misparse the `int...` in `vector<int...> abc;` as a
+      // type-id template argument (... is an abstractor-declarator).
+      {
+        rule::template_argument::type_id,
+        guardEllipsisInAbstractDeclarator
+      },
+
       // The grammar distinguishes (only) user-defined vs plain string literals,
       // where the clang lexer distinguishes (only) encoding types.
       {rule::user_defined_string_literal_chunk::STRING_LITERAL,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to