junaire updated this revision to Diff 420178.
junaire retitled this revision from " [Clang][Sema] Prohibit expr statement in 
the default argument" to "[Clang][Sema] Prohibit expr statement in the default 
argument".
junaire edited the summary of this revision.
junaire added a comment.

Add tests for template arguments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119609/new/

https://reviews.llvm.org/D119609

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseTemplate.cpp
  clang/test/Sema/err-expr-stmt-in-default-arg.cpp
  clang/test/SemaTemplate/dependent-expr.cpp

Index: clang/test/SemaTemplate/dependent-expr.cpp
===================================================================
--- clang/test/SemaTemplate/dependent-expr.cpp
+++ clang/test/SemaTemplate/dependent-expr.cpp
@@ -141,15 +141,7 @@
   using U = float; // expected-error {{different types ('float' vs 'decltype(g<int>())' (aka 'void'))}}
 
   void h(auto a, decltype(g<char>())*) {} // expected-note {{previous}}
-  void h(auto a, void*) {} // expected-error {{redefinition}}
-
-  void i(auto a) {
-    [](auto a, int = ({decltype(a) i; i * 2;})){}(a); // expected-error {{invalid operands to binary expression ('decltype(a)' (aka 'void *') and 'int')}} expected-note {{in instantiation of}}
-  }
-  void use_i() {
-    i(0);
-    i((void*)0); // expected-note {{instantiation of}}
-  }
+  void h(auto a, void *) {} // expected-error {{redefinition}}
 }
 
 namespace BindingInStmtExpr {
Index: clang/test/Sema/err-expr-stmt-in-default-arg.cpp
===================================================================
--- /dev/null
+++ clang/test/Sema/err-expr-stmt-in-default-arg.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -std=c++20
+
+void foo() {
+  void fn(int i, int = ({ 1; })); // expected-error {{expression statement not permitted in default argument}}
+
+  auto a = [](int = ({ 1; })) {}; // expected-error {{expression statement not permitted in default argument}}
+
+  auto b = []<int = ({ 1; })>(){}; // expected-error {{expression statement not permitted in default argument}}
+
+  void fn(int i, int j = ({{}, {}, {,}}), int k = ""); // expected-error {{expression statement not permitted in default argument}} expected-error {{cannot initialize a parameter of type 'int' with an lvalue of type 'const char[1]'}} expected-note {{passing argument to parameter 'k' here}}
+}
+
+template<int foo = ({1;})> // expected-error {{expression statement not permitted in default argument}}
+void f() {}
+
+template<int bar = ({1;})> // expected-error {{expression statement not permitted in default argument}}
+class S{};
+
+template <typename Callable>
+int bar(Callable &&Call) {
+  return Call();
+}
+
+int baz() {
+  auto l = [](int a = ({ int x = 12; x; })) { // expected-error {{expression statement not permitted in default argument}}
+    return 1;
+  };
+  return bar(l);
+}
Index: clang/lib/Parse/ParseTemplate.cpp
===================================================================
--- clang/lib/Parse/ParseTemplate.cpp
+++ clang/lib/Parse/ParseTemplate.cpp
@@ -19,6 +19,7 @@
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaDiagnostic.h"
 #include "llvm/Support/TimeProfiler.h"
 using namespace clang;
 
@@ -1007,18 +1008,23 @@
   SourceLocation EqualLoc;
   ExprResult DefaultArg;
   if (TryConsumeToken(tok::equal, EqualLoc)) {
-    // C++ [temp.param]p15:
-    //   When parsing a default template-argument for a non-type
-    //   template-parameter, the first non-nested > is taken as the
-    //   end of the template-parameter-list rather than a greater-than
-    //   operator.
-    GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
-    EnterExpressionEvaluationContext ConstantEvaluated(
-        Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
-
-    DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
-    if (DefaultArg.isInvalid())
+    if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) {
+      Diag(Tok.getLocation(), diag::err_expr_statement_in_default_arg);
       SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
+    } else {
+      // C++ [temp.param]p15:
+      //   When parsing a default template-argument for a non-type
+      //   template-parameter, the first non-nested > is taken as the
+      //   end of the template-parameter-list rather than a greater-than
+      //   operator.
+      GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+      EnterExpressionEvaluationContext ConstantEvaluated(
+          Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+      DefaultArg =
+          Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
+      if (DefaultArg.isInvalid())
+        SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
+    }
   }
 
   // Create the parameter.
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -7066,8 +7066,16 @@
           if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
             Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
             DefArgResult = ParseBraceInitializer();
-          } else
+          } else {
+            if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) {
+              Diag(Tok, diag::err_expr_statement_in_default_arg);
+              Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
+              // Skip the expression statement and continue parsing
+              SkipUntil(tok::comma, StopBeforeMatch);
+              continue;
+            }
             DefArgResult = ParseAssignmentExpression();
+          }
           DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);
           if (DefArgResult.isInvalid()) {
             Actions.ActOnParamDefaultArgumentError(Param, EqualLoc);
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4380,6 +4380,8 @@
 def err_default_arg_makes_ctor_special : Error<
   "addition of default argument on redeclaration makes this constructor a "
   "%select{default|copy|move}0 constructor">;
+def err_expr_statement_in_default_arg : Error<
+  "expression statement not permitted in default argument">;
 
 def err_use_of_default_argument_to_function_declared_later : Error<
   "use of default argument to function %0 that is declared later in class %1">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to