From: James Y Knight Date: Fri, 5 Oct 2018 21:53:51 +0000 (+0000) Subject: Emit CK_NoOp casts in C mode, not just C++. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e9572058168186802774ab6338031fec098f6c38;p=clang Emit CK_NoOp casts in C mode, not just C++. Previously, it had been using CK_BitCast even for casts that only change const/restrict/volatile. Now it will use CK_Noop where appropriate. This is an alternate solution to r336746. Differential Revision: https://reviews.llvm.org/D52918 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@343892 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 8a2cbdc187..a2e71ea061 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -5864,11 +5864,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { - // If we changed anything other than cvr-qualifiers, we can't use this - // value for constant folding. FIXME: Qualification conversions should - // always be CK_NoOp, but we get this wrong in C. - if (!Info.Ctx.hasCvrSimilarType(E->getType(), E->getSubExpr()->getType())) - Result.Designator.setInvalid(); + Result.Designator.setInvalid(); if (SubExpr->getType()->isVoidPointerType()) CCEDiag(E, diag::note_constexpr_invalid_cast) << 3 << SubExpr->getType(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index cb4b6f18d8..8144b3a779 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5862,6 +5862,8 @@ CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { LangAS DestAS = DestTy->getPointeeType().getAddressSpace(); if (SrcAS != DestAS) return CK_AddressSpaceConversion; + if (Context.hasCvrSimilarType(SrcTy, DestTy)) + return CK_NoOp; return CK_BitCast; } case Type::STK_BlockPointer: @@ -7762,7 +7764,12 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, if (isa(RHSType)) { LangAS AddrSpaceL = LHSPointer->getPointeeType().getAddressSpace(); LangAS AddrSpaceR = RHSType->getPointeeType().getAddressSpace(); - Kind = AddrSpaceL != AddrSpaceR ? CK_AddressSpaceConversion : CK_BitCast; + if (AddrSpaceL != AddrSpaceR) + Kind = CK_AddressSpaceConversion; + else if (Context.hasCvrSimilarType(RHSType, LHSType)) + Kind = CK_NoOp; + else + Kind = CK_BitCast; return checkPointerTypesForAssignment(*this, LHSType, RHSType); } diff --git a/test/Sema/c-casts.c b/test/Sema/c-casts.c new file mode 100644 index 0000000000..c3a58ed827 --- /dev/null +++ b/test/Sema/c-casts.c @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -w -ast-dump %s | FileCheck %s + +// The cast construction code both for implicit and c-style casts is very +// different in C vs C++. This file is intended to test the C behavior. + +// TODO: add tests covering the rest of the code in +// Sema::CheckAssignmentConstraints and Sema::PrepareScalarCast + +// CHECK-LABEL: FunctionDecl {{.*}} cast_cvr_pointer +void cast_cvr_pointer(char volatile * __restrict * const * p) { + char*** x; + // CHECK: ImplicitCastExpr {{.*}} 'char ***' + x = p; + // CHECK: CStyleCastExpr {{.*}} 'char ***' + x = (char***)p; +} + +// CHECK-LABEL: FunctionDecl {{.*}} cast_pointer_type +void cast_pointer_type(char *p) { + void *x; + // CHECK: ImplicitCastExpr {{.*}} 'void *' + x = p; + // CHECK: CStyleCastExpr {{.*}} 'void *' + x = (void*)p; +}