/// CastsAwayConstness - Check if the pointer conversion from SrcType to /// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by /// the cast checkers. Both arguments must denote pointer (possibly to member) /// types. bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { // Casting away constness is defined in C++ 5.2.11p8 with reference to // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since // the rules are non-trivial. So first we construct Tcv *...cv* as described // in C++ 5.2.11p8. assert((SrcType->isPointerType() || SrcType->isMemberPointerType()) && "Source type is not pointer or pointer to member."); assert((DestType->isPointerType() || DestType->isMemberPointerType()) && "Destination type is not pointer or pointer to member."); QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType; llvm::SmallVector<unsigned, 8> cv1, cv2; // Find the qualifications. while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { cv1.push_back(UnwrappedSrcType.getCVRQualifiers()); cv2.push_back(UnwrappedDestType.getCVRQualifiers()); } assert(cv1.size() > 0 && "Must have at least one pointer level."); // Construct void pointers with those qualifiers (in reverse order of // unwrapping, of course). QualType SrcConstruct = Self.Context.VoidTy; QualType DestConstruct = Self.Context.VoidTy; for (llvm::SmallVector<unsigned, 8>::reverse_iterator i1 = cv1.rbegin(), i2 = cv2.rbegin(); i1 != cv1.rend(); ++i1, ++i2) { SrcConstruct = Self.Context.getPointerType( SrcConstruct.getQualifiedType(*i1)); DestConstruct = Self.Context.getPointerType( DestConstruct.getQualifiedType(*i2)); } // Test if they're compatible. return SrcConstruct != DestConstruct && !Self.IsQualificationConversion(SrcConstruct, DestConstruct); }