10b57cec5SDimitry Andric //===--- SemaCast.cpp - Semantic Analysis for Casts -----------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements semantic analysis for cast expressions, including 100b57cec5SDimitry Andric // 1) C-style casts like '(int) x' 110b57cec5SDimitry Andric // 2) C++ functional casts like 'int(x)' 120b57cec5SDimitry Andric // 3) C++ named casts like 'static_cast<int>(x)' 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 17fe6060f1SDimitry Andric #include "clang/AST/ASTStructuralEquivalence.h" 180b57cec5SDimitry Andric #include "clang/AST/CXXInheritance.h" 190b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h" 200b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 210b57cec5SDimitry Andric #include "clang/AST/RecordLayout.h" 220b57cec5SDimitry Andric #include "clang/Basic/PartialDiagnostic.h" 230b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 240b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h" 250b57cec5SDimitry Andric #include "clang/Sema/Initialization.h" 26fe6060f1SDimitry Andric #include "clang/Sema/SemaInternal.h" 27*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h" 28*0fca6ea1SDimitry Andric #include "clang/Sema/SemaRISCV.h" 290b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 3006c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 310b57cec5SDimitry Andric #include <set> 320b57cec5SDimitry Andric using namespace clang; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric enum TryCastResult { 370b57cec5SDimitry Andric TC_NotApplicable, ///< The cast method is not applicable. 380b57cec5SDimitry Andric TC_Success, ///< The cast method is appropriate and successful. 390b57cec5SDimitry Andric TC_Extension, ///< The cast method is appropriate and accepted as a 400b57cec5SDimitry Andric ///< language extension. 410b57cec5SDimitry Andric TC_Failed ///< The cast method is appropriate, but failed. A 420b57cec5SDimitry Andric ///< diagnostic has been emitted. 430b57cec5SDimitry Andric }; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric static bool isValidCast(TryCastResult TCR) { 460b57cec5SDimitry Andric return TCR == TC_Success || TCR == TC_Extension; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric enum CastType { 500b57cec5SDimitry Andric CT_Const, ///< const_cast 510b57cec5SDimitry Andric CT_Static, ///< static_cast 520b57cec5SDimitry Andric CT_Reinterpret, ///< reinterpret_cast 530b57cec5SDimitry Andric CT_Dynamic, ///< dynamic_cast 540b57cec5SDimitry Andric CT_CStyle, ///< (Type)expr 555ffd83dbSDimitry Andric CT_Functional, ///< Type(expr) 565ffd83dbSDimitry Andric CT_Addrspace ///< addrspace_cast 570b57cec5SDimitry Andric }; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric namespace { 600b57cec5SDimitry Andric struct CastOperation { 610b57cec5SDimitry Andric CastOperation(Sema &S, QualType destType, ExprResult src) 620b57cec5SDimitry Andric : Self(S), SrcExpr(src), DestType(destType), 630b57cec5SDimitry Andric ResultType(destType.getNonLValueExprType(S.Context)), 640b57cec5SDimitry Andric ValueKind(Expr::getValueKindForType(destType)), 650b57cec5SDimitry Andric Kind(CK_Dependent), IsARCUnbridgedCast(false) { 660b57cec5SDimitry Andric 67fe6060f1SDimitry Andric // C++ [expr.type]/8.2.2: 68fe6060f1SDimitry Andric // If a pr-value initially has the type cv-T, where T is a 69fe6060f1SDimitry Andric // cv-unqualified non-class, non-array type, the type of the 70fe6060f1SDimitry Andric // expression is adjusted to T prior to any further analysis. 715f757f3fSDimitry Andric // C23 6.5.4p6: 7206c3fb27SDimitry Andric // Preceding an expression by a parenthesized type name converts the 7306c3fb27SDimitry Andric // value of the expression to the unqualified, non-atomic version of 7406c3fb27SDimitry Andric // the named type. 75fe6060f1SDimitry Andric if (!S.Context.getLangOpts().ObjC && !DestType->isRecordType() && 76fe6060f1SDimitry Andric !DestType->isArrayType()) { 7706c3fb27SDimitry Andric DestType = DestType.getAtomicUnqualifiedType(); 78fe6060f1SDimitry Andric } 79fe6060f1SDimitry Andric 800b57cec5SDimitry Andric if (const BuiltinType *placeholder = 810b57cec5SDimitry Andric src.get()->getType()->getAsPlaceholderType()) { 820b57cec5SDimitry Andric PlaceholderKind = placeholder->getKind(); 830b57cec5SDimitry Andric } else { 840b57cec5SDimitry Andric PlaceholderKind = (BuiltinType::Kind) 0; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric Sema &Self; 890b57cec5SDimitry Andric ExprResult SrcExpr; 900b57cec5SDimitry Andric QualType DestType; 910b57cec5SDimitry Andric QualType ResultType; 920b57cec5SDimitry Andric ExprValueKind ValueKind; 930b57cec5SDimitry Andric CastKind Kind; 940b57cec5SDimitry Andric BuiltinType::Kind PlaceholderKind; 950b57cec5SDimitry Andric CXXCastPath BasePath; 960b57cec5SDimitry Andric bool IsARCUnbridgedCast; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric SourceRange OpRange; 990b57cec5SDimitry Andric SourceRange DestRange; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric // Top-level semantics-checking routines. 1020b57cec5SDimitry Andric void CheckConstCast(); 1030b57cec5SDimitry Andric void CheckReinterpretCast(); 1040b57cec5SDimitry Andric void CheckStaticCast(); 1050b57cec5SDimitry Andric void CheckDynamicCast(); 1060b57cec5SDimitry Andric void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization); 1070b57cec5SDimitry Andric void CheckCStyleCast(); 1080b57cec5SDimitry Andric void CheckBuiltinBitCast(); 1095ffd83dbSDimitry Andric void CheckAddrspaceCast(); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric void updatePartOfExplicitCastFlags(CastExpr *CE) { 1120b57cec5SDimitry Andric // Walk down from the CE to the OrigSrcExpr, and mark all immediate 1130b57cec5SDimitry Andric // ImplicitCastExpr's as being part of ExplicitCastExpr. The original CE 1140b57cec5SDimitry Andric // (which is a ExplicitCastExpr), and the OrigSrcExpr are not touched. 1150b57cec5SDimitry Andric for (; auto *ICE = dyn_cast<ImplicitCastExpr>(CE->getSubExpr()); CE = ICE) 1160b57cec5SDimitry Andric ICE->setIsPartOfExplicitCast(true); 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric /// Complete an apparently-successful cast operation that yields 1200b57cec5SDimitry Andric /// the given expression. 1210b57cec5SDimitry Andric ExprResult complete(CastExpr *castExpr) { 1220b57cec5SDimitry Andric // If this is an unbridged cast, wrap the result in an implicit 1230b57cec5SDimitry Andric // cast that yields the unbridged-cast placeholder type. 1240b57cec5SDimitry Andric if (IsARCUnbridgedCast) { 125e8d8bef9SDimitry Andric castExpr = ImplicitCastExpr::Create( 126e8d8bef9SDimitry Andric Self.Context, Self.Context.ARCUnbridgedCastTy, CK_Dependent, 127e8d8bef9SDimitry Andric castExpr, nullptr, castExpr->getValueKind(), 128e8d8bef9SDimitry Andric Self.CurFPFeatureOverrides()); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric updatePartOfExplicitCastFlags(castExpr); 1310b57cec5SDimitry Andric return castExpr; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric // Internal convenience methods. 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric /// Try to handle the given placeholder expression kind. Return 1370b57cec5SDimitry Andric /// true if the source expression has the appropriate placeholder 1380b57cec5SDimitry Andric /// kind. A placeholder can only be claimed once. 1390b57cec5SDimitry Andric bool claimPlaceholder(BuiltinType::Kind K) { 1400b57cec5SDimitry Andric if (PlaceholderKind != K) return false; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric PlaceholderKind = (BuiltinType::Kind) 0; 1430b57cec5SDimitry Andric return true; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric bool isPlaceholder() const { 1470b57cec5SDimitry Andric return PlaceholderKind != 0; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric bool isPlaceholder(BuiltinType::Kind K) const { 1500b57cec5SDimitry Andric return PlaceholderKind == K; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric // Language specific cast restrictions for address spaces. 1540b57cec5SDimitry Andric void checkAddressSpaceCast(QualType SrcType, QualType DestType); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric void checkCastAlign() { 1570b57cec5SDimitry Andric Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 160*0fca6ea1SDimitry Andric void checkObjCConversion(CheckedConversionKind CCK) { 1610b57cec5SDimitry Andric assert(Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()); 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric Expr *src = SrcExpr.get(); 164*0fca6ea1SDimitry Andric if (Self.ObjC().CheckObjCConversion(OpRange, DestType, src, CCK) == 165*0fca6ea1SDimitry Andric SemaObjC::ACR_unbridged) 1660b57cec5SDimitry Andric IsARCUnbridgedCast = true; 1670b57cec5SDimitry Andric SrcExpr = src; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric /// Check for and handle non-overload placeholder expressions. 1710b57cec5SDimitry Andric void checkNonOverloadPlaceholders() { 1720b57cec5SDimitry Andric if (!isPlaceholder() || isPlaceholder(BuiltinType::Overload)) 1730b57cec5SDimitry Andric return; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get()); 1760b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 1770b57cec5SDimitry Andric return; 1780b57cec5SDimitry Andric PlaceholderKind = (BuiltinType::Kind) 0; 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric }; 1815ffd83dbSDimitry Andric 1825ffd83dbSDimitry Andric void CheckNoDeref(Sema &S, const QualType FromType, const QualType ToType, 1835ffd83dbSDimitry Andric SourceLocation OpLoc) { 1845ffd83dbSDimitry Andric if (const auto *PtrType = dyn_cast<PointerType>(FromType)) { 1855ffd83dbSDimitry Andric if (PtrType->getPointeeType()->hasAttr(attr::NoDeref)) { 1865ffd83dbSDimitry Andric if (const auto *DestType = dyn_cast<PointerType>(ToType)) { 1875ffd83dbSDimitry Andric if (!DestType->getPointeeType()->hasAttr(attr::NoDeref)) { 1885ffd83dbSDimitry Andric S.Diag(OpLoc, diag::warn_noderef_to_dereferenceable_pointer); 1895ffd83dbSDimitry Andric } 1905ffd83dbSDimitry Andric } 1915ffd83dbSDimitry Andric } 1925ffd83dbSDimitry Andric } 1935ffd83dbSDimitry Andric } 1945ffd83dbSDimitry Andric 1955ffd83dbSDimitry Andric struct CheckNoDerefRAII { 1965ffd83dbSDimitry Andric CheckNoDerefRAII(CastOperation &Op) : Op(Op) {} 1975ffd83dbSDimitry Andric ~CheckNoDerefRAII() { 1985ffd83dbSDimitry Andric if (!Op.SrcExpr.isInvalid()) 1995ffd83dbSDimitry Andric CheckNoDeref(Op.Self, Op.SrcExpr.get()->getType(), Op.ResultType, 2005ffd83dbSDimitry Andric Op.OpRange.getBegin()); 2015ffd83dbSDimitry Andric } 2025ffd83dbSDimitry Andric 2035ffd83dbSDimitry Andric CastOperation &Op; 2045ffd83dbSDimitry Andric }; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr, 2080b57cec5SDimitry Andric QualType DestType); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric // The Try functions attempt a specific way of casting. If they succeed, they 2110b57cec5SDimitry Andric // return TC_Success. If their way of casting is not appropriate for the given 2120b57cec5SDimitry Andric // arguments, they return TC_NotApplicable and *may* set diag to a diagnostic 2130b57cec5SDimitry Andric // to emit if no other way succeeds. If their way of casting is appropriate but 2140b57cec5SDimitry Andric // fails, they return TC_Failed and *must* set diag; they can set it to 0 if 2150b57cec5SDimitry Andric // they emit a specialized diagnostic. 2160b57cec5SDimitry Andric // All diagnostics returned by these functions must expect the same three 2170b57cec5SDimitry Andric // arguments: 2180b57cec5SDimitry Andric // %0: Cast Type (a value from the CastType enumeration) 2190b57cec5SDimitry Andric // %1: Source Type 2200b57cec5SDimitry Andric // %2: Destination Type 2210b57cec5SDimitry Andric static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, 2220b57cec5SDimitry Andric QualType DestType, bool CStyle, 2230b57cec5SDimitry Andric CastKind &Kind, 2240b57cec5SDimitry Andric CXXCastPath &BasePath, 2250b57cec5SDimitry Andric unsigned &msg); 2260b57cec5SDimitry Andric static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, 2270b57cec5SDimitry Andric QualType DestType, bool CStyle, 2280b57cec5SDimitry Andric SourceRange OpRange, 2290b57cec5SDimitry Andric unsigned &msg, 2300b57cec5SDimitry Andric CastKind &Kind, 2310b57cec5SDimitry Andric CXXCastPath &BasePath); 2320b57cec5SDimitry Andric static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, 2330b57cec5SDimitry Andric QualType DestType, bool CStyle, 2340b57cec5SDimitry Andric SourceRange OpRange, 2350b57cec5SDimitry Andric unsigned &msg, 2360b57cec5SDimitry Andric CastKind &Kind, 2370b57cec5SDimitry Andric CXXCastPath &BasePath); 2380b57cec5SDimitry Andric static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, 2390b57cec5SDimitry Andric CanQualType DestType, bool CStyle, 2400b57cec5SDimitry Andric SourceRange OpRange, 2410b57cec5SDimitry Andric QualType OrigSrcType, 2420b57cec5SDimitry Andric QualType OrigDestType, unsigned &msg, 2430b57cec5SDimitry Andric CastKind &Kind, 2440b57cec5SDimitry Andric CXXCastPath &BasePath); 2450b57cec5SDimitry Andric static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, 2460b57cec5SDimitry Andric QualType SrcType, 2470b57cec5SDimitry Andric QualType DestType,bool CStyle, 2480b57cec5SDimitry Andric SourceRange OpRange, 2490b57cec5SDimitry Andric unsigned &msg, 2500b57cec5SDimitry Andric CastKind &Kind, 2510b57cec5SDimitry Andric CXXCastPath &BasePath); 2520b57cec5SDimitry Andric 253*0fca6ea1SDimitry Andric static TryCastResult 254*0fca6ea1SDimitry Andric TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, 255*0fca6ea1SDimitry Andric CheckedConversionKind CCK, SourceRange OpRange, 256*0fca6ea1SDimitry Andric unsigned &msg, CastKind &Kind, bool ListInitialization); 2570b57cec5SDimitry Andric static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, 258*0fca6ea1SDimitry Andric QualType DestType, CheckedConversionKind CCK, 259*0fca6ea1SDimitry Andric SourceRange OpRange, unsigned &msg, 260*0fca6ea1SDimitry Andric CastKind &Kind, CXXCastPath &BasePath, 2610b57cec5SDimitry Andric bool ListInitialization); 2620b57cec5SDimitry Andric static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, 2630b57cec5SDimitry Andric QualType DestType, bool CStyle, 2640b57cec5SDimitry Andric unsigned &msg); 2650b57cec5SDimitry Andric static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, 2660b57cec5SDimitry Andric QualType DestType, bool CStyle, 2675ffd83dbSDimitry Andric SourceRange OpRange, unsigned &msg, 2680b57cec5SDimitry Andric CastKind &Kind); 2695ffd83dbSDimitry Andric static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr, 2705ffd83dbSDimitry Andric QualType DestType, bool CStyle, 2715ffd83dbSDimitry Andric unsigned &msg, CastKind &Kind); 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric ExprResult 2740b57cec5SDimitry Andric Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, 2750b57cec5SDimitry Andric SourceLocation LAngleBracketLoc, Declarator &D, 2760b57cec5SDimitry Andric SourceLocation RAngleBracketLoc, 2770b57cec5SDimitry Andric SourceLocation LParenLoc, Expr *E, 2780b57cec5SDimitry Andric SourceLocation RParenLoc) { 2790b57cec5SDimitry Andric 2800b57cec5SDimitry Andric assert(!D.isInvalidType()); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric TypeSourceInfo *TInfo = GetTypeForDeclaratorCast(D, E->getType()); 2830b57cec5SDimitry Andric if (D.isInvalidType()) 2840b57cec5SDimitry Andric return ExprError(); 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) { 2870b57cec5SDimitry Andric // Check that there are no default arguments (C++ only). 2880b57cec5SDimitry Andric CheckExtraCXXDefaultArguments(D); 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric return BuildCXXNamedCast(OpLoc, Kind, TInfo, E, 2920b57cec5SDimitry Andric SourceRange(LAngleBracketLoc, RAngleBracketLoc), 2930b57cec5SDimitry Andric SourceRange(LParenLoc, RParenLoc)); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric ExprResult 2970b57cec5SDimitry Andric Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, 2980b57cec5SDimitry Andric TypeSourceInfo *DestTInfo, Expr *E, 2990b57cec5SDimitry Andric SourceRange AngleBrackets, SourceRange Parens) { 3000b57cec5SDimitry Andric ExprResult Ex = E; 3010b57cec5SDimitry Andric QualType DestType = DestTInfo->getType(); 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric // If the type is dependent, we won't do the semantic analysis now. 3040b57cec5SDimitry Andric bool TypeDependent = 3050b57cec5SDimitry Andric DestType->isDependentType() || Ex.get()->isTypeDependent(); 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric CastOperation Op(*this, DestType, E); 3080b57cec5SDimitry Andric Op.OpRange = SourceRange(OpLoc, Parens.getEnd()); 3090b57cec5SDimitry Andric Op.DestRange = AngleBrackets; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric switch (Kind) { 3120b57cec5SDimitry Andric default: llvm_unreachable("Unknown C++ cast!"); 3130b57cec5SDimitry Andric 3145ffd83dbSDimitry Andric case tok::kw_addrspace_cast: 3155ffd83dbSDimitry Andric if (!TypeDependent) { 3165ffd83dbSDimitry Andric Op.CheckAddrspaceCast(); 3175ffd83dbSDimitry Andric if (Op.SrcExpr.isInvalid()) 3185ffd83dbSDimitry Andric return ExprError(); 3195ffd83dbSDimitry Andric } 3205ffd83dbSDimitry Andric return Op.complete(CXXAddrspaceCastExpr::Create( 3215ffd83dbSDimitry Andric Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(), 3225ffd83dbSDimitry Andric DestTInfo, OpLoc, Parens.getEnd(), AngleBrackets)); 3235ffd83dbSDimitry Andric 3240b57cec5SDimitry Andric case tok::kw_const_cast: 3250b57cec5SDimitry Andric if (!TypeDependent) { 3260b57cec5SDimitry Andric Op.CheckConstCast(); 3270b57cec5SDimitry Andric if (Op.SrcExpr.isInvalid()) 3280b57cec5SDimitry Andric return ExprError(); 3290b57cec5SDimitry Andric DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType, 3320b57cec5SDimitry Andric Op.ValueKind, Op.SrcExpr.get(), DestTInfo, 3330b57cec5SDimitry Andric OpLoc, Parens.getEnd(), 3340b57cec5SDimitry Andric AngleBrackets)); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric case tok::kw_dynamic_cast: { 3370b57cec5SDimitry Andric // dynamic_cast is not supported in C++ for OpenCL. 3380b57cec5SDimitry Andric if (getLangOpts().OpenCLCPlusPlus) { 3390b57cec5SDimitry Andric return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported) 3400b57cec5SDimitry Andric << "dynamic_cast"); 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric if (!TypeDependent) { 3440b57cec5SDimitry Andric Op.CheckDynamicCast(); 3450b57cec5SDimitry Andric if (Op.SrcExpr.isInvalid()) 3460b57cec5SDimitry Andric return ExprError(); 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType, 3490b57cec5SDimitry Andric Op.ValueKind, Op.Kind, Op.SrcExpr.get(), 3500b57cec5SDimitry Andric &Op.BasePath, DestTInfo, 3510b57cec5SDimitry Andric OpLoc, Parens.getEnd(), 3520b57cec5SDimitry Andric AngleBrackets)); 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric case tok::kw_reinterpret_cast: { 3550b57cec5SDimitry Andric if (!TypeDependent) { 3560b57cec5SDimitry Andric Op.CheckReinterpretCast(); 3570b57cec5SDimitry Andric if (Op.SrcExpr.isInvalid()) 3580b57cec5SDimitry Andric return ExprError(); 3590b57cec5SDimitry Andric DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType, 3620b57cec5SDimitry Andric Op.ValueKind, Op.Kind, Op.SrcExpr.get(), 3630b57cec5SDimitry Andric nullptr, DestTInfo, OpLoc, 3640b57cec5SDimitry Andric Parens.getEnd(), 3650b57cec5SDimitry Andric AngleBrackets)); 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric case tok::kw_static_cast: { 3680b57cec5SDimitry Andric if (!TypeDependent) { 3690b57cec5SDimitry Andric Op.CheckStaticCast(); 3700b57cec5SDimitry Andric if (Op.SrcExpr.isInvalid()) 3710b57cec5SDimitry Andric return ExprError(); 3720b57cec5SDimitry Andric DiscardMisalignedMemberAddress(DestType.getTypePtr(), E); 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 375e8d8bef9SDimitry Andric return Op.complete(CXXStaticCastExpr::Create( 376e8d8bef9SDimitry Andric Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(), 377e8d8bef9SDimitry Andric &Op.BasePath, DestTInfo, CurFPFeatureOverrides(), OpLoc, 378e8d8bef9SDimitry Andric Parens.getEnd(), AngleBrackets)); 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric ExprResult Sema::ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &D, 3840b57cec5SDimitry Andric ExprResult Operand, 3850b57cec5SDimitry Andric SourceLocation RParenLoc) { 3860b57cec5SDimitry Andric assert(!D.isInvalidType()); 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric TypeSourceInfo *TInfo = GetTypeForDeclaratorCast(D, Operand.get()->getType()); 3890b57cec5SDimitry Andric if (D.isInvalidType()) 3900b57cec5SDimitry Andric return ExprError(); 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric return BuildBuiltinBitCastExpr(KWLoc, TInfo, Operand.get(), RParenLoc); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric ExprResult Sema::BuildBuiltinBitCastExpr(SourceLocation KWLoc, 3960b57cec5SDimitry Andric TypeSourceInfo *TSI, Expr *Operand, 3970b57cec5SDimitry Andric SourceLocation RParenLoc) { 3980b57cec5SDimitry Andric CastOperation Op(*this, TSI->getType(), Operand); 3990b57cec5SDimitry Andric Op.OpRange = SourceRange(KWLoc, RParenLoc); 4000b57cec5SDimitry Andric TypeLoc TL = TSI->getTypeLoc(); 4010b57cec5SDimitry Andric Op.DestRange = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric if (!Operand->isTypeDependent() && !TSI->getType()->isDependentType()) { 4040b57cec5SDimitry Andric Op.CheckBuiltinBitCast(); 4050b57cec5SDimitry Andric if (Op.SrcExpr.isInvalid()) 4060b57cec5SDimitry Andric return ExprError(); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric BuiltinBitCastExpr *BCE = 4100b57cec5SDimitry Andric new (Context) BuiltinBitCastExpr(Op.ResultType, Op.ValueKind, Op.Kind, 4110b57cec5SDimitry Andric Op.SrcExpr.get(), TSI, KWLoc, RParenLoc); 4120b57cec5SDimitry Andric return Op.complete(BCE); 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric /// Try to diagnose a failed overloaded cast. Returns true if 4160b57cec5SDimitry Andric /// diagnostics were emitted. 4170b57cec5SDimitry Andric static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, 4180b57cec5SDimitry Andric SourceRange range, Expr *src, 4190b57cec5SDimitry Andric QualType destType, 4200b57cec5SDimitry Andric bool listInitialization) { 4210b57cec5SDimitry Andric switch (CT) { 4220b57cec5SDimitry Andric // These cast kinds don't consider user-defined conversions. 4230b57cec5SDimitry Andric case CT_Const: 4240b57cec5SDimitry Andric case CT_Reinterpret: 4250b57cec5SDimitry Andric case CT_Dynamic: 4265ffd83dbSDimitry Andric case CT_Addrspace: 4270b57cec5SDimitry Andric return false; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric // These do. 4300b57cec5SDimitry Andric case CT_Static: 4310b57cec5SDimitry Andric case CT_CStyle: 4320b57cec5SDimitry Andric case CT_Functional: 4330b57cec5SDimitry Andric break; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric QualType srcType = src->getType(); 4370b57cec5SDimitry Andric if (!destType->isRecordType() && !srcType->isRecordType()) 4380b57cec5SDimitry Andric return false; 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric InitializedEntity entity = InitializedEntity::InitializeTemporary(destType); 4410b57cec5SDimitry Andric InitializationKind initKind 4420b57cec5SDimitry Andric = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(), 4430b57cec5SDimitry Andric range, listInitialization) 4440b57cec5SDimitry Andric : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range, 4450b57cec5SDimitry Andric listInitialization) 4460b57cec5SDimitry Andric : InitializationKind::CreateCast(/*type range?*/ range); 4470b57cec5SDimitry Andric InitializationSequence sequence(S, entity, initKind, src); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric assert(sequence.Failed() && "initialization succeeded on second try?"); 4500b57cec5SDimitry Andric switch (sequence.getFailureKind()) { 4510b57cec5SDimitry Andric default: return false; 4520b57cec5SDimitry Andric 45306c3fb27SDimitry Andric case InitializationSequence::FK_ParenthesizedListInitFailed: 45406c3fb27SDimitry Andric // In C++20, if the underlying destination type is a RecordType, Clang 45506c3fb27SDimitry Andric // attempts to perform parentesized aggregate initialization if constructor 45606c3fb27SDimitry Andric // overload fails: 45706c3fb27SDimitry Andric // 45806c3fb27SDimitry Andric // C++20 [expr.static.cast]p4: 45906c3fb27SDimitry Andric // An expression E can be explicitly converted to a type T...if overload 46006c3fb27SDimitry Andric // resolution for a direct-initialization...would find at least one viable 46106c3fb27SDimitry Andric // function ([over.match.viable]), or if T is an aggregate type having a 46206c3fb27SDimitry Andric // first element X and there is an implicit conversion sequence from E to 46306c3fb27SDimitry Andric // the type of X. 46406c3fb27SDimitry Andric // 46506c3fb27SDimitry Andric // If that fails, then we'll generate the diagnostics from the failed 46606c3fb27SDimitry Andric // previous constructor overload attempt. Array initialization, however, is 46706c3fb27SDimitry Andric // not done after attempting constructor overloading, so we exit as there 46806c3fb27SDimitry Andric // won't be a failed overload result. 46906c3fb27SDimitry Andric if (destType->isArrayType()) 47006c3fb27SDimitry Andric return false; 47106c3fb27SDimitry Andric break; 4720b57cec5SDimitry Andric case InitializationSequence::FK_ConstructorOverloadFailed: 4730b57cec5SDimitry Andric case InitializationSequence::FK_UserConversionOverloadFailed: 4740b57cec5SDimitry Andric break; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric OverloadCandidateSet &candidates = sequence.getFailedCandidateSet(); 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric unsigned msg = 0; 4800b57cec5SDimitry Andric OverloadCandidateDisplayKind howManyCandidates = OCD_AllCandidates; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric switch (sequence.getFailedOverloadResult()) { 4830b57cec5SDimitry Andric case OR_Success: llvm_unreachable("successful failed overload"); 4840b57cec5SDimitry Andric case OR_No_Viable_Function: 4850b57cec5SDimitry Andric if (candidates.empty()) 4860b57cec5SDimitry Andric msg = diag::err_ovl_no_conversion_in_cast; 4870b57cec5SDimitry Andric else 4880b57cec5SDimitry Andric msg = diag::err_ovl_no_viable_conversion_in_cast; 4890b57cec5SDimitry Andric howManyCandidates = OCD_AllCandidates; 4900b57cec5SDimitry Andric break; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric case OR_Ambiguous: 4930b57cec5SDimitry Andric msg = diag::err_ovl_ambiguous_conversion_in_cast; 494480093f4SDimitry Andric howManyCandidates = OCD_AmbiguousCandidates; 4950b57cec5SDimitry Andric break; 4960b57cec5SDimitry Andric 497*0fca6ea1SDimitry Andric case OR_Deleted: { 498*0fca6ea1SDimitry Andric OverloadCandidateSet::iterator Best; 499*0fca6ea1SDimitry Andric [[maybe_unused]] OverloadingResult Res = 500*0fca6ea1SDimitry Andric candidates.BestViableFunction(S, range.getBegin(), Best); 501*0fca6ea1SDimitry Andric assert(Res == OR_Deleted && "Inconsistent overload resolution"); 502*0fca6ea1SDimitry Andric 503*0fca6ea1SDimitry Andric StringLiteral *Msg = Best->Function->getDeletedMessage(); 504*0fca6ea1SDimitry Andric candidates.NoteCandidates( 505*0fca6ea1SDimitry Andric PartialDiagnosticAt(range.getBegin(), 506*0fca6ea1SDimitry Andric S.PDiag(diag::err_ovl_deleted_conversion_in_cast) 507*0fca6ea1SDimitry Andric << CT << srcType << destType << (Msg != nullptr) 508*0fca6ea1SDimitry Andric << (Msg ? Msg->getString() : StringRef()) 509*0fca6ea1SDimitry Andric << range << src->getSourceRange()), 510*0fca6ea1SDimitry Andric S, OCD_ViableCandidates, src); 511*0fca6ea1SDimitry Andric return true; 512*0fca6ea1SDimitry Andric } 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric candidates.NoteCandidates( 5160b57cec5SDimitry Andric PartialDiagnosticAt(range.getBegin(), 5170b57cec5SDimitry Andric S.PDiag(msg) << CT << srcType << destType << range 5180b57cec5SDimitry Andric << src->getSourceRange()), 5190b57cec5SDimitry Andric S, howManyCandidates, src); 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric return true; 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric /// Diagnose a failed cast. 5250b57cec5SDimitry Andric static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, 5260b57cec5SDimitry Andric SourceRange opRange, Expr *src, QualType destType, 5270b57cec5SDimitry Andric bool listInitialization) { 5280b57cec5SDimitry Andric if (msg == diag::err_bad_cxx_cast_generic && 5290b57cec5SDimitry Andric tryDiagnoseOverloadedCast(S, castType, opRange, src, destType, 5300b57cec5SDimitry Andric listInitialization)) 5310b57cec5SDimitry Andric return; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric S.Diag(opRange.getBegin(), msg) << castType 5340b57cec5SDimitry Andric << src->getType() << destType << opRange << src->getSourceRange(); 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric // Detect if both types are (ptr to) class, and note any incompleteness. 5370b57cec5SDimitry Andric int DifferentPtrness = 0; 5380b57cec5SDimitry Andric QualType From = destType; 5390b57cec5SDimitry Andric if (auto Ptr = From->getAs<PointerType>()) { 5400b57cec5SDimitry Andric From = Ptr->getPointeeType(); 5410b57cec5SDimitry Andric DifferentPtrness++; 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric QualType To = src->getType(); 5440b57cec5SDimitry Andric if (auto Ptr = To->getAs<PointerType>()) { 5450b57cec5SDimitry Andric To = Ptr->getPointeeType(); 5460b57cec5SDimitry Andric DifferentPtrness--; 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric if (!DifferentPtrness) { 5490b57cec5SDimitry Andric auto RecFrom = From->getAs<RecordType>(); 5500b57cec5SDimitry Andric auto RecTo = To->getAs<RecordType>(); 5510b57cec5SDimitry Andric if (RecFrom && RecTo) { 5520b57cec5SDimitry Andric auto DeclFrom = RecFrom->getAsCXXRecordDecl(); 5530b57cec5SDimitry Andric if (!DeclFrom->isCompleteDefinition()) 554e8d8bef9SDimitry Andric S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) << DeclFrom; 5550b57cec5SDimitry Andric auto DeclTo = RecTo->getAsCXXRecordDecl(); 5560b57cec5SDimitry Andric if (!DeclTo->isCompleteDefinition()) 557e8d8bef9SDimitry Andric S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) << DeclTo; 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric namespace { 5630b57cec5SDimitry Andric /// The kind of unwrapping we did when determining whether a conversion casts 5640b57cec5SDimitry Andric /// away constness. 5650b57cec5SDimitry Andric enum CastAwayConstnessKind { 5660b57cec5SDimitry Andric /// The conversion does not cast away constness. 5670b57cec5SDimitry Andric CACK_None = 0, 5680b57cec5SDimitry Andric /// We unwrapped similar types. 5690b57cec5SDimitry Andric CACK_Similar = 1, 5700b57cec5SDimitry Andric /// We unwrapped dissimilar types with similar representations (eg, a pointer 5710b57cec5SDimitry Andric /// versus an Objective-C object pointer). 5720b57cec5SDimitry Andric CACK_SimilarKind = 2, 5730b57cec5SDimitry Andric /// We unwrapped representationally-unrelated types, such as a pointer versus 5740b57cec5SDimitry Andric /// a pointer-to-member. 5750b57cec5SDimitry Andric CACK_Incoherent = 3, 5760b57cec5SDimitry Andric }; 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric /// Unwrap one level of types for CastsAwayConstness. 5800b57cec5SDimitry Andric /// 5810b57cec5SDimitry Andric /// Like Sema::UnwrapSimilarTypes, this removes one level of indirection from 5820b57cec5SDimitry Andric /// both types, provided that they're both pointer-like or array-like. Unlike 5830b57cec5SDimitry Andric /// the Sema function, doesn't care if the unwrapped pieces are related. 5840b57cec5SDimitry Andric /// 5850b57cec5SDimitry Andric /// This function may remove additional levels as necessary for correctness: 5860b57cec5SDimitry Andric /// the resulting T1 is unwrapped sufficiently that it is never an array type, 5870b57cec5SDimitry Andric /// so that its qualifiers can be directly compared to those of T2 (which will 5880b57cec5SDimitry Andric /// have the combined set of qualifiers from all indermediate levels of T2), 5890b57cec5SDimitry Andric /// as (effectively) required by [expr.const.cast]p7 replacing T1's qualifiers 5900b57cec5SDimitry Andric /// with those from T2. 5910b57cec5SDimitry Andric static CastAwayConstnessKind 5920b57cec5SDimitry Andric unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) { 5930b57cec5SDimitry Andric enum { None, Ptr, MemPtr, BlockPtr, Array }; 5940b57cec5SDimitry Andric auto Classify = [](QualType T) { 5950b57cec5SDimitry Andric if (T->isAnyPointerType()) return Ptr; 5960b57cec5SDimitry Andric if (T->isMemberPointerType()) return MemPtr; 5970b57cec5SDimitry Andric if (T->isBlockPointerType()) return BlockPtr; 5980b57cec5SDimitry Andric // We somewhat-arbitrarily don't look through VLA types here. This is at 5990b57cec5SDimitry Andric // least consistent with the behavior of UnwrapSimilarTypes. 6000b57cec5SDimitry Andric if (T->isConstantArrayType() || T->isIncompleteArrayType()) return Array; 6010b57cec5SDimitry Andric return None; 6020b57cec5SDimitry Andric }; 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric auto Unwrap = [&](QualType T) { 6050b57cec5SDimitry Andric if (auto *AT = Context.getAsArrayType(T)) 6060b57cec5SDimitry Andric return AT->getElementType(); 6070b57cec5SDimitry Andric return T->getPointeeType(); 6080b57cec5SDimitry Andric }; 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric CastAwayConstnessKind Kind; 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric if (T2->isReferenceType()) { 6130b57cec5SDimitry Andric // Special case: if the destination type is a reference type, unwrap it as 6140b57cec5SDimitry Andric // the first level. (The source will have been an lvalue expression in this 6150b57cec5SDimitry Andric // case, so there is no corresponding "reference to" in T1 to remove.) This 6160b57cec5SDimitry Andric // simulates removing a "pointer to" from both sides. 6170b57cec5SDimitry Andric T2 = T2->getPointeeType(); 6180b57cec5SDimitry Andric Kind = CastAwayConstnessKind::CACK_Similar; 6190b57cec5SDimitry Andric } else if (Context.UnwrapSimilarTypes(T1, T2)) { 6200b57cec5SDimitry Andric Kind = CastAwayConstnessKind::CACK_Similar; 6210b57cec5SDimitry Andric } else { 6220b57cec5SDimitry Andric // Try unwrapping mismatching levels. 6230b57cec5SDimitry Andric int T1Class = Classify(T1); 6240b57cec5SDimitry Andric if (T1Class == None) 6250b57cec5SDimitry Andric return CastAwayConstnessKind::CACK_None; 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric int T2Class = Classify(T2); 6280b57cec5SDimitry Andric if (T2Class == None) 6290b57cec5SDimitry Andric return CastAwayConstnessKind::CACK_None; 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric T1 = Unwrap(T1); 6320b57cec5SDimitry Andric T2 = Unwrap(T2); 6330b57cec5SDimitry Andric Kind = T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind 6340b57cec5SDimitry Andric : CastAwayConstnessKind::CACK_Incoherent; 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric // We've unwrapped at least one level. If the resulting T1 is a (possibly 6380b57cec5SDimitry Andric // multidimensional) array type, any qualifier on any matching layer of 6390b57cec5SDimitry Andric // T2 is considered to correspond to T1. Decompose down to the element 6400b57cec5SDimitry Andric // type of T1 so that we can compare properly. 6410b57cec5SDimitry Andric while (true) { 6420b57cec5SDimitry Andric Context.UnwrapSimilarArrayTypes(T1, T2); 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric if (Classify(T1) != Array) 6450b57cec5SDimitry Andric break; 6460b57cec5SDimitry Andric 6470b57cec5SDimitry Andric auto T2Class = Classify(T2); 6480b57cec5SDimitry Andric if (T2Class == None) 6490b57cec5SDimitry Andric break; 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric if (T2Class != Array) 6520b57cec5SDimitry Andric Kind = CastAwayConstnessKind::CACK_Incoherent; 6530b57cec5SDimitry Andric else if (Kind != CastAwayConstnessKind::CACK_Incoherent) 6540b57cec5SDimitry Andric Kind = CastAwayConstnessKind::CACK_SimilarKind; 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric T1 = Unwrap(T1); 6570b57cec5SDimitry Andric T2 = Unwrap(T2).withCVRQualifiers(T2.getCVRQualifiers()); 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric return Kind; 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric /// Check if the pointer conversion from SrcType to DestType casts away 6640b57cec5SDimitry Andric /// constness as defined in C++ [expr.const.cast]. This is used by the cast 6650b57cec5SDimitry Andric /// checkers. Both arguments must denote pointer (possibly to member) types. 6660b57cec5SDimitry Andric /// 6670b57cec5SDimitry Andric /// \param CheckCVR Whether to check for const/volatile/restrict qualifiers. 6680b57cec5SDimitry Andric /// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers. 6690b57cec5SDimitry Andric static CastAwayConstnessKind 6700b57cec5SDimitry Andric CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType, 6710b57cec5SDimitry Andric bool CheckCVR, bool CheckObjCLifetime, 6720b57cec5SDimitry Andric QualType *TheOffendingSrcType = nullptr, 6730b57cec5SDimitry Andric QualType *TheOffendingDestType = nullptr, 6740b57cec5SDimitry Andric Qualifiers *CastAwayQualifiers = nullptr) { 6750b57cec5SDimitry Andric // If the only checking we care about is for Objective-C lifetime qualifiers, 6760b57cec5SDimitry Andric // and we're not in ObjC mode, there's nothing to check. 6770b57cec5SDimitry Andric if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC) 6780b57cec5SDimitry Andric return CastAwayConstnessKind::CACK_None; 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric if (!DestType->isReferenceType()) { 6810b57cec5SDimitry Andric assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() || 6820b57cec5SDimitry Andric SrcType->isBlockPointerType()) && 6830b57cec5SDimitry Andric "Source type is not pointer or pointer to member."); 6840b57cec5SDimitry Andric assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() || 6850b57cec5SDimitry Andric DestType->isBlockPointerType()) && 6860b57cec5SDimitry Andric "Destination type is not pointer or pointer to member."); 6870b57cec5SDimitry Andric } 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), 6900b57cec5SDimitry Andric UnwrappedDestType = Self.Context.getCanonicalType(DestType); 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric // Find the qualifiers. We only care about cvr-qualifiers for the 6930b57cec5SDimitry Andric // purpose of this check, because other qualifiers (address spaces, 6940b57cec5SDimitry Andric // Objective-C GC, etc.) are part of the type's identity. 6950b57cec5SDimitry Andric QualType PrevUnwrappedSrcType = UnwrappedSrcType; 6960b57cec5SDimitry Andric QualType PrevUnwrappedDestType = UnwrappedDestType; 6970b57cec5SDimitry Andric auto WorstKind = CastAwayConstnessKind::CACK_Similar; 6980b57cec5SDimitry Andric bool AllConstSoFar = true; 6990b57cec5SDimitry Andric while (auto Kind = unwrapCastAwayConstnessLevel( 7000b57cec5SDimitry Andric Self.Context, UnwrappedSrcType, UnwrappedDestType)) { 7010b57cec5SDimitry Andric // Track the worst kind of unwrap we needed to do before we found a 7020b57cec5SDimitry Andric // problem. 7030b57cec5SDimitry Andric if (Kind > WorstKind) 7040b57cec5SDimitry Andric WorstKind = Kind; 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric // Determine the relevant qualifiers at this level. 7070b57cec5SDimitry Andric Qualifiers SrcQuals, DestQuals; 7080b57cec5SDimitry Andric Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals); 7090b57cec5SDimitry Andric Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals); 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric // We do not meaningfully track object const-ness of Objective-C object 7120b57cec5SDimitry Andric // types. Remove const from the source type if either the source or 7130b57cec5SDimitry Andric // the destination is an Objective-C object type. 7140b57cec5SDimitry Andric if (UnwrappedSrcType->isObjCObjectType() || 7150b57cec5SDimitry Andric UnwrappedDestType->isObjCObjectType()) 7160b57cec5SDimitry Andric SrcQuals.removeConst(); 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric if (CheckCVR) { 7190b57cec5SDimitry Andric Qualifiers SrcCvrQuals = 7200b57cec5SDimitry Andric Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers()); 7210b57cec5SDimitry Andric Qualifiers DestCvrQuals = 7220b57cec5SDimitry Andric Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers()); 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric if (SrcCvrQuals != DestCvrQuals) { 7250b57cec5SDimitry Andric if (CastAwayQualifiers) 7260b57cec5SDimitry Andric *CastAwayQualifiers = SrcCvrQuals - DestCvrQuals; 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric // If we removed a cvr-qualifier, this is casting away 'constness'. 7290b57cec5SDimitry Andric if (!DestCvrQuals.compatiblyIncludes(SrcCvrQuals)) { 7300b57cec5SDimitry Andric if (TheOffendingSrcType) 7310b57cec5SDimitry Andric *TheOffendingSrcType = PrevUnwrappedSrcType; 7320b57cec5SDimitry Andric if (TheOffendingDestType) 7330b57cec5SDimitry Andric *TheOffendingDestType = PrevUnwrappedDestType; 7340b57cec5SDimitry Andric return WorstKind; 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric // If any prior level was not 'const', this is also casting away 7380b57cec5SDimitry Andric // 'constness'. We noted the outermost type missing a 'const' already. 7390b57cec5SDimitry Andric if (!AllConstSoFar) 7400b57cec5SDimitry Andric return WorstKind; 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric if (CheckObjCLifetime && 7450b57cec5SDimitry Andric !DestQuals.compatiblyIncludesObjCLifetime(SrcQuals)) 7460b57cec5SDimitry Andric return WorstKind; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric // If we found our first non-const-qualified type, this may be the place 7490b57cec5SDimitry Andric // where things start to go wrong. 7500b57cec5SDimitry Andric if (AllConstSoFar && !DestQuals.hasConst()) { 7510b57cec5SDimitry Andric AllConstSoFar = false; 7520b57cec5SDimitry Andric if (TheOffendingSrcType) 7530b57cec5SDimitry Andric *TheOffendingSrcType = PrevUnwrappedSrcType; 7540b57cec5SDimitry Andric if (TheOffendingDestType) 7550b57cec5SDimitry Andric *TheOffendingDestType = PrevUnwrappedDestType; 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric PrevUnwrappedSrcType = UnwrappedSrcType; 7590b57cec5SDimitry Andric PrevUnwrappedDestType = UnwrappedDestType; 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric return CastAwayConstnessKind::CACK_None; 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric static TryCastResult getCastAwayConstnessCastKind(CastAwayConstnessKind CACK, 7660b57cec5SDimitry Andric unsigned &DiagID) { 7670b57cec5SDimitry Andric switch (CACK) { 7680b57cec5SDimitry Andric case CastAwayConstnessKind::CACK_None: 7690b57cec5SDimitry Andric llvm_unreachable("did not cast away constness"); 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric case CastAwayConstnessKind::CACK_Similar: 7720b57cec5SDimitry Andric // FIXME: Accept these as an extension too? 7730b57cec5SDimitry Andric case CastAwayConstnessKind::CACK_SimilarKind: 7740b57cec5SDimitry Andric DiagID = diag::err_bad_cxx_cast_qualifiers_away; 7750b57cec5SDimitry Andric return TC_Failed; 7760b57cec5SDimitry Andric 7770b57cec5SDimitry Andric case CastAwayConstnessKind::CACK_Incoherent: 7780b57cec5SDimitry Andric DiagID = diag::ext_bad_cxx_cast_qualifiers_away_incoherent; 7790b57cec5SDimitry Andric return TC_Extension; 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric llvm_unreachable("unexpected cast away constness kind"); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric /// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid. 7860b57cec5SDimitry Andric /// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime- 7870b57cec5SDimitry Andric /// checked downcasts in class hierarchies. 7880b57cec5SDimitry Andric void CastOperation::CheckDynamicCast() { 7895ffd83dbSDimitry Andric CheckNoDerefRAII NoderefCheck(*this); 7905ffd83dbSDimitry Andric 791fe6060f1SDimitry Andric if (ValueKind == VK_PRValue) 7920b57cec5SDimitry Andric SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); 7930b57cec5SDimitry Andric else if (isPlaceholder()) 7940b57cec5SDimitry Andric SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get()); 7950b57cec5SDimitry Andric if (SrcExpr.isInvalid()) // if conversion failed, don't report another error 7960b57cec5SDimitry Andric return; 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric QualType OrigSrcType = SrcExpr.get()->getType(); 7990b57cec5SDimitry Andric QualType DestType = Self.Context.getCanonicalType(this->DestType); 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type, 8020b57cec5SDimitry Andric // or "pointer to cv void". 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric QualType DestPointee; 8050b57cec5SDimitry Andric const PointerType *DestPointer = DestType->getAs<PointerType>(); 8060b57cec5SDimitry Andric const ReferenceType *DestReference = nullptr; 8070b57cec5SDimitry Andric if (DestPointer) { 8080b57cec5SDimitry Andric DestPointee = DestPointer->getPointeeType(); 8090b57cec5SDimitry Andric } else if ((DestReference = DestType->getAs<ReferenceType>())) { 8100b57cec5SDimitry Andric DestPointee = DestReference->getPointeeType(); 8110b57cec5SDimitry Andric } else { 8120b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr) 8130b57cec5SDimitry Andric << this->DestType << DestRange; 8140b57cec5SDimitry Andric SrcExpr = ExprError(); 8150b57cec5SDimitry Andric return; 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric const RecordType *DestRecord = DestPointee->getAs<RecordType>(); 8190b57cec5SDimitry Andric if (DestPointee->isVoidType()) { 8200b57cec5SDimitry Andric assert(DestPointer && "Reference to void is not possible"); 8210b57cec5SDimitry Andric } else if (DestRecord) { 8220b57cec5SDimitry Andric if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee, 823480093f4SDimitry Andric diag::err_bad_cast_incomplete, 8240b57cec5SDimitry Andric DestRange)) { 8250b57cec5SDimitry Andric SrcExpr = ExprError(); 8260b57cec5SDimitry Andric return; 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric } else { 8290b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) 8300b57cec5SDimitry Andric << DestPointee.getUnqualifiedType() << DestRange; 8310b57cec5SDimitry Andric SrcExpr = ExprError(); 8320b57cec5SDimitry Andric return; 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to 8360b57cec5SDimitry Andric // complete class type, [...]. If T is an lvalue reference type, v shall be 8370b57cec5SDimitry Andric // an lvalue of a complete class type, [...]. If T is an rvalue reference 8380b57cec5SDimitry Andric // type, v shall be an expression having a complete class type, [...] 8390b57cec5SDimitry Andric QualType SrcType = Self.Context.getCanonicalType(OrigSrcType); 8400b57cec5SDimitry Andric QualType SrcPointee; 8410b57cec5SDimitry Andric if (DestPointer) { 8420b57cec5SDimitry Andric if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) { 8430b57cec5SDimitry Andric SrcPointee = SrcPointer->getPointeeType(); 8440b57cec5SDimitry Andric } else { 8450b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr) 846480093f4SDimitry Andric << OrigSrcType << this->DestType << SrcExpr.get()->getSourceRange(); 8470b57cec5SDimitry Andric SrcExpr = ExprError(); 8480b57cec5SDimitry Andric return; 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric } else if (DestReference->isLValueReferenceType()) { 8510b57cec5SDimitry Andric if (!SrcExpr.get()->isLValue()) { 8520b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) 8530b57cec5SDimitry Andric << CT_Dynamic << OrigSrcType << this->DestType << OpRange; 8540b57cec5SDimitry Andric } 8550b57cec5SDimitry Andric SrcPointee = SrcType; 8560b57cec5SDimitry Andric } else { 8570b57cec5SDimitry Andric // If we're dynamic_casting from a prvalue to an rvalue reference, we need 8580b57cec5SDimitry Andric // to materialize the prvalue before we bind the reference to it. 859fe6060f1SDimitry Andric if (SrcExpr.get()->isPRValue()) 8600b57cec5SDimitry Andric SrcExpr = Self.CreateMaterializeTemporaryExpr( 8610b57cec5SDimitry Andric SrcType, SrcExpr.get(), /*IsLValueReference*/ false); 8620b57cec5SDimitry Andric SrcPointee = SrcType; 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric const RecordType *SrcRecord = SrcPointee->getAs<RecordType>(); 8660b57cec5SDimitry Andric if (SrcRecord) { 8670b57cec5SDimitry Andric if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, 868480093f4SDimitry Andric diag::err_bad_cast_incomplete, 8690b57cec5SDimitry Andric SrcExpr.get())) { 8700b57cec5SDimitry Andric SrcExpr = ExprError(); 8710b57cec5SDimitry Andric return; 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric } else { 8740b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) 8750b57cec5SDimitry Andric << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); 8760b57cec5SDimitry Andric SrcExpr = ExprError(); 8770b57cec5SDimitry Andric return; 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric assert((DestPointer || DestReference) && 8810b57cec5SDimitry Andric "Bad destination non-ptr/ref slipped through."); 8820b57cec5SDimitry Andric assert((DestRecord || DestPointee->isVoidType()) && 8830b57cec5SDimitry Andric "Bad destination pointee slipped through."); 8840b57cec5SDimitry Andric assert(SrcRecord && "Bad source pointee slipped through."); 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness. 8870b57cec5SDimitry Andric if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { 8880b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away) 8890b57cec5SDimitry Andric << CT_Dynamic << OrigSrcType << this->DestType << OpRange; 8900b57cec5SDimitry Andric SrcExpr = ExprError(); 8910b57cec5SDimitry Andric return; 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric // C++ 5.2.7p3: If the type of v is the same as the required result type, 8950b57cec5SDimitry Andric // [except for cv]. 8960b57cec5SDimitry Andric if (DestRecord == SrcRecord) { 8970b57cec5SDimitry Andric Kind = CK_NoOp; 8980b57cec5SDimitry Andric return; 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric // C++ 5.2.7p5 9020b57cec5SDimitry Andric // Upcasts are resolved statically. 9030b57cec5SDimitry Andric if (DestRecord && 9040b57cec5SDimitry Andric Self.IsDerivedFrom(OpRange.getBegin(), SrcPointee, DestPointee)) { 9050b57cec5SDimitry Andric if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee, 9060b57cec5SDimitry Andric OpRange.getBegin(), OpRange, 9070b57cec5SDimitry Andric &BasePath)) { 9080b57cec5SDimitry Andric SrcExpr = ExprError(); 9090b57cec5SDimitry Andric return; 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric 9120b57cec5SDimitry Andric Kind = CK_DerivedToBase; 9130b57cec5SDimitry Andric return; 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric // C++ 5.2.7p6: Otherwise, v shall be [polymorphic]. 9170b57cec5SDimitry Andric const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(); 9180b57cec5SDimitry Andric assert(SrcDecl && "Definition missing"); 9190b57cec5SDimitry Andric if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) { 9200b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) 9210b57cec5SDimitry Andric << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); 9220b57cec5SDimitry Andric SrcExpr = ExprError(); 9230b57cec5SDimitry Andric } 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric // dynamic_cast is not available with -fno-rtti. 9260b57cec5SDimitry Andric // As an exception, dynamic_cast to void* is available because it doesn't 9270b57cec5SDimitry Andric // use RTTI. 9280b57cec5SDimitry Andric if (!Self.getLangOpts().RTTI && !DestPointee->isVoidType()) { 9290b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_no_dynamic_cast_with_fno_rtti); 9300b57cec5SDimitry Andric SrcExpr = ExprError(); 9310b57cec5SDimitry Andric return; 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric 934e8d8bef9SDimitry Andric // Warns when dynamic_cast is used with RTTI data disabled. 935e8d8bef9SDimitry Andric if (!Self.getLangOpts().RTTIData) { 936e8d8bef9SDimitry Andric bool MicrosoftABI = 937e8d8bef9SDimitry Andric Self.getASTContext().getTargetInfo().getCXXABI().isMicrosoft(); 938e8d8bef9SDimitry Andric bool isClangCL = Self.getDiagnostics().getDiagnosticOptions().getFormat() == 939e8d8bef9SDimitry Andric DiagnosticOptions::MSVC; 940e8d8bef9SDimitry Andric if (MicrosoftABI || !DestPointee->isVoidType()) 941e8d8bef9SDimitry Andric Self.Diag(OpRange.getBegin(), 942e8d8bef9SDimitry Andric diag::warn_no_dynamic_cast_with_rtti_disabled) 943e8d8bef9SDimitry Andric << isClangCL; 944e8d8bef9SDimitry Andric } 945e8d8bef9SDimitry Andric 9468a4dda33SDimitry Andric // For a dynamic_cast to a final type, IR generation might emit a reference 9478a4dda33SDimitry Andric // to the vtable. 9488a4dda33SDimitry Andric if (DestRecord) { 9498a4dda33SDimitry Andric auto *DestDecl = DestRecord->getAsCXXRecordDecl(); 9508a4dda33SDimitry Andric if (DestDecl->isEffectivelyFinal()) 9518a4dda33SDimitry Andric Self.MarkVTableUsed(OpRange.getBegin(), DestDecl); 9528a4dda33SDimitry Andric } 9538a4dda33SDimitry Andric 9540b57cec5SDimitry Andric // Done. Everything else is run-time checks. 9550b57cec5SDimitry Andric Kind = CK_Dynamic; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric /// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid. 9590b57cec5SDimitry Andric /// Refer to C++ 5.2.11 for details. const_cast is typically used in code 9600b57cec5SDimitry Andric /// like this: 9610b57cec5SDimitry Andric /// const char *str = "literal"; 9620b57cec5SDimitry Andric /// legacy_function(const_cast\<char*\>(str)); 9630b57cec5SDimitry Andric void CastOperation::CheckConstCast() { 9645ffd83dbSDimitry Andric CheckNoDerefRAII NoderefCheck(*this); 9655ffd83dbSDimitry Andric 966fe6060f1SDimitry Andric if (ValueKind == VK_PRValue) 9670b57cec5SDimitry Andric SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); 9680b57cec5SDimitry Andric else if (isPlaceholder()) 9690b57cec5SDimitry Andric SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get()); 9700b57cec5SDimitry Andric if (SrcExpr.isInvalid()) // if conversion failed, don't report another error 9710b57cec5SDimitry Andric return; 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric unsigned msg = diag::err_bad_cxx_cast_generic; 9740b57cec5SDimitry Andric auto TCR = TryConstCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg); 9750b57cec5SDimitry Andric if (TCR != TC_Success && msg != 0) { 9760b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), msg) << CT_Const 9770b57cec5SDimitry Andric << SrcExpr.get()->getType() << DestType << OpRange; 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric if (!isValidCast(TCR)) 9800b57cec5SDimitry Andric SrcExpr = ExprError(); 9810b57cec5SDimitry Andric } 9820b57cec5SDimitry Andric 9835ffd83dbSDimitry Andric void CastOperation::CheckAddrspaceCast() { 9845ffd83dbSDimitry Andric unsigned msg = diag::err_bad_cxx_cast_generic; 9855ffd83dbSDimitry Andric auto TCR = 9865ffd83dbSDimitry Andric TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg, Kind); 9875ffd83dbSDimitry Andric if (TCR != TC_Success && msg != 0) { 9885ffd83dbSDimitry Andric Self.Diag(OpRange.getBegin(), msg) 9895ffd83dbSDimitry Andric << CT_Addrspace << SrcExpr.get()->getType() << DestType << OpRange; 9905ffd83dbSDimitry Andric } 9915ffd83dbSDimitry Andric if (!isValidCast(TCR)) 9925ffd83dbSDimitry Andric SrcExpr = ExprError(); 9935ffd83dbSDimitry Andric } 9945ffd83dbSDimitry Andric 9950b57cec5SDimitry Andric /// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast 9960b57cec5SDimitry Andric /// or downcast between respective pointers or references. 9970b57cec5SDimitry Andric static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr, 9980b57cec5SDimitry Andric QualType DestType, 9990b57cec5SDimitry Andric SourceRange OpRange) { 10000b57cec5SDimitry Andric QualType SrcType = SrcExpr->getType(); 10010b57cec5SDimitry Andric // When casting from pointer or reference, get pointee type; use original 10020b57cec5SDimitry Andric // type otherwise. 10030b57cec5SDimitry Andric const CXXRecordDecl *SrcPointeeRD = SrcType->getPointeeCXXRecordDecl(); 10040b57cec5SDimitry Andric const CXXRecordDecl *SrcRD = 10050b57cec5SDimitry Andric SrcPointeeRD ? SrcPointeeRD : SrcType->getAsCXXRecordDecl(); 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric // Examining subobjects for records is only possible if the complete and 10080b57cec5SDimitry Andric // valid definition is available. Also, template instantiation is not 10090b57cec5SDimitry Andric // allowed here. 10100b57cec5SDimitry Andric if (!SrcRD || !SrcRD->isCompleteDefinition() || SrcRD->isInvalidDecl()) 10110b57cec5SDimitry Andric return; 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric const CXXRecordDecl *DestRD = DestType->getPointeeCXXRecordDecl(); 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric if (!DestRD || !DestRD->isCompleteDefinition() || DestRD->isInvalidDecl()) 10160b57cec5SDimitry Andric return; 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric enum { 10190b57cec5SDimitry Andric ReinterpretUpcast, 10200b57cec5SDimitry Andric ReinterpretDowncast 10210b57cec5SDimitry Andric } ReinterpretKind; 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric CXXBasePaths BasePaths; 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric if (SrcRD->isDerivedFrom(DestRD, BasePaths)) 10260b57cec5SDimitry Andric ReinterpretKind = ReinterpretUpcast; 10270b57cec5SDimitry Andric else if (DestRD->isDerivedFrom(SrcRD, BasePaths)) 10280b57cec5SDimitry Andric ReinterpretKind = ReinterpretDowncast; 10290b57cec5SDimitry Andric else 10300b57cec5SDimitry Andric return; 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric bool VirtualBase = true; 10330b57cec5SDimitry Andric bool NonZeroOffset = false; 10340b57cec5SDimitry Andric for (CXXBasePaths::const_paths_iterator I = BasePaths.begin(), 10350b57cec5SDimitry Andric E = BasePaths.end(); 10360b57cec5SDimitry Andric I != E; ++I) { 10370b57cec5SDimitry Andric const CXXBasePath &Path = *I; 10380b57cec5SDimitry Andric CharUnits Offset = CharUnits::Zero(); 10390b57cec5SDimitry Andric bool IsVirtual = false; 10400b57cec5SDimitry Andric for (CXXBasePath::const_iterator IElem = Path.begin(), EElem = Path.end(); 10410b57cec5SDimitry Andric IElem != EElem; ++IElem) { 10420b57cec5SDimitry Andric IsVirtual = IElem->Base->isVirtual(); 10430b57cec5SDimitry Andric if (IsVirtual) 10440b57cec5SDimitry Andric break; 10450b57cec5SDimitry Andric const CXXRecordDecl *BaseRD = IElem->Base->getType()->getAsCXXRecordDecl(); 10460b57cec5SDimitry Andric assert(BaseRD && "Base type should be a valid unqualified class type"); 10470b57cec5SDimitry Andric // Don't check if any base has invalid declaration or has no definition 10480b57cec5SDimitry Andric // since it has no layout info. 10490b57cec5SDimitry Andric const CXXRecordDecl *Class = IElem->Class, 10500b57cec5SDimitry Andric *ClassDefinition = Class->getDefinition(); 10510b57cec5SDimitry Andric if (Class->isInvalidDecl() || !ClassDefinition || 10520b57cec5SDimitry Andric !ClassDefinition->isCompleteDefinition()) 10530b57cec5SDimitry Andric return; 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric const ASTRecordLayout &DerivedLayout = 10560b57cec5SDimitry Andric Self.Context.getASTRecordLayout(Class); 10570b57cec5SDimitry Andric Offset += DerivedLayout.getBaseClassOffset(BaseRD); 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric if (!IsVirtual) { 10600b57cec5SDimitry Andric // Don't warn if any path is a non-virtually derived base at offset zero. 10610b57cec5SDimitry Andric if (Offset.isZero()) 10620b57cec5SDimitry Andric return; 10630b57cec5SDimitry Andric // Offset makes sense only for non-virtual bases. 10640b57cec5SDimitry Andric else 10650b57cec5SDimitry Andric NonZeroOffset = true; 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric VirtualBase = VirtualBase && IsVirtual; 10680b57cec5SDimitry Andric } 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric (void) NonZeroOffset; // Silence set but not used warning. 10710b57cec5SDimitry Andric assert((VirtualBase || NonZeroOffset) && 10720b57cec5SDimitry Andric "Should have returned if has non-virtual base with zero offset"); 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric QualType BaseType = 10750b57cec5SDimitry Andric ReinterpretKind == ReinterpretUpcast? DestType : SrcType; 10760b57cec5SDimitry Andric QualType DerivedType = 10770b57cec5SDimitry Andric ReinterpretKind == ReinterpretUpcast? SrcType : DestType; 10780b57cec5SDimitry Andric 10790b57cec5SDimitry Andric SourceLocation BeginLoc = OpRange.getBegin(); 10800b57cec5SDimitry Andric Self.Diag(BeginLoc, diag::warn_reinterpret_different_from_static) 10810b57cec5SDimitry Andric << DerivedType << BaseType << !VirtualBase << int(ReinterpretKind) 10820b57cec5SDimitry Andric << OpRange; 10830b57cec5SDimitry Andric Self.Diag(BeginLoc, diag::note_reinterpret_updowncast_use_static) 10840b57cec5SDimitry Andric << int(ReinterpretKind) 10850b57cec5SDimitry Andric << FixItHint::CreateReplacement(BeginLoc, "static_cast"); 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric 1088fe6060f1SDimitry Andric static bool argTypeIsABIEquivalent(QualType SrcType, QualType DestType, 1089fe6060f1SDimitry Andric ASTContext &Context) { 1090fe6060f1SDimitry Andric if (SrcType->isPointerType() && DestType->isPointerType()) 1091fe6060f1SDimitry Andric return true; 1092fe6060f1SDimitry Andric 1093fe6060f1SDimitry Andric // Allow integral type mismatch if their size are equal. 1094*0fca6ea1SDimitry Andric if ((SrcType->isIntegralType(Context) || SrcType->isEnumeralType()) && 1095*0fca6ea1SDimitry Andric (DestType->isIntegralType(Context) || DestType->isEnumeralType())) 1096*0fca6ea1SDimitry Andric if (Context.getTypeSizeInChars(SrcType) == 1097*0fca6ea1SDimitry Andric Context.getTypeSizeInChars(DestType)) 1098fe6060f1SDimitry Andric return true; 1099fe6060f1SDimitry Andric 1100fe6060f1SDimitry Andric return Context.hasSameUnqualifiedType(SrcType, DestType); 1101fe6060f1SDimitry Andric } 1102fe6060f1SDimitry Andric 1103bdd1243dSDimitry Andric static unsigned int checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr, 1104fe6060f1SDimitry Andric QualType DestType) { 1105bdd1243dSDimitry Andric unsigned int DiagID = 0; 1106bdd1243dSDimitry Andric const unsigned int DiagList[] = {diag::warn_cast_function_type_strict, 1107bdd1243dSDimitry Andric diag::warn_cast_function_type}; 1108bdd1243dSDimitry Andric for (auto ID : DiagList) { 1109bdd1243dSDimitry Andric if (!Self.Diags.isIgnored(ID, SrcExpr.get()->getExprLoc())) { 1110bdd1243dSDimitry Andric DiagID = ID; 1111bdd1243dSDimitry Andric break; 1112bdd1243dSDimitry Andric } 1113bdd1243dSDimitry Andric } 1114bdd1243dSDimitry Andric if (!DiagID) 1115bdd1243dSDimitry Andric return 0; 1116fe6060f1SDimitry Andric 1117fe6060f1SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 1118fe6060f1SDimitry Andric const FunctionType *SrcFTy = nullptr; 1119fe6060f1SDimitry Andric const FunctionType *DstFTy = nullptr; 1120fe6060f1SDimitry Andric if (((SrcType->isBlockPointerType() || SrcType->isFunctionPointerType()) && 1121fe6060f1SDimitry Andric DestType->isFunctionPointerType()) || 1122fe6060f1SDimitry Andric (SrcType->isMemberFunctionPointerType() && 1123fe6060f1SDimitry Andric DestType->isMemberFunctionPointerType())) { 1124fe6060f1SDimitry Andric SrcFTy = SrcType->getPointeeType()->castAs<FunctionType>(); 1125fe6060f1SDimitry Andric DstFTy = DestType->getPointeeType()->castAs<FunctionType>(); 1126fe6060f1SDimitry Andric } else if (SrcType->isFunctionType() && DestType->isFunctionReferenceType()) { 1127fe6060f1SDimitry Andric SrcFTy = SrcType->castAs<FunctionType>(); 1128fe6060f1SDimitry Andric DstFTy = DestType.getNonReferenceType()->castAs<FunctionType>(); 1129fe6060f1SDimitry Andric } else { 1130bdd1243dSDimitry Andric return 0; 1131fe6060f1SDimitry Andric } 1132fe6060f1SDimitry Andric assert(SrcFTy && DstFTy); 1133fe6060f1SDimitry Andric 1134bdd1243dSDimitry Andric if (Self.Context.hasSameType(SrcFTy, DstFTy)) 1135bdd1243dSDimitry Andric return 0; 1136bdd1243dSDimitry Andric 1137bdd1243dSDimitry Andric // For strict checks, ensure we have an exact match. 1138bdd1243dSDimitry Andric if (DiagID == diag::warn_cast_function_type_strict) 1139bdd1243dSDimitry Andric return DiagID; 1140bdd1243dSDimitry Andric 1141fe6060f1SDimitry Andric auto IsVoidVoid = [](const FunctionType *T) { 1142fe6060f1SDimitry Andric if (!T->getReturnType()->isVoidType()) 1143fe6060f1SDimitry Andric return false; 1144fe6060f1SDimitry Andric if (const auto *PT = T->getAs<FunctionProtoType>()) 1145fe6060f1SDimitry Andric return !PT->isVariadic() && PT->getNumParams() == 0; 1146fe6060f1SDimitry Andric return false; 1147fe6060f1SDimitry Andric }; 1148fe6060f1SDimitry Andric 1149fe6060f1SDimitry Andric // Skip if either function type is void(*)(void) 1150fe6060f1SDimitry Andric if (IsVoidVoid(SrcFTy) || IsVoidVoid(DstFTy)) 1151bdd1243dSDimitry Andric return 0; 1152fe6060f1SDimitry Andric 1153fe6060f1SDimitry Andric // Check return type. 1154fe6060f1SDimitry Andric if (!argTypeIsABIEquivalent(SrcFTy->getReturnType(), DstFTy->getReturnType(), 1155fe6060f1SDimitry Andric Self.Context)) 1156bdd1243dSDimitry Andric return DiagID; 1157fe6060f1SDimitry Andric 1158fe6060f1SDimitry Andric // Check if either has unspecified number of parameters 1159fe6060f1SDimitry Andric if (SrcFTy->isFunctionNoProtoType() || DstFTy->isFunctionNoProtoType()) 1160bdd1243dSDimitry Andric return 0; 1161fe6060f1SDimitry Andric 1162fe6060f1SDimitry Andric // Check parameter types. 1163fe6060f1SDimitry Andric 1164fe6060f1SDimitry Andric const auto *SrcFPTy = cast<FunctionProtoType>(SrcFTy); 1165fe6060f1SDimitry Andric const auto *DstFPTy = cast<FunctionProtoType>(DstFTy); 1166fe6060f1SDimitry Andric 1167fe6060f1SDimitry Andric // In a cast involving function types with a variable argument list only the 1168fe6060f1SDimitry Andric // types of initial arguments that are provided are considered. 1169fe6060f1SDimitry Andric unsigned NumParams = SrcFPTy->getNumParams(); 1170fe6060f1SDimitry Andric unsigned DstNumParams = DstFPTy->getNumParams(); 1171fe6060f1SDimitry Andric if (NumParams > DstNumParams) { 1172fe6060f1SDimitry Andric if (!DstFPTy->isVariadic()) 1173bdd1243dSDimitry Andric return DiagID; 1174fe6060f1SDimitry Andric NumParams = DstNumParams; 1175fe6060f1SDimitry Andric } else if (NumParams < DstNumParams) { 1176fe6060f1SDimitry Andric if (!SrcFPTy->isVariadic()) 1177bdd1243dSDimitry Andric return DiagID; 1178fe6060f1SDimitry Andric } 1179fe6060f1SDimitry Andric 1180fe6060f1SDimitry Andric for (unsigned i = 0; i < NumParams; ++i) 1181fe6060f1SDimitry Andric if (!argTypeIsABIEquivalent(SrcFPTy->getParamType(i), 1182fe6060f1SDimitry Andric DstFPTy->getParamType(i), Self.Context)) 1183bdd1243dSDimitry Andric return DiagID; 1184fe6060f1SDimitry Andric 1185bdd1243dSDimitry Andric return 0; 1186fe6060f1SDimitry Andric } 1187fe6060f1SDimitry Andric 11880b57cec5SDimitry Andric /// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is 11890b57cec5SDimitry Andric /// valid. 11900b57cec5SDimitry Andric /// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code 11910b57cec5SDimitry Andric /// like this: 11920b57cec5SDimitry Andric /// char *bytes = reinterpret_cast\<char*\>(int_ptr); 11930b57cec5SDimitry Andric void CastOperation::CheckReinterpretCast() { 1194fe6060f1SDimitry Andric if (ValueKind == VK_PRValue && !isPlaceholder(BuiltinType::Overload)) 11950b57cec5SDimitry Andric SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); 11960b57cec5SDimitry Andric else 11970b57cec5SDimitry Andric checkNonOverloadPlaceholders(); 11980b57cec5SDimitry Andric if (SrcExpr.isInvalid()) // if conversion failed, don't report another error 11990b57cec5SDimitry Andric return; 12000b57cec5SDimitry Andric 12010b57cec5SDimitry Andric unsigned msg = diag::err_bad_cxx_cast_generic; 12020b57cec5SDimitry Andric TryCastResult tcr = 12030b57cec5SDimitry Andric TryReinterpretCast(Self, SrcExpr, DestType, 12040b57cec5SDimitry Andric /*CStyle*/false, OpRange, msg, Kind); 12050b57cec5SDimitry Andric if (tcr != TC_Success && msg != 0) { 12060b57cec5SDimitry Andric if (SrcExpr.isInvalid()) // if conversion failed, don't report another error 12070b57cec5SDimitry Andric return; 12080b57cec5SDimitry Andric if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { 12090b57cec5SDimitry Andric //FIXME: &f<int>; is overloaded and resolvable 12100b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload) 12110b57cec5SDimitry Andric << OverloadExpr::find(SrcExpr.get()).Expression->getName() 12120b57cec5SDimitry Andric << DestType << OpRange; 12130b57cec5SDimitry Andric Self.NoteAllOverloadCandidates(SrcExpr.get()); 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric } else { 12160b57cec5SDimitry Andric diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), 12170b57cec5SDimitry Andric DestType, /*listInitialization=*/false); 12180b57cec5SDimitry Andric } 12190b57cec5SDimitry Andric } 12200b57cec5SDimitry Andric 12210b57cec5SDimitry Andric if (isValidCast(tcr)) { 12220b57cec5SDimitry Andric if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) 1223*0fca6ea1SDimitry Andric checkObjCConversion(CheckedConversionKind::OtherCast); 12240b57cec5SDimitry Andric DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange); 1225fe6060f1SDimitry Andric 1226bdd1243dSDimitry Andric if (unsigned DiagID = checkCastFunctionType(Self, SrcExpr, DestType)) 1227bdd1243dSDimitry Andric Self.Diag(OpRange.getBegin(), DiagID) 1228fe6060f1SDimitry Andric << SrcExpr.get()->getType() << DestType << OpRange; 12290b57cec5SDimitry Andric } else { 12300b57cec5SDimitry Andric SrcExpr = ExprError(); 12310b57cec5SDimitry Andric } 12320b57cec5SDimitry Andric } 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric /// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid. 12360b57cec5SDimitry Andric /// Refer to C++ 5.2.9 for details. Static casts are mostly used for making 12370b57cec5SDimitry Andric /// implicit conversions explicit and getting rid of data loss warnings. 12380b57cec5SDimitry Andric void CastOperation::CheckStaticCast() { 12395ffd83dbSDimitry Andric CheckNoDerefRAII NoderefCheck(*this); 12405ffd83dbSDimitry Andric 12410b57cec5SDimitry Andric if (isPlaceholder()) { 12420b57cec5SDimitry Andric checkNonOverloadPlaceholders(); 12430b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 12440b57cec5SDimitry Andric return; 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric // This test is outside everything else because it's the only case where 12480b57cec5SDimitry Andric // a non-lvalue-reference target type does not lead to decay. 12490b57cec5SDimitry Andric // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". 12500b57cec5SDimitry Andric if (DestType->isVoidType()) { 12510b57cec5SDimitry Andric Kind = CK_ToVoid; 12520b57cec5SDimitry Andric 12530b57cec5SDimitry Andric if (claimPlaceholder(BuiltinType::Overload)) { 12540b57cec5SDimitry Andric Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr, 12550b57cec5SDimitry Andric false, // Decay Function to ptr 12560b57cec5SDimitry Andric true, // Complain 12570b57cec5SDimitry Andric OpRange, DestType, diag::err_bad_static_cast_overload); 12580b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 12590b57cec5SDimitry Andric return; 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric SrcExpr = Self.IgnoredValueConversions(SrcExpr.get()); 12630b57cec5SDimitry Andric return; 12640b57cec5SDimitry Andric } 12650b57cec5SDimitry Andric 1266fe6060f1SDimitry Andric if (ValueKind == VK_PRValue && !DestType->isRecordType() && 12670b57cec5SDimitry Andric !isPlaceholder(BuiltinType::Overload)) { 12680b57cec5SDimitry Andric SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); 12690b57cec5SDimitry Andric if (SrcExpr.isInvalid()) // if conversion failed, don't report another error 12700b57cec5SDimitry Andric return; 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric 12730b57cec5SDimitry Andric unsigned msg = diag::err_bad_cxx_cast_generic; 1274*0fca6ea1SDimitry Andric TryCastResult tcr = 1275*0fca6ea1SDimitry Andric TryStaticCast(Self, SrcExpr, DestType, CheckedConversionKind::OtherCast, 1276*0fca6ea1SDimitry Andric OpRange, msg, Kind, BasePath, /*ListInitialization=*/false); 12770b57cec5SDimitry Andric if (tcr != TC_Success && msg != 0) { 12780b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 12790b57cec5SDimitry Andric return; 12800b57cec5SDimitry Andric if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { 12810b57cec5SDimitry Andric OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression; 12820b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload) 12830b57cec5SDimitry Andric << oe->getName() << DestType << OpRange 12840b57cec5SDimitry Andric << oe->getQualifierLoc().getSourceRange(); 12850b57cec5SDimitry Andric Self.NoteAllOverloadCandidates(SrcExpr.get()); 12860b57cec5SDimitry Andric } else { 12870b57cec5SDimitry Andric diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType, 12880b57cec5SDimitry Andric /*listInitialization=*/false); 12890b57cec5SDimitry Andric } 12900b57cec5SDimitry Andric } 12910b57cec5SDimitry Andric 12920b57cec5SDimitry Andric if (isValidCast(tcr)) { 12930b57cec5SDimitry Andric if (Kind == CK_BitCast) 12940b57cec5SDimitry Andric checkCastAlign(); 12950b57cec5SDimitry Andric if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) 1296*0fca6ea1SDimitry Andric checkObjCConversion(CheckedConversionKind::OtherCast); 12970b57cec5SDimitry Andric } else { 12980b57cec5SDimitry Andric SrcExpr = ExprError(); 12990b57cec5SDimitry Andric } 13000b57cec5SDimitry Andric } 13010b57cec5SDimitry Andric 13020b57cec5SDimitry Andric static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) { 13030b57cec5SDimitry Andric auto *SrcPtrType = SrcType->getAs<PointerType>(); 13040b57cec5SDimitry Andric if (!SrcPtrType) 13050b57cec5SDimitry Andric return false; 13060b57cec5SDimitry Andric auto *DestPtrType = DestType->getAs<PointerType>(); 13070b57cec5SDimitry Andric if (!DestPtrType) 13080b57cec5SDimitry Andric return false; 13090b57cec5SDimitry Andric return SrcPtrType->getPointeeType().getAddressSpace() != 13100b57cec5SDimitry Andric DestPtrType->getPointeeType().getAddressSpace(); 13110b57cec5SDimitry Andric } 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andric /// TryStaticCast - Check if a static cast can be performed, and do so if 13140b57cec5SDimitry Andric /// possible. If @p CStyle, ignore access restrictions on hierarchy casting 13150b57cec5SDimitry Andric /// and casting away constness. 13160b57cec5SDimitry Andric static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, 1317*0fca6ea1SDimitry Andric QualType DestType, CheckedConversionKind CCK, 13180b57cec5SDimitry Andric SourceRange OpRange, unsigned &msg, 13190b57cec5SDimitry Andric CastKind &Kind, CXXCastPath &BasePath, 13200b57cec5SDimitry Andric bool ListInitialization) { 13210b57cec5SDimitry Andric // Determine whether we have the semantics of a C-style cast. 1322*0fca6ea1SDimitry Andric bool CStyle = (CCK == CheckedConversionKind::CStyleCast || 1323*0fca6ea1SDimitry Andric CCK == CheckedConversionKind::FunctionalCast); 13240b57cec5SDimitry Andric 13250b57cec5SDimitry Andric // The order the tests is not entirely arbitrary. There is one conversion 13260b57cec5SDimitry Andric // that can be handled in two different ways. Given: 13270b57cec5SDimitry Andric // struct A {}; 13280b57cec5SDimitry Andric // struct B : public A { 13290b57cec5SDimitry Andric // B(); B(const A&); 13300b57cec5SDimitry Andric // }; 13310b57cec5SDimitry Andric // const A &a = B(); 13320b57cec5SDimitry Andric // the cast static_cast<const B&>(a) could be seen as either a static 13330b57cec5SDimitry Andric // reference downcast, or an explicit invocation of the user-defined 13340b57cec5SDimitry Andric // conversion using B's conversion constructor. 13350b57cec5SDimitry Andric // DR 427 specifies that the downcast is to be applied here. 13360b57cec5SDimitry Andric 13370b57cec5SDimitry Andric // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". 13380b57cec5SDimitry Andric // Done outside this function. 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric TryCastResult tcr; 13410b57cec5SDimitry Andric 13420b57cec5SDimitry Andric // C++ 5.2.9p5, reference downcast. 13430b57cec5SDimitry Andric // See the function for details. 13440b57cec5SDimitry Andric // DR 427 specifies that this is to be applied before paragraph 2. 13450b57cec5SDimitry Andric tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, 13460b57cec5SDimitry Andric OpRange, msg, Kind, BasePath); 13470b57cec5SDimitry Andric if (tcr != TC_NotApplicable) 13480b57cec5SDimitry Andric return tcr; 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric // C++11 [expr.static.cast]p3: 13510b57cec5SDimitry Andric // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2 13520b57cec5SDimitry Andric // T2" if "cv2 T2" is reference-compatible with "cv1 T1". 13530b57cec5SDimitry Andric tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, 13540b57cec5SDimitry Andric BasePath, msg); 13550b57cec5SDimitry Andric if (tcr != TC_NotApplicable) 13560b57cec5SDimitry Andric return tcr; 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric // C++ 5.2.9p2: An expression e can be explicitly converted to a type T 13590b57cec5SDimitry Andric // [...] if the declaration "T t(e);" is well-formed, [...]. 13600b57cec5SDimitry Andric tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg, 13610b57cec5SDimitry Andric Kind, ListInitialization); 13620b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 13630b57cec5SDimitry Andric return TC_Failed; 13640b57cec5SDimitry Andric if (tcr != TC_NotApplicable) 13650b57cec5SDimitry Andric return tcr; 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric // C++ 5.2.9p6: May apply the reverse of any standard conversion, except 13680b57cec5SDimitry Andric // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean 13690b57cec5SDimitry Andric // conversions, subject to further restrictions. 13700b57cec5SDimitry Andric // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal 1371349cc55cSDimitry Andric // of qualification conversions impossible. (In C++20, adding an array bound 1372349cc55cSDimitry Andric // would be the reverse of a qualification conversion, but adding permission 1373349cc55cSDimitry Andric // to add an array bound in a static_cast is a wording oversight.) 13740b57cec5SDimitry Andric // In the CStyle case, the earlier attempt to const_cast should have taken 13750b57cec5SDimitry Andric // care of reverse qualification conversions. 13760b57cec5SDimitry Andric 13770b57cec5SDimitry Andric QualType SrcType = Self.Context.getCanonicalType(SrcExpr.get()->getType()); 13780b57cec5SDimitry Andric 13790b57cec5SDimitry Andric // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly 13800b57cec5SDimitry Andric // converted to an integral type. [...] A value of a scoped enumeration type 13810b57cec5SDimitry Andric // can also be explicitly converted to a floating-point type [...]. 13820b57cec5SDimitry Andric if (const EnumType *Enum = SrcType->getAs<EnumType>()) { 13830b57cec5SDimitry Andric if (Enum->getDecl()->isScoped()) { 13840b57cec5SDimitry Andric if (DestType->isBooleanType()) { 13850b57cec5SDimitry Andric Kind = CK_IntegralToBoolean; 13860b57cec5SDimitry Andric return TC_Success; 13870b57cec5SDimitry Andric } else if (DestType->isIntegralType(Self.Context)) { 13880b57cec5SDimitry Andric Kind = CK_IntegralCast; 13890b57cec5SDimitry Andric return TC_Success; 13900b57cec5SDimitry Andric } else if (DestType->isRealFloatingType()) { 13910b57cec5SDimitry Andric Kind = CK_IntegralToFloating; 13920b57cec5SDimitry Andric return TC_Success; 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric } 13950b57cec5SDimitry Andric } 13960b57cec5SDimitry Andric 13970b57cec5SDimitry Andric // Reverse integral promotion/conversion. All such conversions are themselves 13980b57cec5SDimitry Andric // again integral promotions or conversions and are thus already handled by 13990b57cec5SDimitry Andric // p2 (TryDirectInitialization above). 14000b57cec5SDimitry Andric // (Note: any data loss warnings should be suppressed.) 14010b57cec5SDimitry Andric // The exception is the reverse of enum->integer, i.e. integer->enum (and 14020b57cec5SDimitry Andric // enum->enum). See also C++ 5.2.9p7. 14030b57cec5SDimitry Andric // The same goes for reverse floating point promotion/conversion and 14040b57cec5SDimitry Andric // floating-integral conversions. Again, only floating->enum is relevant. 14050b57cec5SDimitry Andric if (DestType->isEnumeralType()) { 1406480093f4SDimitry Andric if (Self.RequireCompleteType(OpRange.getBegin(), DestType, 1407480093f4SDimitry Andric diag::err_bad_cast_incomplete)) { 1408480093f4SDimitry Andric SrcExpr = ExprError(); 1409480093f4SDimitry Andric return TC_Failed; 1410480093f4SDimitry Andric } 14110b57cec5SDimitry Andric if (SrcType->isIntegralOrEnumerationType()) { 1412e8d8bef9SDimitry Andric // [expr.static.cast]p10 If the enumeration type has a fixed underlying 1413e8d8bef9SDimitry Andric // type, the value is first converted to that type by integral conversion 141481ad6265SDimitry Andric const EnumType *Enum = DestType->castAs<EnumType>(); 1415e8d8bef9SDimitry Andric Kind = Enum->getDecl()->isFixed() && 1416e8d8bef9SDimitry Andric Enum->getDecl()->getIntegerType()->isBooleanType() 1417e8d8bef9SDimitry Andric ? CK_IntegralToBoolean 1418e8d8bef9SDimitry Andric : CK_IntegralCast; 14190b57cec5SDimitry Andric return TC_Success; 14200b57cec5SDimitry Andric } else if (SrcType->isRealFloatingType()) { 14210b57cec5SDimitry Andric Kind = CK_FloatingToIntegral; 14220b57cec5SDimitry Andric return TC_Success; 14230b57cec5SDimitry Andric } 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric 14260b57cec5SDimitry Andric // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast. 14270b57cec5SDimitry Andric // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance. 14280b57cec5SDimitry Andric tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg, 14290b57cec5SDimitry Andric Kind, BasePath); 14300b57cec5SDimitry Andric if (tcr != TC_NotApplicable) 14310b57cec5SDimitry Andric return tcr; 14320b57cec5SDimitry Andric 14330b57cec5SDimitry Andric // Reverse member pointer conversion. C++ 4.11 specifies member pointer 14340b57cec5SDimitry Andric // conversion. C++ 5.2.9p9 has additional information. 14350b57cec5SDimitry Andric // DR54's access restrictions apply here also. 14360b57cec5SDimitry Andric tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle, 14370b57cec5SDimitry Andric OpRange, msg, Kind, BasePath); 14380b57cec5SDimitry Andric if (tcr != TC_NotApplicable) 14390b57cec5SDimitry Andric return tcr; 14400b57cec5SDimitry Andric 14410b57cec5SDimitry Andric // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to 14420b57cec5SDimitry Andric // void*. C++ 5.2.9p10 specifies additional restrictions, which really is 14430b57cec5SDimitry Andric // just the usual constness stuff. 14440b57cec5SDimitry Andric if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) { 14450b57cec5SDimitry Andric QualType SrcPointee = SrcPointer->getPointeeType(); 14460b57cec5SDimitry Andric if (SrcPointee->isVoidType()) { 14470b57cec5SDimitry Andric if (const PointerType *DestPointer = DestType->getAs<PointerType>()) { 14480b57cec5SDimitry Andric QualType DestPointee = DestPointer->getPointeeType(); 14490b57cec5SDimitry Andric if (DestPointee->isIncompleteOrObjectType()) { 14500b57cec5SDimitry Andric // This is definitely the intended conversion, but it might fail due 14510b57cec5SDimitry Andric // to a qualifier violation. Note that we permit Objective-C lifetime 14520b57cec5SDimitry Andric // and GC qualifier mismatches here. 14530b57cec5SDimitry Andric if (!CStyle) { 14540b57cec5SDimitry Andric Qualifiers DestPointeeQuals = DestPointee.getQualifiers(); 14550b57cec5SDimitry Andric Qualifiers SrcPointeeQuals = SrcPointee.getQualifiers(); 14560b57cec5SDimitry Andric DestPointeeQuals.removeObjCGCAttr(); 14570b57cec5SDimitry Andric DestPointeeQuals.removeObjCLifetime(); 14580b57cec5SDimitry Andric SrcPointeeQuals.removeObjCGCAttr(); 14590b57cec5SDimitry Andric SrcPointeeQuals.removeObjCLifetime(); 14600b57cec5SDimitry Andric if (DestPointeeQuals != SrcPointeeQuals && 14610b57cec5SDimitry Andric !DestPointeeQuals.compatiblyIncludes(SrcPointeeQuals)) { 14620b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_qualifiers_away; 14630b57cec5SDimitry Andric return TC_Failed; 14640b57cec5SDimitry Andric } 14650b57cec5SDimitry Andric } 14660b57cec5SDimitry Andric Kind = IsAddressSpaceConversion(SrcType, DestType) 14670b57cec5SDimitry Andric ? CK_AddressSpaceConversion 14680b57cec5SDimitry Andric : CK_BitCast; 14690b57cec5SDimitry Andric return TC_Success; 14700b57cec5SDimitry Andric } 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric // Microsoft permits static_cast from 'pointer-to-void' to 14730b57cec5SDimitry Andric // 'pointer-to-function'. 14740b57cec5SDimitry Andric if (!CStyle && Self.getLangOpts().MSVCCompat && 14750b57cec5SDimitry Andric DestPointee->isFunctionType()) { 14760b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::ext_ms_cast_fn_obj) << OpRange; 14770b57cec5SDimitry Andric Kind = CK_BitCast; 14780b57cec5SDimitry Andric return TC_Success; 14790b57cec5SDimitry Andric } 14800b57cec5SDimitry Andric } 14810b57cec5SDimitry Andric else if (DestType->isObjCObjectPointerType()) { 14820b57cec5SDimitry Andric // allow both c-style cast and static_cast of objective-c pointers as 14830b57cec5SDimitry Andric // they are pervasive. 14840b57cec5SDimitry Andric Kind = CK_CPointerToObjCPointerCast; 14850b57cec5SDimitry Andric return TC_Success; 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric else if (CStyle && DestType->isBlockPointerType()) { 14880b57cec5SDimitry Andric // allow c-style cast of void * to block pointers. 14890b57cec5SDimitry Andric Kind = CK_AnyPointerToBlockPointerCast; 14900b57cec5SDimitry Andric return TC_Success; 14910b57cec5SDimitry Andric } 14920b57cec5SDimitry Andric } 14930b57cec5SDimitry Andric } 14940b57cec5SDimitry Andric // Allow arbitrary objective-c pointer conversion with static casts. 14950b57cec5SDimitry Andric if (SrcType->isObjCObjectPointerType() && 14960b57cec5SDimitry Andric DestType->isObjCObjectPointerType()) { 14970b57cec5SDimitry Andric Kind = CK_BitCast; 14980b57cec5SDimitry Andric return TC_Success; 14990b57cec5SDimitry Andric } 15000b57cec5SDimitry Andric // Allow ns-pointer to cf-pointer conversion in either direction 15010b57cec5SDimitry Andric // with static casts. 15020b57cec5SDimitry Andric if (!CStyle && 1503*0fca6ea1SDimitry Andric Self.ObjC().CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind)) 15040b57cec5SDimitry Andric return TC_Success; 15050b57cec5SDimitry Andric 15060b57cec5SDimitry Andric // See if it looks like the user is trying to convert between 15070b57cec5SDimitry Andric // related record types, and select a better diagnostic if so. 15080b57cec5SDimitry Andric if (auto SrcPointer = SrcType->getAs<PointerType>()) 15090b57cec5SDimitry Andric if (auto DestPointer = DestType->getAs<PointerType>()) 15100b57cec5SDimitry Andric if (SrcPointer->getPointeeType()->getAs<RecordType>() && 15110b57cec5SDimitry Andric DestPointer->getPointeeType()->getAs<RecordType>()) 15120b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_unrelated_class; 15130b57cec5SDimitry Andric 1514fe6060f1SDimitry Andric if (SrcType->isMatrixType() && DestType->isMatrixType()) { 1515fe6060f1SDimitry Andric if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind)) { 1516fe6060f1SDimitry Andric SrcExpr = ExprError(); 1517fe6060f1SDimitry Andric return TC_Failed; 1518fe6060f1SDimitry Andric } 1519fe6060f1SDimitry Andric return TC_Success; 1520fe6060f1SDimitry Andric } 1521fe6060f1SDimitry Andric 15220b57cec5SDimitry Andric // We tried everything. Everything! Nothing works! :-( 15230b57cec5SDimitry Andric return TC_NotApplicable; 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric 15260b57cec5SDimitry Andric /// Tests whether a conversion according to N2844 is valid. 15270b57cec5SDimitry Andric TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, 15280b57cec5SDimitry Andric QualType DestType, bool CStyle, 15290b57cec5SDimitry Andric CastKind &Kind, CXXCastPath &BasePath, 15300b57cec5SDimitry Andric unsigned &msg) { 15310b57cec5SDimitry Andric // C++11 [expr.static.cast]p3: 15320b57cec5SDimitry Andric // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to 15330b57cec5SDimitry Andric // cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". 15340b57cec5SDimitry Andric const RValueReferenceType *R = DestType->getAs<RValueReferenceType>(); 15350b57cec5SDimitry Andric if (!R) 15360b57cec5SDimitry Andric return TC_NotApplicable; 15370b57cec5SDimitry Andric 15380b57cec5SDimitry Andric if (!SrcExpr->isGLValue()) 15390b57cec5SDimitry Andric return TC_NotApplicable; 15400b57cec5SDimitry Andric 15410b57cec5SDimitry Andric // Because we try the reference downcast before this function, from now on 15420b57cec5SDimitry Andric // this is the only cast possibility, so we issue an error if we fail now. 15430b57cec5SDimitry Andric // FIXME: Should allow casting away constness if CStyle. 15440b57cec5SDimitry Andric QualType FromType = SrcExpr->getType(); 15450b57cec5SDimitry Andric QualType ToType = R->getPointeeType(); 15460b57cec5SDimitry Andric if (CStyle) { 15470b57cec5SDimitry Andric FromType = FromType.getUnqualifiedType(); 15480b57cec5SDimitry Andric ToType = ToType.getUnqualifiedType(); 15490b57cec5SDimitry Andric } 15500b57cec5SDimitry Andric 1551480093f4SDimitry Andric Sema::ReferenceConversions RefConv; 15520b57cec5SDimitry Andric Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship( 1553480093f4SDimitry Andric SrcExpr->getBeginLoc(), ToType, FromType, &RefConv); 15540b57cec5SDimitry Andric if (RefResult != Sema::Ref_Compatible) { 15550b57cec5SDimitry Andric if (CStyle || RefResult == Sema::Ref_Incompatible) 15560b57cec5SDimitry Andric return TC_NotApplicable; 15570b57cec5SDimitry Andric // Diagnose types which are reference-related but not compatible here since 15580b57cec5SDimitry Andric // we can provide better diagnostics. In these cases forwarding to 15590b57cec5SDimitry Andric // [expr.static.cast]p4 should never result in a well-formed cast. 15600b57cec5SDimitry Andric msg = SrcExpr->isLValue() ? diag::err_bad_lvalue_to_rvalue_cast 15610b57cec5SDimitry Andric : diag::err_bad_rvalue_to_rvalue_cast; 15620b57cec5SDimitry Andric return TC_Failed; 15630b57cec5SDimitry Andric } 15640b57cec5SDimitry Andric 1565480093f4SDimitry Andric if (RefConv & Sema::ReferenceConversions::DerivedToBase) { 15660b57cec5SDimitry Andric Kind = CK_DerivedToBase; 15670b57cec5SDimitry Andric CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 15680b57cec5SDimitry Andric /*DetectVirtual=*/true); 15690b57cec5SDimitry Andric if (!Self.IsDerivedFrom(SrcExpr->getBeginLoc(), SrcExpr->getType(), 15700b57cec5SDimitry Andric R->getPointeeType(), Paths)) 15710b57cec5SDimitry Andric return TC_NotApplicable; 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric Self.BuildBasePathArray(Paths, BasePath); 15740b57cec5SDimitry Andric } else 15750b57cec5SDimitry Andric Kind = CK_NoOp; 15760b57cec5SDimitry Andric 15770b57cec5SDimitry Andric return TC_Success; 15780b57cec5SDimitry Andric } 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric /// Tests whether a conversion according to C++ 5.2.9p5 is valid. 15810b57cec5SDimitry Andric TryCastResult 15820b57cec5SDimitry Andric TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, 15830b57cec5SDimitry Andric bool CStyle, SourceRange OpRange, 15840b57cec5SDimitry Andric unsigned &msg, CastKind &Kind, 15850b57cec5SDimitry Andric CXXCastPath &BasePath) { 15860b57cec5SDimitry Andric // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be 15870b57cec5SDimitry Andric // cast to type "reference to cv2 D", where D is a class derived from B, 15880b57cec5SDimitry Andric // if a valid standard conversion from "pointer to D" to "pointer to B" 15890b57cec5SDimitry Andric // exists, cv2 >= cv1, and B is not a virtual base class of D. 15900b57cec5SDimitry Andric // In addition, DR54 clarifies that the base must be accessible in the 15910b57cec5SDimitry Andric // current context. Although the wording of DR54 only applies to the pointer 15920b57cec5SDimitry Andric // variant of this rule, the intent is clearly for it to apply to the this 15930b57cec5SDimitry Andric // conversion as well. 15940b57cec5SDimitry Andric 15950b57cec5SDimitry Andric const ReferenceType *DestReference = DestType->getAs<ReferenceType>(); 15960b57cec5SDimitry Andric if (!DestReference) { 15970b57cec5SDimitry Andric return TC_NotApplicable; 15980b57cec5SDimitry Andric } 15990b57cec5SDimitry Andric bool RValueRef = DestReference->isRValueReferenceType(); 16000b57cec5SDimitry Andric if (!RValueRef && !SrcExpr->isLValue()) { 16010b57cec5SDimitry Andric // We know the left side is an lvalue reference, so we can suggest a reason. 16020b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_rvalue; 16030b57cec5SDimitry Andric return TC_NotApplicable; 16040b57cec5SDimitry Andric } 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric QualType DestPointee = DestReference->getPointeeType(); 16070b57cec5SDimitry Andric 16080b57cec5SDimitry Andric // FIXME: If the source is a prvalue, we should issue a warning (because the 16090b57cec5SDimitry Andric // cast always has undefined behavior), and for AST consistency, we should 16100b57cec5SDimitry Andric // materialize a temporary. 16110b57cec5SDimitry Andric return TryStaticDowncast(Self, 16120b57cec5SDimitry Andric Self.Context.getCanonicalType(SrcExpr->getType()), 16130b57cec5SDimitry Andric Self.Context.getCanonicalType(DestPointee), CStyle, 16140b57cec5SDimitry Andric OpRange, SrcExpr->getType(), DestType, msg, Kind, 16150b57cec5SDimitry Andric BasePath); 16160b57cec5SDimitry Andric } 16170b57cec5SDimitry Andric 16180b57cec5SDimitry Andric /// Tests whether a conversion according to C++ 5.2.9p8 is valid. 16190b57cec5SDimitry Andric TryCastResult 16200b57cec5SDimitry Andric TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, 16210b57cec5SDimitry Andric bool CStyle, SourceRange OpRange, 16220b57cec5SDimitry Andric unsigned &msg, CastKind &Kind, 16230b57cec5SDimitry Andric CXXCastPath &BasePath) { 16240b57cec5SDimitry Andric // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class 16250b57cec5SDimitry Andric // type, can be converted to an rvalue of type "pointer to cv2 D", where D 16260b57cec5SDimitry Andric // is a class derived from B, if a valid standard conversion from "pointer 16270b57cec5SDimitry Andric // to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base 16280b57cec5SDimitry Andric // class of D. 16290b57cec5SDimitry Andric // In addition, DR54 clarifies that the base must be accessible in the 16300b57cec5SDimitry Andric // current context. 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric const PointerType *DestPointer = DestType->getAs<PointerType>(); 16330b57cec5SDimitry Andric if (!DestPointer) { 16340b57cec5SDimitry Andric return TC_NotApplicable; 16350b57cec5SDimitry Andric } 16360b57cec5SDimitry Andric 16370b57cec5SDimitry Andric const PointerType *SrcPointer = SrcType->getAs<PointerType>(); 16380b57cec5SDimitry Andric if (!SrcPointer) { 16390b57cec5SDimitry Andric msg = diag::err_bad_static_cast_pointer_nonpointer; 16400b57cec5SDimitry Andric return TC_NotApplicable; 16410b57cec5SDimitry Andric } 16420b57cec5SDimitry Andric 16430b57cec5SDimitry Andric return TryStaticDowncast(Self, 16440b57cec5SDimitry Andric Self.Context.getCanonicalType(SrcPointer->getPointeeType()), 16450b57cec5SDimitry Andric Self.Context.getCanonicalType(DestPointer->getPointeeType()), 16460b57cec5SDimitry Andric CStyle, OpRange, SrcType, DestType, msg, Kind, 16470b57cec5SDimitry Andric BasePath); 16480b57cec5SDimitry Andric } 16490b57cec5SDimitry Andric 16500b57cec5SDimitry Andric /// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and 16510b57cec5SDimitry Andric /// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to 16520b57cec5SDimitry Andric /// DestType is possible and allowed. 16530b57cec5SDimitry Andric TryCastResult 16540b57cec5SDimitry Andric TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, 16550b57cec5SDimitry Andric bool CStyle, SourceRange OpRange, QualType OrigSrcType, 16560b57cec5SDimitry Andric QualType OrigDestType, unsigned &msg, 16570b57cec5SDimitry Andric CastKind &Kind, CXXCastPath &BasePath) { 16580b57cec5SDimitry Andric // We can only work with complete types. But don't complain if it doesn't work 16590b57cec5SDimitry Andric if (!Self.isCompleteType(OpRange.getBegin(), SrcType) || 16600b57cec5SDimitry Andric !Self.isCompleteType(OpRange.getBegin(), DestType)) 16610b57cec5SDimitry Andric return TC_NotApplicable; 16620b57cec5SDimitry Andric 16630b57cec5SDimitry Andric // Downcast can only happen in class hierarchies, so we need classes. 16640b57cec5SDimitry Andric if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) { 16650b57cec5SDimitry Andric return TC_NotApplicable; 16660b57cec5SDimitry Andric } 16670b57cec5SDimitry Andric 16680b57cec5SDimitry Andric CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 16690b57cec5SDimitry Andric /*DetectVirtual=*/true); 16700b57cec5SDimitry Andric if (!Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths)) { 16710b57cec5SDimitry Andric return TC_NotApplicable; 16720b57cec5SDimitry Andric } 16730b57cec5SDimitry Andric 16740b57cec5SDimitry Andric // Target type does derive from source type. Now we're serious. If an error 16750b57cec5SDimitry Andric // appears now, it's not ignored. 16760b57cec5SDimitry Andric // This may not be entirely in line with the standard. Take for example: 16770b57cec5SDimitry Andric // struct A {}; 16780b57cec5SDimitry Andric // struct B : virtual A { 16790b57cec5SDimitry Andric // B(A&); 16800b57cec5SDimitry Andric // }; 16810b57cec5SDimitry Andric // 16820b57cec5SDimitry Andric // void f() 16830b57cec5SDimitry Andric // { 16840b57cec5SDimitry Andric // (void)static_cast<const B&>(*((A*)0)); 16850b57cec5SDimitry Andric // } 16860b57cec5SDimitry Andric // As far as the standard is concerned, p5 does not apply (A is virtual), so 16870b57cec5SDimitry Andric // p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid. 16880b57cec5SDimitry Andric // However, both GCC and Comeau reject this example, and accepting it would 16890b57cec5SDimitry Andric // mean more complex code if we're to preserve the nice error message. 16900b57cec5SDimitry Andric // FIXME: Being 100% compliant here would be nice to have. 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric // Must preserve cv, as always, unless we're in C-style mode. 16930b57cec5SDimitry Andric if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) { 16940b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_qualifiers_away; 16950b57cec5SDimitry Andric return TC_Failed; 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric 16980b57cec5SDimitry Andric if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) { 16990b57cec5SDimitry Andric // This code is analoguous to that in CheckDerivedToBaseConversion, except 17000b57cec5SDimitry Andric // that it builds the paths in reverse order. 17010b57cec5SDimitry Andric // To sum up: record all paths to the base and build a nice string from 17020b57cec5SDimitry Andric // them. Use it to spice up the error message. 17030b57cec5SDimitry Andric if (!Paths.isRecordingPaths()) { 17040b57cec5SDimitry Andric Paths.clear(); 17050b57cec5SDimitry Andric Paths.setRecordingPaths(true); 17060b57cec5SDimitry Andric Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths); 17070b57cec5SDimitry Andric } 17080b57cec5SDimitry Andric std::string PathDisplayStr; 17090b57cec5SDimitry Andric std::set<unsigned> DisplayedPaths; 17100b57cec5SDimitry Andric for (clang::CXXBasePath &Path : Paths) { 17110b57cec5SDimitry Andric if (DisplayedPaths.insert(Path.back().SubobjectNumber).second) { 17120b57cec5SDimitry Andric // We haven't displayed a path to this particular base 17130b57cec5SDimitry Andric // class subobject yet. 17140b57cec5SDimitry Andric PathDisplayStr += "\n "; 17150b57cec5SDimitry Andric for (CXXBasePathElement &PE : llvm::reverse(Path)) 17160b57cec5SDimitry Andric PathDisplayStr += PE.Base->getType().getAsString() + " -> "; 17170b57cec5SDimitry Andric PathDisplayStr += QualType(DestType).getAsString(); 17180b57cec5SDimitry Andric } 17190b57cec5SDimitry Andric } 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast) 17220b57cec5SDimitry Andric << QualType(SrcType).getUnqualifiedType() 17230b57cec5SDimitry Andric << QualType(DestType).getUnqualifiedType() 17240b57cec5SDimitry Andric << PathDisplayStr << OpRange; 17250b57cec5SDimitry Andric msg = 0; 17260b57cec5SDimitry Andric return TC_Failed; 17270b57cec5SDimitry Andric } 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric if (Paths.getDetectedVirtual() != nullptr) { 17300b57cec5SDimitry Andric QualType VirtualBase(Paths.getDetectedVirtual(), 0); 17310b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual) 17320b57cec5SDimitry Andric << OrigSrcType << OrigDestType << VirtualBase << OpRange; 17330b57cec5SDimitry Andric msg = 0; 17340b57cec5SDimitry Andric return TC_Failed; 17350b57cec5SDimitry Andric } 17360b57cec5SDimitry Andric 17370b57cec5SDimitry Andric if (!CStyle) { 17380b57cec5SDimitry Andric switch (Self.CheckBaseClassAccess(OpRange.getBegin(), 17390b57cec5SDimitry Andric SrcType, DestType, 17400b57cec5SDimitry Andric Paths.front(), 17410b57cec5SDimitry Andric diag::err_downcast_from_inaccessible_base)) { 17420b57cec5SDimitry Andric case Sema::AR_accessible: 17430b57cec5SDimitry Andric case Sema::AR_delayed: // be optimistic 17440b57cec5SDimitry Andric case Sema::AR_dependent: // be optimistic 17450b57cec5SDimitry Andric break; 17460b57cec5SDimitry Andric 17470b57cec5SDimitry Andric case Sema::AR_inaccessible: 17480b57cec5SDimitry Andric msg = 0; 17490b57cec5SDimitry Andric return TC_Failed; 17500b57cec5SDimitry Andric } 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric 17530b57cec5SDimitry Andric Self.BuildBasePathArray(Paths, BasePath); 17540b57cec5SDimitry Andric Kind = CK_BaseToDerived; 17550b57cec5SDimitry Andric return TC_Success; 17560b57cec5SDimitry Andric } 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric /// TryStaticMemberPointerUpcast - Tests whether a conversion according to 17590b57cec5SDimitry Andric /// C++ 5.2.9p9 is valid: 17600b57cec5SDimitry Andric /// 17610b57cec5SDimitry Andric /// An rvalue of type "pointer to member of D of type cv1 T" can be 17620b57cec5SDimitry Andric /// converted to an rvalue of type "pointer to member of B of type cv2 T", 17630b57cec5SDimitry Andric /// where B is a base class of D [...]. 17640b57cec5SDimitry Andric /// 17650b57cec5SDimitry Andric TryCastResult 17660b57cec5SDimitry Andric TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, 17670b57cec5SDimitry Andric QualType DestType, bool CStyle, 17680b57cec5SDimitry Andric SourceRange OpRange, 17690b57cec5SDimitry Andric unsigned &msg, CastKind &Kind, 17700b57cec5SDimitry Andric CXXCastPath &BasePath) { 17710b57cec5SDimitry Andric const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(); 17720b57cec5SDimitry Andric if (!DestMemPtr) 17730b57cec5SDimitry Andric return TC_NotApplicable; 17740b57cec5SDimitry Andric 17750b57cec5SDimitry Andric bool WasOverloadedFunction = false; 17760b57cec5SDimitry Andric DeclAccessPair FoundOverload; 17770b57cec5SDimitry Andric if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { 17780b57cec5SDimitry Andric if (FunctionDecl *Fn 17790b57cec5SDimitry Andric = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false, 17800b57cec5SDimitry Andric FoundOverload)) { 17810b57cec5SDimitry Andric CXXMethodDecl *M = cast<CXXMethodDecl>(Fn); 17820b57cec5SDimitry Andric SrcType = Self.Context.getMemberPointerType(Fn->getType(), 17830b57cec5SDimitry Andric Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); 17840b57cec5SDimitry Andric WasOverloadedFunction = true; 17850b57cec5SDimitry Andric } 17860b57cec5SDimitry Andric } 17870b57cec5SDimitry Andric 17880b57cec5SDimitry Andric const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>(); 17890b57cec5SDimitry Andric if (!SrcMemPtr) { 17900b57cec5SDimitry Andric msg = diag::err_bad_static_cast_member_pointer_nonmp; 17910b57cec5SDimitry Andric return TC_NotApplicable; 17920b57cec5SDimitry Andric } 17930b57cec5SDimitry Andric 17940b57cec5SDimitry Andric // Lock down the inheritance model right now in MS ABI, whether or not the 17950b57cec5SDimitry Andric // pointee types are the same. 17960b57cec5SDimitry Andric if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) { 17970b57cec5SDimitry Andric (void)Self.isCompleteType(OpRange.getBegin(), SrcType); 17980b57cec5SDimitry Andric (void)Self.isCompleteType(OpRange.getBegin(), DestType); 17990b57cec5SDimitry Andric } 18000b57cec5SDimitry Andric 18010b57cec5SDimitry Andric // T == T, modulo cv 18020b57cec5SDimitry Andric if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(), 18030b57cec5SDimitry Andric DestMemPtr->getPointeeType())) 18040b57cec5SDimitry Andric return TC_NotApplicable; 18050b57cec5SDimitry Andric 18060b57cec5SDimitry Andric // B base of D 18070b57cec5SDimitry Andric QualType SrcClass(SrcMemPtr->getClass(), 0); 18080b57cec5SDimitry Andric QualType DestClass(DestMemPtr->getClass(), 0); 18090b57cec5SDimitry Andric CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, 18100b57cec5SDimitry Andric /*DetectVirtual=*/true); 18110b57cec5SDimitry Andric if (!Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths)) 18120b57cec5SDimitry Andric return TC_NotApplicable; 18130b57cec5SDimitry Andric 18140b57cec5SDimitry Andric // B is a base of D. But is it an allowed base? If not, it's a hard error. 18150b57cec5SDimitry Andric if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) { 18160b57cec5SDimitry Andric Paths.clear(); 18170b57cec5SDimitry Andric Paths.setRecordingPaths(true); 18180b57cec5SDimitry Andric bool StillOkay = 18190b57cec5SDimitry Andric Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths); 18200b57cec5SDimitry Andric assert(StillOkay); 18210b57cec5SDimitry Andric (void)StillOkay; 18220b57cec5SDimitry Andric std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths); 18230b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv) 18240b57cec5SDimitry Andric << 1 << SrcClass << DestClass << PathDisplayStr << OpRange; 18250b57cec5SDimitry Andric msg = 0; 18260b57cec5SDimitry Andric return TC_Failed; 18270b57cec5SDimitry Andric } 18280b57cec5SDimitry Andric 18290b57cec5SDimitry Andric if (const RecordType *VBase = Paths.getDetectedVirtual()) { 18300b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual) 18310b57cec5SDimitry Andric << SrcClass << DestClass << QualType(VBase, 0) << OpRange; 18320b57cec5SDimitry Andric msg = 0; 18330b57cec5SDimitry Andric return TC_Failed; 18340b57cec5SDimitry Andric } 18350b57cec5SDimitry Andric 18360b57cec5SDimitry Andric if (!CStyle) { 18370b57cec5SDimitry Andric switch (Self.CheckBaseClassAccess(OpRange.getBegin(), 18380b57cec5SDimitry Andric DestClass, SrcClass, 18390b57cec5SDimitry Andric Paths.front(), 18400b57cec5SDimitry Andric diag::err_upcast_to_inaccessible_base)) { 18410b57cec5SDimitry Andric case Sema::AR_accessible: 18420b57cec5SDimitry Andric case Sema::AR_delayed: 18430b57cec5SDimitry Andric case Sema::AR_dependent: 18440b57cec5SDimitry Andric // Optimistically assume that the delayed and dependent cases 18450b57cec5SDimitry Andric // will work out. 18460b57cec5SDimitry Andric break; 18470b57cec5SDimitry Andric 18480b57cec5SDimitry Andric case Sema::AR_inaccessible: 18490b57cec5SDimitry Andric msg = 0; 18500b57cec5SDimitry Andric return TC_Failed; 18510b57cec5SDimitry Andric } 18520b57cec5SDimitry Andric } 18530b57cec5SDimitry Andric 18540b57cec5SDimitry Andric if (WasOverloadedFunction) { 18550b57cec5SDimitry Andric // Resolve the address of the overloaded function again, this time 18560b57cec5SDimitry Andric // allowing complaints if something goes wrong. 18570b57cec5SDimitry Andric FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), 18580b57cec5SDimitry Andric DestType, 18590b57cec5SDimitry Andric true, 18600b57cec5SDimitry Andric FoundOverload); 18610b57cec5SDimitry Andric if (!Fn) { 18620b57cec5SDimitry Andric msg = 0; 18630b57cec5SDimitry Andric return TC_Failed; 18640b57cec5SDimitry Andric } 18650b57cec5SDimitry Andric 18660b57cec5SDimitry Andric SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn); 18670b57cec5SDimitry Andric if (!SrcExpr.isUsable()) { 18680b57cec5SDimitry Andric msg = 0; 18690b57cec5SDimitry Andric return TC_Failed; 18700b57cec5SDimitry Andric } 18710b57cec5SDimitry Andric } 18720b57cec5SDimitry Andric 18730b57cec5SDimitry Andric Self.BuildBasePathArray(Paths, BasePath); 18740b57cec5SDimitry Andric Kind = CK_DerivedToBaseMemberPointer; 18750b57cec5SDimitry Andric return TC_Success; 18760b57cec5SDimitry Andric } 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric /// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2 18790b57cec5SDimitry Andric /// is valid: 18800b57cec5SDimitry Andric /// 18810b57cec5SDimitry Andric /// An expression e can be explicitly converted to a type T using a 18820b57cec5SDimitry Andric /// @c static_cast if the declaration "T t(e);" is well-formed [...]. 1883*0fca6ea1SDimitry Andric TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, 1884*0fca6ea1SDimitry Andric QualType DestType, 1885*0fca6ea1SDimitry Andric CheckedConversionKind CCK, 18860b57cec5SDimitry Andric SourceRange OpRange, unsigned &msg, 18870b57cec5SDimitry Andric CastKind &Kind, bool ListInitialization) { 18880b57cec5SDimitry Andric if (DestType->isRecordType()) { 18890b57cec5SDimitry Andric if (Self.RequireCompleteType(OpRange.getBegin(), DestType, 1890480093f4SDimitry Andric diag::err_bad_cast_incomplete) || 18910b57cec5SDimitry Andric Self.RequireNonAbstractType(OpRange.getBegin(), DestType, 18920b57cec5SDimitry Andric diag::err_allocation_of_abstract_type)) { 18930b57cec5SDimitry Andric msg = 0; 18940b57cec5SDimitry Andric return TC_Failed; 18950b57cec5SDimitry Andric } 18960b57cec5SDimitry Andric } 18970b57cec5SDimitry Andric 18980b57cec5SDimitry Andric InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); 1899*0fca6ea1SDimitry Andric InitializationKind InitKind = 1900*0fca6ea1SDimitry Andric (CCK == CheckedConversionKind::CStyleCast) 19010b57cec5SDimitry Andric ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange, 19020b57cec5SDimitry Andric ListInitialization) 1903*0fca6ea1SDimitry Andric : (CCK == CheckedConversionKind::FunctionalCast) 1904*0fca6ea1SDimitry Andric ? InitializationKind::CreateFunctionalCast(OpRange, 1905*0fca6ea1SDimitry Andric ListInitialization) 19060b57cec5SDimitry Andric : InitializationKind::CreateCast(OpRange); 19070b57cec5SDimitry Andric Expr *SrcExprRaw = SrcExpr.get(); 19080b57cec5SDimitry Andric // FIXME: Per DR242, we should check for an implicit conversion sequence 19090b57cec5SDimitry Andric // or for a constructor that could be invoked by direct-initialization 19100b57cec5SDimitry Andric // here, not for an initialization sequence. 19110b57cec5SDimitry Andric InitializationSequence InitSeq(Self, Entity, InitKind, SrcExprRaw); 19120b57cec5SDimitry Andric 19130b57cec5SDimitry Andric // At this point of CheckStaticCast, if the destination is a reference, 19140b57cec5SDimitry Andric // or the expression is an overload expression this has to work. 19150b57cec5SDimitry Andric // There is no other way that works. 19160b57cec5SDimitry Andric // On the other hand, if we're checking a C-style cast, we've still got 19170b57cec5SDimitry Andric // the reinterpret_cast way. 1918*0fca6ea1SDimitry Andric bool CStyle = (CCK == CheckedConversionKind::CStyleCast || 1919*0fca6ea1SDimitry Andric CCK == CheckedConversionKind::FunctionalCast); 19200b57cec5SDimitry Andric if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType())) 19210b57cec5SDimitry Andric return TC_NotApplicable; 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric ExprResult Result = InitSeq.Perform(Self, Entity, InitKind, SrcExprRaw); 19240b57cec5SDimitry Andric if (Result.isInvalid()) { 19250b57cec5SDimitry Andric msg = 0; 19260b57cec5SDimitry Andric return TC_Failed; 19270b57cec5SDimitry Andric } 19280b57cec5SDimitry Andric 19290b57cec5SDimitry Andric if (InitSeq.isConstructorInitialization()) 19300b57cec5SDimitry Andric Kind = CK_ConstructorConversion; 19310b57cec5SDimitry Andric else 19320b57cec5SDimitry Andric Kind = CK_NoOp; 19330b57cec5SDimitry Andric 19340b57cec5SDimitry Andric SrcExpr = Result; 19350b57cec5SDimitry Andric return TC_Success; 19360b57cec5SDimitry Andric } 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric /// TryConstCast - See if a const_cast from source to destination is allowed, 19390b57cec5SDimitry Andric /// and perform it if it is. 19400b57cec5SDimitry Andric static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, 19410b57cec5SDimitry Andric QualType DestType, bool CStyle, 19420b57cec5SDimitry Andric unsigned &msg) { 19430b57cec5SDimitry Andric DestType = Self.Context.getCanonicalType(DestType); 19440b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 19450b57cec5SDimitry Andric bool NeedToMaterializeTemporary = false; 19460b57cec5SDimitry Andric 19470b57cec5SDimitry Andric if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) { 19480b57cec5SDimitry Andric // C++11 5.2.11p4: 19490b57cec5SDimitry Andric // if a pointer to T1 can be explicitly converted to the type "pointer to 19500b57cec5SDimitry Andric // T2" using a const_cast, then the following conversions can also be 19510b57cec5SDimitry Andric // made: 19520b57cec5SDimitry Andric // -- an lvalue of type T1 can be explicitly converted to an lvalue of 19530b57cec5SDimitry Andric // type T2 using the cast const_cast<T2&>; 19540b57cec5SDimitry Andric // -- a glvalue of type T1 can be explicitly converted to an xvalue of 19550b57cec5SDimitry Andric // type T2 using the cast const_cast<T2&&>; and 19560b57cec5SDimitry Andric // -- if T1 is a class type, a prvalue of type T1 can be explicitly 19570b57cec5SDimitry Andric // converted to an xvalue of type T2 using the cast const_cast<T2&&>. 19580b57cec5SDimitry Andric 19590b57cec5SDimitry Andric if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr.get()->isLValue()) { 19600b57cec5SDimitry Andric // Cannot const_cast non-lvalue to lvalue reference type. But if this 19610b57cec5SDimitry Andric // is C-style, static_cast might find a way, so we simply suggest a 19620b57cec5SDimitry Andric // message and tell the parent to keep searching. 19630b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_rvalue; 19640b57cec5SDimitry Andric return TC_NotApplicable; 19650b57cec5SDimitry Andric } 19660b57cec5SDimitry Andric 1967fe6060f1SDimitry Andric if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isPRValue()) { 19680b57cec5SDimitry Andric if (!SrcType->isRecordType()) { 19690b57cec5SDimitry Andric // Cannot const_cast non-class prvalue to rvalue reference type. But if 19700b57cec5SDimitry Andric // this is C-style, static_cast can do this. 19710b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_rvalue; 19720b57cec5SDimitry Andric return TC_NotApplicable; 19730b57cec5SDimitry Andric } 19740b57cec5SDimitry Andric 19750b57cec5SDimitry Andric // Materialize the class prvalue so that the const_cast can bind a 19760b57cec5SDimitry Andric // reference to it. 19770b57cec5SDimitry Andric NeedToMaterializeTemporary = true; 19780b57cec5SDimitry Andric } 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric // It's not completely clear under the standard whether we can 19810b57cec5SDimitry Andric // const_cast bit-field gl-values. Doing so would not be 19820b57cec5SDimitry Andric // intrinsically complicated, but for now, we say no for 19830b57cec5SDimitry Andric // consistency with other compilers and await the word of the 19840b57cec5SDimitry Andric // committee. 19850b57cec5SDimitry Andric if (SrcExpr.get()->refersToBitField()) { 19860b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_bitfield; 19870b57cec5SDimitry Andric return TC_NotApplicable; 19880b57cec5SDimitry Andric } 19890b57cec5SDimitry Andric 19900b57cec5SDimitry Andric DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); 19910b57cec5SDimitry Andric SrcType = Self.Context.getPointerType(SrcType); 19920b57cec5SDimitry Andric } 19930b57cec5SDimitry Andric 19940b57cec5SDimitry Andric // C++ 5.2.11p5: For a const_cast involving pointers to data members [...] 19950b57cec5SDimitry Andric // the rules for const_cast are the same as those used for pointers. 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric if (!DestType->isPointerType() && 19980b57cec5SDimitry Andric !DestType->isMemberPointerType() && 19990b57cec5SDimitry Andric !DestType->isObjCObjectPointerType()) { 20000b57cec5SDimitry Andric // Cannot cast to non-pointer, non-reference type. Note that, if DestType 20010b57cec5SDimitry Andric // was a reference type, we converted it to a pointer above. 20020b57cec5SDimitry Andric // The status of rvalue references isn't entirely clear, but it looks like 20030b57cec5SDimitry Andric // conversion to them is simply invalid. 20040b57cec5SDimitry Andric // C++ 5.2.11p3: For two pointer types [...] 20050b57cec5SDimitry Andric if (!CStyle) 20060b57cec5SDimitry Andric msg = diag::err_bad_const_cast_dest; 20070b57cec5SDimitry Andric return TC_NotApplicable; 20080b57cec5SDimitry Andric } 20090b57cec5SDimitry Andric if (DestType->isFunctionPointerType() || 20100b57cec5SDimitry Andric DestType->isMemberFunctionPointerType()) { 20110b57cec5SDimitry Andric // Cannot cast direct function pointers. 20120b57cec5SDimitry Andric // C++ 5.2.11p2: [...] where T is any object type or the void type [...] 20130b57cec5SDimitry Andric // T is the ultimate pointee of source and target type. 20140b57cec5SDimitry Andric if (!CStyle) 20150b57cec5SDimitry Andric msg = diag::err_bad_const_cast_dest; 20160b57cec5SDimitry Andric return TC_NotApplicable; 20170b57cec5SDimitry Andric } 20180b57cec5SDimitry Andric 20190b57cec5SDimitry Andric // C++ [expr.const.cast]p3: 20200b57cec5SDimitry Andric // "For two similar types T1 and T2, [...]" 20210b57cec5SDimitry Andric // 20220b57cec5SDimitry Andric // We only allow a const_cast to change cvr-qualifiers, not other kinds of 20230b57cec5SDimitry Andric // type qualifiers. (Likewise, we ignore other changes when determining 20240b57cec5SDimitry Andric // whether a cast casts away constness.) 20250b57cec5SDimitry Andric if (!Self.Context.hasCvrSimilarType(SrcType, DestType)) 20260b57cec5SDimitry Andric return TC_NotApplicable; 20270b57cec5SDimitry Andric 20280b57cec5SDimitry Andric if (NeedToMaterializeTemporary) 20290b57cec5SDimitry Andric // This is a const_cast from a class prvalue to an rvalue reference type. 20300b57cec5SDimitry Andric // Materialize a temporary to store the result of the conversion. 20310b57cec5SDimitry Andric SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcExpr.get()->getType(), 20320b57cec5SDimitry Andric SrcExpr.get(), 20330b57cec5SDimitry Andric /*IsLValueReference*/ false); 20340b57cec5SDimitry Andric 20350b57cec5SDimitry Andric return TC_Success; 20360b57cec5SDimitry Andric } 20370b57cec5SDimitry Andric 20380b57cec5SDimitry Andric // Checks for undefined behavior in reinterpret_cast. 20390b57cec5SDimitry Andric // The cases that is checked for is: 20400b57cec5SDimitry Andric // *reinterpret_cast<T*>(&a) 20410b57cec5SDimitry Andric // reinterpret_cast<T&>(a) 20420b57cec5SDimitry Andric // where accessing 'a' as type 'T' will result in undefined behavior. 20430b57cec5SDimitry Andric void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, 20440b57cec5SDimitry Andric bool IsDereference, 20450b57cec5SDimitry Andric SourceRange Range) { 20460b57cec5SDimitry Andric unsigned DiagID = IsDereference ? 20470b57cec5SDimitry Andric diag::warn_pointer_indirection_from_incompatible_type : 20480b57cec5SDimitry Andric diag::warn_undefined_reinterpret_cast; 20490b57cec5SDimitry Andric 20500b57cec5SDimitry Andric if (Diags.isIgnored(DiagID, Range.getBegin())) 20510b57cec5SDimitry Andric return; 20520b57cec5SDimitry Andric 20530b57cec5SDimitry Andric QualType SrcTy, DestTy; 20540b57cec5SDimitry Andric if (IsDereference) { 20550b57cec5SDimitry Andric if (!SrcType->getAs<PointerType>() || !DestType->getAs<PointerType>()) { 20560b57cec5SDimitry Andric return; 20570b57cec5SDimitry Andric } 20580b57cec5SDimitry Andric SrcTy = SrcType->getPointeeType(); 20590b57cec5SDimitry Andric DestTy = DestType->getPointeeType(); 20600b57cec5SDimitry Andric } else { 20610b57cec5SDimitry Andric if (!DestType->getAs<ReferenceType>()) { 20620b57cec5SDimitry Andric return; 20630b57cec5SDimitry Andric } 20640b57cec5SDimitry Andric SrcTy = SrcType; 20650b57cec5SDimitry Andric DestTy = DestType->getPointeeType(); 20660b57cec5SDimitry Andric } 20670b57cec5SDimitry Andric 20680b57cec5SDimitry Andric // Cast is compatible if the types are the same. 20690b57cec5SDimitry Andric if (Context.hasSameUnqualifiedType(DestTy, SrcTy)) { 20700b57cec5SDimitry Andric return; 20710b57cec5SDimitry Andric } 20720b57cec5SDimitry Andric // or one of the types is a char or void type 20730b57cec5SDimitry Andric if (DestTy->isAnyCharacterType() || DestTy->isVoidType() || 20740b57cec5SDimitry Andric SrcTy->isAnyCharacterType() || SrcTy->isVoidType()) { 20750b57cec5SDimitry Andric return; 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric // or one of the types is a tag type. 20780b57cec5SDimitry Andric if (SrcTy->getAs<TagType>() || DestTy->getAs<TagType>()) { 20790b57cec5SDimitry Andric return; 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric 20820b57cec5SDimitry Andric // FIXME: Scoped enums? 20830b57cec5SDimitry Andric if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) || 20840b57cec5SDimitry Andric (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) { 20850b57cec5SDimitry Andric if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) { 20860b57cec5SDimitry Andric return; 20870b57cec5SDimitry Andric } 20880b57cec5SDimitry Andric } 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range; 20910b57cec5SDimitry Andric } 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr, 20940b57cec5SDimitry Andric QualType DestType) { 20950b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 20960b57cec5SDimitry Andric if (Self.Context.hasSameType(SrcType, DestType)) 20970b57cec5SDimitry Andric return; 20980b57cec5SDimitry Andric if (const PointerType *SrcPtrTy = SrcType->getAs<PointerType>()) 20990b57cec5SDimitry Andric if (SrcPtrTy->isObjCSelType()) { 21000b57cec5SDimitry Andric QualType DT = DestType; 21010b57cec5SDimitry Andric if (isa<PointerType>(DestType)) 21020b57cec5SDimitry Andric DT = DestType->getPointeeType(); 21030b57cec5SDimitry Andric if (!DT.getUnqualifiedType()->isVoidType()) 21040b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getExprLoc(), 21050b57cec5SDimitry Andric diag::warn_cast_pointer_from_sel) 21060b57cec5SDimitry Andric << SrcType << DestType << SrcExpr.get()->getSourceRange(); 21070b57cec5SDimitry Andric } 21080b57cec5SDimitry Andric } 21090b57cec5SDimitry Andric 21100b57cec5SDimitry Andric /// Diagnose casts that change the calling convention of a pointer to a function 21110b57cec5SDimitry Andric /// defined in the current TU. 21120b57cec5SDimitry Andric static void DiagnoseCallingConvCast(Sema &Self, const ExprResult &SrcExpr, 21130b57cec5SDimitry Andric QualType DstType, SourceRange OpRange) { 21140b57cec5SDimitry Andric // Check if this cast would change the calling convention of a function 21150b57cec5SDimitry Andric // pointer type. 21160b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 21170b57cec5SDimitry Andric if (Self.Context.hasSameType(SrcType, DstType) || 21180b57cec5SDimitry Andric !SrcType->isFunctionPointerType() || !DstType->isFunctionPointerType()) 21190b57cec5SDimitry Andric return; 21200b57cec5SDimitry Andric const auto *SrcFTy = 21210b57cec5SDimitry Andric SrcType->castAs<PointerType>()->getPointeeType()->castAs<FunctionType>(); 21220b57cec5SDimitry Andric const auto *DstFTy = 21230b57cec5SDimitry Andric DstType->castAs<PointerType>()->getPointeeType()->castAs<FunctionType>(); 21240b57cec5SDimitry Andric CallingConv SrcCC = SrcFTy->getCallConv(); 21250b57cec5SDimitry Andric CallingConv DstCC = DstFTy->getCallConv(); 21260b57cec5SDimitry Andric if (SrcCC == DstCC) 21270b57cec5SDimitry Andric return; 21280b57cec5SDimitry Andric 21290b57cec5SDimitry Andric // We have a calling convention cast. Check if the source is a pointer to a 21300b57cec5SDimitry Andric // known, specific function that has already been defined. 21310b57cec5SDimitry Andric Expr *Src = SrcExpr.get()->IgnoreParenImpCasts(); 21320b57cec5SDimitry Andric if (auto *UO = dyn_cast<UnaryOperator>(Src)) 21330b57cec5SDimitry Andric if (UO->getOpcode() == UO_AddrOf) 21340b57cec5SDimitry Andric Src = UO->getSubExpr()->IgnoreParenImpCasts(); 21350b57cec5SDimitry Andric auto *DRE = dyn_cast<DeclRefExpr>(Src); 21360b57cec5SDimitry Andric if (!DRE) 21370b57cec5SDimitry Andric return; 21380b57cec5SDimitry Andric auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()); 21390b57cec5SDimitry Andric if (!FD) 21400b57cec5SDimitry Andric return; 21410b57cec5SDimitry Andric 21420b57cec5SDimitry Andric // Only warn if we are casting from the default convention to a non-default 21430b57cec5SDimitry Andric // convention. This can happen when the programmer forgot to apply the calling 21440b57cec5SDimitry Andric // convention to the function declaration and then inserted this cast to 21450b57cec5SDimitry Andric // satisfy the type system. 21460b57cec5SDimitry Andric CallingConv DefaultCC = Self.getASTContext().getDefaultCallingConvention( 21470b57cec5SDimitry Andric FD->isVariadic(), FD->isCXXInstanceMember()); 21480b57cec5SDimitry Andric if (DstCC == DefaultCC || SrcCC != DefaultCC) 21490b57cec5SDimitry Andric return; 21500b57cec5SDimitry Andric 21510b57cec5SDimitry Andric // Diagnose this cast, as it is probably bad. 21520b57cec5SDimitry Andric StringRef SrcCCName = FunctionType::getNameForCallConv(SrcCC); 21530b57cec5SDimitry Andric StringRef DstCCName = FunctionType::getNameForCallConv(DstCC); 21540b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::warn_cast_calling_conv) 21550b57cec5SDimitry Andric << SrcCCName << DstCCName << OpRange; 21560b57cec5SDimitry Andric 21570b57cec5SDimitry Andric // The checks above are cheaper than checking if the diagnostic is enabled. 21580b57cec5SDimitry Andric // However, it's worth checking if the warning is enabled before we construct 21590b57cec5SDimitry Andric // a fixit. 21600b57cec5SDimitry Andric if (Self.Diags.isIgnored(diag::warn_cast_calling_conv, OpRange.getBegin())) 21610b57cec5SDimitry Andric return; 21620b57cec5SDimitry Andric 21630b57cec5SDimitry Andric // Try to suggest a fixit to change the calling convention of the function 21640b57cec5SDimitry Andric // whose address was taken. Try to use the latest macro for the convention. 21650b57cec5SDimitry Andric // For example, users probably want to write "WINAPI" instead of "__stdcall" 21660b57cec5SDimitry Andric // to match the Windows header declarations. 21670b57cec5SDimitry Andric SourceLocation NameLoc = FD->getFirstDecl()->getNameInfo().getLoc(); 21680b57cec5SDimitry Andric Preprocessor &PP = Self.getPreprocessor(); 21690b57cec5SDimitry Andric SmallVector<TokenValue, 6> AttrTokens; 21700b57cec5SDimitry Andric SmallString<64> CCAttrText; 21710b57cec5SDimitry Andric llvm::raw_svector_ostream OS(CCAttrText); 21720b57cec5SDimitry Andric if (Self.getLangOpts().MicrosoftExt) { 21730b57cec5SDimitry Andric // __stdcall or __vectorcall 21740b57cec5SDimitry Andric OS << "__" << DstCCName; 21750b57cec5SDimitry Andric IdentifierInfo *II = PP.getIdentifierInfo(OS.str()); 21760b57cec5SDimitry Andric AttrTokens.push_back(II->isKeyword(Self.getLangOpts()) 21770b57cec5SDimitry Andric ? TokenValue(II->getTokenID()) 21780b57cec5SDimitry Andric : TokenValue(II)); 21790b57cec5SDimitry Andric } else { 21800b57cec5SDimitry Andric // __attribute__((stdcall)) or __attribute__((vectorcall)) 21810b57cec5SDimitry Andric OS << "__attribute__((" << DstCCName << "))"; 21820b57cec5SDimitry Andric AttrTokens.push_back(tok::kw___attribute); 21830b57cec5SDimitry Andric AttrTokens.push_back(tok::l_paren); 21840b57cec5SDimitry Andric AttrTokens.push_back(tok::l_paren); 21850b57cec5SDimitry Andric IdentifierInfo *II = PP.getIdentifierInfo(DstCCName); 21860b57cec5SDimitry Andric AttrTokens.push_back(II->isKeyword(Self.getLangOpts()) 21870b57cec5SDimitry Andric ? TokenValue(II->getTokenID()) 21880b57cec5SDimitry Andric : TokenValue(II)); 21890b57cec5SDimitry Andric AttrTokens.push_back(tok::r_paren); 21900b57cec5SDimitry Andric AttrTokens.push_back(tok::r_paren); 21910b57cec5SDimitry Andric } 21920b57cec5SDimitry Andric StringRef AttrSpelling = PP.getLastMacroWithSpelling(NameLoc, AttrTokens); 21930b57cec5SDimitry Andric if (!AttrSpelling.empty()) 21940b57cec5SDimitry Andric CCAttrText = AttrSpelling; 21950b57cec5SDimitry Andric OS << ' '; 21960b57cec5SDimitry Andric Self.Diag(NameLoc, diag::note_change_calling_conv_fixit) 21970b57cec5SDimitry Andric << FD << DstCCName << FixItHint::CreateInsertion(NameLoc, CCAttrText); 21980b57cec5SDimitry Andric } 21990b57cec5SDimitry Andric 22005ffd83dbSDimitry Andric static void checkIntToPointerCast(bool CStyle, const SourceRange &OpRange, 22010b57cec5SDimitry Andric const Expr *SrcExpr, QualType DestType, 22020b57cec5SDimitry Andric Sema &Self) { 22030b57cec5SDimitry Andric QualType SrcType = SrcExpr->getType(); 22040b57cec5SDimitry Andric 22050b57cec5SDimitry Andric // Not warning on reinterpret_cast, boolean, constant expressions, etc 22060b57cec5SDimitry Andric // are not explicit design choices, but consistent with GCC's behavior. 22070b57cec5SDimitry Andric // Feel free to modify them if you've reason/evidence for an alternative. 22080b57cec5SDimitry Andric if (CStyle && SrcType->isIntegralType(Self.Context) 22090b57cec5SDimitry Andric && !SrcType->isBooleanType() 22100b57cec5SDimitry Andric && !SrcType->isEnumeralType() 22110b57cec5SDimitry Andric && !SrcExpr->isIntegerConstantExpr(Self.Context) 22120b57cec5SDimitry Andric && Self.Context.getTypeSize(DestType) > 22130b57cec5SDimitry Andric Self.Context.getTypeSize(SrcType)) { 22140b57cec5SDimitry Andric // Separate between casts to void* and non-void* pointers. 22150b57cec5SDimitry Andric // Some APIs use (abuse) void* for something like a user context, 22160b57cec5SDimitry Andric // and often that value is an integer even if it isn't a pointer itself. 22170b57cec5SDimitry Andric // Having a separate warning flag allows users to control the warning 22180b57cec5SDimitry Andric // for their workflow. 22190b57cec5SDimitry Andric unsigned Diag = DestType->isVoidPointerType() ? 22200b57cec5SDimitry Andric diag::warn_int_to_void_pointer_cast 22210b57cec5SDimitry Andric : diag::warn_int_to_pointer_cast; 22225ffd83dbSDimitry Andric Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange; 22230b57cec5SDimitry Andric } 22240b57cec5SDimitry Andric } 22250b57cec5SDimitry Andric 22260b57cec5SDimitry Andric static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType, 22270b57cec5SDimitry Andric ExprResult &Result) { 22280b57cec5SDimitry Andric // We can only fix an overloaded reinterpret_cast if 22290b57cec5SDimitry Andric // - it is a template with explicit arguments that resolves to an lvalue 22300b57cec5SDimitry Andric // unambiguously, or 22310b57cec5SDimitry Andric // - it is the only function in an overload set that may have its address 22320b57cec5SDimitry Andric // taken. 22330b57cec5SDimitry Andric 22340b57cec5SDimitry Andric Expr *E = Result.get(); 22350b57cec5SDimitry Andric // TODO: what if this fails because of DiagnoseUseOfDecl or something 22360b57cec5SDimitry Andric // like it? 22370b57cec5SDimitry Andric if (Self.ResolveAndFixSingleFunctionTemplateSpecialization( 22380b57cec5SDimitry Andric Result, 2239fe6060f1SDimitry Andric Expr::getValueKindForType(DestType) == 2240fe6060f1SDimitry Andric VK_PRValue // Convert Fun to Ptr 22410b57cec5SDimitry Andric ) && 22420b57cec5SDimitry Andric Result.isUsable()) 22430b57cec5SDimitry Andric return true; 22440b57cec5SDimitry Andric 22450b57cec5SDimitry Andric // No guarantees that ResolveAndFixSingleFunctionTemplateSpecialization 22460b57cec5SDimitry Andric // preserves Result. 22470b57cec5SDimitry Andric Result = E; 2248480093f4SDimitry Andric if (!Self.resolveAndFixAddressOfSingleOverloadCandidate( 22490b57cec5SDimitry Andric Result, /*DoFunctionPointerConversion=*/true)) 22500b57cec5SDimitry Andric return false; 22510b57cec5SDimitry Andric return Result.isUsable(); 22520b57cec5SDimitry Andric } 22530b57cec5SDimitry Andric 22540b57cec5SDimitry Andric static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, 22550b57cec5SDimitry Andric QualType DestType, bool CStyle, 22560b57cec5SDimitry Andric SourceRange OpRange, 22570b57cec5SDimitry Andric unsigned &msg, 22580b57cec5SDimitry Andric CastKind &Kind) { 22590b57cec5SDimitry Andric bool IsLValueCast = false; 22600b57cec5SDimitry Andric 22610b57cec5SDimitry Andric DestType = Self.Context.getCanonicalType(DestType); 22620b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 22630b57cec5SDimitry Andric 22640b57cec5SDimitry Andric // Is the source an overloaded name? (i.e. &foo) 22650b57cec5SDimitry Andric // If so, reinterpret_cast generally can not help us here (13.4, p1, bullet 5) 22660b57cec5SDimitry Andric if (SrcType == Self.Context.OverloadTy) { 22670b57cec5SDimitry Andric ExprResult FixedExpr = SrcExpr; 22680b57cec5SDimitry Andric if (!fixOverloadedReinterpretCastExpr(Self, DestType, FixedExpr)) 22690b57cec5SDimitry Andric return TC_NotApplicable; 22700b57cec5SDimitry Andric 22710b57cec5SDimitry Andric assert(FixedExpr.isUsable() && "Invalid result fixing overloaded expr"); 22720b57cec5SDimitry Andric SrcExpr = FixedExpr; 22730b57cec5SDimitry Andric SrcType = SrcExpr.get()->getType(); 22740b57cec5SDimitry Andric } 22750b57cec5SDimitry Andric 22760b57cec5SDimitry Andric if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) { 22770b57cec5SDimitry Andric if (!SrcExpr.get()->isGLValue()) { 22780b57cec5SDimitry Andric // Cannot cast non-glvalue to (lvalue or rvalue) reference type. See the 22790b57cec5SDimitry Andric // similar comment in const_cast. 22800b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_rvalue; 22810b57cec5SDimitry Andric return TC_NotApplicable; 22820b57cec5SDimitry Andric } 22830b57cec5SDimitry Andric 22840b57cec5SDimitry Andric if (!CStyle) { 22850b57cec5SDimitry Andric Self.CheckCompatibleReinterpretCast(SrcType, DestType, 22860b57cec5SDimitry Andric /*IsDereference=*/false, OpRange); 22870b57cec5SDimitry Andric } 22880b57cec5SDimitry Andric 22890b57cec5SDimitry Andric // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the 22900b57cec5SDimitry Andric // same effect as the conversion *reinterpret_cast<T*>(&x) with the 22910b57cec5SDimitry Andric // built-in & and * operators. 22920b57cec5SDimitry Andric 22930b57cec5SDimitry Andric const char *inappropriate = nullptr; 22940b57cec5SDimitry Andric switch (SrcExpr.get()->getObjectKind()) { 22950b57cec5SDimitry Andric case OK_Ordinary: 22960b57cec5SDimitry Andric break; 22970b57cec5SDimitry Andric case OK_BitField: 22980b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_bitfield; 22990b57cec5SDimitry Andric return TC_NotApplicable; 23000b57cec5SDimitry Andric // FIXME: Use a specific diagnostic for the rest of these cases. 23010b57cec5SDimitry Andric case OK_VectorComponent: inappropriate = "vector element"; break; 23025ffd83dbSDimitry Andric case OK_MatrixComponent: 23035ffd83dbSDimitry Andric inappropriate = "matrix element"; 23045ffd83dbSDimitry Andric break; 23050b57cec5SDimitry Andric case OK_ObjCProperty: inappropriate = "property expression"; break; 23060b57cec5SDimitry Andric case OK_ObjCSubscript: inappropriate = "container subscripting expression"; 23070b57cec5SDimitry Andric break; 23080b57cec5SDimitry Andric } 23090b57cec5SDimitry Andric if (inappropriate) { 23100b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference) 23110b57cec5SDimitry Andric << inappropriate << DestType 23120b57cec5SDimitry Andric << OpRange << SrcExpr.get()->getSourceRange(); 23130b57cec5SDimitry Andric msg = 0; SrcExpr = ExprError(); 23140b57cec5SDimitry Andric return TC_NotApplicable; 23150b57cec5SDimitry Andric } 23160b57cec5SDimitry Andric 23170b57cec5SDimitry Andric // This code does this transformation for the checked types. 23180b57cec5SDimitry Andric DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); 23190b57cec5SDimitry Andric SrcType = Self.Context.getPointerType(SrcType); 23200b57cec5SDimitry Andric 23210b57cec5SDimitry Andric IsLValueCast = true; 23220b57cec5SDimitry Andric } 23230b57cec5SDimitry Andric 23240b57cec5SDimitry Andric // Canonicalize source for comparison. 23250b57cec5SDimitry Andric SrcType = Self.Context.getCanonicalType(SrcType); 23260b57cec5SDimitry Andric 23270b57cec5SDimitry Andric const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(), 23280b57cec5SDimitry Andric *SrcMemPtr = SrcType->getAs<MemberPointerType>(); 23290b57cec5SDimitry Andric if (DestMemPtr && SrcMemPtr) { 23300b57cec5SDimitry Andric // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1" 23310b57cec5SDimitry Andric // can be explicitly converted to an rvalue of type "pointer to member 23320b57cec5SDimitry Andric // of Y of type T2" if T1 and T2 are both function types or both object 23330b57cec5SDimitry Andric // types. 23340b57cec5SDimitry Andric if (DestMemPtr->isMemberFunctionPointer() != 23350b57cec5SDimitry Andric SrcMemPtr->isMemberFunctionPointer()) 23360b57cec5SDimitry Andric return TC_NotApplicable; 23370b57cec5SDimitry Andric 23380b57cec5SDimitry Andric if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) { 23390b57cec5SDimitry Andric // We need to determine the inheritance model that the class will use if 23400b57cec5SDimitry Andric // haven't yet. 23410b57cec5SDimitry Andric (void)Self.isCompleteType(OpRange.getBegin(), SrcType); 23420b57cec5SDimitry Andric (void)Self.isCompleteType(OpRange.getBegin(), DestType); 23430b57cec5SDimitry Andric } 23440b57cec5SDimitry Andric 23450b57cec5SDimitry Andric // Don't allow casting between member pointers of different sizes. 23460b57cec5SDimitry Andric if (Self.Context.getTypeSize(DestMemPtr) != 23470b57cec5SDimitry Andric Self.Context.getTypeSize(SrcMemPtr)) { 23480b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_member_pointer_size; 23490b57cec5SDimitry Andric return TC_Failed; 23500b57cec5SDimitry Andric } 23510b57cec5SDimitry Andric 23520b57cec5SDimitry Andric // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away 23530b57cec5SDimitry Andric // constness. 23540b57cec5SDimitry Andric // A reinterpret_cast followed by a const_cast can, though, so in C-style, 23550b57cec5SDimitry Andric // we accept it. 23560b57cec5SDimitry Andric if (auto CACK = 23570b57cec5SDimitry Andric CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, 23580b57cec5SDimitry Andric /*CheckObjCLifetime=*/CStyle)) 23590b57cec5SDimitry Andric return getCastAwayConstnessCastKind(CACK, msg); 23600b57cec5SDimitry Andric 23610b57cec5SDimitry Andric // A valid member pointer cast. 23620b57cec5SDimitry Andric assert(!IsLValueCast); 23630b57cec5SDimitry Andric Kind = CK_ReinterpretMemberPointer; 23640b57cec5SDimitry Andric return TC_Success; 23650b57cec5SDimitry Andric } 23660b57cec5SDimitry Andric 23670b57cec5SDimitry Andric // See below for the enumeral issue. 23680b57cec5SDimitry Andric if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) { 23690b57cec5SDimitry Andric // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral 23700b57cec5SDimitry Andric // type large enough to hold it. A value of std::nullptr_t can be 23710b57cec5SDimitry Andric // converted to an integral type; the conversion has the same meaning 23720b57cec5SDimitry Andric // and validity as a conversion of (void*)0 to the integral type. 23730b57cec5SDimitry Andric if (Self.Context.getTypeSize(SrcType) > 23740b57cec5SDimitry Andric Self.Context.getTypeSize(DestType)) { 23750b57cec5SDimitry Andric msg = diag::err_bad_reinterpret_cast_small_int; 23760b57cec5SDimitry Andric return TC_Failed; 23770b57cec5SDimitry Andric } 23780b57cec5SDimitry Andric Kind = CK_PointerToIntegral; 23790b57cec5SDimitry Andric return TC_Success; 23800b57cec5SDimitry Andric } 23810b57cec5SDimitry Andric 23820b57cec5SDimitry Andric // Allow reinterpret_casts between vectors of the same size and 23830b57cec5SDimitry Andric // between vectors and integers of the same size. 23840b57cec5SDimitry Andric bool destIsVector = DestType->isVectorType(); 23850b57cec5SDimitry Andric bool srcIsVector = SrcType->isVectorType(); 23860b57cec5SDimitry Andric if (srcIsVector || destIsVector) { 2387e8d8bef9SDimitry Andric // Allow bitcasting between SVE VLATs and VLSTs, and vice-versa. 2388e8d8bef9SDimitry Andric if (Self.isValidSveBitcast(SrcType, DestType)) { 2389e8d8bef9SDimitry Andric Kind = CK_BitCast; 2390e8d8bef9SDimitry Andric return TC_Success; 2391e8d8bef9SDimitry Andric } 2392e8d8bef9SDimitry Andric 239306c3fb27SDimitry Andric // Allow bitcasting between SVE VLATs and VLSTs, and vice-versa. 2394*0fca6ea1SDimitry Andric if (Self.RISCV().isValidRVVBitcast(SrcType, DestType)) { 239506c3fb27SDimitry Andric Kind = CK_BitCast; 239606c3fb27SDimitry Andric return TC_Success; 239706c3fb27SDimitry Andric } 239806c3fb27SDimitry Andric 23990b57cec5SDimitry Andric // The non-vector type, if any, must have integral type. This is 24000b57cec5SDimitry Andric // the same rule that C vector casts use; note, however, that enum 24010b57cec5SDimitry Andric // types are not integral in C++. 24020b57cec5SDimitry Andric if ((!destIsVector && !DestType->isIntegralType(Self.Context)) || 24030b57cec5SDimitry Andric (!srcIsVector && !SrcType->isIntegralType(Self.Context))) 24040b57cec5SDimitry Andric return TC_NotApplicable; 24050b57cec5SDimitry Andric 24060b57cec5SDimitry Andric // The size we want to consider is eltCount * eltSize. 24070b57cec5SDimitry Andric // That's exactly what the lax-conversion rules will check. 24080b57cec5SDimitry Andric if (Self.areLaxCompatibleVectorTypes(SrcType, DestType)) { 24090b57cec5SDimitry Andric Kind = CK_BitCast; 24100b57cec5SDimitry Andric return TC_Success; 24110b57cec5SDimitry Andric } 24120b57cec5SDimitry Andric 2413fe6060f1SDimitry Andric if (Self.LangOpts.OpenCL && !CStyle) { 2414fe6060f1SDimitry Andric if (DestType->isExtVectorType() || SrcType->isExtVectorType()) { 2415fe6060f1SDimitry Andric // FIXME: Allow for reinterpret cast between 3 and 4 element vectors 2416fe6060f1SDimitry Andric if (Self.areVectorTypesSameSize(SrcType, DestType)) { 2417fe6060f1SDimitry Andric Kind = CK_BitCast; 2418fe6060f1SDimitry Andric return TC_Success; 2419fe6060f1SDimitry Andric } 2420fe6060f1SDimitry Andric } 2421fe6060f1SDimitry Andric } 2422fe6060f1SDimitry Andric 24230b57cec5SDimitry Andric // Otherwise, pick a reasonable diagnostic. 24240b57cec5SDimitry Andric if (!destIsVector) 24250b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size; 24260b57cec5SDimitry Andric else if (!srcIsVector) 24270b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size; 24280b57cec5SDimitry Andric else 24290b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_vector_to_vector_different_size; 24300b57cec5SDimitry Andric 24310b57cec5SDimitry Andric return TC_Failed; 24320b57cec5SDimitry Andric } 24330b57cec5SDimitry Andric 24340b57cec5SDimitry Andric if (SrcType == DestType) { 24350b57cec5SDimitry Andric // C++ 5.2.10p2 has a note that mentions that, subject to all other 24360b57cec5SDimitry Andric // restrictions, a cast to the same type is allowed so long as it does not 24370b57cec5SDimitry Andric // cast away constness. In C++98, the intent was not entirely clear here, 24380b57cec5SDimitry Andric // since all other paragraphs explicitly forbid casts to the same type. 24390b57cec5SDimitry Andric // C++11 clarifies this case with p2. 24400b57cec5SDimitry Andric // 24410b57cec5SDimitry Andric // The only allowed types are: integral, enumeration, pointer, or 24420b57cec5SDimitry Andric // pointer-to-member types. We also won't restrict Obj-C pointers either. 24430b57cec5SDimitry Andric Kind = CK_NoOp; 24440b57cec5SDimitry Andric TryCastResult Result = TC_NotApplicable; 24450b57cec5SDimitry Andric if (SrcType->isIntegralOrEnumerationType() || 24460b57cec5SDimitry Andric SrcType->isAnyPointerType() || 24470b57cec5SDimitry Andric SrcType->isMemberPointerType() || 24480b57cec5SDimitry Andric SrcType->isBlockPointerType()) { 24490b57cec5SDimitry Andric Result = TC_Success; 24500b57cec5SDimitry Andric } 24510b57cec5SDimitry Andric return Result; 24520b57cec5SDimitry Andric } 24530b57cec5SDimitry Andric 24540b57cec5SDimitry Andric bool destIsPtr = DestType->isAnyPointerType() || 24550b57cec5SDimitry Andric DestType->isBlockPointerType(); 24560b57cec5SDimitry Andric bool srcIsPtr = SrcType->isAnyPointerType() || 24570b57cec5SDimitry Andric SrcType->isBlockPointerType(); 24580b57cec5SDimitry Andric if (!destIsPtr && !srcIsPtr) { 24590b57cec5SDimitry Andric // Except for std::nullptr_t->integer and lvalue->reference, which are 24600b57cec5SDimitry Andric // handled above, at least one of the two arguments must be a pointer. 24610b57cec5SDimitry Andric return TC_NotApplicable; 24620b57cec5SDimitry Andric } 24630b57cec5SDimitry Andric 24640b57cec5SDimitry Andric if (DestType->isIntegralType(Self.Context)) { 24650b57cec5SDimitry Andric assert(srcIsPtr && "One type must be a pointer"); 24660b57cec5SDimitry Andric // C++ 5.2.10p4: A pointer can be explicitly converted to any integral 24670b57cec5SDimitry Andric // type large enough to hold it; except in Microsoft mode, where the 24680b57cec5SDimitry Andric // integral type size doesn't matter (except we don't allow bool). 24690b57cec5SDimitry Andric if ((Self.Context.getTypeSize(SrcType) > 24705ffd83dbSDimitry Andric Self.Context.getTypeSize(DestType))) { 24715ffd83dbSDimitry Andric bool MicrosoftException = 24725ffd83dbSDimitry Andric Self.getLangOpts().MicrosoftExt && !DestType->isBooleanType(); 24735ffd83dbSDimitry Andric if (MicrosoftException) { 24745ffd83dbSDimitry Andric unsigned Diag = SrcType->isVoidPointerType() 24755ffd83dbSDimitry Andric ? diag::warn_void_pointer_to_int_cast 24765ffd83dbSDimitry Andric : diag::warn_pointer_to_int_cast; 24775ffd83dbSDimitry Andric Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange; 24785ffd83dbSDimitry Andric } else { 24790b57cec5SDimitry Andric msg = diag::err_bad_reinterpret_cast_small_int; 24800b57cec5SDimitry Andric return TC_Failed; 24810b57cec5SDimitry Andric } 24825ffd83dbSDimitry Andric } 24830b57cec5SDimitry Andric Kind = CK_PointerToIntegral; 24840b57cec5SDimitry Andric return TC_Success; 24850b57cec5SDimitry Andric } 24860b57cec5SDimitry Andric 24870b57cec5SDimitry Andric if (SrcType->isIntegralOrEnumerationType()) { 24880b57cec5SDimitry Andric assert(destIsPtr && "One type must be a pointer"); 24895ffd83dbSDimitry Andric checkIntToPointerCast(CStyle, OpRange, SrcExpr.get(), DestType, Self); 24900b57cec5SDimitry Andric // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly 24910b57cec5SDimitry Andric // converted to a pointer. 24920b57cec5SDimitry Andric // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not 24930b57cec5SDimitry Andric // necessarily converted to a null pointer value.] 24940b57cec5SDimitry Andric Kind = CK_IntegralToPointer; 24950b57cec5SDimitry Andric return TC_Success; 24960b57cec5SDimitry Andric } 24970b57cec5SDimitry Andric 24980b57cec5SDimitry Andric if (!destIsPtr || !srcIsPtr) { 24990b57cec5SDimitry Andric // With the valid non-pointer conversions out of the way, we can be even 25000b57cec5SDimitry Andric // more stringent. 25010b57cec5SDimitry Andric return TC_NotApplicable; 25020b57cec5SDimitry Andric } 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric // Cannot convert between block pointers and Objective-C object pointers. 25050b57cec5SDimitry Andric if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) || 25060b57cec5SDimitry Andric (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType())) 25070b57cec5SDimitry Andric return TC_NotApplicable; 25080b57cec5SDimitry Andric 25090b57cec5SDimitry Andric // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. 25100b57cec5SDimitry Andric // The C-style cast operator can. 25110b57cec5SDimitry Andric TryCastResult SuccessResult = TC_Success; 25120b57cec5SDimitry Andric if (auto CACK = 25130b57cec5SDimitry Andric CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle, 25140b57cec5SDimitry Andric /*CheckObjCLifetime=*/CStyle)) 25150b57cec5SDimitry Andric SuccessResult = getCastAwayConstnessCastKind(CACK, msg); 25160b57cec5SDimitry Andric 25170b57cec5SDimitry Andric if (IsAddressSpaceConversion(SrcType, DestType)) { 25180b57cec5SDimitry Andric Kind = CK_AddressSpaceConversion; 25190b57cec5SDimitry Andric assert(SrcType->isPointerType() && DestType->isPointerType()); 25200b57cec5SDimitry Andric if (!CStyle && 25210b57cec5SDimitry Andric !DestType->getPointeeType().getQualifiers().isAddressSpaceSupersetOf( 25220b57cec5SDimitry Andric SrcType->getPointeeType().getQualifiers())) { 25230b57cec5SDimitry Andric SuccessResult = TC_Failed; 25240b57cec5SDimitry Andric } 25250b57cec5SDimitry Andric } else if (IsLValueCast) { 25260b57cec5SDimitry Andric Kind = CK_LValueBitCast; 25270b57cec5SDimitry Andric } else if (DestType->isObjCObjectPointerType()) { 2528*0fca6ea1SDimitry Andric Kind = Self.ObjC().PrepareCastToObjCObjectPointer(SrcExpr); 25290b57cec5SDimitry Andric } else if (DestType->isBlockPointerType()) { 25300b57cec5SDimitry Andric if (!SrcType->isBlockPointerType()) { 25310b57cec5SDimitry Andric Kind = CK_AnyPointerToBlockPointerCast; 25320b57cec5SDimitry Andric } else { 25330b57cec5SDimitry Andric Kind = CK_BitCast; 25340b57cec5SDimitry Andric } 25350b57cec5SDimitry Andric } else { 25360b57cec5SDimitry Andric Kind = CK_BitCast; 25370b57cec5SDimitry Andric } 25380b57cec5SDimitry Andric 25390b57cec5SDimitry Andric // Any pointer can be cast to an Objective-C pointer type with a C-style 25400b57cec5SDimitry Andric // cast. 25410b57cec5SDimitry Andric if (CStyle && DestType->isObjCObjectPointerType()) { 25420b57cec5SDimitry Andric return SuccessResult; 25430b57cec5SDimitry Andric } 25440b57cec5SDimitry Andric if (CStyle) 25450b57cec5SDimitry Andric DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType); 25460b57cec5SDimitry Andric 25470b57cec5SDimitry Andric DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange); 25480b57cec5SDimitry Andric 25490b57cec5SDimitry Andric // Not casting away constness, so the only remaining check is for compatible 25500b57cec5SDimitry Andric // pointer categories. 25510b57cec5SDimitry Andric 25520b57cec5SDimitry Andric if (SrcType->isFunctionPointerType()) { 25530b57cec5SDimitry Andric if (DestType->isFunctionPointerType()) { 25540b57cec5SDimitry Andric // C++ 5.2.10p6: A pointer to a function can be explicitly converted to 25550b57cec5SDimitry Andric // a pointer to a function of a different type. 25560b57cec5SDimitry Andric return SuccessResult; 25570b57cec5SDimitry Andric } 25580b57cec5SDimitry Andric 25590b57cec5SDimitry Andric // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to 25600b57cec5SDimitry Andric // an object type or vice versa is conditionally-supported. 25610b57cec5SDimitry Andric // Compilers support it in C++03 too, though, because it's necessary for 25620b57cec5SDimitry Andric // casting the return value of dlsym() and GetProcAddress(). 25630b57cec5SDimitry Andric // FIXME: Conditionally-supported behavior should be configurable in the 25640b57cec5SDimitry Andric // TargetInfo or similar. 25650b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), 25660b57cec5SDimitry Andric Self.getLangOpts().CPlusPlus11 ? 25670b57cec5SDimitry Andric diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) 25680b57cec5SDimitry Andric << OpRange; 25690b57cec5SDimitry Andric return SuccessResult; 25700b57cec5SDimitry Andric } 25710b57cec5SDimitry Andric 25720b57cec5SDimitry Andric if (DestType->isFunctionPointerType()) { 25730b57cec5SDimitry Andric // See above. 25740b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), 25750b57cec5SDimitry Andric Self.getLangOpts().CPlusPlus11 ? 25760b57cec5SDimitry Andric diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) 25770b57cec5SDimitry Andric << OpRange; 25780b57cec5SDimitry Andric return SuccessResult; 25790b57cec5SDimitry Andric } 25800b57cec5SDimitry Andric 258113138422SDimitry Andric // Diagnose address space conversion in nested pointers. 258213138422SDimitry Andric QualType DestPtee = DestType->getPointeeType().isNull() 258313138422SDimitry Andric ? DestType->getPointeeType() 258413138422SDimitry Andric : DestType->getPointeeType()->getPointeeType(); 258513138422SDimitry Andric QualType SrcPtee = SrcType->getPointeeType().isNull() 258613138422SDimitry Andric ? SrcType->getPointeeType() 258713138422SDimitry Andric : SrcType->getPointeeType()->getPointeeType(); 258813138422SDimitry Andric while (!DestPtee.isNull() && !SrcPtee.isNull()) { 258913138422SDimitry Andric if (DestPtee.getAddressSpace() != SrcPtee.getAddressSpace()) { 259013138422SDimitry Andric Self.Diag(OpRange.getBegin(), 259113138422SDimitry Andric diag::warn_bad_cxx_cast_nested_pointer_addr_space) 259213138422SDimitry Andric << CStyle << SrcType << DestType << SrcExpr.get()->getSourceRange(); 259313138422SDimitry Andric break; 259413138422SDimitry Andric } 259513138422SDimitry Andric DestPtee = DestPtee->getPointeeType(); 259613138422SDimitry Andric SrcPtee = SrcPtee->getPointeeType(); 259713138422SDimitry Andric } 259813138422SDimitry Andric 25990b57cec5SDimitry Andric // C++ 5.2.10p7: A pointer to an object can be explicitly converted to 26000b57cec5SDimitry Andric // a pointer to an object of different type. 26010b57cec5SDimitry Andric // Void pointers are not specified, but supported by every compiler out there. 26020b57cec5SDimitry Andric // So we finish by allowing everything that remains - it's got to be two 26030b57cec5SDimitry Andric // object pointers. 26040b57cec5SDimitry Andric return SuccessResult; 26050b57cec5SDimitry Andric } 26060b57cec5SDimitry Andric 26070b57cec5SDimitry Andric static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr, 26080b57cec5SDimitry Andric QualType DestType, bool CStyle, 26095ffd83dbSDimitry Andric unsigned &msg, CastKind &Kind) { 261081ad6265SDimitry Andric if (!Self.getLangOpts().OpenCL && !Self.getLangOpts().SYCLIsDevice) 26110b57cec5SDimitry Andric // FIXME: As compiler doesn't have any information about overlapping addr 26120b57cec5SDimitry Andric // spaces at the moment we have to be permissive here. 26130b57cec5SDimitry Andric return TC_NotApplicable; 26140b57cec5SDimitry Andric // Even though the logic below is general enough and can be applied to 26150b57cec5SDimitry Andric // non-OpenCL mode too, we fast-path above because no other languages 26160b57cec5SDimitry Andric // define overlapping address spaces currently. 26170b57cec5SDimitry Andric auto SrcType = SrcExpr.get()->getType(); 26185ffd83dbSDimitry Andric // FIXME: Should this be generalized to references? The reference parameter 26195ffd83dbSDimitry Andric // however becomes a reference pointee type here and therefore rejected. 26205ffd83dbSDimitry Andric // Perhaps this is the right behavior though according to C++. 26210b57cec5SDimitry Andric auto SrcPtrType = SrcType->getAs<PointerType>(); 26220b57cec5SDimitry Andric if (!SrcPtrType) 26230b57cec5SDimitry Andric return TC_NotApplicable; 26240b57cec5SDimitry Andric auto DestPtrType = DestType->getAs<PointerType>(); 26250b57cec5SDimitry Andric if (!DestPtrType) 26260b57cec5SDimitry Andric return TC_NotApplicable; 26270b57cec5SDimitry Andric auto SrcPointeeType = SrcPtrType->getPointeeType(); 26280b57cec5SDimitry Andric auto DestPointeeType = DestPtrType->getPointeeType(); 26295ffd83dbSDimitry Andric if (!DestPointeeType.isAddressSpaceOverlapping(SrcPointeeType)) { 26300b57cec5SDimitry Andric msg = diag::err_bad_cxx_cast_addr_space_mismatch; 26310b57cec5SDimitry Andric return TC_Failed; 26320b57cec5SDimitry Andric } 26330b57cec5SDimitry Andric auto SrcPointeeTypeWithoutAS = 26340b57cec5SDimitry Andric Self.Context.removeAddrSpaceQualType(SrcPointeeType.getCanonicalType()); 26350b57cec5SDimitry Andric auto DestPointeeTypeWithoutAS = 26360b57cec5SDimitry Andric Self.Context.removeAddrSpaceQualType(DestPointeeType.getCanonicalType()); 26375ffd83dbSDimitry Andric if (Self.Context.hasSameType(SrcPointeeTypeWithoutAS, 26385ffd83dbSDimitry Andric DestPointeeTypeWithoutAS)) { 26395ffd83dbSDimitry Andric Kind = SrcPointeeType.getAddressSpace() == DestPointeeType.getAddressSpace() 26405ffd83dbSDimitry Andric ? CK_NoOp 26415ffd83dbSDimitry Andric : CK_AddressSpaceConversion; 26425ffd83dbSDimitry Andric return TC_Success; 26435ffd83dbSDimitry Andric } else { 26445ffd83dbSDimitry Andric return TC_NotApplicable; 26455ffd83dbSDimitry Andric } 26460b57cec5SDimitry Andric } 26470b57cec5SDimitry Andric 26480b57cec5SDimitry Andric void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) { 26490b57cec5SDimitry Andric // In OpenCL only conversions between pointers to objects in overlapping 26500b57cec5SDimitry Andric // addr spaces are allowed. v2.0 s6.5.5 - Generic addr space overlaps 26510b57cec5SDimitry Andric // with any named one, except for constant. 26520b57cec5SDimitry Andric 26530b57cec5SDimitry Andric // Converting the top level pointee addrspace is permitted for compatible 26540b57cec5SDimitry Andric // addrspaces (such as 'generic int *' to 'local int *' or vice versa), but 26550b57cec5SDimitry Andric // if any of the nested pointee addrspaces differ, we emit a warning 26560b57cec5SDimitry Andric // regardless of addrspace compatibility. This makes 26570b57cec5SDimitry Andric // local int ** p; 26580b57cec5SDimitry Andric // return (generic int **) p; 26590b57cec5SDimitry Andric // warn even though local -> generic is permitted. 26600b57cec5SDimitry Andric if (Self.getLangOpts().OpenCL) { 26610b57cec5SDimitry Andric const Type *DestPtr, *SrcPtr; 26620b57cec5SDimitry Andric bool Nested = false; 26630b57cec5SDimitry Andric unsigned DiagID = diag::err_typecheck_incompatible_address_space; 26640b57cec5SDimitry Andric DestPtr = Self.getASTContext().getCanonicalType(DestType.getTypePtr()), 26650b57cec5SDimitry Andric SrcPtr = Self.getASTContext().getCanonicalType(SrcType.getTypePtr()); 26660b57cec5SDimitry Andric 26670b57cec5SDimitry Andric while (isa<PointerType>(DestPtr) && isa<PointerType>(SrcPtr)) { 26680b57cec5SDimitry Andric const PointerType *DestPPtr = cast<PointerType>(DestPtr); 26690b57cec5SDimitry Andric const PointerType *SrcPPtr = cast<PointerType>(SrcPtr); 26700b57cec5SDimitry Andric QualType DestPPointee = DestPPtr->getPointeeType(); 26710b57cec5SDimitry Andric QualType SrcPPointee = SrcPPtr->getPointeeType(); 26725ffd83dbSDimitry Andric if (Nested 26735ffd83dbSDimitry Andric ? DestPPointee.getAddressSpace() != SrcPPointee.getAddressSpace() 26745ffd83dbSDimitry Andric : !DestPPointee.isAddressSpaceOverlapping(SrcPPointee)) { 26750b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), DiagID) 26760b57cec5SDimitry Andric << SrcType << DestType << Sema::AA_Casting 26770b57cec5SDimitry Andric << SrcExpr.get()->getSourceRange(); 26780b57cec5SDimitry Andric if (!Nested) 26790b57cec5SDimitry Andric SrcExpr = ExprError(); 26800b57cec5SDimitry Andric return; 26810b57cec5SDimitry Andric } 26820b57cec5SDimitry Andric 26830b57cec5SDimitry Andric DestPtr = DestPPtr->getPointeeType().getTypePtr(); 26840b57cec5SDimitry Andric SrcPtr = SrcPPtr->getPointeeType().getTypePtr(); 26850b57cec5SDimitry Andric Nested = true; 26860b57cec5SDimitry Andric DiagID = diag::ext_nested_pointer_qualifier_mismatch; 26870b57cec5SDimitry Andric } 26880b57cec5SDimitry Andric } 26890b57cec5SDimitry Andric } 26900b57cec5SDimitry Andric 2691fe6060f1SDimitry Andric bool Sema::ShouldSplatAltivecScalarInCast(const VectorType *VecTy) { 2692fe6060f1SDimitry Andric bool SrcCompatXL = this->getLangOpts().getAltivecSrcCompat() == 2693fe6060f1SDimitry Andric LangOptions::AltivecSrcCompatKind::XL; 26945f757f3fSDimitry Andric VectorKind VKind = VecTy->getVectorKind(); 2695fe6060f1SDimitry Andric 26965f757f3fSDimitry Andric if ((VKind == VectorKind::AltiVecVector) || 26975f757f3fSDimitry Andric (SrcCompatXL && ((VKind == VectorKind::AltiVecBool) || 26985f757f3fSDimitry Andric (VKind == VectorKind::AltiVecPixel)))) { 2699fe6060f1SDimitry Andric return true; 2700fe6060f1SDimitry Andric } 2701fe6060f1SDimitry Andric return false; 2702fe6060f1SDimitry Andric } 2703fe6060f1SDimitry Andric 2704349cc55cSDimitry Andric bool Sema::CheckAltivecInitFromScalar(SourceRange R, QualType VecTy, 2705349cc55cSDimitry Andric QualType SrcTy) { 2706349cc55cSDimitry Andric bool SrcCompatGCC = this->getLangOpts().getAltivecSrcCompat() == 2707349cc55cSDimitry Andric LangOptions::AltivecSrcCompatKind::GCC; 2708349cc55cSDimitry Andric if (this->getLangOpts().AltiVec && SrcCompatGCC) { 2709349cc55cSDimitry Andric this->Diag(R.getBegin(), 2710349cc55cSDimitry Andric diag::err_invalid_conversion_between_vector_and_integer) 2711349cc55cSDimitry Andric << VecTy << SrcTy << R; 2712349cc55cSDimitry Andric return true; 2713349cc55cSDimitry Andric } 2714349cc55cSDimitry Andric return false; 2715349cc55cSDimitry Andric } 2716349cc55cSDimitry Andric 27170b57cec5SDimitry Andric void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, 27180b57cec5SDimitry Andric bool ListInitialization) { 27190b57cec5SDimitry Andric assert(Self.getLangOpts().CPlusPlus); 27200b57cec5SDimitry Andric 27210b57cec5SDimitry Andric // Handle placeholders. 27220b57cec5SDimitry Andric if (isPlaceholder()) { 27230b57cec5SDimitry Andric // C-style casts can resolve __unknown_any types. 27240b57cec5SDimitry Andric if (claimPlaceholder(BuiltinType::UnknownAny)) { 27250b57cec5SDimitry Andric SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, 27260b57cec5SDimitry Andric SrcExpr.get(), Kind, 27270b57cec5SDimitry Andric ValueKind, BasePath); 27280b57cec5SDimitry Andric return; 27290b57cec5SDimitry Andric } 27300b57cec5SDimitry Andric 27310b57cec5SDimitry Andric checkNonOverloadPlaceholders(); 27320b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 27330b57cec5SDimitry Andric return; 27340b57cec5SDimitry Andric } 27350b57cec5SDimitry Andric 27360b57cec5SDimitry Andric // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". 27370b57cec5SDimitry Andric // This test is outside everything else because it's the only case where 27380b57cec5SDimitry Andric // a non-lvalue-reference target type does not lead to decay. 27390b57cec5SDimitry Andric if (DestType->isVoidType()) { 27400b57cec5SDimitry Andric Kind = CK_ToVoid; 27410b57cec5SDimitry Andric 27420b57cec5SDimitry Andric if (claimPlaceholder(BuiltinType::Overload)) { 27430b57cec5SDimitry Andric Self.ResolveAndFixSingleFunctionTemplateSpecialization( 27440b57cec5SDimitry Andric SrcExpr, /* Decay Function to ptr */ false, 27450b57cec5SDimitry Andric /* Complain */ true, DestRange, DestType, 27460b57cec5SDimitry Andric diag::err_bad_cstyle_cast_overload); 27470b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 27480b57cec5SDimitry Andric return; 27490b57cec5SDimitry Andric } 27500b57cec5SDimitry Andric 27510b57cec5SDimitry Andric SrcExpr = Self.IgnoredValueConversions(SrcExpr.get()); 27520b57cec5SDimitry Andric return; 27530b57cec5SDimitry Andric } 27540b57cec5SDimitry Andric 27550b57cec5SDimitry Andric // If the type is dependent, we won't do any other semantic analysis now. 27560b57cec5SDimitry Andric if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() || 27570b57cec5SDimitry Andric SrcExpr.get()->isValueDependent()) { 27580b57cec5SDimitry Andric assert(Kind == CK_Dependent); 27590b57cec5SDimitry Andric return; 27600b57cec5SDimitry Andric } 27610b57cec5SDimitry Andric 2762fe6060f1SDimitry Andric if (ValueKind == VK_PRValue && !DestType->isRecordType() && 27630b57cec5SDimitry Andric !isPlaceholder(BuiltinType::Overload)) { 27640b57cec5SDimitry Andric SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); 27650b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 27660b57cec5SDimitry Andric return; 27670b57cec5SDimitry Andric } 27680b57cec5SDimitry Andric 27690b57cec5SDimitry Andric // AltiVec vector initialization with a single literal. 2770349cc55cSDimitry Andric if (const VectorType *vecTy = DestType->getAs<VectorType>()) { 2771349cc55cSDimitry Andric if (Self.CheckAltivecInitFromScalar(OpRange, DestType, 2772349cc55cSDimitry Andric SrcExpr.get()->getType())) { 2773349cc55cSDimitry Andric SrcExpr = ExprError(); 2774349cc55cSDimitry Andric return; 2775349cc55cSDimitry Andric } 2776fe6060f1SDimitry Andric if (Self.ShouldSplatAltivecScalarInCast(vecTy) && 2777fe6060f1SDimitry Andric (SrcExpr.get()->getType()->isIntegerType() || 2778fe6060f1SDimitry Andric SrcExpr.get()->getType()->isFloatingType())) { 27790b57cec5SDimitry Andric Kind = CK_VectorSplat; 27800b57cec5SDimitry Andric SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); 27810b57cec5SDimitry Andric return; 27820b57cec5SDimitry Andric } 2783349cc55cSDimitry Andric } 27840b57cec5SDimitry Andric 278506c3fb27SDimitry Andric // WebAssembly tables cannot be cast. 278606c3fb27SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 278706c3fb27SDimitry Andric if (SrcType->isWebAssemblyTableType()) { 278806c3fb27SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_wasm_cast_table) 278906c3fb27SDimitry Andric << 1 << SrcExpr.get()->getSourceRange(); 279006c3fb27SDimitry Andric SrcExpr = ExprError(); 279106c3fb27SDimitry Andric return; 279206c3fb27SDimitry Andric } 279306c3fb27SDimitry Andric 27940b57cec5SDimitry Andric // C++ [expr.cast]p5: The conversions performed by 27950b57cec5SDimitry Andric // - a const_cast, 27960b57cec5SDimitry Andric // - a static_cast, 27970b57cec5SDimitry Andric // - a static_cast followed by a const_cast, 27980b57cec5SDimitry Andric // - a reinterpret_cast, or 27990b57cec5SDimitry Andric // - a reinterpret_cast followed by a const_cast, 28000b57cec5SDimitry Andric // can be performed using the cast notation of explicit type conversion. 28010b57cec5SDimitry Andric // [...] If a conversion can be interpreted in more than one of the ways 28020b57cec5SDimitry Andric // listed above, the interpretation that appears first in the list is used, 28030b57cec5SDimitry Andric // even if a cast resulting from that interpretation is ill-formed. 28040b57cec5SDimitry Andric // In plain language, this means trying a const_cast ... 28050b57cec5SDimitry Andric // Note that for address space we check compatibility after const_cast. 28060b57cec5SDimitry Andric unsigned msg = diag::err_bad_cxx_cast_generic; 28070b57cec5SDimitry Andric TryCastResult tcr = TryConstCast(Self, SrcExpr, DestType, 28080b57cec5SDimitry Andric /*CStyle*/ true, msg); 28090b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 28100b57cec5SDimitry Andric return; 28110b57cec5SDimitry Andric if (isValidCast(tcr)) 28120b57cec5SDimitry Andric Kind = CK_NoOp; 28130b57cec5SDimitry Andric 2814*0fca6ea1SDimitry Andric CheckedConversionKind CCK = FunctionalStyle 2815*0fca6ea1SDimitry Andric ? CheckedConversionKind::FunctionalCast 2816*0fca6ea1SDimitry Andric : CheckedConversionKind::CStyleCast; 28170b57cec5SDimitry Andric if (tcr == TC_NotApplicable) { 28185ffd83dbSDimitry Andric tcr = TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ true, msg, 28195ffd83dbSDimitry Andric Kind); 28200b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 28210b57cec5SDimitry Andric return; 28220b57cec5SDimitry Andric 28230b57cec5SDimitry Andric if (tcr == TC_NotApplicable) { 28245ffd83dbSDimitry Andric // ... or if that is not possible, a static_cast, ignoring const and 28255ffd83dbSDimitry Andric // addr space, ... 28260b57cec5SDimitry Andric tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange, msg, Kind, 28270b57cec5SDimitry Andric BasePath, ListInitialization); 28280b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 28290b57cec5SDimitry Andric return; 28300b57cec5SDimitry Andric 28310b57cec5SDimitry Andric if (tcr == TC_NotApplicable) { 28325ffd83dbSDimitry Andric // ... and finally a reinterpret_cast, ignoring const and addr space. 28330b57cec5SDimitry Andric tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/ true, 28340b57cec5SDimitry Andric OpRange, msg, Kind); 28350b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 28360b57cec5SDimitry Andric return; 28370b57cec5SDimitry Andric } 28380b57cec5SDimitry Andric } 28390b57cec5SDimitry Andric } 28400b57cec5SDimitry Andric 28410b57cec5SDimitry Andric if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() && 28420b57cec5SDimitry Andric isValidCast(tcr)) 28430b57cec5SDimitry Andric checkObjCConversion(CCK); 28440b57cec5SDimitry Andric 28450b57cec5SDimitry Andric if (tcr != TC_Success && msg != 0) { 28460b57cec5SDimitry Andric if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { 28470b57cec5SDimitry Andric DeclAccessPair Found; 28480b57cec5SDimitry Andric FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), 28490b57cec5SDimitry Andric DestType, 28500b57cec5SDimitry Andric /*Complain*/ true, 28510b57cec5SDimitry Andric Found); 28520b57cec5SDimitry Andric if (Fn) { 28530b57cec5SDimitry Andric // If DestType is a function type (not to be confused with the function 28540b57cec5SDimitry Andric // pointer type), it will be possible to resolve the function address, 28550b57cec5SDimitry Andric // but the type cast should be considered as failure. 28560b57cec5SDimitry Andric OverloadExpr *OE = OverloadExpr::find(SrcExpr.get()).Expression; 28570b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bad_cstyle_cast_overload) 28580b57cec5SDimitry Andric << OE->getName() << DestType << OpRange 28590b57cec5SDimitry Andric << OE->getQualifierLoc().getSourceRange(); 28600b57cec5SDimitry Andric Self.NoteAllOverloadCandidates(SrcExpr.get()); 28610b57cec5SDimitry Andric } 28620b57cec5SDimitry Andric } else { 28630b57cec5SDimitry Andric diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle), 28640b57cec5SDimitry Andric OpRange, SrcExpr.get(), DestType, ListInitialization); 28650b57cec5SDimitry Andric } 28660b57cec5SDimitry Andric } 28670b57cec5SDimitry Andric 28680b57cec5SDimitry Andric if (isValidCast(tcr)) { 28690b57cec5SDimitry Andric if (Kind == CK_BitCast) 28700b57cec5SDimitry Andric checkCastAlign(); 2871fe6060f1SDimitry Andric 2872bdd1243dSDimitry Andric if (unsigned DiagID = checkCastFunctionType(Self, SrcExpr, DestType)) 2873bdd1243dSDimitry Andric Self.Diag(OpRange.getBegin(), DiagID) 2874fe6060f1SDimitry Andric << SrcExpr.get()->getType() << DestType << OpRange; 2875fe6060f1SDimitry Andric 28760b57cec5SDimitry Andric } else { 28770b57cec5SDimitry Andric SrcExpr = ExprError(); 28780b57cec5SDimitry Andric } 28790b57cec5SDimitry Andric } 28800b57cec5SDimitry Andric 28810b57cec5SDimitry Andric /// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a 28820b57cec5SDimitry Andric /// non-matching type. Such as enum function call to int, int call to 28830b57cec5SDimitry Andric /// pointer; etc. Cast to 'void' is an exception. 28840b57cec5SDimitry Andric static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr, 28850b57cec5SDimitry Andric QualType DestType) { 28860b57cec5SDimitry Andric if (Self.Diags.isIgnored(diag::warn_bad_function_cast, 28870b57cec5SDimitry Andric SrcExpr.get()->getExprLoc())) 28880b57cec5SDimitry Andric return; 28890b57cec5SDimitry Andric 28900b57cec5SDimitry Andric if (!isa<CallExpr>(SrcExpr.get())) 28910b57cec5SDimitry Andric return; 28920b57cec5SDimitry Andric 28930b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 28940b57cec5SDimitry Andric if (DestType.getUnqualifiedType()->isVoidType()) 28950b57cec5SDimitry Andric return; 28960b57cec5SDimitry Andric if ((SrcType->isAnyPointerType() || SrcType->isBlockPointerType()) 28970b57cec5SDimitry Andric && (DestType->isAnyPointerType() || DestType->isBlockPointerType())) 28980b57cec5SDimitry Andric return; 28990b57cec5SDimitry Andric if (SrcType->isIntegerType() && DestType->isIntegerType() && 29000b57cec5SDimitry Andric (SrcType->isBooleanType() == DestType->isBooleanType()) && 29010b57cec5SDimitry Andric (SrcType->isEnumeralType() == DestType->isEnumeralType())) 29020b57cec5SDimitry Andric return; 29030b57cec5SDimitry Andric if (SrcType->isRealFloatingType() && DestType->isRealFloatingType()) 29040b57cec5SDimitry Andric return; 29050b57cec5SDimitry Andric if (SrcType->isEnumeralType() && DestType->isEnumeralType()) 29060b57cec5SDimitry Andric return; 29070b57cec5SDimitry Andric if (SrcType->isComplexType() && DestType->isComplexType()) 29080b57cec5SDimitry Andric return; 29090b57cec5SDimitry Andric if (SrcType->isComplexIntegerType() && DestType->isComplexIntegerType()) 29100b57cec5SDimitry Andric return; 2911e8d8bef9SDimitry Andric if (SrcType->isFixedPointType() && DestType->isFixedPointType()) 2912e8d8bef9SDimitry Andric return; 29130b57cec5SDimitry Andric 29140b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getExprLoc(), 29150b57cec5SDimitry Andric diag::warn_bad_function_cast) 29160b57cec5SDimitry Andric << SrcType << DestType << SrcExpr.get()->getSourceRange(); 29170b57cec5SDimitry Andric } 29180b57cec5SDimitry Andric 29190b57cec5SDimitry Andric /// Check the semantics of a C-style cast operation, in C. 29200b57cec5SDimitry Andric void CastOperation::CheckCStyleCast() { 29210b57cec5SDimitry Andric assert(!Self.getLangOpts().CPlusPlus); 29220b57cec5SDimitry Andric 29230b57cec5SDimitry Andric // C-style casts can resolve __unknown_any types. 29240b57cec5SDimitry Andric if (claimPlaceholder(BuiltinType::UnknownAny)) { 29250b57cec5SDimitry Andric SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, 29260b57cec5SDimitry Andric SrcExpr.get(), Kind, 29270b57cec5SDimitry Andric ValueKind, BasePath); 29280b57cec5SDimitry Andric return; 29290b57cec5SDimitry Andric } 29300b57cec5SDimitry Andric 29310b57cec5SDimitry Andric // C99 6.5.4p2: the cast type needs to be void or scalar and the expression 29320b57cec5SDimitry Andric // type needs to be scalar. 29330b57cec5SDimitry Andric if (DestType->isVoidType()) { 29340b57cec5SDimitry Andric // We don't necessarily do lvalue-to-rvalue conversions on this. 29350b57cec5SDimitry Andric SrcExpr = Self.IgnoredValueConversions(SrcExpr.get()); 29360b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 29370b57cec5SDimitry Andric return; 29380b57cec5SDimitry Andric 29390b57cec5SDimitry Andric // Cast to void allows any expr type. 29400b57cec5SDimitry Andric Kind = CK_ToVoid; 29410b57cec5SDimitry Andric return; 29420b57cec5SDimitry Andric } 29430b57cec5SDimitry Andric 2944e8d8bef9SDimitry Andric // If the type is dependent, we won't do any other semantic analysis now. 2945e8d8bef9SDimitry Andric if (Self.getASTContext().isDependenceAllowed() && 2946e8d8bef9SDimitry Andric (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() || 2947e8d8bef9SDimitry Andric SrcExpr.get()->isValueDependent())) { 2948e8d8bef9SDimitry Andric assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() || 2949e8d8bef9SDimitry Andric SrcExpr.get()->containsErrors()) && 2950e8d8bef9SDimitry Andric "should only occur in error-recovery path."); 2951e8d8bef9SDimitry Andric assert(Kind == CK_Dependent); 2952e8d8bef9SDimitry Andric return; 2953e8d8bef9SDimitry Andric } 2954e8d8bef9SDimitry Andric 29550b57cec5SDimitry Andric // Overloads are allowed with C extensions, so we need to support them. 29560b57cec5SDimitry Andric if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { 29570b57cec5SDimitry Andric DeclAccessPair DAP; 29580b57cec5SDimitry Andric if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction( 29590b57cec5SDimitry Andric SrcExpr.get(), DestType, /*Complain=*/true, DAP)) 29600b57cec5SDimitry Andric SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD); 29610b57cec5SDimitry Andric else 29620b57cec5SDimitry Andric return; 29630b57cec5SDimitry Andric assert(SrcExpr.isUsable()); 29640b57cec5SDimitry Andric } 29650b57cec5SDimitry Andric SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); 29660b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 29670b57cec5SDimitry Andric return; 29680b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 29690b57cec5SDimitry Andric 297006c3fb27SDimitry Andric if (SrcType->isWebAssemblyTableType()) { 297106c3fb27SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_wasm_cast_table) 297206c3fb27SDimitry Andric << 1 << SrcExpr.get()->getSourceRange(); 297306c3fb27SDimitry Andric SrcExpr = ExprError(); 297406c3fb27SDimitry Andric return; 297506c3fb27SDimitry Andric } 297606c3fb27SDimitry Andric 29770b57cec5SDimitry Andric assert(!SrcType->isPlaceholderType()); 29780b57cec5SDimitry Andric 29790b57cec5SDimitry Andric checkAddressSpaceCast(SrcType, DestType); 29800b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 29810b57cec5SDimitry Andric return; 29820b57cec5SDimitry Andric 29830b57cec5SDimitry Andric if (Self.RequireCompleteType(OpRange.getBegin(), DestType, 29840b57cec5SDimitry Andric diag::err_typecheck_cast_to_incomplete)) { 29850b57cec5SDimitry Andric SrcExpr = ExprError(); 29860b57cec5SDimitry Andric return; 29870b57cec5SDimitry Andric } 29880b57cec5SDimitry Andric 29895ffd83dbSDimitry Andric // Allow casting a sizeless built-in type to itself. 29905ffd83dbSDimitry Andric if (DestType->isSizelessBuiltinType() && 29915ffd83dbSDimitry Andric Self.Context.hasSameUnqualifiedType(DestType, SrcType)) { 29925ffd83dbSDimitry Andric Kind = CK_NoOp; 29935ffd83dbSDimitry Andric return; 29945ffd83dbSDimitry Andric } 29955ffd83dbSDimitry Andric 2996e8d8bef9SDimitry Andric // Allow bitcasting between compatible SVE vector types. 2997e8d8bef9SDimitry Andric if ((SrcType->isVectorType() || DestType->isVectorType()) && 2998e8d8bef9SDimitry Andric Self.isValidSveBitcast(SrcType, DestType)) { 2999e8d8bef9SDimitry Andric Kind = CK_BitCast; 3000e8d8bef9SDimitry Andric return; 3001e8d8bef9SDimitry Andric } 3002e8d8bef9SDimitry Andric 300306c3fb27SDimitry Andric // Allow bitcasting between compatible RVV vector types. 300406c3fb27SDimitry Andric if ((SrcType->isVectorType() || DestType->isVectorType()) && 3005*0fca6ea1SDimitry Andric Self.RISCV().isValidRVVBitcast(SrcType, DestType)) { 300606c3fb27SDimitry Andric Kind = CK_BitCast; 300706c3fb27SDimitry Andric return; 300806c3fb27SDimitry Andric } 300906c3fb27SDimitry Andric 3010fe6060f1SDimitry Andric if (!DestType->isScalarType() && !DestType->isVectorType() && 3011fe6060f1SDimitry Andric !DestType->isMatrixType()) { 30120b57cec5SDimitry Andric const RecordType *DestRecordTy = DestType->getAs<RecordType>(); 30130b57cec5SDimitry Andric 30140b57cec5SDimitry Andric if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){ 30150b57cec5SDimitry Andric // GCC struct/union extension: allow cast to self. 30160b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar) 30170b57cec5SDimitry Andric << DestType << SrcExpr.get()->getSourceRange(); 30180b57cec5SDimitry Andric Kind = CK_NoOp; 30190b57cec5SDimitry Andric return; 30200b57cec5SDimitry Andric } 30210b57cec5SDimitry Andric 30220b57cec5SDimitry Andric // GCC's cast to union extension. 30230b57cec5SDimitry Andric if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) { 30240b57cec5SDimitry Andric RecordDecl *RD = DestRecordTy->getDecl(); 30250b57cec5SDimitry Andric if (CastExpr::getTargetFieldForToUnionCast(RD, SrcType)) { 30260b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union) 30270b57cec5SDimitry Andric << SrcExpr.get()->getSourceRange(); 30280b57cec5SDimitry Andric Kind = CK_ToUnion; 30290b57cec5SDimitry Andric return; 30300b57cec5SDimitry Andric } else { 30310b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type) 30320b57cec5SDimitry Andric << SrcType << SrcExpr.get()->getSourceRange(); 30330b57cec5SDimitry Andric SrcExpr = ExprError(); 30340b57cec5SDimitry Andric return; 30350b57cec5SDimitry Andric } 30360b57cec5SDimitry Andric } 30370b57cec5SDimitry Andric 30380b57cec5SDimitry Andric // OpenCL v2.0 s6.13.10 - Allow casts from '0' to event_t type. 30390b57cec5SDimitry Andric if (Self.getLangOpts().OpenCL && DestType->isEventT()) { 30400b57cec5SDimitry Andric Expr::EvalResult Result; 30410b57cec5SDimitry Andric if (SrcExpr.get()->EvaluateAsInt(Result, Self.Context)) { 30420b57cec5SDimitry Andric llvm::APSInt CastInt = Result.Val.getInt(); 30430b57cec5SDimitry Andric if (0 == CastInt) { 30440b57cec5SDimitry Andric Kind = CK_ZeroToOCLOpaqueType; 30450b57cec5SDimitry Andric return; 30460b57cec5SDimitry Andric } 30470b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), 30480b57cec5SDimitry Andric diag::err_opencl_cast_non_zero_to_event_t) 3049fe6060f1SDimitry Andric << toString(CastInt, 10) << SrcExpr.get()->getSourceRange(); 30500b57cec5SDimitry Andric SrcExpr = ExprError(); 30510b57cec5SDimitry Andric return; 30520b57cec5SDimitry Andric } 30530b57cec5SDimitry Andric } 30540b57cec5SDimitry Andric 30550b57cec5SDimitry Andric // Reject any other conversions to non-scalar types. 30560b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_typecheck_cond_expect_scalar) 30570b57cec5SDimitry Andric << DestType << SrcExpr.get()->getSourceRange(); 30580b57cec5SDimitry Andric SrcExpr = ExprError(); 30590b57cec5SDimitry Andric return; 30600b57cec5SDimitry Andric } 30610b57cec5SDimitry Andric 3062fe6060f1SDimitry Andric // The type we're casting to is known to be a scalar, a vector, or a matrix. 30630b57cec5SDimitry Andric 3064fe6060f1SDimitry Andric // Require the operand to be a scalar, a vector, or a matrix. 3065fe6060f1SDimitry Andric if (!SrcType->isScalarType() && !SrcType->isVectorType() && 3066fe6060f1SDimitry Andric !SrcType->isMatrixType()) { 30670b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getExprLoc(), 30680b57cec5SDimitry Andric diag::err_typecheck_expect_scalar_operand) 30690b57cec5SDimitry Andric << SrcType << SrcExpr.get()->getSourceRange(); 30700b57cec5SDimitry Andric SrcExpr = ExprError(); 30710b57cec5SDimitry Andric return; 30720b57cec5SDimitry Andric } 30730b57cec5SDimitry Andric 30745f757f3fSDimitry Andric // C23 6.5.4p4: 3075bdd1243dSDimitry Andric // The type nullptr_t shall not be converted to any type other than void, 3076bdd1243dSDimitry Andric // bool, or a pointer type. No type other than nullptr_t shall be converted 3077bdd1243dSDimitry Andric // to nullptr_t. 3078bdd1243dSDimitry Andric if (SrcType->isNullPtrType()) { 3079bdd1243dSDimitry Andric // FIXME: 6.3.2.4p2 says that nullptr_t can be converted to itself, but 3080bdd1243dSDimitry Andric // 6.5.4p4 is a constraint check and nullptr_t is not void, bool, or a 3081bdd1243dSDimitry Andric // pointer type. We're not going to diagnose that as a constraint violation. 3082bdd1243dSDimitry Andric if (!DestType->isVoidType() && !DestType->isBooleanType() && 3083bdd1243dSDimitry Andric !DestType->isPointerType() && !DestType->isNullPtrType()) { 3084bdd1243dSDimitry Andric Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast) 3085bdd1243dSDimitry Andric << /*nullptr to type*/ 0 << DestType; 3086bdd1243dSDimitry Andric SrcExpr = ExprError(); 3087bdd1243dSDimitry Andric return; 3088bdd1243dSDimitry Andric } 3089bdd1243dSDimitry Andric if (!DestType->isNullPtrType()) { 3090bdd1243dSDimitry Andric // Implicitly cast from the null pointer type to the type of the 3091bdd1243dSDimitry Andric // destination. 3092bdd1243dSDimitry Andric CastKind CK = DestType->isPointerType() ? CK_NullToPointer : CK_BitCast; 3093bdd1243dSDimitry Andric SrcExpr = ImplicitCastExpr::Create(Self.Context, DestType, CK, 3094bdd1243dSDimitry Andric SrcExpr.get(), nullptr, VK_PRValue, 3095bdd1243dSDimitry Andric Self.CurFPFeatureOverrides()); 3096bdd1243dSDimitry Andric } 3097bdd1243dSDimitry Andric } 3098bdd1243dSDimitry Andric if (DestType->isNullPtrType() && !SrcType->isNullPtrType()) { 3099bdd1243dSDimitry Andric Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_nullptr_cast) 3100bdd1243dSDimitry Andric << /*type to nullptr*/ 1 << SrcType; 3101bdd1243dSDimitry Andric SrcExpr = ExprError(); 3102bdd1243dSDimitry Andric return; 3103bdd1243dSDimitry Andric } 3104bdd1243dSDimitry Andric 31050b57cec5SDimitry Andric if (DestType->isExtVectorType()) { 31060b57cec5SDimitry Andric SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.get(), Kind); 31070b57cec5SDimitry Andric return; 31080b57cec5SDimitry Andric } 31090b57cec5SDimitry Andric 3110fe6060f1SDimitry Andric if (DestType->getAs<MatrixType>() || SrcType->getAs<MatrixType>()) { 3111fe6060f1SDimitry Andric if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind)) 3112fe6060f1SDimitry Andric SrcExpr = ExprError(); 3113fe6060f1SDimitry Andric return; 3114fe6060f1SDimitry Andric } 3115fe6060f1SDimitry Andric 31160b57cec5SDimitry Andric if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) { 3117349cc55cSDimitry Andric if (Self.CheckAltivecInitFromScalar(OpRange, DestType, SrcType)) { 3118349cc55cSDimitry Andric SrcExpr = ExprError(); 3119349cc55cSDimitry Andric return; 3120349cc55cSDimitry Andric } 3121fe6060f1SDimitry Andric if (Self.ShouldSplatAltivecScalarInCast(DestVecTy) && 31220b57cec5SDimitry Andric (SrcType->isIntegerType() || SrcType->isFloatingType())) { 31230b57cec5SDimitry Andric Kind = CK_VectorSplat; 31240b57cec5SDimitry Andric SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get()); 31250b57cec5SDimitry Andric } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) { 31260b57cec5SDimitry Andric SrcExpr = ExprError(); 31270b57cec5SDimitry Andric } 31280b57cec5SDimitry Andric return; 31290b57cec5SDimitry Andric } 31300b57cec5SDimitry Andric 31310b57cec5SDimitry Andric if (SrcType->isVectorType()) { 31320b57cec5SDimitry Andric if (Self.CheckVectorCast(OpRange, SrcType, DestType, Kind)) 31330b57cec5SDimitry Andric SrcExpr = ExprError(); 31340b57cec5SDimitry Andric return; 31350b57cec5SDimitry Andric } 31360b57cec5SDimitry Andric 31370b57cec5SDimitry Andric // The source and target types are both scalars, i.e. 31380b57cec5SDimitry Andric // - arithmetic types (fundamental, enum, and complex) 31390b57cec5SDimitry Andric // - all kinds of pointers 31400b57cec5SDimitry Andric // Note that member pointers were filtered out with C++, above. 31410b57cec5SDimitry Andric 31420b57cec5SDimitry Andric if (isa<ObjCSelectorExpr>(SrcExpr.get())) { 31430b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_selector_expr); 31440b57cec5SDimitry Andric SrcExpr = ExprError(); 31450b57cec5SDimitry Andric return; 31460b57cec5SDimitry Andric } 31470b57cec5SDimitry Andric 31480b57cec5SDimitry Andric // If either type is a pointer, the other type has to be either an 31490b57cec5SDimitry Andric // integer or a pointer. 31500b57cec5SDimitry Andric if (!DestType->isArithmeticType()) { 31510b57cec5SDimitry Andric if (!SrcType->isIntegralType(Self.Context) && SrcType->isArithmeticType()) { 31520b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getExprLoc(), 31530b57cec5SDimitry Andric diag::err_cast_pointer_from_non_pointer_int) 31540b57cec5SDimitry Andric << SrcType << SrcExpr.get()->getSourceRange(); 31550b57cec5SDimitry Andric SrcExpr = ExprError(); 31560b57cec5SDimitry Andric return; 31570b57cec5SDimitry Andric } 31585ffd83dbSDimitry Andric checkIntToPointerCast(/* CStyle */ true, OpRange, SrcExpr.get(), DestType, 31595ffd83dbSDimitry Andric Self); 31600b57cec5SDimitry Andric } else if (!SrcType->isArithmeticType()) { 31610b57cec5SDimitry Andric if (!DestType->isIntegralType(Self.Context) && 31620b57cec5SDimitry Andric DestType->isArithmeticType()) { 31630b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getBeginLoc(), 31640b57cec5SDimitry Andric diag::err_cast_pointer_to_non_pointer_int) 31650b57cec5SDimitry Andric << DestType << SrcExpr.get()->getSourceRange(); 31660b57cec5SDimitry Andric SrcExpr = ExprError(); 31670b57cec5SDimitry Andric return; 31680b57cec5SDimitry Andric } 31695ffd83dbSDimitry Andric 31705ffd83dbSDimitry Andric if ((Self.Context.getTypeSize(SrcType) > 31715ffd83dbSDimitry Andric Self.Context.getTypeSize(DestType)) && 31725ffd83dbSDimitry Andric !DestType->isBooleanType()) { 31735ffd83dbSDimitry Andric // C 6.3.2.3p6: Any pointer type may be converted to an integer type. 31745ffd83dbSDimitry Andric // Except as previously specified, the result is implementation-defined. 31755ffd83dbSDimitry Andric // If the result cannot be represented in the integer type, the behavior 31765ffd83dbSDimitry Andric // is undefined. The result need not be in the range of values of any 31775ffd83dbSDimitry Andric // integer type. 31785ffd83dbSDimitry Andric unsigned Diag; 31795ffd83dbSDimitry Andric if (SrcType->isVoidPointerType()) 31805ffd83dbSDimitry Andric Diag = DestType->isEnumeralType() ? diag::warn_void_pointer_to_enum_cast 31815ffd83dbSDimitry Andric : diag::warn_void_pointer_to_int_cast; 31825ffd83dbSDimitry Andric else if (DestType->isEnumeralType()) 31835ffd83dbSDimitry Andric Diag = diag::warn_pointer_to_enum_cast; 31845ffd83dbSDimitry Andric else 31855ffd83dbSDimitry Andric Diag = diag::warn_pointer_to_int_cast; 31865ffd83dbSDimitry Andric Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange; 31875ffd83dbSDimitry Andric } 31880b57cec5SDimitry Andric } 31890b57cec5SDimitry Andric 3190fe6060f1SDimitry Andric if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().isAvailableOption( 3191fe6060f1SDimitry Andric "cl_khr_fp16", Self.getLangOpts())) { 31920b57cec5SDimitry Andric if (DestType->isHalfType()) { 31930b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_opencl_cast_to_half) 31940b57cec5SDimitry Andric << DestType << SrcExpr.get()->getSourceRange(); 31950b57cec5SDimitry Andric SrcExpr = ExprError(); 31960b57cec5SDimitry Andric return; 31970b57cec5SDimitry Andric } 31980b57cec5SDimitry Andric } 31990b57cec5SDimitry Andric 32000b57cec5SDimitry Andric // ARC imposes extra restrictions on casts. 32010b57cec5SDimitry Andric if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) { 3202*0fca6ea1SDimitry Andric checkObjCConversion(CheckedConversionKind::CStyleCast); 32030b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 32040b57cec5SDimitry Andric return; 32050b57cec5SDimitry Andric 32060b57cec5SDimitry Andric const PointerType *CastPtr = DestType->getAs<PointerType>(); 32070b57cec5SDimitry Andric if (Self.getLangOpts().ObjCAutoRefCount && CastPtr) { 32080b57cec5SDimitry Andric if (const PointerType *ExprPtr = SrcType->getAs<PointerType>()) { 32090b57cec5SDimitry Andric Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers(); 32100b57cec5SDimitry Andric Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers(); 32110b57cec5SDimitry Andric if (CastPtr->getPointeeType()->isObjCLifetimeType() && 32120b57cec5SDimitry Andric ExprPtr->getPointeeType()->isObjCLifetimeType() && 32130b57cec5SDimitry Andric !CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) { 32140b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getBeginLoc(), 32150b57cec5SDimitry Andric diag::err_typecheck_incompatible_ownership) 32160b57cec5SDimitry Andric << SrcType << DestType << Sema::AA_Casting 32170b57cec5SDimitry Andric << SrcExpr.get()->getSourceRange(); 32180b57cec5SDimitry Andric return; 32190b57cec5SDimitry Andric } 32200b57cec5SDimitry Andric } 3221*0fca6ea1SDimitry Andric } else if (!Self.ObjC().CheckObjCARCUnavailableWeakConversion(DestType, 3222*0fca6ea1SDimitry Andric SrcType)) { 32230b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getBeginLoc(), 32240b57cec5SDimitry Andric diag::err_arc_convesion_of_weak_unavailable) 32250b57cec5SDimitry Andric << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange(); 32260b57cec5SDimitry Andric SrcExpr = ExprError(); 32270b57cec5SDimitry Andric return; 32280b57cec5SDimitry Andric } 32290b57cec5SDimitry Andric } 32300b57cec5SDimitry Andric 3231bdd1243dSDimitry Andric if (unsigned DiagID = checkCastFunctionType(Self, SrcExpr, DestType)) 3232bdd1243dSDimitry Andric Self.Diag(OpRange.getBegin(), DiagID) << SrcType << DestType << OpRange; 3233fe6060f1SDimitry Andric 323481ad6265SDimitry Andric if (isa<PointerType>(SrcType) && isa<PointerType>(DestType)) { 323581ad6265SDimitry Andric QualType SrcTy = cast<PointerType>(SrcType)->getPointeeType(); 323681ad6265SDimitry Andric QualType DestTy = cast<PointerType>(DestType)->getPointeeType(); 323781ad6265SDimitry Andric 323881ad6265SDimitry Andric const RecordDecl *SrcRD = SrcTy->getAsRecordDecl(); 323981ad6265SDimitry Andric const RecordDecl *DestRD = DestTy->getAsRecordDecl(); 324081ad6265SDimitry Andric 324181ad6265SDimitry Andric if (SrcRD && DestRD && SrcRD->hasAttr<RandomizeLayoutAttr>() && 324281ad6265SDimitry Andric SrcRD != DestRD) { 324381ad6265SDimitry Andric // The struct we are casting the pointer from was randomized. 324481ad6265SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_cast_from_randomized_struct) 324581ad6265SDimitry Andric << SrcType << DestType; 324681ad6265SDimitry Andric SrcExpr = ExprError(); 324781ad6265SDimitry Andric return; 324881ad6265SDimitry Andric } 324981ad6265SDimitry Andric } 325081ad6265SDimitry Andric 32510b57cec5SDimitry Andric DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType); 32520b57cec5SDimitry Andric DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange); 32530b57cec5SDimitry Andric DiagnoseBadFunctionCast(Self, SrcExpr, DestType); 32540b57cec5SDimitry Andric Kind = Self.PrepareScalarCast(SrcExpr, DestType); 32550b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 32560b57cec5SDimitry Andric return; 32570b57cec5SDimitry Andric 32580b57cec5SDimitry Andric if (Kind == CK_BitCast) 32590b57cec5SDimitry Andric checkCastAlign(); 32600b57cec5SDimitry Andric } 32610b57cec5SDimitry Andric 32620b57cec5SDimitry Andric void CastOperation::CheckBuiltinBitCast() { 32630b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 3264a7dea167SDimitry Andric 3265a7dea167SDimitry Andric if (Self.RequireCompleteType(OpRange.getBegin(), DestType, 3266a7dea167SDimitry Andric diag::err_typecheck_cast_to_incomplete) || 3267a7dea167SDimitry Andric Self.RequireCompleteType(OpRange.getBegin(), SrcType, 3268a7dea167SDimitry Andric diag::err_incomplete_type)) { 3269a7dea167SDimitry Andric SrcExpr = ExprError(); 3270a7dea167SDimitry Andric return; 3271a7dea167SDimitry Andric } 3272a7dea167SDimitry Andric 3273fe6060f1SDimitry Andric if (SrcExpr.get()->isPRValue()) 32740b57cec5SDimitry Andric SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcType, SrcExpr.get(), 32750b57cec5SDimitry Andric /*IsLValueReference=*/false); 32760b57cec5SDimitry Andric 32770b57cec5SDimitry Andric CharUnits DestSize = Self.Context.getTypeSizeInChars(DestType); 32780b57cec5SDimitry Andric CharUnits SourceSize = Self.Context.getTypeSizeInChars(SrcType); 32790b57cec5SDimitry Andric if (DestSize != SourceSize) { 32800b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bit_cast_type_size_mismatch) 32810b57cec5SDimitry Andric << (int)SourceSize.getQuantity() << (int)DestSize.getQuantity(); 32820b57cec5SDimitry Andric SrcExpr = ExprError(); 32830b57cec5SDimitry Andric return; 32840b57cec5SDimitry Andric } 32850b57cec5SDimitry Andric 32860b57cec5SDimitry Andric if (!DestType.isTriviallyCopyableType(Self.Context)) { 32870b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bit_cast_non_trivially_copyable) 32880b57cec5SDimitry Andric << 1; 32890b57cec5SDimitry Andric SrcExpr = ExprError(); 32900b57cec5SDimitry Andric return; 32910b57cec5SDimitry Andric } 32920b57cec5SDimitry Andric 32930b57cec5SDimitry Andric if (!SrcType.isTriviallyCopyableType(Self.Context)) { 32940b57cec5SDimitry Andric Self.Diag(OpRange.getBegin(), diag::err_bit_cast_non_trivially_copyable) 32950b57cec5SDimitry Andric << 0; 32960b57cec5SDimitry Andric SrcExpr = ExprError(); 32970b57cec5SDimitry Andric return; 32980b57cec5SDimitry Andric } 32990b57cec5SDimitry Andric 33000b57cec5SDimitry Andric Kind = CK_LValueToRValueBitCast; 33010b57cec5SDimitry Andric } 33020b57cec5SDimitry Andric 33030b57cec5SDimitry Andric /// DiagnoseCastQual - Warn whenever casts discards a qualifiers, be it either 33040b57cec5SDimitry Andric /// const, volatile or both. 33050b57cec5SDimitry Andric static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr, 33060b57cec5SDimitry Andric QualType DestType) { 33070b57cec5SDimitry Andric if (SrcExpr.isInvalid()) 33080b57cec5SDimitry Andric return; 33090b57cec5SDimitry Andric 33100b57cec5SDimitry Andric QualType SrcType = SrcExpr.get()->getType(); 33110b57cec5SDimitry Andric if (!((SrcType->isAnyPointerType() && DestType->isAnyPointerType()) || 33120b57cec5SDimitry Andric DestType->isLValueReferenceType())) 33130b57cec5SDimitry Andric return; 33140b57cec5SDimitry Andric 33150b57cec5SDimitry Andric QualType TheOffendingSrcType, TheOffendingDestType; 33160b57cec5SDimitry Andric Qualifiers CastAwayQualifiers; 33170b57cec5SDimitry Andric if (CastsAwayConstness(Self, SrcType, DestType, true, false, 33180b57cec5SDimitry Andric &TheOffendingSrcType, &TheOffendingDestType, 33190b57cec5SDimitry Andric &CastAwayQualifiers) != 33200b57cec5SDimitry Andric CastAwayConstnessKind::CACK_Similar) 33210b57cec5SDimitry Andric return; 33220b57cec5SDimitry Andric 33230b57cec5SDimitry Andric // FIXME: 'restrict' is not properly handled here. 33240b57cec5SDimitry Andric int qualifiers = -1; 33250b57cec5SDimitry Andric if (CastAwayQualifiers.hasConst() && CastAwayQualifiers.hasVolatile()) { 33260b57cec5SDimitry Andric qualifiers = 0; 33270b57cec5SDimitry Andric } else if (CastAwayQualifiers.hasConst()) { 33280b57cec5SDimitry Andric qualifiers = 1; 33290b57cec5SDimitry Andric } else if (CastAwayQualifiers.hasVolatile()) { 33300b57cec5SDimitry Andric qualifiers = 2; 33310b57cec5SDimitry Andric } 33320b57cec5SDimitry Andric // This is a variant of int **x; const int **y = (const int **)x; 33330b57cec5SDimitry Andric if (qualifiers == -1) 33340b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual2) 33350b57cec5SDimitry Andric << SrcType << DestType; 33360b57cec5SDimitry Andric else 33370b57cec5SDimitry Andric Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual) 33380b57cec5SDimitry Andric << TheOffendingSrcType << TheOffendingDestType << qualifiers; 33390b57cec5SDimitry Andric } 33400b57cec5SDimitry Andric 33410b57cec5SDimitry Andric ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, 33420b57cec5SDimitry Andric TypeSourceInfo *CastTypeInfo, 33430b57cec5SDimitry Andric SourceLocation RPLoc, 33440b57cec5SDimitry Andric Expr *CastExpr) { 33450b57cec5SDimitry Andric CastOperation Op(*this, CastTypeInfo->getType(), CastExpr); 33460b57cec5SDimitry Andric Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); 33470b57cec5SDimitry Andric Op.OpRange = SourceRange(LPLoc, CastExpr->getEndLoc()); 33480b57cec5SDimitry Andric 33490b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) { 33500b57cec5SDimitry Andric Op.CheckCXXCStyleCast(/*FunctionalCast=*/ false, 33510b57cec5SDimitry Andric isa<InitListExpr>(CastExpr)); 33520b57cec5SDimitry Andric } else { 33530b57cec5SDimitry Andric Op.CheckCStyleCast(); 33540b57cec5SDimitry Andric } 33550b57cec5SDimitry Andric 33560b57cec5SDimitry Andric if (Op.SrcExpr.isInvalid()) 33570b57cec5SDimitry Andric return ExprError(); 33580b57cec5SDimitry Andric 33590b57cec5SDimitry Andric // -Wcast-qual 33600b57cec5SDimitry Andric DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType); 33610b57cec5SDimitry Andric 3362e8d8bef9SDimitry Andric return Op.complete(CStyleCastExpr::Create( 3363e8d8bef9SDimitry Andric Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(), 3364e8d8bef9SDimitry Andric &Op.BasePath, CurFPFeatureOverrides(), CastTypeInfo, LPLoc, RPLoc)); 33650b57cec5SDimitry Andric } 33660b57cec5SDimitry Andric 33670b57cec5SDimitry Andric ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, 33680b57cec5SDimitry Andric QualType Type, 33690b57cec5SDimitry Andric SourceLocation LPLoc, 33700b57cec5SDimitry Andric Expr *CastExpr, 33710b57cec5SDimitry Andric SourceLocation RPLoc) { 33720b57cec5SDimitry Andric assert(LPLoc.isValid() && "List-initialization shouldn't get here."); 33730b57cec5SDimitry Andric CastOperation Op(*this, Type, CastExpr); 33740b57cec5SDimitry Andric Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); 33755f757f3fSDimitry Andric Op.OpRange = SourceRange(Op.DestRange.getBegin(), RPLoc); 33760b57cec5SDimitry Andric 33770b57cec5SDimitry Andric Op.CheckCXXCStyleCast(/*FunctionalCast=*/true, /*ListInit=*/false); 33780b57cec5SDimitry Andric if (Op.SrcExpr.isInvalid()) 33790b57cec5SDimitry Andric return ExprError(); 33800b57cec5SDimitry Andric 33810b57cec5SDimitry Andric auto *SubExpr = Op.SrcExpr.get(); 33820b57cec5SDimitry Andric if (auto *BindExpr = dyn_cast<CXXBindTemporaryExpr>(SubExpr)) 33830b57cec5SDimitry Andric SubExpr = BindExpr->getSubExpr(); 33840b57cec5SDimitry Andric if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr)) 33850b57cec5SDimitry Andric ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc)); 33860b57cec5SDimitry Andric 33875f757f3fSDimitry Andric // -Wcast-qual 33885f757f3fSDimitry Andric DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType); 33895f757f3fSDimitry Andric 3390e8d8bef9SDimitry Andric return Op.complete(CXXFunctionalCastExpr::Create( 3391e8d8bef9SDimitry Andric Context, Op.ResultType, Op.ValueKind, CastTypeInfo, Op.Kind, 3392e8d8bef9SDimitry Andric Op.SrcExpr.get(), &Op.BasePath, CurFPFeatureOverrides(), LPLoc, RPLoc)); 33930b57cec5SDimitry Andric } 3394