summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaCast.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-07-11 00:19:19 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-07-11 00:19:19 +0000
commit295c88685f7c285358db0d83f1fc315ac23677e3 (patch)
tree054f8c88ea571d0fddb19dcb52bc312451994ba2 /lib/Sema/SemaCast.cpp
parent3c6b78637e54fd4bc2f6413e2f34439b51da65fa (diff)
downloadclang-295c88685f7c285358db0d83f1fc315ac23677e3.tar.gz
DR330: look through array types when forming the cv-decomposition of a type.
This allows more qualification conversions, eg. conversion from 'int *(*)[]' -> 'const int *const (*)[]' is now permitted, along with all the consequences of that: more types are similar, more cases are permitted by const_cast, and conversely, fewer "casting away constness" cases are permitted by reinterpret_cast. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336745 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaCast.cpp')
-rw-r--r--lib/Sema/SemaCast.cpp58
1 files changed, 28 insertions, 30 deletions
diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp
index a2e2950556..ec95032c4e 100644
--- a/lib/Sema/SemaCast.cpp
+++ b/lib/Sema/SemaCast.cpp
@@ -456,12 +456,16 @@ enum CastAwayConstnessKind {
/// Unwrap one level of types for CastsAwayConstness.
///
-/// Like Sema::UnwrapSimilarPointerTypes, this removes one level of
-/// indirection from both types, provided that they're both pointer-like.
-/// Unlike the Sema function, doesn't care if the unwrapped pieces are related.
+/// Like Sema::UnwrapSimilarTypes, this removes one level of indirection from
+/// both types, provided that they're both pointer-like or array-like. Unlike
+/// the Sema function, doesn't care if the unwrapped pieces are related.
static CastAwayConstnessKind
unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) {
- if (Context.UnwrapSimilarPointerTypes(T1, T2))
+ // Note, even if this returns false, it may have unwrapped some number of
+ // matching "array of" pieces. That's OK, we don't need to check their
+ // cv-qualifiers (that check is covered by checking the qualifiers on the
+ // array types themselves).
+ if (Context.UnwrapSimilarTypes(T1, T2))
return CastAwayConstnessKind::CACK_Similar;
// Special case: if the destination type is a reference type, unwrap it as
@@ -473,8 +477,11 @@ unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) {
auto Classify = [](QualType T) {
if (T->isAnyPointerType()) return 1;
- if (T->getAs<MemberPointerType>()) return 2;
- if (T->getAs<BlockPointerType>()) return 3;
+ if (T->isMemberPointerType()) return 2;
+ if (T->isBlockPointerType()) return 3;
+ // We somewhat-arbitrarily don't look through VLA types here. This is at
+ // least consistent with the behavior of UnwrapSimilarTypes.
+ if (T->isConstantArrayType() || T->isIncompleteArrayType()) return 4;
return 0;
};
@@ -486,8 +493,14 @@ unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) {
if (!T2Class)
return CastAwayConstnessKind::CACK_None;
- T1 = T1->getPointeeType();
- T2 = T2->getPointeeType();
+ auto Unwrap = [&](QualType T) {
+ if (auto *AT = Context.getAsArrayType(T))
+ return AT->getElementType();
+ return T->getPointeeType();
+ };
+
+ T1 = Unwrap(T1);
+ T2 = Unwrap(T2);
return T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind
: CastAwayConstnessKind::CACK_Incoherent;
}
@@ -1674,29 +1687,14 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
msg = diag::err_bad_const_cast_dest;
return TC_NotApplicable;
}
- SrcType = Self.Context.getCanonicalType(SrcType);
- // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
- // completely equal.
- // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
- // in multi-level pointers may change, but the level count must be the same,
- // as must be the final pointee type.
- while (SrcType != DestType &&
- Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
- Qualifiers SrcQuals, DestQuals;
- SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals);
- DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals);
-
- // const_cast is permitted to strip cvr-qualifiers, only. Make sure that
- // the other qualifiers (e.g., address spaces) are identical.
- SrcQuals.removeCVRQualifiers();
- DestQuals.removeCVRQualifiers();
- if (SrcQuals != DestQuals)
- return TC_NotApplicable;
- }
-
- // Since we're dealing in canonical types, the remainder must be the same.
- if (SrcType != DestType)
+ // C++ [expr.const.cast]p3:
+ // "For two similar types T1 and T2, [...]"
+ //
+ // We only allow a const_cast to change cvr-qualifiers, not other kinds of
+ // type qualifiers. (Likewise, we ignore other changes when determining
+ // whether a cast casts away constness.)
+ if (!Self.Context.hasCvrSimilarType(SrcType, DestType))
return TC_NotApplicable;
if (NeedToMaterializeTemporary)