[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