riccibruno updated this revision to Diff 284718. Repository: rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D85613/new/ https://reviews.llvm.org/D85613 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
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,5 +1,20 @@ // RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s +namespace std { +using size_t = decltype(sizeof(int)); +template <typename> struct tuple_size; +template <size_t, typename> struct tuple_element; +} // namespace std +using size_t = std::size_t; + +struct E {}; +template <size_t> int get(E); + +namespace std { +template <> struct tuple_size<E> { static constexpr size_t value = 2; }; +template <size_t I> struct tuple_element<I, E> { using type = int; }; +}; // namespace std + void h() { int i1 = 0; extern void h1(int x = i1); @@ -24,8 +39,19 @@ extern void h6(int = i5); // expected-error@-1 {{default argument references local variable '' of enclosing function}} - struct S { int i; }; - auto [x] = S(); + struct S { + int i, j; + }; + auto [x, y] = S(); + + extern void h7(int = x); // expected-error {{default argument references local binding 'x'}} + + auto [z, w] = E(); + extern void h8a(int = sizeof(z)); // ok + extern void h8b(int = w); // expected-error {{default argument references local binding 'w'}} - extern void h7(int = x); // FIXME: reject + extern auto get_array()->int(&)[2]; + auto [a0, a1] = get_array(); + extern void h9a(int = sizeof(a0)); + extern void h9b(int = a1); // expected-error {{default argument references local binding 'a1'}} } Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -86,6 +86,20 @@ /// argument expression. bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(const DeclRefExpr *DRE) { const NamedDecl *Decl = DRE->getDecl(); + + auto DiagnoseIfOdrUse = [&](const VarDecl *VD, unsigned DiagID, + const auto &... DiagArgs) -> bool { + if (!DRE->isNonOdrUse()) { + auto DB = S.Diag(DRE->getBeginLoc(), DiagID); + int dummy[] = {0, (DB << DiagArgs, 0)...}; + (void)dummy; + DB << DefaultArg->getSourceRange(); + return true; + } + + return false; + }; + if (const auto *Param = dyn_cast<ParmVarDecl>(Decl)) { // C++ [dcl.fct.default]p9: // [...] parameters of a function shall not be used in default @@ -111,10 +125,29 @@ // C++20 [dcl.fct.default]p7 (DR as part of P0588R1, see also CWG 2346): // Note: A local variable cannot be odr-used (6.3) in a default argument. // - if (VDecl->isLocalVarDecl() && !DRE->isNonOdrUse()) - return S.Diag(DRE->getBeginLoc(), - diag::err_param_default_argument_references_local) - << VDecl->getDeclName() << DefaultArg->getSourceRange(); + if (VDecl->isLocalVarDecl() && + DiagnoseIfOdrUse(VDecl, + diag::err_param_default_argument_references_local, + /*variable*/ 0, VDecl)) + return true; + + } else if (const auto *Binding = dyn_cast<BindingDecl>(Decl)) { + // C++20 [basic.pre]p7: + // A local entity is [...] a structured binding whose corresponding + // variable is such an entity [...] + // + // C++20 [basic.def.odr]p9: + // A local entity (6.1) is odr-usable in a declarative region if [...] + // + // Note that this was not entirely clear in C++17 since [dcl.fct.default]p7 + // only prohibited local variables (a structured binding declaration + // introduces identifiers as names). + // + const auto *VD = cast<VarDecl>(Binding->getDecomposedDecl()); + if (VD->isLocalVarDecl() && + DiagnoseIfOdrUse(VD, diag::err_param_default_argument_references_local, + /*binding*/ 1, Binding)) + return true; } return false; Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3994,7 +3994,8 @@ def err_param_default_argument_references_param : Error< "default argument references parameter %0">; def err_param_default_argument_references_local : Error< - "default argument references local variable %0 of enclosing function">; + "default argument references local %select{variable|binding}0 %1 " + "of enclosing function">; def err_param_default_argument_references_this : Error< "default argument references 'this'">; def err_param_default_argument_nonfunc : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits