Author: rsmith Date: Sun Aug 14 21:34:23 2016 New Revision: 278648 URL: http://llvm.org/viewvc/llvm-project?rev=278648&view=rev Log: Disable lambda-capture of decomposition declaration bindings for now, until CWG agrees on how they're supposed to work.
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=278648&r1=278647&r2=278648&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun Aug 14 21:34:23 2016 @@ -7046,14 +7046,9 @@ def ext_ms_anonymous_record : ExtWarn< InGroup<MicrosoftAnonTag>; // C++ local classes -def err_reference_to_local_var_in_enclosing_function : Error< - "reference to local variable %0 declared in enclosing function %1">; -def err_reference_to_local_var_in_enclosing_block : Error< - "reference to local variable %0 declared in enclosing block literal">; -def err_reference_to_local_var_in_enclosing_lambda : Error< - "reference to local variable %0 declared in enclosing lambda expression">; -def err_reference_to_local_var_in_enclosing_context : Error< - "reference to local variable %0 declared in enclosing context">; +def err_reference_to_local_in_enclosing_context : Error< + "reference to local %select{variable|binding}1 %0 declared in enclosing " + "%select{%3|block literal|lambda expression|context}2">; def err_static_data_member_not_allowed_in_local_class : Error< "static data member %0 not allowed in local class %1">; Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=278648&r1=278647&r2=278648&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Aug 14 21:34:23 2016 @@ -2838,6 +2838,10 @@ ExprResult Sema::BuildDeclarationNameExp return ULE; } +static void +diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, + ValueDecl *var, DeclContext *DC); + /// \brief Complete semantic analysis for a reference to the given declaration. ExprResult Sema::BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, @@ -2981,7 +2985,12 @@ ExprResult Sema::BuildDeclarationNameExp // These are always lvalues. valueKind = VK_LValue; type = type.getNonReferenceType(); - // FIXME: Adjust cv-qualifiers for capture. + // FIXME: Support lambda-capture of BindingDecls, once CWG actually + // decides how that's supposed to work. + auto *BD = cast<BindingDecl>(VD); + if (BD->getDeclContext()->isFunctionOrMethod() && + BD->getDeclContext() != CurContext) + diagnoseUncapturableValueReference(*this, Loc, BD, CurContext); break; } @@ -13214,7 +13223,7 @@ void Sema::MarkFunctionReferenced(Source static void diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, - VarDecl *var, DeclContext *DC) { + ValueDecl *var, DeclContext *DC) { DeclContext *VarDC = var->getDeclContext(); // If the parameter still belongs to the translation unit, then @@ -13234,25 +13243,21 @@ diagnoseUncapturableValueReference(Sema if (!S.getLangOpts().CPlusPlus && !S.CurContext->isFunctionOrMethod()) return; + unsigned ValueKind = isa<BindingDecl>(var) ? 1 : 0; + unsigned ContextKind = 3; // unknown if (isa<CXXMethodDecl>(VarDC) && cast<CXXRecordDecl>(VarDC->getParent())->isLambda()) { - S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_lambda) - << var->getIdentifier(); - } else if (FunctionDecl *fn = dyn_cast<FunctionDecl>(VarDC)) { - S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function) - << var->getIdentifier() << fn->getDeclName(); + ContextKind = 2; + } else if (isa<FunctionDecl>(VarDC)) { + ContextKind = 0; } else if (isa<BlockDecl>(VarDC)) { - S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_block) - << var->getIdentifier(); - } else { - // FIXME: Is there any other context where a local variable can be - // declared? - S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_context) - << var->getIdentifier(); + ContextKind = 1; } + S.Diag(loc, diag::err_reference_to_local_in_enclosing_context) + << var << ValueKind << ContextKind << VarDC; S.Diag(var->getLocation(), diag::note_entity_declared_at) - << var->getIdentifier(); + << var; // FIXME: Add additional diagnostic info about class etc. which prevents // capture. Modified: cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp?rev=278648&r1=278647&r2=278648&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp Sun Aug 14 21:34:23 2016 @@ -37,4 +37,14 @@ constexpr bool g(S &&s) { } static_assert(g({1, 2})); +void enclosing() { + struct S { int a; }; + auto [n] = S(); // expected-note 2{{'n' declared here}} + + struct Q { int f() { return n; } }; // expected-error {{reference to local binding 'n' declared in enclosing function}} + // FIXME: This is probably supposed to be valid, but we do not have clear rules on how it's supposed to work. + (void) [&] { return n; }; // expected-error {{reference to local binding 'n' declared in enclosing function}} + (void) [n] {}; // expected-error {{'n' in capture list does not name a variable}} +} + // FIXME: by-value array copies _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits