[PATCH] D65696: Implements CWG 2082 Referring to parameters in unevaluated operands of default arguments

2021-02-24 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added inline comments.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:143-148
+  /// CheckDefaultArgumentVisitorODR - C++ [dcl.fct.default] Traverses
+  /// the default argument of a parameter to determine whether it
+  /// contains ODR violations. These violations cannot be checked in
+  /// \ref CheckDefaultArgumentVisitor since the DeclRefExp's may be changed to
+  /// an implicit cast from an LValue to RValue by \ref 
SetParamDefaultArgument.
+  /// When that happens the ODR usage may be allowed.

Instead of visiting the default argument twice, can we call 
`SetParamDefaultArgument` first before doing the checks?


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

https://reviews.llvm.org/D65696

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65696: Implements CWG 2082 Referring to parameters in unevaluated operands of default arguments

2019-08-15 Thread Mark de Wever via Phabricator via cfe-commits
Mordante updated this revision to Diff 215448.
Mordante added a comment.

Updated the unit tests as requested. This required the 
`Sema::ActOnParamDefaultArgument` to delay a part of the ODR validation until 
the default argument has been 'instantiated'.
As discussed on IRC; the up to date `cwg_index.html` is not public, so I only 
updated the unit test and removed the changes to `cxx_dr_status.html`.


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

https://reviews.llvm.org/D65696

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p9.cpp
  clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
  clang/test/CXX/drs/dr20xx.cpp

Index: clang/test/CXX/drs/dr20xx.cpp
===
--- clang/test/CXX/drs/dr20xx.cpp
+++ clang/test/CXX/drs/dr20xx.cpp
@@ -8,6 +8,76 @@
 #define static_assert(...) _Static_assert(__VA_ARGS__)
 #endif
 
+
+namespace dr2082 { // dr2082: 10
+namespace local_var {
+void g() {
+  int k = 42;
+  void l(int m = k); // expected-error {{default argument references local variable 'k' of enclosing function}}
+}
+} // namespace local_var
+namespace local_const {
+void g() {
+  const int k = 42;
+  void l(int m = k);
+}
+} // namespace local_const
+#if __cplusplus >= 201103L
+namespace local_constexpr {
+void g() {
+  constexpr int k = 42;
+  void l(int m = k);
+}
+} // namespace local_constexpr
+#endif
+
+namespace local_const_float_to_integral {
+void g() {
+  const double k = 42;
+  void l(int m = k); // expected-error {{default argument references local variable 'k' of enclosing function}}
+}
+} // namespace local_const_float_to_integral
+#if __cplusplus >= 201103L
+namespace local_constexpr_float_to_integral {
+void g() {
+  constexpr double k = 42;
+  void l(int m = k);
+}
+} // namespace local_constexpr_float_to_integral
+
+namespace local_member_const {
+struct a {
+  int b;
+  int c;
+};
+void g() {
+  const a n{42, 42};
+  void l(int m = n.b); // expected-error {{default argument references local variable 'n' of enclosing function}}
+}
+} // namespace local_member_const
+namespace local_member_constexpr {
+struct a {
+  int b;
+  int c;
+};
+void g() {
+  constexpr a n{42, 42};
+  void l(int m = n.b);
+}
+} // namespace local_member_constexpr
+namespace local_member_mutable {
+struct a {
+  int b;
+  mutable int c;
+};
+void g() {
+  constexpr a n{42, 42};
+  void l(int m = n.b); // expected-error {{default argument references local variable 'n' of enclosing function}}
+}
+} // namespace local_member_mutable
+#endif
+}
+
 namespace dr2083 { // dr2083: partial
 #if __cplusplus >= 201103L
   void non_const_mem_ptr() {
Index: clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
===
--- clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
+++ clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-void h()
+void f()
 {
   int i;
-  extern void h2(int x = sizeof(i)); // expected-error {{default argument references local variable 'i' of enclosing function}}
+  extern void g(int x = i); // expected-error {{default argument references local variable 'i' of enclosing function}}
+  extern void h(int x = sizeof(i));
 }
Index: clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p9.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p9.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int a;
+int f(int a, int b = a); // expected-error {{default argument references parameter 'a'}}
+typedef int I;
+int g(float I, int b = I(2)); // expected-error {{called object type 'float' is not a function or function pointer}}
+int h(int a, int b = sizeof(a));
+
+int b;
+class X {
+  int a;
+  int mem1(int i = a); // expected-error {{invalid use of non-static data member 'a'}}
+  int mem2(int i = b);
+  static int b;
+};
+
+int f(int = 0);
+void h() {
+  int j = f(1);
+  int k = f();
+}
+int (*p1)(int) = 
+int (*p2)() =  // expected-error {{cannot initialize a variable of type 'int (*)()' with an rvalue of type 'int (*)(int)': different number of parameters (0 vs 1)}}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -86,29 +86,22 @@
 NamedDecl *Decl = DRE->getDecl();
 if (ParmVarDecl *Param = dyn_cast(Decl)) {
   // C++ [dcl.fct.default]p9
-  //   Default arguments are evaluated each time the function is
-  //   called. The order of evaluation of function arguments is
-  //   unspecified. Consequently, parameters of a function shall not
-  //   be used in default argument expressions, even if they are not
-  //   evaluated. Parameters of a function declared before a default
-

[PATCH] D65696: Implements CWG 2082 Referring to parameters in unevaluated operands of default arguments

2019-08-04 Thread Mark de Wever via Phabricator via cfe-commits
Mordante marked 2 inline comments as done.
Mordante added inline comments.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:103-105
+  //   A local variable cannot be odr-used (6.2) in a default argument.
+  if (DRE->isNonOdrUse() != NOUR_None)
+return false;

rsmith wrote:
> Please add tests for the distinction between "potentially-evaluated" and 
> "odr-used" here, for example:
> 
> ```
> void f() {
>   const int n = 123;
>   void g(int k = n); // ok, not an odr-use
> }
> ```
I added the test but unfortunately clang disagrees with you and considers `n` 
ODR used. 
I'll have look how to teach clang `n` is not ODR used.



Comment at: clang/www/cxx_dr_status.html:3
   "http://www.w3.org/TR/html4/strict.dtd;>
 
 

rsmith wrote:
> Note that this is an auto-generated file. To update it, you need to add a 
> test to the relevant file (`test/CXX/drs/dr20xx.cpp`) with a suitable comment 
> (`// dr2082: 10` to mark this implemented in Clang 10), grab a recent 
> `cwg_index.html` file, and run the `make_cxx_dr_status` script.
Thanks for the info, I'll have a look at it after I fix the ODR used part.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65696



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65696: Implements CWG 2082 Referring to parameters in unevaluated operands of default arguments

2019-08-03 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added inline comments.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:103-105
+  //   A local variable cannot be odr-used (6.2) in a default argument.
+  if (DRE->isNonOdrUse() != NOUR_None)
+return false;

Please add tests for the distinction between "potentially-evaluated" and 
"odr-used" here, for example:

```
void f() {
  const int n = 123;
  void g(int k = n); // ok, not an odr-use
}
```



Comment at: clang/www/cxx_dr_status.html:3
   "http://www.w3.org/TR/html4/strict.dtd;>
 
 

Note that this is an auto-generated file. To update it, you need to add a test 
to the relevant file (`test/CXX/drs/dr20xx.cpp`) with a suitable comment (`// 
dr2082: 10` to mark this implemented in Clang 10), grab a recent 
`cwg_index.html` file, and run the `make_cxx_dr_status` script.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65696



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D65696: Implements CWG 2082 Referring to parameters in unevaluated operands of default arguments

2019-08-03 Thread Mark de Wever via Phabricator via cfe-commits
Mordante created this revision.
Mordante added a reviewer: rsmith.
Mordante added a project: clang.

This implements the current standard wording for [dcl.fct.default]p9 and 
[dcl.fct.default]p7. This has been changed by CWG 2082.

  

Note: I don't have access to the paper therefore I assume it retroactively 
applies to all C++ standards.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D65696

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p9.cpp
  clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
  clang/www/cxx_dr_status.html


Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -12307,7 +12307,7 @@
 http://wg21.link/cwg2082;>2082
 CD4
 Referring to parameters in unevaluated operands of default 
arguments
-Unknown
+SVN
   
   
 http://wg21.link/cwg2083;>2083
Index: clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
===
--- clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
+++ clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
@@ -1,7 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
-void h()
+void f()
 {
   int i;
-  extern void h2(int x = sizeof(i)); // expected-error {{default argument 
references local variable 'i' of enclosing function}}
+  extern void g(int x = i); // expected-error {{default argument references 
local variable 'i' of enclosing function}}
+  extern void h(int x = sizeof(i));
 }
Index: clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p9.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p9.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+int a;
+int f(int a, int b = a); // expected-error {{default argument references 
parameter 'a'}}
+typedef int I;
+int g(float I, int b = I(2)); // expected-error {{called object type 'float' 
is not a function or function pointer}}
+int h(int a, int b = sizeof(a));
+
+int b;
+class X {
+  int a;
+  int mem1(int i = a); // expected-error {{invalid use of non-static data 
member 'a'}}
+  int mem2(int i = b);
+  static int b;
+};
+
+int f(int = 0);
+void h() {
+  int j = f(1);
+  int k = f();
+}
+int (*p1)(int) = 
+int (*p2)() =  // expected-error {{cannot initialize a variable of type 
'int (*)()' with an rvalue of type 'int (*)(int)': different number of 
parameters (0 vs 1)}}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -86,20 +86,24 @@
 NamedDecl *Decl = DRE->getDecl();
 if (ParmVarDecl *Param = dyn_cast(Decl)) {
   // C++ [dcl.fct.default]p9
-  //   Default arguments are evaluated each time the function is
-  //   called. The order of evaluation of function arguments is
-  //   unspecified. Consequently, parameters of a function shall not
-  //   be used in default argument expressions, even if they are not
-  //   evaluated. Parameters of a function declared before a default
-  //   argument expression are in scope and can hide namespace and
-  //   class member names.
+  //   A default argument is evaluated each time the function is called
+  //   with no argument for the corresponding parameter. A parameter shall
+  //   not appear as a potentially-evaluated expression in a default
+  //   argument. Parameters of a function declared before a default
+  //   argument are in scope and can hide namespace and class member
+  //   names.
+  if (DRE->isNonOdrUse() == NOUR_Unevaluated)
+return false;
+
   return S->Diag(DRE->getBeginLoc(),
  diag::err_param_default_argument_references_param)
  << Param->getDeclName() << DefaultArg->getSourceRange();
 } else if (VarDecl *VDecl = dyn_cast(Decl)) {
   // C++ [dcl.fct.default]p7
-  //   Local variables shall not be used in default argument
-  //   expressions.
+  //   A local variable cannot be odr-used (6.2) in a default argument.
+  if (DRE->isNonOdrUse() != NOUR_None)
+return false;
+
   if (VDecl->isLocalVarDecl())
 return S->Diag(DRE->getBeginLoc(),
diag::err_param_default_argument_references_local)


Index: clang/www/cxx_dr_status.html
===
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -12307,7 +12307,7 @@
 http://wg21.link/cwg2082;>2082
 CD4
 Referring to parameters in unevaluated operands of default arguments
-Unknown
+SVN
   
   
 http://wg21.link/cwg2083;>2083
Index: clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp