summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorJames Y Knight <jyknight@google.com>2018-10-05 21:53:51 +0000
committerJames Y Knight <jyknight@google.com>2018-10-05 21:53:51 +0000
commit49bf370a8b38a9fde6979fb4be71c06c61671014 (patch)
tree61a1477c9fa6354b7f56fd49fe3489ffa102a79f /clang
parentdc97118efe3135cdaa4aa697e9f92ca6ea294fd3 (diff)
downloadbcm5719-llvm-49bf370a8b38a9fde6979fb4be71c06c61671014.tar.gz
bcm5719-llvm-49bf370a8b38a9fde6979fb4be71c06c61671014.zip
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 llvm-svn: 343892
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/AST/ExprConstant.cpp6
-rw-r--r--clang/lib/Sema/SemaExpr.cpp9
-rw-r--r--clang/test/Sema/c-casts.c25
3 files changed, 34 insertions, 6 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8a2cbdc1871..a2e71ea061e 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index cb4b6f18d8e..8144b3a7796 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/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<PointerType>(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/clang/test/Sema/c-casts.c b/clang/test/Sema/c-casts.c
new file mode 100644
index 00000000000..c3a58ed8274
--- /dev/null
+++ b/clang/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 ***' <NoOp>
+ x = p;
+ // CHECK: CStyleCastExpr {{.*}} 'char ***' <NoOp>
+ x = (char***)p;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} cast_pointer_type
+void cast_pointer_type(char *p) {
+ void *x;
+ // CHECK: ImplicitCastExpr {{.*}} 'void *' <BitCast>
+ x = p;
+ // CHECK: CStyleCastExpr {{.*}} 'void *' <BitCast>
+ x = (void*)p;
+}
OpenPOWER on IntegriCloud