[cfe-commits] r152593 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/Basic/DiagnosticSemaKinds.td lib/AST/ExprClassification.cpp lib/Sema/SemaExpr.cpp test/SemaCXX/lambda-expressions.cpp
Richard Smith
richard at metafoo.co.uk
Mon Mar 12 17:52:40 PDT 2012
On Mon, Mar 12, 2012 at 5:37 PM, John McCall <rjmccall at apple.com> wrote:
> Author: rjmccall
> Date: Mon Mar 12 19:37:01 2012
> New Revision: 152593
>
> URL: http://llvm.org/viewvc/llvm-project?rev=152593&view=rev
> Log:
> Alternate fix to PR12248: put Sema in charge of special-casing
> the diagnostic for assigning to a copied block capture. This has
> the pleasant side-effect of letting us special-case the diagnostic
> for assigning to a copied lambda capture as well, without introducing
> a new non-modifiable enumerator for it.
>
> Modified:
> cfe/trunk/include/clang/AST/Expr.h
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/lib/AST/ExprClassification.cpp
> cfe/trunk/lib/Sema/SemaExpr.cpp
> cfe/trunk/test/SemaCXX/lambda-expressions.cpp
>
> Modified: cfe/trunk/include/clang/AST/Expr.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=152593&r1=152592&r2=152593&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Expr.h (original)
> +++ cfe/trunk/include/clang/AST/Expr.h Mon Mar 12 19:37:01 2012
> @@ -236,7 +236,6 @@
> MLV_IncompleteType,
> MLV_ConstQualified,
> MLV_ArrayType,
> - MLV_NotBlockQualified,
> MLV_ReadonlyProperty,
> MLV_NoSetterProperty,
> MLV_MemberFunction,
> @@ -272,7 +271,6 @@
> CM_RValue, // Not modifiable because it's an rvalue
> CM_Function, // Not modifiable because it's a function; C++ only
> CM_LValueCast, // Same as CM_RValue, but indicates GCC
> cast-as-lvalue ext
> - CM_NotBlockQualified, // Not captured in the closure
> CM_NoSetterProperty,// Implicit assignment to ObjC property without
> setter
> CM_ConstQualified,
> CM_ArrayType,
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=152593&r1=152592&r2=152593&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Mar 12
> 19:37:01 2012
> @@ -4387,6 +4387,8 @@
> "vector is not assignable (contains duplicate components)">;
> def err_block_decl_ref_not_modifiable_lvalue : Error<
> "variable is not assignable (missing __block type specifier)">;
> +def err_lambda_decl_ref_not_modifiable_lvalue : Error<
> + "variable is not assignable (captured by copy)">;
> def err_typecheck_call_not_function : Error<
> "called object type %0 is not a function or function pointer">;
> def err_call_incomplete_return : Error<
>
> Modified: cfe/trunk/lib/AST/ExprClassification.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=152593&r1=152592&r2=152593&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/AST/ExprClassification.cpp (original)
> +++ cfe/trunk/lib/AST/ExprClassification.cpp Mon Mar 12 19:37:01 2012
> @@ -567,18 +567,8 @@
>
> CanQualType CT = Ctx.getCanonicalType(E->getType());
> // Const stuff is obviously not modifiable.
> - if (CT.isConstQualified()) {
> - // Special-case variables captured by blocks to get an improved
> - // diagnostic.
> - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
> - if (DRE->refersToEnclosingLocal() &&
> - isa<VarDecl>(DRE->getDecl()) &&
> - cast<VarDecl>(DRE->getDecl())->hasLocalStorage() &&
> - !DRE->getDecl()->hasAttr<BlocksAttr>())
> - return Cl::CM_NotBlockQualified;
> - }
> + if (CT.isConstQualified())
> return Cl::CM_ConstQualified;
> - }
>
> // Arrays are not modifiable, only their elements are.
> if (CT->isArrayType())
> @@ -645,7 +635,6 @@
> case Cl::CM_Function: return MLV_NotObjectType;
> case Cl::CM_LValueCast:
> llvm_unreachable("CM_LValueCast and CL_LValue don't match");
> - case Cl::CM_NotBlockQualified: return MLV_NotBlockQualified;
> case Cl::CM_NoSetterProperty: return MLV_NoSetterProperty;
> case Cl::CM_ConstQualified: return MLV_ConstQualified;
> case Cl::CM_ArrayType: return MLV_ArrayType;
>
> Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=152593&r1=152592&r2=152593&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Mar 12 19:37:01 2012
> @@ -7127,6 +7127,32 @@
> return Base->getMethodDecl() != 0;
> }
>
> +/// Is the given expression (which must be 'const') a reference to a
> +/// variable which was originally non-const, but which has become
> +/// 'const' due to being captured within a block?
> +enum NonConstCaptureKind { NCCK_None, NCCK_Block, NCCK_Lambda };
> +static NonConstCaptureKind isReferenceToNonConstCapture(Sema &S, Expr *E)
> {
> + assert(E->isLValue() && E->getType().isConstQualified());
> + E = E->IgnoreParens();
> +
> + // Must be a reference to a declaration from an enclosing scope.
> + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
> + if (!DRE) return NCCK_None;
> + if (!DRE->refersToEnclosingLocal()) return NCCK_None;
> +
> + // The declaration must be a variable which is not declared 'const'.
> + VarDecl *var = dyn_cast<VarDecl>(DRE->getDecl());
> + if (!var) return NCCK_None;
> + if (var->getType().isConstQualified()) return NCCK_None;
> + assert(var->hasLocalStorage() && "capture added 'const' to non-local?");
> +
> + // Decide whether the first capture was for a block or a lambda.
> + DeclContext *DC = S.CurContext;
> + while (DC->getParent() != var->getDeclContext())
> + DC = DC->getParent();
> + return (isa<BlockDecl>(DC) ? NCCK_Block : NCCK_Lambda);
> +}
> +
> /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If
> not,
> /// emit an error and return true. If so, return false.
> static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema
> &S) {
> @@ -7148,6 +7174,16 @@
> case Expr::MLV_ConstQualified:
> Diag = diag::err_typecheck_assign_const;
>
> + // Use a specialized diagnostic when we're assigning to an object
> + // from an enclosing function or block.
> + if (NonConstCaptureKind NCCK = isReferenceToNonConstCapture(S, E)) {
> + if (NCCK == NCCK_Block)
> + Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
> + else
> + Diag = diag::err_lambda_decl_ref_not_modifiable_lvalue;
> + break;
> + }
> +
> // In ARC, use some specialized diagnostics for occasions where we
> // infer 'const'. These are always pseudo-strong variables.
> if (S.getLangOpts().ObjCAutoRefCount) {
> @@ -7210,9 +7246,6 @@
> case Expr::MLV_DuplicateVectorComponents:
> Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue;
> break;
> - case Expr::MLV_NotBlockQualified:
> - Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
> - break;
> case Expr::MLV_ReadonlyProperty:
> case Expr::MLV_NoSetterProperty:
> llvm_unreachable("readonly properties should be processed
> differently");
>
> Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=152593&r1=152592&r2=152593&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original)
> +++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Mon Mar 12 19:37:01 2012
> @@ -139,3 +139,12 @@
> unsigned int result = 0;
> auto l = [&]() { ++result; };
> }
> +
> +namespace ModifyingCapture {
> + void test() {
> + int n = 0;
> + [=] {
> + n = 1; // expected-error {{variable is not assignable (captured by
> copy)}}
>
It would be great if this diagnostic mentioned that the lambda is not
marked as 'mutable'.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120312/6fb8ad64/attachment.html>
More information about the cfe-commits
mailing list