[PATCH] D65696: Implements CWG 2082 Referring to parameters in unevaluated operands of default arguments
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
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
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
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
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