2011-10-12 01:38:55 +08:00
|
|
|
//===--- SemaCast.cpp - Semantic Analysis for Casts -----------------------===//
|
2008-11-06 05:50:06 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2011-10-12 01:38:55 +08:00
|
|
|
// This file implements semantic analysis for cast expressions, including
|
|
|
|
// 1) C-style casts like '(int) x'
|
|
|
|
// 2) C++ functional casts like 'int(x)'
|
|
|
|
// 3) C++ named casts like 'static_cast<int>(x)'
|
2008-11-06 05:50:06 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-08-26 06:03:47 +08:00
|
|
|
#include "clang/Sema/SemaInternal.h"
|
2008-11-06 05:50:06 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2009-10-07 01:59:45 +08:00
|
|
|
#include "clang/AST/CXXInheritance.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/AST/ExprCXX.h"
|
|
|
|
#include "clang/AST/ExprObjC.h"
|
2013-03-22 10:58:14 +08:00
|
|
|
#include "clang/AST/RecordLayout.h"
|
2009-08-27 07:45:07 +08:00
|
|
|
#include "clang/Basic/PartialDiagnostic.h"
|
2014-01-17 17:01:00 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/Initialization.h"
|
2008-11-06 05:50:06 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2008-11-08 07:29:29 +08:00
|
|
|
#include <set>
|
2008-11-06 05:50:06 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2010-11-08 11:40:48 +08:00
|
|
|
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
enum TryCastResult {
|
|
|
|
TC_NotApplicable, ///< The cast method is not applicable.
|
|
|
|
TC_Success, ///< The cast method is appropriate and successful.
|
|
|
|
TC_Failed ///< The cast method is appropriate, but failed. A
|
|
|
|
///< diagnostic has been emitted.
|
|
|
|
};
|
|
|
|
|
|
|
|
enum CastType {
|
|
|
|
CT_Const, ///< const_cast
|
|
|
|
CT_Static, ///< static_cast
|
|
|
|
CT_Reinterpret, ///< reinterpret_cast
|
|
|
|
CT_Dynamic, ///< dynamic_cast
|
|
|
|
CT_CStyle, ///< (Type)expr
|
|
|
|
CT_Functional ///< Type(expr)
|
2008-11-08 21:00:26 +08:00
|
|
|
};
|
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
namespace {
|
|
|
|
struct CastOperation {
|
|
|
|
CastOperation(Sema &S, QualType destType, ExprResult src)
|
|
|
|
: Self(S), SrcExpr(src), DestType(destType),
|
|
|
|
ResultType(destType.getNonLValueExprType(S.Context)),
|
|
|
|
ValueKind(Expr::getValueKindForType(destType)),
|
2011-10-18 02:40:02 +08:00
|
|
|
Kind(CK_Dependent), IsARCUnbridgedCast(false) {
|
2011-10-07 07:25:11 +08:00
|
|
|
|
|
|
|
if (const BuiltinType *placeholder =
|
|
|
|
src.get()->getType()->getAsPlaceholderType()) {
|
|
|
|
PlaceholderKind = placeholder->getKind();
|
|
|
|
} else {
|
|
|
|
PlaceholderKind = (BuiltinType::Kind) 0;
|
|
|
|
}
|
|
|
|
}
|
2011-10-05 15:41:44 +08:00
|
|
|
|
|
|
|
Sema &Self;
|
|
|
|
ExprResult SrcExpr;
|
|
|
|
QualType DestType;
|
|
|
|
QualType ResultType;
|
|
|
|
ExprValueKind ValueKind;
|
|
|
|
CastKind Kind;
|
2011-10-07 07:25:11 +08:00
|
|
|
BuiltinType::Kind PlaceholderKind;
|
2011-10-05 15:41:44 +08:00
|
|
|
CXXCastPath BasePath;
|
2011-10-18 02:40:02 +08:00
|
|
|
bool IsARCUnbridgedCast;
|
2010-11-08 11:40:48 +08:00
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
SourceRange OpRange;
|
|
|
|
SourceRange DestRange;
|
2010-11-08 11:40:48 +08:00
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
// Top-level semantics-checking routines.
|
2011-10-05 15:41:44 +08:00
|
|
|
void CheckConstCast();
|
|
|
|
void CheckReinterpretCast();
|
2011-11-30 06:48:16 +08:00
|
|
|
void CheckStaticCast();
|
2011-10-05 15:41:44 +08:00
|
|
|
void CheckDynamicCast();
|
2012-02-13 02:41:05 +08:00
|
|
|
void CheckCXXCStyleCast(bool FunctionalCast, bool ListInitialization);
|
2011-10-07 07:25:11 +08:00
|
|
|
void CheckCStyleCast();
|
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
/// Complete an apparently-successful cast operation that yields
|
|
|
|
/// the given expression.
|
|
|
|
ExprResult complete(CastExpr *castExpr) {
|
|
|
|
// If this is an unbridged cast, wrap the result in an implicit
|
|
|
|
// cast that yields the unbridged-cast placeholder type.
|
|
|
|
if (IsARCUnbridgedCast) {
|
|
|
|
castExpr = ImplicitCastExpr::Create(Self.Context,
|
|
|
|
Self.Context.ARCUnbridgedCastTy,
|
2014-05-26 14:22:03 +08:00
|
|
|
CK_Dependent, castExpr, nullptr,
|
2011-10-18 02:40:02 +08:00
|
|
|
castExpr->getValueKind());
|
|
|
|
}
|
2014-05-29 22:05:12 +08:00
|
|
|
return castExpr;
|
2011-10-18 02:40:02 +08:00
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
// Internal convenience methods.
|
|
|
|
|
|
|
|
/// Try to handle the given placeholder expression kind. Return
|
|
|
|
/// true if the source expression has the appropriate placeholder
|
|
|
|
/// kind. A placeholder can only be claimed once.
|
|
|
|
bool claimPlaceholder(BuiltinType::Kind K) {
|
|
|
|
if (PlaceholderKind != K) return false;
|
|
|
|
|
|
|
|
PlaceholderKind = (BuiltinType::Kind) 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isPlaceholder() const {
|
|
|
|
return PlaceholderKind != 0;
|
|
|
|
}
|
|
|
|
bool isPlaceholder(BuiltinType::Kind K) const {
|
|
|
|
return PlaceholderKind == K;
|
|
|
|
}
|
2010-11-08 11:40:48 +08:00
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
void checkCastAlign() {
|
|
|
|
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
|
|
|
|
}
|
|
|
|
|
|
|
|
void checkObjCARCConversion(Sema::CheckedConversionKind CCK) {
|
2012-03-11 15:00:24 +08:00
|
|
|
assert(Self.getLangOpts().ObjCAutoRefCount);
|
2011-10-18 02:40:02 +08:00
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
Expr *src = SrcExpr.get();
|
2011-10-18 02:40:02 +08:00
|
|
|
if (Self.CheckObjCARCConversion(OpRange, DestType, src, CCK) ==
|
|
|
|
Sema::ACR_unbridged)
|
|
|
|
IsARCUnbridgedCast = true;
|
2011-10-05 15:41:44 +08:00
|
|
|
SrcExpr = src;
|
|
|
|
}
|
2011-10-07 07:25:11 +08:00
|
|
|
|
|
|
|
/// Check for and handle non-overload placeholder expressions.
|
|
|
|
void checkNonOverloadPlaceholders() {
|
|
|
|
if (!isPlaceholder() || isPlaceholder(BuiltinType::Overload))
|
|
|
|
return;
|
|
|
|
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
|
2011-10-07 07:25:11 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
PlaceholderKind = (BuiltinType::Kind) 0;
|
|
|
|
}
|
2011-10-05 15:41:44 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2008-11-08 21:00:26 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// The Try functions attempt a specific way of casting. If they succeed, they
|
|
|
|
// return TC_Success. If their way of casting is not appropriate for the given
|
|
|
|
// arguments, they return TC_NotApplicable and *may* set diag to a diagnostic
|
|
|
|
// to emit if no other way succeeds. If their way of casting is appropriate but
|
|
|
|
// fails, they return TC_Failed and *must* set diag; they can set it to 0 if
|
|
|
|
// they emit a specialized diagnostic.
|
|
|
|
// All diagnostics returned by these functions must expect the same three
|
|
|
|
// arguments:
|
|
|
|
// %0: Cast Type (a value from the CastType enumeration)
|
|
|
|
// %1: Source Type
|
|
|
|
// %2: Destination Type
|
|
|
|
static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
|
2011-01-27 05:04:06 +08:00
|
|
|
QualType DestType, bool CStyle,
|
|
|
|
CastKind &Kind,
|
2011-01-26 00:13:26 +08:00
|
|
|
CXXCastPath &BasePath,
|
|
|
|
unsigned &msg);
|
2009-07-25 23:41:38 +08:00
|
|
|
static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
|
2010-04-25 03:36:51 +08:00
|
|
|
QualType DestType, bool CStyle,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2010-04-25 03:36:51 +08:00
|
|
|
unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind,
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath &BasePath);
|
2009-07-25 23:41:38 +08:00
|
|
|
static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
|
|
|
|
QualType DestType, bool CStyle,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2009-11-13 00:53:16 +08:00
|
|
|
unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind,
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath &BasePath);
|
2009-11-15 17:20:52 +08:00
|
|
|
static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
|
|
|
|
CanQualType DestType, bool CStyle,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2009-07-25 23:41:38 +08:00
|
|
|
QualType OrigSrcType,
|
2009-11-13 00:53:16 +08:00
|
|
|
QualType OrigDestType, unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind,
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath &BasePath);
|
2011-04-09 02:41:53 +08:00
|
|
|
static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
|
2010-04-25 03:22:20 +08:00
|
|
|
QualType SrcType,
|
|
|
|
QualType DestType,bool CStyle,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2010-04-25 03:22:20 +08:00
|
|
|
unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind,
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath &BasePath);
|
2010-04-25 03:22:20 +08:00
|
|
|
|
2011-04-09 02:41:53 +08:00
|
|
|
static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
|
2011-06-16 07:02:42 +08:00
|
|
|
QualType DestType,
|
|
|
|
Sema::CheckedConversionKind CCK,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2012-02-13 02:41:05 +08:00
|
|
|
unsigned &msg, CastKind &Kind,
|
|
|
|
bool ListInitialization);
|
2011-04-09 02:41:53 +08:00
|
|
|
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
|
2011-06-16 07:02:42 +08:00
|
|
|
QualType DestType,
|
|
|
|
Sema::CheckedConversionKind CCK,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2012-02-13 02:41:05 +08:00
|
|
|
unsigned &msg, CastKind &Kind,
|
|
|
|
CXXCastPath &BasePath,
|
|
|
|
bool ListInitialization);
|
2013-06-15 06:27:52 +08:00
|
|
|
static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
|
|
|
|
QualType DestType, bool CStyle,
|
|
|
|
unsigned &msg);
|
2011-04-09 02:41:53 +08:00
|
|
|
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
2009-07-25 23:41:38 +08:00
|
|
|
QualType DestType, bool CStyle,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2009-09-26 08:12:34 +08:00
|
|
|
unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind);
|
2008-11-08 21:00:26 +08:00
|
|
|
|
2011-02-20 05:32:49 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2008-11-06 05:50:06 +08:00
|
|
|
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
2011-07-02 06:22:50 +08:00
|
|
|
SourceLocation LAngleBracketLoc, Declarator &D,
|
2008-11-06 05:50:06 +08:00
|
|
|
SourceLocation RAngleBracketLoc,
|
2010-08-27 07:41:50 +08:00
|
|
|
SourceLocation LParenLoc, Expr *E,
|
2008-11-06 05:50:06 +08:00
|
|
|
SourceLocation RParenLoc) {
|
2010-01-16 03:13:16 +08:00
|
|
|
|
2011-07-02 06:22:50 +08:00
|
|
|
assert(!D.isInvalidType());
|
|
|
|
|
|
|
|
TypeSourceInfo *TInfo = GetTypeForDeclaratorCast(D, E->getType());
|
|
|
|
if (D.isInvalidType())
|
|
|
|
return ExprError();
|
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus) {
|
2011-07-02 06:22:50 +08:00
|
|
|
// Check that there are no default arguments (C++ only).
|
|
|
|
CheckExtraCXXDefaultArguments(D);
|
|
|
|
}
|
|
|
|
|
2012-08-24 05:35:17 +08:00
|
|
|
return BuildCXXNamedCast(OpLoc, Kind, TInfo, E,
|
2010-01-16 03:13:16 +08:00
|
|
|
SourceRange(LAngleBracketLoc, RAngleBracketLoc),
|
|
|
|
SourceRange(LParenLoc, RParenLoc));
|
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2010-01-16 03:13:16 +08:00
|
|
|
Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
2011-04-09 02:41:53 +08:00
|
|
|
TypeSourceInfo *DestTInfo, Expr *E,
|
2010-01-16 03:13:16 +08:00
|
|
|
SourceRange AngleBrackets, SourceRange Parens) {
|
2014-05-29 22:05:12 +08:00
|
|
|
ExprResult Ex = E;
|
2010-01-16 03:13:16 +08:00
|
|
|
QualType DestType = DestTInfo->getType();
|
|
|
|
|
2008-12-18 06:52:20 +08:00
|
|
|
// If the type is dependent, we won't do the semantic analysis now.
|
2014-12-16 08:46:30 +08:00
|
|
|
bool TypeDependent =
|
|
|
|
DestType->isDependentType() || Ex.get()->isTypeDependent();
|
2008-12-18 06:52:20 +08:00
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
CastOperation Op(*this, DestType, E);
|
|
|
|
Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
|
|
|
|
Op.DestRange = AngleBrackets;
|
2010-11-26 18:57:22 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
switch (Kind) {
|
2010-11-15 17:13:47 +08:00
|
|
|
default: llvm_unreachable("Unknown C++ cast!");
|
2008-11-06 05:50:06 +08:00
|
|
|
|
|
|
|
case tok::kw_const_cast:
|
2011-04-09 02:41:53 +08:00
|
|
|
if (!TypeDependent) {
|
2011-10-05 15:41:44 +08:00
|
|
|
Op.CheckConstCast();
|
|
|
|
if (Op.SrcExpr.isInvalid())
|
2011-04-09 02:41:53 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
|
2014-05-29 18:55:11 +08:00
|
|
|
Op.ValueKind, Op.SrcExpr.get(), DestTInfo,
|
2013-02-23 06:02:53 +08:00
|
|
|
OpLoc, Parens.getEnd(),
|
|
|
|
AngleBrackets));
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-08-03 03:07:59 +08:00
|
|
|
case tok::kw_dynamic_cast: {
|
2011-04-09 02:41:53 +08:00
|
|
|
if (!TypeDependent) {
|
2011-10-05 15:41:44 +08:00
|
|
|
Op.CheckDynamicCast();
|
|
|
|
if (Op.SrcExpr.isInvalid())
|
2011-04-09 02:41:53 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType,
|
2014-05-29 18:55:11 +08:00
|
|
|
Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
2011-10-18 02:40:02 +08:00
|
|
|
&Op.BasePath, DestTInfo,
|
2013-02-23 06:02:53 +08:00
|
|
|
OpLoc, Parens.getEnd(),
|
|
|
|
AngleBrackets));
|
2009-08-03 03:07:59 +08:00
|
|
|
}
|
2009-09-15 12:48:33 +08:00
|
|
|
case tok::kw_reinterpret_cast: {
|
2011-04-09 02:41:53 +08:00
|
|
|
if (!TypeDependent) {
|
2011-10-05 15:41:44 +08:00
|
|
|
Op.CheckReinterpretCast();
|
|
|
|
if (Op.SrcExpr.isInvalid())
|
2011-04-09 02:41:53 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2011-10-18 02:40:02 +08:00
|
|
|
return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
|
2014-05-29 18:55:11 +08:00
|
|
|
Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
2014-05-26 14:22:03 +08:00
|
|
|
nullptr, DestTInfo, OpLoc,
|
2013-02-23 06:02:53 +08:00
|
|
|
Parens.getEnd(),
|
|
|
|
AngleBrackets));
|
2009-09-15 12:48:33 +08:00
|
|
|
}
|
2009-08-08 06:21:05 +08:00
|
|
|
case tok::kw_static_cast: {
|
2011-04-09 02:41:53 +08:00
|
|
|
if (!TypeDependent) {
|
2011-11-30 06:48:16 +08:00
|
|
|
Op.CheckStaticCast();
|
2011-10-05 15:41:44 +08:00
|
|
|
if (Op.SrcExpr.isInvalid())
|
2011-04-09 02:41:53 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2009-09-10 05:33:21 +08:00
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
|
2014-05-29 18:55:11 +08:00
|
|
|
Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
2011-10-18 02:40:02 +08:00
|
|
|
&Op.BasePath, DestTInfo,
|
2013-02-23 06:02:53 +08:00
|
|
|
OpLoc, Parens.getEnd(),
|
|
|
|
AngleBrackets));
|
2009-08-08 06:21:05 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-15 02:34:10 +08:00
|
|
|
/// Try to diagnose a failed overloaded cast. Returns true if
|
|
|
|
/// diagnostics were emitted.
|
|
|
|
static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
|
|
|
|
SourceRange range, Expr *src,
|
2012-02-14 03:55:43 +08:00
|
|
|
QualType destType,
|
|
|
|
bool listInitialization) {
|
2011-02-15 02:34:10 +08:00
|
|
|
switch (CT) {
|
|
|
|
// These cast kinds don't consider user-defined conversions.
|
|
|
|
case CT_Const:
|
|
|
|
case CT_Reinterpret:
|
|
|
|
case CT_Dynamic:
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// These do.
|
|
|
|
case CT_Static:
|
|
|
|
case CT_CStyle:
|
|
|
|
case CT_Functional:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
QualType srcType = src->getType();
|
|
|
|
if (!destType->isRecordType() && !srcType->isRecordType())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
|
|
|
|
InitializationKind initKind
|
2011-06-16 07:02:42 +08:00
|
|
|
= (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(),
|
2012-02-14 03:55:43 +08:00
|
|
|
range, listInitialization)
|
2012-02-13 00:37:36 +08:00
|
|
|
: (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range,
|
2012-02-14 03:55:43 +08:00
|
|
|
listInitialization)
|
2011-11-30 06:48:16 +08:00
|
|
|
: InitializationKind::CreateCast(/*type range?*/ range);
|
2013-05-03 23:05:50 +08:00
|
|
|
InitializationSequence sequence(S, entity, initKind, src);
|
2011-02-15 02:34:10 +08:00
|
|
|
|
2011-06-05 20:23:28 +08:00
|
|
|
assert(sequence.Failed() && "initialization succeeded on second try?");
|
2011-02-15 02:34:10 +08:00
|
|
|
switch (sequence.getFailureKind()) {
|
|
|
|
default: return false;
|
|
|
|
|
|
|
|
case InitializationSequence::FK_ConstructorOverloadFailed:
|
|
|
|
case InitializationSequence::FK_UserConversionOverloadFailed:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
OverloadCandidateSet &candidates = sequence.getFailedCandidateSet();
|
|
|
|
|
|
|
|
unsigned msg = 0;
|
|
|
|
OverloadCandidateDisplayKind howManyCandidates = OCD_AllCandidates;
|
|
|
|
|
|
|
|
switch (sequence.getFailedOverloadResult()) {
|
|
|
|
case OR_Success: llvm_unreachable("successful failed overload");
|
|
|
|
case OR_No_Viable_Function:
|
|
|
|
if (candidates.empty())
|
|
|
|
msg = diag::err_ovl_no_conversion_in_cast;
|
|
|
|
else
|
|
|
|
msg = diag::err_ovl_no_viable_conversion_in_cast;
|
|
|
|
howManyCandidates = OCD_AllCandidates;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OR_Ambiguous:
|
|
|
|
msg = diag::err_ovl_ambiguous_conversion_in_cast;
|
|
|
|
howManyCandidates = OCD_ViableCandidates;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OR_Deleted:
|
|
|
|
msg = diag::err_ovl_deleted_conversion_in_cast;
|
|
|
|
howManyCandidates = OCD_ViableCandidates;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
S.Diag(range.getBegin(), msg)
|
|
|
|
<< CT << srcType << destType
|
|
|
|
<< range << src->getSourceRange();
|
|
|
|
|
2012-02-25 19:00:22 +08:00
|
|
|
candidates.NoteCandidates(S, howManyCandidates, src);
|
2011-02-15 02:34:10 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Diagnose a failed cast.
|
|
|
|
static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
|
2012-02-14 03:55:43 +08:00
|
|
|
SourceRange opRange, Expr *src, QualType destType,
|
|
|
|
bool listInitialization) {
|
2011-02-15 02:34:10 +08:00
|
|
|
if (msg == diag::err_bad_cxx_cast_generic &&
|
2012-02-14 03:55:43 +08:00
|
|
|
tryDiagnoseOverloadedCast(S, castType, opRange, src, destType,
|
|
|
|
listInitialization))
|
2011-02-15 02:34:10 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
S.Diag(opRange.getBegin(), msg) << castType
|
|
|
|
<< src->getType() << destType << opRange << src->getSourceRange();
|
2015-01-29 05:31:26 +08:00
|
|
|
|
|
|
|
// Detect if both types are (ptr to) class, and note any incompleteness.
|
|
|
|
int DifferentPtrness = 0;
|
|
|
|
QualType From = destType;
|
|
|
|
if (auto Ptr = From->getAs<PointerType>()) {
|
|
|
|
From = Ptr->getPointeeType();
|
|
|
|
DifferentPtrness++;
|
|
|
|
}
|
|
|
|
QualType To = src->getType();
|
|
|
|
if (auto Ptr = To->getAs<PointerType>()) {
|
|
|
|
To = Ptr->getPointeeType();
|
|
|
|
DifferentPtrness--;
|
|
|
|
}
|
|
|
|
if (!DifferentPtrness) {
|
|
|
|
auto RecFrom = From->getAs<RecordType>();
|
|
|
|
auto RecTo = To->getAs<RecordType>();
|
|
|
|
if (RecFrom && RecTo) {
|
|
|
|
auto DeclFrom = RecFrom->getAsCXXRecordDecl();
|
|
|
|
if (!DeclFrom->isCompleteDefinition())
|
|
|
|
S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete)
|
|
|
|
<< DeclFrom->getDeclName();
|
|
|
|
auto DeclTo = RecTo->getAsCXXRecordDecl();
|
|
|
|
if (!DeclTo->isCompleteDefinition())
|
|
|
|
S.Diag(DeclTo->getLocation(), diag::note_type_incomplete)
|
|
|
|
<< DeclTo->getDeclName();
|
|
|
|
}
|
|
|
|
}
|
2011-02-15 02:34:10 +08:00
|
|
|
}
|
|
|
|
|
2009-11-19 02:10:53 +08:00
|
|
|
/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes,
|
|
|
|
/// this removes one level of indirection from both types, provided that they're
|
|
|
|
/// the same kind of pointer (plain or to-member). Unlike the Sema function,
|
|
|
|
/// this one doesn't care if the two pointers-to-member don't point into the
|
|
|
|
/// same class. This is because CastsAwayConstness doesn't care.
|
2010-07-27 05:25:24 +08:00
|
|
|
static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) {
|
2009-11-19 02:10:53 +08:00
|
|
|
const PointerType *T1PtrType = T1->getAs<PointerType>(),
|
|
|
|
*T2PtrType = T2->getAs<PointerType>();
|
|
|
|
if (T1PtrType && T2PtrType) {
|
|
|
|
T1 = T1PtrType->getPointeeType();
|
|
|
|
T2 = T2PtrType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
2010-02-04 04:32:31 +08:00
|
|
|
const ObjCObjectPointerType *T1ObjCPtrType =
|
|
|
|
T1->getAs<ObjCObjectPointerType>(),
|
|
|
|
*T2ObjCPtrType =
|
|
|
|
T2->getAs<ObjCObjectPointerType>();
|
|
|
|
if (T1ObjCPtrType) {
|
|
|
|
if (T2ObjCPtrType) {
|
|
|
|
T1 = T1ObjCPtrType->getPointeeType();
|
|
|
|
T2 = T2ObjCPtrType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (T2PtrType) {
|
|
|
|
T1 = T1ObjCPtrType->getPointeeType();
|
|
|
|
T2 = T2PtrType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (T2ObjCPtrType) {
|
|
|
|
if (T1PtrType) {
|
|
|
|
T2 = T2ObjCPtrType->getPointeeType();
|
|
|
|
T1 = T1PtrType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-19 02:10:53 +08:00
|
|
|
const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(),
|
|
|
|
*T2MPType = T2->getAs<MemberPointerType>();
|
|
|
|
if (T1MPType && T2MPType) {
|
|
|
|
T1 = T1MPType->getPointeeType();
|
|
|
|
T2 = T2MPType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
2010-07-09 04:27:32 +08:00
|
|
|
|
|
|
|
const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(),
|
|
|
|
*T2BPType = T2->getAs<BlockPointerType>();
|
|
|
|
if (T1BPType && T2BPType) {
|
|
|
|
T1 = T1BPType->getPointeeType();
|
|
|
|
T2 = T2BPType->getPointeeType();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-11-19 02:10:53 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
/// CastsAwayConstness - Check if the pointer conversion from SrcType to
|
|
|
|
/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by
|
|
|
|
/// the cast checkers. Both arguments must denote pointer (possibly to member)
|
|
|
|
/// types.
|
2011-06-16 07:02:42 +08:00
|
|
|
///
|
|
|
|
/// \param CheckCVR Whether to check for const/volatile/restrict qualifiers.
|
|
|
|
///
|
|
|
|
/// \param CheckObjCLifetime Whether to check Objective-C lifetime qualifiers.
|
2009-10-22 23:07:22 +08:00
|
|
|
static bool
|
2011-06-16 07:02:42 +08:00
|
|
|
CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
|
2014-11-22 05:03:10 +08:00
|
|
|
bool CheckCVR, bool CheckObjCLifetime,
|
|
|
|
QualType *TheOffendingSrcType = nullptr,
|
|
|
|
QualType *TheOffendingDestType = nullptr,
|
|
|
|
Qualifiers *CastAwayQualifiers = nullptr) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// If the only checking we care about is for Objective-C lifetime qualifiers,
|
|
|
|
// and we're not in ARC mode, there's nothing to check.
|
|
|
|
if (!CheckCVR && CheckObjCLifetime &&
|
2012-03-11 15:00:24 +08:00
|
|
|
!Self.Context.getLangOpts().ObjCAutoRefCount)
|
2011-06-16 07:02:42 +08:00
|
|
|
return false;
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Casting away constness is defined in C++ 5.2.11p8 with reference to
|
|
|
|
// C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since
|
|
|
|
// the rules are non-trivial. So first we construct Tcv *...cv* as described
|
|
|
|
// in C++ 5.2.11p8.
|
2010-07-09 04:27:32 +08:00
|
|
|
assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
|
|
|
|
SrcType->isBlockPointerType()) &&
|
2009-07-25 23:41:38 +08:00
|
|
|
"Source type is not pointer or pointer to member.");
|
2010-07-09 04:27:32 +08:00
|
|
|
assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
|
|
|
|
DestType->isBlockPointerType()) &&
|
2009-07-25 23:41:38 +08:00
|
|
|
"Destination type is not pointer or pointer to member.");
|
2009-01-27 06:19:12 +08:00
|
|
|
|
2009-11-15 17:20:52 +08:00
|
|
|
QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
|
|
|
|
UnwrappedDestType = Self.Context.getCanonicalType(DestType);
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<Qualifiers, 8> cv1, cv2;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
Implement appropriate semantics for C++ casting and conversion when
dealing with address-space- and GC-qualified pointers. Previously,
these qualifiers were being treated just like cvr-qualifiers (in some
cases) or were completely ignored, leading to uneven behavior. For
example, const_cast would allow conversion between pointers to
different address spaces.
The new semantics are fairly simple: reinterpret_cast can be used to
explicitly cast between pointers to different address spaces
(including adding/removing addresss spaces), while
static_cast/dynamic_cast/const_cast do not tolerate any changes in the
address space. C-style casts can add/remove/change address spaces
through the reinterpret_cast mechanism. Other non-CVR qualifiers
(e.g., Objective-C GC qualifiers) work similarly.
As part of this change, I tweaked the "casts away constness"
diagnostic to use the term "casts away qualifiers". The term
"constness" actually comes from the C++ standard, despite the fact
that removing "volatile" also falls under that category. In Clang, we
also have restrict, address spaces, ObjC GC attributes, etc., so the
more general "qualifiers" is clearer.
llvm-svn: 129583
2011-04-16 01:59:54 +08:00
|
|
|
// Find the qualifiers. We only care about cvr-qualifiers for the
|
|
|
|
// purpose of this check, because other qualifiers (address spaces,
|
|
|
|
// Objective-C GC, etc.) are part of the type's identity.
|
2014-11-22 05:03:10 +08:00
|
|
|
QualType PrevUnwrappedSrcType = UnwrappedSrcType;
|
|
|
|
QualType PrevUnwrappedDestType = UnwrappedDestType;
|
2009-11-19 02:10:53 +08:00
|
|
|
while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// Determine the relevant qualifiers at this level.
|
|
|
|
Qualifiers SrcQuals, DestQuals;
|
2010-06-05 06:47:55 +08:00
|
|
|
Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals);
|
|
|
|
Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
|
|
|
Qualifiers RetainedSrcQuals, RetainedDestQuals;
|
|
|
|
if (CheckCVR) {
|
|
|
|
RetainedSrcQuals.setCVRQualifiers(SrcQuals.getCVRQualifiers());
|
|
|
|
RetainedDestQuals.setCVRQualifiers(DestQuals.getCVRQualifiers());
|
2014-11-22 05:03:10 +08:00
|
|
|
|
|
|
|
if (RetainedSrcQuals != RetainedDestQuals && TheOffendingSrcType &&
|
|
|
|
TheOffendingDestType && CastAwayQualifiers) {
|
|
|
|
*TheOffendingSrcType = PrevUnwrappedSrcType;
|
|
|
|
*TheOffendingDestType = PrevUnwrappedDestType;
|
|
|
|
*CastAwayQualifiers = RetainedSrcQuals - RetainedDestQuals;
|
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (CheckObjCLifetime &&
|
|
|
|
!DestQuals.compatiblyIncludesObjCLifetime(SrcQuals))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
cv1.push_back(RetainedSrcQuals);
|
|
|
|
cv2.push_back(RetainedDestQuals);
|
2014-11-22 05:03:10 +08:00
|
|
|
|
|
|
|
PrevUnwrappedSrcType = UnwrappedSrcType;
|
|
|
|
PrevUnwrappedDestType = UnwrappedDestType;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2010-07-09 04:27:32 +08:00
|
|
|
if (cv1.empty())
|
|
|
|
return false;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Construct void pointers with those qualifiers (in reverse order of
|
|
|
|
// unwrapping, of course).
|
|
|
|
QualType SrcConstruct = Self.Context.VoidTy;
|
|
|
|
QualType DestConstruct = Self.Context.VoidTy;
|
2009-09-25 03:53:00 +08:00
|
|
|
ASTContext &Context = Self.Context;
|
2013-07-08 11:55:09 +08:00
|
|
|
for (SmallVectorImpl<Qualifiers>::reverse_iterator i1 = cv1.rbegin(),
|
|
|
|
i2 = cv2.rbegin();
|
2009-09-09 23:08:12 +08:00
|
|
|
i1 != cv1.rend(); ++i1, ++i2) {
|
2009-09-25 03:53:00 +08:00
|
|
|
SrcConstruct
|
|
|
|
= Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
|
|
|
|
DestConstruct
|
|
|
|
= Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2));
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Test if they're compatible.
|
2011-06-16 07:02:42 +08:00
|
|
|
bool ObjCLifetimeConversion;
|
2009-07-25 23:41:38 +08:00
|
|
|
return SrcConstruct != DestConstruct &&
|
2011-06-16 07:02:42 +08:00
|
|
|
!Self.IsQualificationConversion(SrcConstruct, DestConstruct, false,
|
|
|
|
ObjCLifetimeConversion);
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
|
|
|
|
/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
|
|
|
|
/// checked downcasts in class hierarchies.
|
2011-10-05 15:41:44 +08:00
|
|
|
void CastOperation::CheckDynamicCast() {
|
2012-01-12 08:44:34 +08:00
|
|
|
if (ValueKind == VK_RValue)
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
|
2012-01-12 08:44:34 +08:00
|
|
|
else if (isPlaceholder())
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
|
2012-01-12 08:44:34 +08:00
|
|
|
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
|
|
|
return;
|
2011-11-01 04:59:03 +08:00
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
QualType OrigSrcType = SrcExpr.get()->getType();
|
|
|
|
QualType DestType = Self.Context.getCanonicalType(this->DestType);
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.7p1: T shall be a pointer or reference to a complete class type,
|
|
|
|
// or "pointer to cv void".
|
2009-03-17 07:22:08 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
QualType DestPointee;
|
2009-07-30 05:53:49 +08:00
|
|
|
const PointerType *DestPointer = DestType->getAs<PointerType>();
|
2014-05-26 14:22:03 +08:00
|
|
|
const ReferenceType *DestReference = nullptr;
|
2009-07-25 23:41:38 +08:00
|
|
|
if (DestPointer) {
|
|
|
|
DestPointee = DestPointer->getPointeeType();
|
2010-11-18 14:31:45 +08:00
|
|
|
} else if ((DestReference = DestType->getAs<ReferenceType>())) {
|
2009-07-25 23:41:38 +08:00
|
|
|
DestPointee = DestReference->getPointeeType();
|
2008-11-06 05:50:06 +08:00
|
|
|
} else {
|
2009-07-25 23:41:38 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
|
2011-10-05 15:41:44 +08:00
|
|
|
<< this->DestType << DestRange;
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2009-05-11 02:38:11 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const RecordType *DestRecord = DestPointee->getAs<RecordType>();
|
2009-07-25 23:41:38 +08:00
|
|
|
if (DestPointee->isVoidType()) {
|
|
|
|
assert(DestPointer && "Reference to void is not possible");
|
|
|
|
} else if (DestRecord) {
|
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
|
2012-05-05 00:32:21 +08:00
|
|
|
diag::err_bad_dynamic_cast_incomplete,
|
2013-07-27 07:47:47 +08:00
|
|
|
DestRange)) {
|
|
|
|
SrcExpr = ExprError();
|
2009-07-25 23:41:38 +08:00
|
|
|
return;
|
2013-07-27 07:47:47 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
} else {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
|
|
|
|
<< DestPointee.getUnqualifiedType() << DestRange;
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2008-11-06 05:50:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
|
|
|
|
// complete class type, [...]. If T is an lvalue reference type, v shall be
|
2011-01-22 08:06:57 +08:00
|
|
|
// an lvalue of a complete class type, [...]. If T is an rvalue reference
|
|
|
|
// type, v shall be an expression having a complete class type, [...]
|
2009-07-25 23:41:38 +08:00
|
|
|
QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
|
|
|
|
QualType SrcPointee;
|
|
|
|
if (DestPointer) {
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
|
2009-07-25 23:41:38 +08:00
|
|
|
SrcPointee = SrcPointer->getPointeeType();
|
|
|
|
} else {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr)
|
2011-04-09 02:41:53 +08:00
|
|
|
<< OrigSrcType << SrcExpr.get()->getSourceRange();
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2009-07-25 23:41:38 +08:00
|
|
|
return;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
} else if (DestReference->isLValueReferenceType()) {
|
2011-04-09 02:41:53 +08:00
|
|
|
if (!SrcExpr.get()->isLValue()) {
|
2009-07-25 23:41:38 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
|
2011-10-05 15:41:44 +08:00
|
|
|
<< CT_Dynamic << OrigSrcType << this->DestType << OpRange;
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
SrcPointee = SrcType;
|
|
|
|
} else {
|
2014-07-09 01:25:14 +08:00
|
|
|
// If we're dynamic_casting from a prvalue to an rvalue reference, we need
|
|
|
|
// to materialize the prvalue before we bind the reference to it.
|
|
|
|
if (SrcExpr.get()->isRValue())
|
|
|
|
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
|
|
|
|
SrcType, SrcExpr.get(), /*IsLValueReference*/false);
|
2009-07-25 23:41:38 +08:00
|
|
|
SrcPointee = SrcType;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const RecordType *SrcRecord = SrcPointee->getAs<RecordType>();
|
2009-07-25 23:41:38 +08:00
|
|
|
if (SrcRecord) {
|
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
|
2012-05-05 00:32:21 +08:00
|
|
|
diag::err_bad_dynamic_cast_incomplete,
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr.get())) {
|
|
|
|
SrcExpr = ExprError();
|
2009-07-25 23:41:38 +08:00
|
|
|
return;
|
2013-07-27 07:47:47 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
} else {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
|
2011-04-09 02:41:53 +08:00
|
|
|
<< SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2008-11-06 05:50:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
assert((DestPointer || DestReference) &&
|
|
|
|
"Bad destination non-ptr/ref slipped through.");
|
|
|
|
assert((DestRecord || DestPointee->isVoidType()) &&
|
|
|
|
"Bad destination pointee slipped through.");
|
|
|
|
assert(SrcRecord && "Bad source pointee slipped through.");
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness.
|
|
|
|
if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
|
Implement appropriate semantics for C++ casting and conversion when
dealing with address-space- and GC-qualified pointers. Previously,
these qualifiers were being treated just like cvr-qualifiers (in some
cases) or were completely ignored, leading to uneven behavior. For
example, const_cast would allow conversion between pointers to
different address spaces.
The new semantics are fairly simple: reinterpret_cast can be used to
explicitly cast between pointers to different address spaces
(including adding/removing addresss spaces), while
static_cast/dynamic_cast/const_cast do not tolerate any changes in the
address space. C-style casts can add/remove/change address spaces
through the reinterpret_cast mechanism. Other non-CVR qualifiers
(e.g., Objective-C GC qualifiers) work similarly.
As part of this change, I tweaked the "casts away constness"
diagnostic to use the term "casts away qualifiers". The term
"constness" actually comes from the C++ standard, despite the fact
that removing "volatile" also falls under that category. In Clang, we
also have restrict, address spaces, ObjC GC attributes, etc., so the
more general "qualifiers" is clearer.
llvm-svn: 129583
2011-04-16 01:59:54 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away)
|
2011-10-05 15:41:44 +08:00
|
|
|
<< CT_Dynamic << OrigSrcType << this->DestType << OpRange;
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2008-11-06 05:50:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.7p3: If the type of v is the same as the required result type,
|
|
|
|
// [except for cv].
|
|
|
|
if (DestRecord == SrcRecord) {
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_NoOp;
|
2008-11-06 05:50:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.7p5
|
|
|
|
// Upcasts are resolved statically.
|
|
|
|
if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
|
2010-04-25 03:06:50 +08:00
|
|
|
if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
|
|
|
|
OpRange.getBegin(), OpRange,
|
2013-07-27 07:47:47 +08:00
|
|
|
&BasePath)) {
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
2014-07-09 01:25:14 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_DerivedToBase;
|
2008-11-06 05:50:06 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.7p6: Otherwise, v shall be [polymorphic].
|
2010-02-11 09:04:33 +08:00
|
|
|
const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition();
|
2009-07-25 23:41:38 +08:00
|
|
|
assert(SrcDecl && "Definition missing");
|
|
|
|
if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
|
2011-04-09 02:41:53 +08:00
|
|
|
<< SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
|
2013-09-25 07:21:41 +08:00
|
|
|
// dynamic_cast is not available with -fno-rtti.
|
|
|
|
// As an exception, dynamic_cast to void* is available because it doesn't
|
|
|
|
// use RTTI.
|
|
|
|
if (!Self.getLangOpts().RTTI && !DestPointee->isVoidType()) {
|
2013-08-01 16:28:32 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_no_dynamic_cast_with_fno_rtti);
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Done. Everything else is run-time checks.
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_Dynamic;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid.
|
|
|
|
/// Refer to C++ 5.2.11 for details. const_cast is typically used in code
|
|
|
|
/// like this:
|
|
|
|
/// const char *str = "literal";
|
|
|
|
/// legacy_function(const_cast\<char*\>(str));
|
2011-10-05 15:41:44 +08:00
|
|
|
void CastOperation::CheckConstCast() {
|
2012-01-12 08:44:34 +08:00
|
|
|
if (ValueKind == VK_RValue)
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
|
2012-01-12 08:44:34 +08:00
|
|
|
else if (isPlaceholder())
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.get());
|
2012-01-12 08:44:34 +08:00
|
|
|
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
|
|
|
return;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
unsigned msg = diag::err_bad_cxx_cast_generic;
|
2013-06-15 06:27:52 +08:00
|
|
|
if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
|
2013-07-27 07:47:47 +08:00
|
|
|
&& msg != 0) {
|
2009-07-25 23:41:38 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), msg) << CT_Const
|
2011-04-09 02:41:53 +08:00
|
|
|
<< SrcExpr.get()->getType() << DestType << OpRange;
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2013-03-22 10:58:14 +08:00
|
|
|
/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast
|
|
|
|
/// or downcast between respective pointers or references.
|
|
|
|
static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
|
|
|
|
QualType DestType,
|
|
|
|
SourceRange OpRange) {
|
|
|
|
QualType SrcType = SrcExpr->getType();
|
|
|
|
// When casting from pointer or reference, get pointee type; use original
|
|
|
|
// type otherwise.
|
|
|
|
const CXXRecordDecl *SrcPointeeRD = SrcType->getPointeeCXXRecordDecl();
|
|
|
|
const CXXRecordDecl *SrcRD =
|
|
|
|
SrcPointeeRD ? SrcPointeeRD : SrcType->getAsCXXRecordDecl();
|
|
|
|
|
2013-03-27 08:03:48 +08:00
|
|
|
// Examining subobjects for records is only possible if the complete and
|
|
|
|
// valid definition is available. Also, template instantiation is not
|
|
|
|
// allowed here.
|
|
|
|
if (!SrcRD || !SrcRD->isCompleteDefinition() || SrcRD->isInvalidDecl())
|
2013-03-22 10:58:14 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
const CXXRecordDecl *DestRD = DestType->getPointeeCXXRecordDecl();
|
|
|
|
|
2013-03-27 08:03:48 +08:00
|
|
|
if (!DestRD || !DestRD->isCompleteDefinition() || DestRD->isInvalidDecl())
|
2013-03-22 10:58:14 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ReinterpretUpcast,
|
|
|
|
ReinterpretDowncast
|
|
|
|
} ReinterpretKind;
|
|
|
|
|
|
|
|
CXXBasePaths BasePaths;
|
|
|
|
|
|
|
|
if (SrcRD->isDerivedFrom(DestRD, BasePaths))
|
|
|
|
ReinterpretKind = ReinterpretUpcast;
|
|
|
|
else if (DestRD->isDerivedFrom(SrcRD, BasePaths))
|
|
|
|
ReinterpretKind = ReinterpretDowncast;
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool VirtualBase = true;
|
|
|
|
bool NonZeroOffset = false;
|
2013-03-27 08:03:48 +08:00
|
|
|
for (CXXBasePaths::const_paths_iterator I = BasePaths.begin(),
|
2013-03-22 10:58:14 +08:00
|
|
|
E = BasePaths.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
const CXXBasePath &Path = *I;
|
|
|
|
CharUnits Offset = CharUnits::Zero();
|
|
|
|
bool IsVirtual = false;
|
|
|
|
for (CXXBasePath::const_iterator IElem = Path.begin(), EElem = Path.end();
|
|
|
|
IElem != EElem; ++IElem) {
|
|
|
|
IsVirtual = IElem->Base->isVirtual();
|
|
|
|
if (IsVirtual)
|
|
|
|
break;
|
|
|
|
const CXXRecordDecl *BaseRD = IElem->Base->getType()->getAsCXXRecordDecl();
|
|
|
|
assert(BaseRD && "Base type should be a valid unqualified class type");
|
2013-03-27 08:03:48 +08:00
|
|
|
// Don't check if any base has invalid declaration or has no definition
|
|
|
|
// since it has no layout info.
|
|
|
|
const CXXRecordDecl *Class = IElem->Class,
|
|
|
|
*ClassDefinition = Class->getDefinition();
|
|
|
|
if (Class->isInvalidDecl() || !ClassDefinition ||
|
|
|
|
!ClassDefinition->isCompleteDefinition())
|
|
|
|
return;
|
|
|
|
|
2013-03-22 10:58:14 +08:00
|
|
|
const ASTRecordLayout &DerivedLayout =
|
2013-03-27 08:03:48 +08:00
|
|
|
Self.Context.getASTRecordLayout(Class);
|
2013-03-22 10:58:14 +08:00
|
|
|
Offset += DerivedLayout.getBaseClassOffset(BaseRD);
|
|
|
|
}
|
|
|
|
if (!IsVirtual) {
|
|
|
|
// Don't warn if any path is a non-virtually derived base at offset zero.
|
|
|
|
if (Offset.isZero())
|
|
|
|
return;
|
|
|
|
// Offset makes sense only for non-virtual bases.
|
|
|
|
else
|
|
|
|
NonZeroOffset = true;
|
|
|
|
}
|
|
|
|
VirtualBase = VirtualBase && IsVirtual;
|
|
|
|
}
|
|
|
|
|
2013-06-19 21:33:37 +08:00
|
|
|
(void) NonZeroOffset; // Silence set but not used warning.
|
2013-03-22 10:58:14 +08:00
|
|
|
assert((VirtualBase || NonZeroOffset) &&
|
|
|
|
"Should have returned if has non-virtual base with zero offset");
|
|
|
|
|
|
|
|
QualType BaseType =
|
|
|
|
ReinterpretKind == ReinterpretUpcast? DestType : SrcType;
|
|
|
|
QualType DerivedType =
|
|
|
|
ReinterpretKind == ReinterpretUpcast? SrcType : DestType;
|
|
|
|
|
2013-03-29 03:09:40 +08:00
|
|
|
SourceLocation BeginLoc = OpRange.getBegin();
|
|
|
|
Self.Diag(BeginLoc, diag::warn_reinterpret_different_from_static)
|
2013-06-27 05:31:47 +08:00
|
|
|
<< DerivedType << BaseType << !VirtualBase << int(ReinterpretKind)
|
2013-03-29 03:09:40 +08:00
|
|
|
<< OpRange;
|
|
|
|
Self.Diag(BeginLoc, diag::note_reinterpret_updowncast_use_static)
|
2013-06-27 05:31:47 +08:00
|
|
|
<< int(ReinterpretKind)
|
2013-03-29 03:09:40 +08:00
|
|
|
<< FixItHint::CreateReplacement(BeginLoc, "static_cast");
|
2013-03-22 10:58:14 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is
|
|
|
|
/// valid.
|
|
|
|
/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
|
|
|
|
/// like this:
|
|
|
|
/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
|
2011-10-05 15:41:44 +08:00
|
|
|
void CastOperation::CheckReinterpretCast() {
|
2012-01-12 08:44:34 +08:00
|
|
|
if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload))
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
|
2012-01-12 08:44:34 +08:00
|
|
|
else
|
|
|
|
checkNonOverloadPlaceholders();
|
|
|
|
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
|
|
|
return;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
unsigned msg = diag::err_bad_cxx_cast_generic;
|
2011-06-16 07:02:42 +08:00
|
|
|
TryCastResult tcr =
|
|
|
|
TryReinterpretCast(Self, SrcExpr, DestType,
|
|
|
|
/*CStyle*/false, OpRange, msg, Kind);
|
|
|
|
if (tcr != TC_Success && msg != 0)
|
2010-11-08 11:40:48 +08:00
|
|
|
{
|
2011-04-09 02:41:53 +08:00
|
|
|
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
|
|
|
return;
|
|
|
|
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
|
2010-11-08 11:40:48 +08:00
|
|
|
//FIXME: &f<int>; is overloaded and resolvable
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload)
|
2011-04-09 02:41:53 +08:00
|
|
|
<< OverloadExpr::find(SrcExpr.get()).Expression->getName()
|
2010-11-08 11:40:48 +08:00
|
|
|
<< DestType << OpRange;
|
2011-04-09 02:41:53 +08:00
|
|
|
Self.NoteAllOverloadCandidates(SrcExpr.get());
|
2010-11-08 11:40:48 +08:00
|
|
|
|
2011-02-15 02:34:10 +08:00
|
|
|
} else {
|
2012-02-14 03:55:43 +08:00
|
|
|
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
|
|
|
|
DestType, /*listInitialization=*/false);
|
2010-11-08 11:40:48 +08:00
|
|
|
}
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2013-03-22 10:58:14 +08:00
|
|
|
} else if (tcr == TC_Success) {
|
|
|
|
if (Self.getLangOpts().ObjCAutoRefCount)
|
|
|
|
checkObjCARCConversion(Sema::CCK_OtherCast);
|
|
|
|
DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange);
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid.
|
|
|
|
/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making
|
|
|
|
/// implicit conversions explicit and getting rid of data loss warnings.
|
2011-11-30 06:48:16 +08:00
|
|
|
void CastOperation::CheckStaticCast() {
|
2011-10-07 07:25:11 +08:00
|
|
|
if (isPlaceholder()) {
|
|
|
|
checkNonOverloadPlaceholders();
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// This test is outside everything else because it's the only case where
|
|
|
|
// a non-lvalue-reference target type does not lead to decay.
|
|
|
|
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
2009-11-16 13:44:20 +08:00
|
|
|
if (DestType->isVoidType()) {
|
2011-10-07 07:25:11 +08:00
|
|
|
Kind = CK_ToVoid;
|
|
|
|
|
|
|
|
if (claimPlaceholder(BuiltinType::Overload)) {
|
2011-10-12 07:14:30 +08:00
|
|
|
Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr,
|
2011-02-20 05:32:49 +08:00
|
|
|
false, // Decay Function to ptr
|
|
|
|
true, // Complain
|
|
|
|
OpRange, DestType, diag::err_bad_static_cast_overload);
|
2011-10-12 07:14:30 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2011-02-20 05:32:49 +08:00
|
|
|
}
|
2011-10-07 07:25:11 +08:00
|
|
|
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.IgnoredValueConversions(SrcExpr.get());
|
2009-07-25 23:41:38 +08:00
|
|
|
return;
|
2009-11-16 13:44:20 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2011-10-12 07:14:30 +08:00
|
|
|
if (ValueKind == VK_RValue && !DestType->isRecordType() &&
|
|
|
|
!isPlaceholder(BuiltinType::Overload)) {
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
|
2011-04-09 02:41:53 +08:00
|
|
|
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
|
|
|
return;
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
|
|
|
unsigned msg = diag::err_bad_cxx_cast_generic;
|
2011-06-16 07:02:42 +08:00
|
|
|
TryCastResult tcr
|
2011-11-30 06:48:16 +08:00
|
|
|
= TryStaticCast(Self, SrcExpr, DestType, Sema::CCK_OtherCast, OpRange, msg,
|
2012-02-13 02:41:05 +08:00
|
|
|
Kind, BasePath, /*ListInitialization=*/false);
|
2011-06-16 07:02:42 +08:00
|
|
|
if (tcr != TC_Success && msg != 0) {
|
2011-04-09 02:41:53 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
|
|
|
|
OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression;
|
2010-11-08 11:40:48 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
|
2011-03-01 04:01:57 +08:00
|
|
|
<< oe->getName() << DestType << OpRange
|
|
|
|
<< oe->getQualifierLoc().getSourceRange();
|
2011-04-09 02:41:53 +08:00
|
|
|
Self.NoteAllOverloadCandidates(SrcExpr.get());
|
2011-02-15 02:34:10 +08:00
|
|
|
} else {
|
2012-02-14 03:55:43 +08:00
|
|
|
diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType,
|
|
|
|
/*listInitialization=*/false);
|
2010-11-08 11:40:48 +08:00
|
|
|
}
|
2013-07-27 07:47:47 +08:00
|
|
|
SrcExpr = ExprError();
|
2011-06-16 07:02:42 +08:00
|
|
|
} else if (tcr == TC_Success) {
|
|
|
|
if (Kind == CK_BitCast)
|
2011-10-05 15:41:44 +08:00
|
|
|
checkCastAlign();
|
2012-03-11 15:00:24 +08:00
|
|
|
if (Self.getLangOpts().ObjCAutoRefCount)
|
2011-11-30 06:48:16 +08:00
|
|
|
checkObjCARCConversion(Sema::CCK_OtherCast);
|
2011-10-05 15:41:44 +08:00
|
|
|
} else if (Kind == CK_BitCast) {
|
|
|
|
checkCastAlign();
|
2010-11-08 11:40:48 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// TryStaticCast - Check if a static cast can be performed, and do so if
|
|
|
|
/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
|
|
|
|
/// and casting away constness.
|
2011-04-09 02:41:53 +08:00
|
|
|
static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
|
2011-06-16 07:02:42 +08:00
|
|
|
QualType DestType,
|
|
|
|
Sema::CheckedConversionKind CCK,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange, unsigned &msg,
|
2012-02-13 02:41:05 +08:00
|
|
|
CastKind &Kind, CXXCastPath &BasePath,
|
|
|
|
bool ListInitialization) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// Determine whether we have the semantics of a C-style cast.
|
|
|
|
bool CStyle
|
|
|
|
= (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
|
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
// The order the tests is not entirely arbitrary. There is one conversion
|
|
|
|
// that can be handled in two different ways. Given:
|
|
|
|
// struct A {};
|
|
|
|
// struct B : public A {
|
|
|
|
// B(); B(const A&);
|
|
|
|
// };
|
|
|
|
// const A &a = B();
|
|
|
|
// the cast static_cast<const B&>(a) could be seen as either a static
|
|
|
|
// reference downcast, or an explicit invocation of the user-defined
|
|
|
|
// conversion using B's conversion constructor.
|
|
|
|
// DR 427 specifies that the downcast is to be applied here.
|
|
|
|
|
|
|
|
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
2009-07-25 23:41:38 +08:00
|
|
|
// Done outside this function.
|
|
|
|
|
|
|
|
TryCastResult tcr;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
|
|
|
// C++ 5.2.9p5, reference downcast.
|
|
|
|
// See the function for details.
|
|
|
|
// DR 427 specifies that this is to be applied before paragraph 2.
|
2012-02-13 02:41:05 +08:00
|
|
|
tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle,
|
|
|
|
OpRange, msg, Kind, BasePath);
|
2009-07-25 23:41:38 +08:00
|
|
|
if (tcr != TC_NotApplicable)
|
|
|
|
return tcr;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2015-07-13 06:10:56 +08:00
|
|
|
// C++11 [expr.static.cast]p3:
|
2011-01-22 08:06:57 +08:00
|
|
|
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
|
|
|
|
// T2" if "cv2 T2" is reference-compatible with "cv1 T1".
|
2012-02-13 02:41:05 +08:00
|
|
|
tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
|
|
|
|
BasePath, msg);
|
2011-01-26 00:13:26 +08:00
|
|
|
if (tcr != TC_NotApplicable)
|
2009-07-25 23:41:38 +08:00
|
|
|
return tcr;
|
2009-03-23 06:30:06 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
// C++ 5.2.9p2: An expression e can be explicitly converted to a type T
|
|
|
|
// [...] if the declaration "T t(e);" is well-formed, [...].
|
2011-06-16 07:02:42 +08:00
|
|
|
tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CCK, OpRange, msg,
|
2012-02-13 02:41:05 +08:00
|
|
|
Kind, ListInitialization);
|
2011-04-09 02:41:53 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return TC_Failed;
|
2009-09-26 08:12:34 +08:00
|
|
|
if (tcr != TC_NotApplicable)
|
2009-07-25 23:41:38 +08:00
|
|
|
return tcr;
|
2009-09-10 05:33:21 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
// C++ 5.2.9p6: May apply the reverse of any standard conversion, except
|
|
|
|
// lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean
|
|
|
|
// conversions, subject to further restrictions.
|
|
|
|
// Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal
|
|
|
|
// of qualification conversions impossible.
|
2009-07-25 23:41:38 +08:00
|
|
|
// In the CStyle case, the earlier attempt to const_cast should have taken
|
|
|
|
// care of reverse qualification conversions.
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2011-04-09 02:41:53 +08:00
|
|
|
QualType SrcType = Self.Context.getCanonicalType(SrcExpr.get()->getType());
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2010-10-09 07:50:27 +08:00
|
|
|
// C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly
|
2011-02-18 11:01:41 +08:00
|
|
|
// converted to an integral type. [...] A value of a scoped enumeration type
|
|
|
|
// can also be explicitly converted to a floating-point type [...].
|
|
|
|
if (const EnumType *Enum = SrcType->getAs<EnumType>()) {
|
|
|
|
if (Enum->getDecl()->isScoped()) {
|
|
|
|
if (DestType->isBooleanType()) {
|
|
|
|
Kind = CK_IntegralToBoolean;
|
|
|
|
return TC_Success;
|
|
|
|
} else if (DestType->isIntegralType(Self.Context)) {
|
|
|
|
Kind = CK_IntegralCast;
|
|
|
|
return TC_Success;
|
|
|
|
} else if (DestType->isRealFloatingType()) {
|
|
|
|
Kind = CK_IntegralToFloating;
|
|
|
|
return TC_Success;
|
|
|
|
}
|
2010-10-09 07:50:27 +08:00
|
|
|
}
|
|
|
|
}
|
2011-02-18 11:01:41 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
// Reverse integral promotion/conversion. All such conversions are themselves
|
|
|
|
// again integral promotions or conversions and are thus already handled by
|
|
|
|
// p2 (TryDirectInitialization above).
|
|
|
|
// (Note: any data loss warnings should be suppressed.)
|
|
|
|
// The exception is the reverse of enum->integer, i.e. integer->enum (and
|
|
|
|
// enum->enum). See also C++ 5.2.9p7.
|
|
|
|
// The same goes for reverse floating point promotion/conversion and
|
|
|
|
// floating-integral conversions. Again, only floating->enum is relevant.
|
|
|
|
if (DestType->isEnumeralType()) {
|
2011-09-03 01:38:59 +08:00
|
|
|
if (SrcType->isIntegralOrEnumerationType()) {
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_IntegralCast;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2011-09-03 01:38:59 +08:00
|
|
|
} else if (SrcType->isRealFloatingType()) {
|
|
|
|
Kind = CK_FloatingToIntegral;
|
|
|
|
return TC_Success;
|
2009-11-16 13:44:20 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast.
|
|
|
|
// C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance.
|
2009-11-13 00:53:16 +08:00
|
|
|
tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg,
|
2010-04-25 03:36:51 +08:00
|
|
|
Kind, BasePath);
|
2009-07-25 23:41:38 +08:00
|
|
|
if (tcr != TC_NotApplicable)
|
|
|
|
return tcr;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-01-29 02:33:18 +08:00
|
|
|
// Reverse member pointer conversion. C++ 4.11 specifies member pointer
|
2008-11-06 05:50:06 +08:00
|
|
|
// conversion. C++ 5.2.9p9 has additional information.
|
|
|
|
// DR54's access restrictions apply here also.
|
2010-03-08 07:24:59 +08:00
|
|
|
tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle,
|
2010-04-25 03:22:20 +08:00
|
|
|
OpRange, msg, Kind, BasePath);
|
2009-07-25 23:41:38 +08:00
|
|
|
if (tcr != TC_NotApplicable)
|
|
|
|
return tcr;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
|
|
|
// Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to
|
|
|
|
// void*. C++ 5.2.9p10 specifies additional restrictions, which really is
|
|
|
|
// just the usual constness stuff.
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) {
|
2008-11-06 05:50:06 +08:00
|
|
|
QualType SrcPointee = SrcPointer->getPointeeType();
|
|
|
|
if (SrcPointee->isVoidType()) {
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const PointerType *DestPointer = DestType->getAs<PointerType>()) {
|
2008-11-06 05:50:06 +08:00
|
|
|
QualType DestPointee = DestPointer->getPointeeType();
|
2009-03-25 04:13:58 +08:00
|
|
|
if (DestPointee->isIncompleteOrObjectType()) {
|
2008-11-06 05:50:06 +08:00
|
|
|
// This is definitely the intended conversion, but it might fail due
|
2011-06-16 07:02:42 +08:00
|
|
|
// to a qualifier violation. Note that we permit Objective-C lifetime
|
|
|
|
// and GC qualifier mismatches here.
|
|
|
|
if (!CStyle) {
|
|
|
|
Qualifiers DestPointeeQuals = DestPointee.getQualifiers();
|
|
|
|
Qualifiers SrcPointeeQuals = SrcPointee.getQualifiers();
|
|
|
|
DestPointeeQuals.removeObjCGCAttr();
|
|
|
|
DestPointeeQuals.removeObjCLifetime();
|
|
|
|
SrcPointeeQuals.removeObjCGCAttr();
|
|
|
|
SrcPointeeQuals.removeObjCLifetime();
|
|
|
|
if (DestPointeeQuals != SrcPointeeQuals &&
|
|
|
|
!DestPointeeQuals.compatiblyIncludes(SrcPointeeQuals)) {
|
|
|
|
msg = diag::err_bad_cxx_cast_qualifiers_away;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_BitCast;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2015-06-03 06:15:12 +08:00
|
|
|
|
|
|
|
// Microsoft permits static_cast from 'pointer-to-void' to
|
|
|
|
// 'pointer-to-function'.
|
2015-06-09 10:41:08 +08:00
|
|
|
if (!CStyle && Self.getLangOpts().MSVCCompat &&
|
|
|
|
DestPointee->isFunctionType()) {
|
2015-06-03 06:15:12 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::ext_ms_cast_fn_obj) << OpRange;
|
|
|
|
Kind = CK_BitCast;
|
|
|
|
return TC_Success;
|
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2010-05-11 07:46:53 +08:00
|
|
|
else if (DestType->isObjCObjectPointerType()) {
|
|
|
|
// allow both c-style cast and static_cast of objective-c pointers as
|
|
|
|
// they are pervasive.
|
2011-09-09 13:25:32 +08:00
|
|
|
Kind = CK_CPointerToObjCPointerCast;
|
2009-12-09 07:09:15 +08:00
|
|
|
return TC_Success;
|
|
|
|
}
|
2009-12-12 06:40:48 +08:00
|
|
|
else if (CStyle && DestType->isBlockPointerType()) {
|
|
|
|
// allow c-style cast of void * to block pointers.
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_AnyPointerToBlockPointerCast;
|
2009-12-12 06:40:48 +08:00
|
|
|
return TC_Success;
|
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
}
|
2010-05-13 02:16:59 +08:00
|
|
|
// Allow arbitray objective-c pointer conversion with static casts.
|
|
|
|
if (SrcType->isObjCObjectPointerType() &&
|
2010-11-15 17:13:47 +08:00
|
|
|
DestType->isObjCObjectPointerType()) {
|
|
|
|
Kind = CK_BitCast;
|
2010-05-13 02:16:59 +08:00
|
|
|
return TC_Success;
|
2010-11-15 17:13:47 +08:00
|
|
|
}
|
2014-05-11 01:40:11 +08:00
|
|
|
// Allow ns-pointer to cf-pointer conversion in either direction
|
|
|
|
// with static casts.
|
|
|
|
if (!CStyle &&
|
|
|
|
Self.CheckTollFreeBridgeStaticCast(DestType, SrcExpr.get(), Kind))
|
|
|
|
return TC_Success;
|
2015-01-29 05:31:26 +08:00
|
|
|
|
|
|
|
// See if it looks like the user is trying to convert between
|
|
|
|
// related record types, and select a better diagnostic if so.
|
|
|
|
if (auto SrcPointer = SrcType->getAs<PointerType>())
|
|
|
|
if (auto DestPointer = DestType->getAs<PointerType>())
|
|
|
|
if (SrcPointer->getPointeeType()->getAs<RecordType>() &&
|
|
|
|
DestPointer->getPointeeType()->getAs<RecordType>())
|
|
|
|
msg = diag::err_bad_cxx_cast_unrelated_class;
|
2010-05-13 02:16:59 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
// We tried everything. Everything! Nothing works! :-(
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-03-23 06:30:06 +08:00
|
|
|
/// Tests whether a conversion according to N2844 is valid.
|
2009-07-25 23:41:38 +08:00
|
|
|
TryCastResult
|
2009-03-23 06:30:06 +08:00
|
|
|
TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
2011-01-27 05:04:06 +08:00
|
|
|
bool CStyle, CastKind &Kind, CXXCastPath &BasePath,
|
|
|
|
unsigned &msg) {
|
2015-07-13 06:10:56 +08:00
|
|
|
// C++11 [expr.static.cast]p3:
|
2011-01-22 08:06:57 +08:00
|
|
|
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
|
|
|
|
// cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
|
2009-07-30 05:53:49 +08:00
|
|
|
const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
|
2009-03-23 06:30:06 +08:00
|
|
|
if (!R)
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2009-03-23 06:30:06 +08:00
|
|
|
|
2011-01-22 08:06:57 +08:00
|
|
|
if (!SrcExpr->isGLValue())
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2009-03-23 06:30:06 +08:00
|
|
|
|
|
|
|
// Because we try the reference downcast before this function, from now on
|
|
|
|
// this is the only cast possibility, so we issue an error if we fail now.
|
2009-07-25 23:41:38 +08:00
|
|
|
// FIXME: Should allow casting away constness if CStyle.
|
2009-03-23 06:30:06 +08:00
|
|
|
bool DerivedToBase;
|
2010-08-07 19:51:51 +08:00
|
|
|
bool ObjCConversion;
|
2011-06-16 07:02:42 +08:00
|
|
|
bool ObjCLifetimeConversion;
|
2011-01-27 05:04:06 +08:00
|
|
|
QualType FromType = SrcExpr->getType();
|
|
|
|
QualType ToType = R->getPointeeType();
|
|
|
|
if (CStyle) {
|
|
|
|
FromType = FromType.getUnqualifiedType();
|
|
|
|
ToType = ToType.getUnqualifiedType();
|
|
|
|
}
|
|
|
|
|
2009-11-05 21:06:35 +08:00
|
|
|
if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
|
2011-01-27 05:04:06 +08:00
|
|
|
ToType, FromType,
|
2011-06-16 07:02:42 +08:00
|
|
|
DerivedToBase, ObjCConversion,
|
|
|
|
ObjCLifetimeConversion)
|
|
|
|
< Sema::Ref_Compatible_With_Added_Qualification) {
|
2015-07-13 06:10:56 +08:00
|
|
|
if (CStyle)
|
|
|
|
return TC_NotApplicable;
|
2009-07-25 23:41:38 +08:00
|
|
|
msg = diag::err_bad_lvalue_to_rvalue_cast;
|
|
|
|
return TC_Failed;
|
2009-03-23 06:30:06 +08:00
|
|
|
}
|
|
|
|
|
2011-01-26 00:13:26 +08:00
|
|
|
if (DerivedToBase) {
|
|
|
|
Kind = CK_DerivedToBase;
|
|
|
|
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
|
|
|
/*DetectVirtual=*/true);
|
|
|
|
if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths))
|
|
|
|
return TC_NotApplicable;
|
|
|
|
|
|
|
|
Self.BuildBasePathArray(Paths, BasePath);
|
|
|
|
} else
|
|
|
|
Kind = CK_NoOp;
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2009-03-23 06:30:06 +08:00
|
|
|
}
|
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
/// Tests whether a conversion according to C++ 5.2.9p5 is valid.
|
2009-07-25 23:41:38 +08:00
|
|
|
TryCastResult
|
2008-11-08 21:00:26 +08:00
|
|
|
TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
2015-10-04 12:53:55 +08:00
|
|
|
bool CStyle, SourceRange OpRange,
|
2010-08-25 19:45:40 +08:00
|
|
|
unsigned &msg, CastKind &Kind,
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath &BasePath) {
|
2008-11-06 05:50:06 +08:00
|
|
|
// C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
|
|
|
|
// cast to type "reference to cv2 D", where D is a class derived from B,
|
|
|
|
// if a valid standard conversion from "pointer to D" to "pointer to B"
|
|
|
|
// exists, cv2 >= cv1, and B is not a virtual base class of D.
|
|
|
|
// In addition, DR54 clarifies that the base must be accessible in the
|
|
|
|
// current context. Although the wording of DR54 only applies to the pointer
|
|
|
|
// variant of this rule, the intent is clearly for it to apply to the this
|
2009-07-25 23:41:38 +08:00
|
|
|
// conversion as well.
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const ReferenceType *DestReference = DestType->getAs<ReferenceType>();
|
2008-11-06 05:50:06 +08:00
|
|
|
if (!DestReference) {
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
|
|
|
bool RValueRef = DestReference->isRValueReferenceType();
|
2010-11-24 13:12:34 +08:00
|
|
|
if (!RValueRef && !SrcExpr->isLValue()) {
|
2009-07-25 23:41:38 +08:00
|
|
|
// We know the left side is an lvalue reference, so we can suggest a reason.
|
|
|
|
msg = diag::err_bad_cxx_cast_rvalue;
|
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
QualType DestPointee = DestReference->getPointeeType();
|
|
|
|
|
2014-07-09 01:25:14 +08:00
|
|
|
// FIXME: If the source is a prvalue, we should issue a warning (because the
|
|
|
|
// cast always has undefined behavior), and for AST consistency, we should
|
|
|
|
// materialize a temporary.
|
2009-11-15 17:20:52 +08:00
|
|
|
return TryStaticDowncast(Self,
|
|
|
|
Self.Context.getCanonicalType(SrcExpr->getType()),
|
|
|
|
Self.Context.getCanonicalType(DestPointee), CStyle,
|
2010-04-25 03:36:51 +08:00
|
|
|
OpRange, SrcExpr->getType(), DestType, msg, Kind,
|
|
|
|
BasePath);
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Tests whether a conversion according to C++ 5.2.9p8 is valid.
|
2009-07-25 23:41:38 +08:00
|
|
|
TryCastResult
|
2008-11-08 21:00:26 +08:00
|
|
|
TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
|
2015-10-04 12:53:55 +08:00
|
|
|
bool CStyle, SourceRange OpRange,
|
2010-08-25 19:45:40 +08:00
|
|
|
unsigned &msg, CastKind &Kind,
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath &BasePath) {
|
2008-11-06 05:50:06 +08:00
|
|
|
// C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
|
|
|
|
// type, can be converted to an rvalue of type "pointer to cv2 D", where D
|
|
|
|
// is a class derived from B, if a valid standard conversion from "pointer
|
|
|
|
// to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base
|
|
|
|
// class of D.
|
|
|
|
// In addition, DR54 clarifies that the base must be accessible in the
|
|
|
|
// current context.
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const PointerType *DestPointer = DestType->getAs<PointerType>();
|
2008-11-06 05:50:06 +08:00
|
|
|
if (!DestPointer) {
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const PointerType *SrcPointer = SrcType->getAs<PointerType>();
|
2009-07-25 23:41:38 +08:00
|
|
|
if (!SrcPointer) {
|
|
|
|
msg = diag::err_bad_static_cast_pointer_nonpointer;
|
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-11-15 17:20:52 +08:00
|
|
|
return TryStaticDowncast(Self,
|
|
|
|
Self.Context.getCanonicalType(SrcPointer->getPointeeType()),
|
|
|
|
Self.Context.getCanonicalType(DestPointer->getPointeeType()),
|
2010-04-25 03:36:51 +08:00
|
|
|
CStyle, OpRange, SrcType, DestType, msg, Kind,
|
|
|
|
BasePath);
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2008-11-08 07:29:29 +08:00
|
|
|
/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and
|
|
|
|
/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to
|
2009-11-15 17:20:52 +08:00
|
|
|
/// DestType is possible and allowed.
|
2009-07-25 23:41:38 +08:00
|
|
|
TryCastResult
|
2009-11-15 17:20:52 +08:00
|
|
|
TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
|
2015-10-04 12:53:55 +08:00
|
|
|
bool CStyle, SourceRange OpRange, QualType OrigSrcType,
|
2009-11-13 00:53:16 +08:00
|
|
|
QualType OrigDestType, unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind, CXXCastPath &BasePath) {
|
2009-10-22 23:07:22 +08:00
|
|
|
// We can only work with complete types. But don't complain if it doesn't work
|
2012-05-05 00:32:21 +08:00
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0) ||
|
|
|
|
Self.RequireCompleteType(OpRange.getBegin(), DestType, 0))
|
2009-10-22 23:07:22 +08:00
|
|
|
return TC_NotApplicable;
|
|
|
|
|
2008-11-06 05:50:06 +08:00
|
|
|
// Downcast can only happen in class hierarchies, so we need classes.
|
2009-11-15 17:20:52 +08:00
|
|
|
if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) {
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2010-04-25 03:36:51 +08:00
|
|
|
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
2009-10-07 01:59:45 +08:00
|
|
|
/*DetectVirtual=*/true);
|
2008-11-08 21:00:26 +08:00
|
|
|
if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) {
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2008-11-08 07:29:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Target type does derive from source type. Now we're serious. If an error
|
|
|
|
// appears now, it's not ignored.
|
|
|
|
// This may not be entirely in line with the standard. Take for example:
|
|
|
|
// struct A {};
|
|
|
|
// struct B : virtual A {
|
|
|
|
// B(A&);
|
|
|
|
// };
|
2009-09-09 23:08:12 +08:00
|
|
|
//
|
2008-11-08 07:29:29 +08:00
|
|
|
// void f()
|
|
|
|
// {
|
|
|
|
// (void)static_cast<const B&>(*((A*)0));
|
|
|
|
// }
|
|
|
|
// As far as the standard is concerned, p5 does not apply (A is virtual), so
|
|
|
|
// p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid.
|
|
|
|
// However, both GCC and Comeau reject this example, and accepting it would
|
|
|
|
// mean more complex code if we're to preserve the nice error message.
|
|
|
|
// FIXME: Being 100% compliant here would be nice to have.
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Must preserve cv, as always, unless we're in C-style mode.
|
|
|
|
if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) {
|
Implement appropriate semantics for C++ casting and conversion when
dealing with address-space- and GC-qualified pointers. Previously,
these qualifiers were being treated just like cvr-qualifiers (in some
cases) or were completely ignored, leading to uneven behavior. For
example, const_cast would allow conversion between pointers to
different address spaces.
The new semantics are fairly simple: reinterpret_cast can be used to
explicitly cast between pointers to different address spaces
(including adding/removing addresss spaces), while
static_cast/dynamic_cast/const_cast do not tolerate any changes in the
address space. C-style casts can add/remove/change address spaces
through the reinterpret_cast mechanism. Other non-CVR qualifiers
(e.g., Objective-C GC qualifiers) work similarly.
As part of this change, I tweaked the "casts away constness"
diagnostic to use the term "casts away qualifiers". The term
"constness" actually comes from the C++ standard, despite the fact
that removing "volatile" also falls under that category. In Clang, we
also have restrict, address spaces, ObjC GC attributes, etc., so the
more general "qualifiers" is clearer.
llvm-svn: 129583
2011-04-16 01:59:54 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_qualifiers_away;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Failed;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) {
|
2008-11-08 07:29:29 +08:00
|
|
|
// This code is analoguous to that in CheckDerivedToBaseConversion, except
|
|
|
|
// that it builds the paths in reverse order.
|
|
|
|
// To sum up: record all paths to the base and build a nice string from
|
|
|
|
// them. Use it to spice up the error message.
|
2009-07-25 23:41:38 +08:00
|
|
|
if (!Paths.isRecordingPaths()) {
|
|
|
|
Paths.clear();
|
|
|
|
Paths.setRecordingPaths(true);
|
|
|
|
Self.IsDerivedFrom(DestType, SrcType, Paths);
|
|
|
|
}
|
2008-11-08 07:29:29 +08:00
|
|
|
std::string PathDisplayStr;
|
|
|
|
std::set<unsigned> DisplayedPaths;
|
2009-10-07 01:59:45 +08:00
|
|
|
for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end();
|
2009-07-25 23:41:38 +08:00
|
|
|
PI != PE; ++PI) {
|
|
|
|
if (DisplayedPaths.insert(PI->back().SubobjectNumber).second) {
|
2008-11-08 07:29:29 +08:00
|
|
|
// We haven't displayed a path to this particular base
|
|
|
|
// class subobject yet.
|
|
|
|
PathDisplayStr += "\n ";
|
2009-10-07 01:59:45 +08:00
|
|
|
for (CXXBasePath::const_reverse_iterator EI = PI->rbegin(),
|
|
|
|
EE = PI->rend();
|
2009-07-25 23:41:38 +08:00
|
|
|
EI != EE; ++EI)
|
|
|
|
PathDisplayStr += EI->Base->getType().getAsString() + " -> ";
|
2009-11-15 17:20:52 +08:00
|
|
|
PathDisplayStr += QualType(DestType).getAsString();
|
2008-11-08 07:29:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-19 06:52:51 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast)
|
2009-11-15 17:20:52 +08:00
|
|
|
<< QualType(SrcType).getUnqualifiedType()
|
|
|
|
<< QualType(DestType).getUnqualifiedType()
|
2008-11-19 06:52:51 +08:00
|
|
|
<< PathDisplayStr << OpRange;
|
2009-07-25 23:41:38 +08:00
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2014-05-26 14:22:03 +08:00
|
|
|
if (Paths.getDetectedVirtual() != nullptr) {
|
2008-11-08 07:29:29 +08:00
|
|
|
QualType VirtualBase(Paths.getDetectedVirtual(), 0);
|
2008-11-19 06:52:51 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual)
|
2008-11-24 14:25:27 +08:00
|
|
|
<< OrigSrcType << OrigDestType << VirtualBase << OpRange;
|
2009-07-25 23:41:38 +08:00
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2011-02-15 07:21:33 +08:00
|
|
|
if (!CStyle) {
|
|
|
|
switch (Self.CheckBaseClassAccess(OpRange.getBegin(),
|
|
|
|
SrcType, DestType,
|
|
|
|
Paths.front(),
|
2010-03-16 13:22:47 +08:00
|
|
|
diag::err_downcast_from_inaccessible_base)) {
|
2011-02-15 07:21:33 +08:00
|
|
|
case Sema::AR_accessible:
|
|
|
|
case Sema::AR_delayed: // be optimistic
|
|
|
|
case Sema::AR_dependent: // be optimistic
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Sema::AR_inaccessible:
|
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2010-04-25 03:36:51 +08:00
|
|
|
Self.BuildBasePathArray(Paths, BasePath);
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_BaseToDerived;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-01-29 02:33:18 +08:00
|
|
|
/// TryStaticMemberPointerUpcast - Tests whether a conversion according to
|
|
|
|
/// C++ 5.2.9p9 is valid:
|
|
|
|
///
|
|
|
|
/// An rvalue of type "pointer to member of D of type cv1 T" can be
|
|
|
|
/// converted to an rvalue of type "pointer to member of B of type cv2 T",
|
|
|
|
/// where B is a base class of D [...].
|
|
|
|
///
|
2009-07-25 23:41:38 +08:00
|
|
|
TryCastResult
|
2011-04-09 02:41:53 +08:00
|
|
|
TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
|
2010-03-08 07:24:59 +08:00
|
|
|
QualType DestType, bool CStyle,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2010-08-25 19:45:40 +08:00
|
|
|
unsigned &msg, CastKind &Kind,
|
2010-08-07 14:22:56 +08:00
|
|
|
CXXCastPath &BasePath) {
|
2009-07-30 05:53:49 +08:00
|
|
|
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
|
2009-01-29 02:33:18 +08:00
|
|
|
if (!DestMemPtr)
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2010-03-08 07:24:59 +08:00
|
|
|
|
|
|
|
bool WasOverloadedFunction = false;
|
2010-03-31 05:47:33 +08:00
|
|
|
DeclAccessPair FoundOverload;
|
2011-04-09 02:41:53 +08:00
|
|
|
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
|
2010-04-15 07:11:21 +08:00
|
|
|
if (FunctionDecl *Fn
|
2011-04-09 02:41:53 +08:00
|
|
|
= Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false,
|
2010-04-15 07:11:21 +08:00
|
|
|
FoundOverload)) {
|
|
|
|
CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
|
|
|
|
SrcType = Self.Context.getMemberPointerType(Fn->getType(),
|
|
|
|
Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
|
|
|
|
WasOverloadedFunction = true;
|
|
|
|
}
|
2010-03-08 07:24:59 +08:00
|
|
|
}
|
2010-04-15 07:11:21 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
|
2009-07-25 23:41:38 +08:00
|
|
|
if (!SrcMemPtr) {
|
|
|
|
msg = diag::err_bad_static_cast_member_pointer_nonmp;
|
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
2015-08-10 12:07:49 +08:00
|
|
|
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft())
|
|
|
|
Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
|
2009-01-29 02:33:18 +08:00
|
|
|
|
|
|
|
// T == T, modulo cv
|
First part of changes to eliminate problems with cv-qualifiers and
sugared types. The basic problem is that our qualifier accessors
(getQualifiers, getCVRQualifiers, isConstQualified, etc.) only look at
the current QualType and not at any qualifiers that come from sugared
types, meaning that we won't see these qualifiers through, e.g.,
typedefs:
typedef const int CInt;
typedef CInt Self;
Self.isConstQualified() currently returns false!
Various bugs (e.g., PR5383) have cropped up all over the front end due
to such problems. I'm addressing this problem by splitting each
qualifier accessor into two versions:
- the "local" version only returns qualifiers on this particular
QualType instance
- the "normal" version that will eventually combine qualifiers from this
QualType instance with the qualifiers on the canonical type to
produce the full set of qualifiers.
This commit adds the local versions and switches a few callers from
the "normal" version (e.g., isConstQualified) over to the "local"
version (e.g., isLocalConstQualified) when that is the right thing to
do, e.g., because we're printing or serializing the qualifiers. Also,
switch a bunch of
Context.getCanonicalType(T1).getUnqualifiedType() == Context.getCanonicalType(T2).getQualifiedType()
expressions over to
Context.hasSameUnqualifiedType(T1, T2)
llvm-svn: 88969
2009-11-17 05:35:15 +08:00
|
|
|
if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(),
|
|
|
|
DestMemPtr->getPointeeType()))
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2009-01-29 02:33:18 +08:00
|
|
|
|
|
|
|
// B base of D
|
|
|
|
QualType SrcClass(SrcMemPtr->getClass(), 0);
|
|
|
|
QualType DestClass(DestMemPtr->getClass(), 0);
|
2010-04-25 03:22:20 +08:00
|
|
|
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
2009-01-29 02:33:18 +08:00
|
|
|
/*DetectVirtual=*/true);
|
2014-01-16 20:02:55 +08:00
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), SrcClass, 0) ||
|
|
|
|
!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) {
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
2009-01-29 02:33:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// B is a base of D. But is it an allowed base? If not, it's a hard error.
|
2010-05-22 04:29:55 +08:00
|
|
|
if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) {
|
2009-01-29 02:33:18 +08:00
|
|
|
Paths.clear();
|
|
|
|
Paths.setRecordingPaths(true);
|
|
|
|
bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths);
|
|
|
|
assert(StillOkay);
|
2010-12-23 09:01:28 +08:00
|
|
|
(void)StillOkay;
|
2009-01-29 02:33:18 +08:00
|
|
|
std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths);
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv)
|
|
|
|
<< 1 << SrcClass << DestClass << PathDisplayStr << OpRange;
|
2009-07-25 23:41:38 +08:00
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
2009-01-29 02:33:18 +08:00
|
|
|
}
|
|
|
|
|
2009-02-28 09:32:25 +08:00
|
|
|
if (const RecordType *VBase = Paths.getDetectedVirtual()) {
|
2009-01-29 02:33:18 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual)
|
|
|
|
<< SrcClass << DestClass << QualType(VBase, 0) << OpRange;
|
2009-07-25 23:41:38 +08:00
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
2009-01-29 02:33:18 +08:00
|
|
|
}
|
|
|
|
|
2011-02-15 07:21:33 +08:00
|
|
|
if (!CStyle) {
|
|
|
|
switch (Self.CheckBaseClassAccess(OpRange.getBegin(),
|
|
|
|
DestClass, SrcClass,
|
|
|
|
Paths.front(),
|
|
|
|
diag::err_upcast_to_inaccessible_base)) {
|
|
|
|
case Sema::AR_accessible:
|
|
|
|
case Sema::AR_delayed:
|
|
|
|
case Sema::AR_dependent:
|
|
|
|
// Optimistically assume that the delayed and dependent cases
|
|
|
|
// will work out.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Sema::AR_inaccessible:
|
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
2009-01-29 02:33:18 +08:00
|
|
|
|
2010-03-08 07:24:59 +08:00
|
|
|
if (WasOverloadedFunction) {
|
|
|
|
// Resolve the address of the overloaded function again, this time
|
|
|
|
// allowing complaints if something goes wrong.
|
2011-04-09 02:41:53 +08:00
|
|
|
FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
|
2010-03-08 07:24:59 +08:00
|
|
|
DestType,
|
2010-03-31 05:47:33 +08:00
|
|
|
true,
|
|
|
|
FoundOverload);
|
2010-03-08 07:24:59 +08:00
|
|
|
if (!Fn) {
|
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
|
|
|
|
2010-03-31 05:47:33 +08:00
|
|
|
SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn);
|
2011-04-09 02:41:53 +08:00
|
|
|
if (!SrcExpr.isUsable()) {
|
2010-03-08 07:24:59 +08:00
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-25 03:22:20 +08:00
|
|
|
Self.BuildBasePathArray(Paths, BasePath);
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_DerivedToBaseMemberPointer;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2009-01-29 02:33:18 +08:00
|
|
|
}
|
|
|
|
|
2008-11-08 07:29:29 +08:00
|
|
|
/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2
|
|
|
|
/// is valid:
|
|
|
|
///
|
|
|
|
/// An expression e can be explicitly converted to a type T using a
|
|
|
|
/// @c static_cast if the declaration "T t(e);" is well-formed [...].
|
2009-07-25 23:41:38 +08:00
|
|
|
TryCastResult
|
2011-04-09 02:41:53 +08:00
|
|
|
TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
2011-06-16 07:02:42 +08:00
|
|
|
Sema::CheckedConversionKind CCK,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange, unsigned &msg,
|
2012-02-13 02:41:05 +08:00
|
|
|
CastKind &Kind, bool ListInitialization) {
|
2009-09-08 02:25:47 +08:00
|
|
|
if (DestType->isRecordType()) {
|
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
|
2012-05-07 08:02:00 +08:00
|
|
|
diag::err_bad_dynamic_cast_incomplete) ||
|
2012-06-16 10:19:17 +08:00
|
|
|
Self.RequireNonAbstractType(OpRange.getBegin(), DestType,
|
2012-05-07 08:02:00 +08:00
|
|
|
diag::err_allocation_of_abstract_type)) {
|
2009-09-08 02:25:47 +08:00
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
|
|
|
}
|
2012-02-13 00:37:36 +08:00
|
|
|
|
2010-04-17 03:30:02 +08:00
|
|
|
InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType);
|
|
|
|
InitializationKind InitKind
|
2011-06-16 07:02:42 +08:00
|
|
|
= (CCK == Sema::CCK_CStyleCast)
|
2012-02-13 00:37:36 +08:00
|
|
|
? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange,
|
2012-02-13 02:41:05 +08:00
|
|
|
ListInitialization)
|
2011-06-16 07:02:42 +08:00
|
|
|
: (CCK == Sema::CCK_FunctionalCast)
|
2012-02-13 02:41:05 +08:00
|
|
|
? InitializationKind::CreateFunctionalCast(OpRange, ListInitialization)
|
2011-11-30 06:48:16 +08:00
|
|
|
: InitializationKind::CreateCast(OpRange);
|
2011-04-09 02:41:53 +08:00
|
|
|
Expr *SrcExprRaw = SrcExpr.get();
|
2013-05-03 23:05:50 +08:00
|
|
|
InitializationSequence InitSeq(Self, Entity, InitKind, SrcExprRaw);
|
2010-11-08 11:40:48 +08:00
|
|
|
|
|
|
|
// At this point of CheckStaticCast, if the destination is a reference,
|
|
|
|
// or the expression is an overload expression this has to work.
|
|
|
|
// There is no other way that works.
|
|
|
|
// On the other hand, if we're checking a C-style cast, we've still got
|
|
|
|
// the reinterpret_cast way.
|
2011-06-16 07:02:42 +08:00
|
|
|
bool CStyle
|
|
|
|
= (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
|
2011-06-05 20:23:28 +08:00
|
|
|
if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType()))
|
2009-09-26 08:12:34 +08:00
|
|
|
return TC_NotApplicable;
|
2010-04-17 06:09:46 +08:00
|
|
|
|
2012-08-24 07:38:35 +08:00
|
|
|
ExprResult Result = InitSeq.Perform(Self, Entity, InitKind, SrcExprRaw);
|
2010-04-17 03:30:02 +08:00
|
|
|
if (Result.isInvalid()) {
|
|
|
|
msg = 0;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
|
|
|
|
2010-04-17 06:09:46 +08:00
|
|
|
if (InitSeq.isConstructorInitialization())
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_ConstructorConversion;
|
2010-04-17 06:09:46 +08:00
|
|
|
else
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_NoOp;
|
2010-04-17 06:09:46 +08:00
|
|
|
|
2012-08-24 05:35:17 +08:00
|
|
|
SrcExpr = Result;
|
2010-04-17 03:30:02 +08:00
|
|
|
return TC_Success;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
/// TryConstCast - See if a const_cast from source to destination is allowed,
|
|
|
|
/// and perform it if it is.
|
2013-06-15 06:27:52 +08:00
|
|
|
static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
|
|
|
|
QualType DestType, bool CStyle,
|
|
|
|
unsigned &msg) {
|
2008-11-08 21:00:26 +08:00
|
|
|
DestType = Self.Context.getCanonicalType(DestType);
|
2013-06-15 06:27:52 +08:00
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
|
|
|
bool NeedToMaterializeTemporary = false;
|
|
|
|
|
2011-01-22 08:19:52 +08:00
|
|
|
if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) {
|
2013-06-15 06:27:52 +08:00
|
|
|
// C++11 5.2.11p4:
|
|
|
|
// if a pointer to T1 can be explicitly converted to the type "pointer to
|
|
|
|
// T2" using a const_cast, then the following conversions can also be
|
|
|
|
// made:
|
|
|
|
// -- an lvalue of type T1 can be explicitly converted to an lvalue of
|
|
|
|
// type T2 using the cast const_cast<T2&>;
|
|
|
|
// -- a glvalue of type T1 can be explicitly converted to an xvalue of
|
|
|
|
// type T2 using the cast const_cast<T2&&>; and
|
|
|
|
// -- if T1 is a class type, a prvalue of type T1 can be explicitly
|
|
|
|
// converted to an xvalue of type T2 using the cast const_cast<T2&&>.
|
|
|
|
|
|
|
|
if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr.get()->isLValue()) {
|
2009-07-25 23:41:38 +08:00
|
|
|
// Cannot const_cast non-lvalue to lvalue reference type. But if this
|
|
|
|
// is C-style, static_cast might find a way, so we simply suggest a
|
|
|
|
// message and tell the parent to keep searching.
|
|
|
|
msg = diag::err_bad_cxx_cast_rvalue;
|
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2013-06-15 06:27:52 +08:00
|
|
|
if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) {
|
|
|
|
if (!SrcType->isRecordType()) {
|
|
|
|
// Cannot const_cast non-class prvalue to rvalue reference type. But if
|
|
|
|
// this is C-style, static_cast can do this.
|
|
|
|
msg = diag::err_bad_cxx_cast_rvalue;
|
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Materialize the class prvalue so that the const_cast can bind a
|
|
|
|
// reference to it.
|
|
|
|
NeedToMaterializeTemporary = true;
|
|
|
|
}
|
|
|
|
|
2013-05-07 05:39:12 +08:00
|
|
|
// It's not completely clear under the standard whether we can
|
|
|
|
// const_cast bit-field gl-values. Doing so would not be
|
|
|
|
// intrinsically complicated, but for now, we say no for
|
|
|
|
// consistency with other compilers and await the word of the
|
|
|
|
// committee.
|
2013-06-15 06:27:52 +08:00
|
|
|
if (SrcExpr.get()->refersToBitField()) {
|
2013-05-07 05:39:12 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_bitfield;
|
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
|
|
|
|
SrcType = Self.Context.getPointerType(SrcType);
|
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.11p5: For a const_cast involving pointers to data members [...]
|
|
|
|
// the rules for const_cast are the same as those used for pointers.
|
|
|
|
|
2010-05-18 17:35:29 +08:00
|
|
|
if (!DestType->isPointerType() &&
|
|
|
|
!DestType->isMemberPointerType() &&
|
|
|
|
!DestType->isObjCObjectPointerType()) {
|
2009-07-25 23:41:38 +08:00
|
|
|
// Cannot cast to non-pointer, non-reference type. Note that, if DestType
|
|
|
|
// was a reference type, we converted it to a pointer above.
|
|
|
|
// The status of rvalue references isn't entirely clear, but it looks like
|
|
|
|
// conversion to them is simply invalid.
|
|
|
|
// C++ 5.2.11p3: For two pointer types [...]
|
|
|
|
if (!CStyle)
|
|
|
|
msg = diag::err_bad_const_cast_dest;
|
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
|
|
|
if (DestType->isFunctionPointerType() ||
|
|
|
|
DestType->isMemberFunctionPointerType()) {
|
|
|
|
// Cannot cast direct function pointers.
|
|
|
|
// C++ 5.2.11p2: [...] where T is any object type or the void type [...]
|
|
|
|
// T is the ultimate pointee of source and target type.
|
|
|
|
if (!CStyle)
|
|
|
|
msg = diag::err_bad_const_cast_dest;
|
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
SrcType = Self.Context.getCanonicalType(SrcType);
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Unwrap the pointers. Ignore qualifiers. Terminate early if the types are
|
|
|
|
// completely equal.
|
|
|
|
// C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers
|
|
|
|
// in multi-level pointers may change, but the level count must be the same,
|
|
|
|
// as must be the final pointee type.
|
|
|
|
while (SrcType != DestType &&
|
2010-06-09 11:53:18 +08:00
|
|
|
Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) {
|
Implement appropriate semantics for C++ casting and conversion when
dealing with address-space- and GC-qualified pointers. Previously,
these qualifiers were being treated just like cvr-qualifiers (in some
cases) or were completely ignored, leading to uneven behavior. For
example, const_cast would allow conversion between pointers to
different address spaces.
The new semantics are fairly simple: reinterpret_cast can be used to
explicitly cast between pointers to different address spaces
(including adding/removing addresss spaces), while
static_cast/dynamic_cast/const_cast do not tolerate any changes in the
address space. C-style casts can add/remove/change address spaces
through the reinterpret_cast mechanism. Other non-CVR qualifiers
(e.g., Objective-C GC qualifiers) work similarly.
As part of this change, I tweaked the "casts away constness"
diagnostic to use the term "casts away qualifiers". The term
"constness" actually comes from the C++ standard, despite the fact
that removing "volatile" also falls under that category. In Clang, we
also have restrict, address spaces, ObjC GC attributes, etc., so the
more general "qualifiers" is clearer.
llvm-svn: 129583
2011-04-16 01:59:54 +08:00
|
|
|
Qualifiers SrcQuals, DestQuals;
|
|
|
|
SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals);
|
|
|
|
DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals);
|
|
|
|
|
|
|
|
// const_cast is permitted to strip cvr-qualifiers, only. Make sure that
|
|
|
|
// the other qualifiers (e.g., address spaces) are identical.
|
|
|
|
SrcQuals.removeCVRQualifiers();
|
|
|
|
DestQuals.removeCVRQualifiers();
|
|
|
|
if (SrcQuals != DestQuals)
|
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Since we're dealing in canonical types, the remainder must be the same.
|
|
|
|
if (SrcType != DestType)
|
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2013-06-15 06:27:52 +08:00
|
|
|
if (NeedToMaterializeTemporary)
|
|
|
|
// This is a const_cast from a class prvalue to an rvalue reference type.
|
|
|
|
// Materialize a temporary to store the result of the conversion.
|
|
|
|
SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcType, SrcExpr.get(), /*IsLValueReference*/ false);
|
2013-06-15 06:27:52 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
|
|
|
}
|
|
|
|
|
2011-05-03 02:21:19 +08:00
|
|
|
// Checks for undefined behavior in reinterpret_cast.
|
|
|
|
// The cases that is checked for is:
|
|
|
|
// *reinterpret_cast<T*>(&a)
|
|
|
|
// reinterpret_cast<T&>(a)
|
|
|
|
// where accessing 'a' as type 'T' will result in undefined behavior.
|
|
|
|
void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType,
|
|
|
|
bool IsDereference,
|
|
|
|
SourceRange Range) {
|
|
|
|
unsigned DiagID = IsDereference ?
|
|
|
|
diag::warn_pointer_indirection_from_incompatible_type :
|
|
|
|
diag::warn_undefined_reinterpret_cast;
|
|
|
|
|
2014-06-16 07:30:39 +08:00
|
|
|
if (Diags.isIgnored(DiagID, Range.getBegin()))
|
2011-05-03 02:21:19 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
QualType SrcTy, DestTy;
|
|
|
|
if (IsDereference) {
|
|
|
|
if (!SrcType->getAs<PointerType>() || !DestType->getAs<PointerType>()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SrcTy = SrcType->getPointeeType();
|
|
|
|
DestTy = DestType->getPointeeType();
|
|
|
|
} else {
|
|
|
|
if (!DestType->getAs<ReferenceType>()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SrcTy = SrcType;
|
|
|
|
DestTy = DestType->getPointeeType();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Cast is compatible if the types are the same.
|
|
|
|
if (Context.hasSameUnqualifiedType(DestTy, SrcTy)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// or one of the types is a char or void type
|
|
|
|
if (DestTy->isAnyCharacterType() || DestTy->isVoidType() ||
|
|
|
|
SrcTy->isAnyCharacterType() || SrcTy->isVoidType()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// or one of the types is a tag type.
|
2011-05-24 15:43:19 +08:00
|
|
|
if (SrcTy->getAs<TagType>() || DestTy->getAs<TagType>()) {
|
2011-05-03 02:21:19 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-05-21 00:38:50 +08:00
|
|
|
// FIXME: Scoped enums?
|
2011-05-03 02:21:19 +08:00
|
|
|
if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) ||
|
|
|
|
(SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) {
|
|
|
|
if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range;
|
|
|
|
}
|
2011-03-12 09:48:56 +08:00
|
|
|
|
2012-08-17 02:33:47 +08:00
|
|
|
static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr,
|
|
|
|
QualType DestType) {
|
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
2012-12-13 08:42:06 +08:00
|
|
|
if (Self.Context.hasSameType(SrcType, DestType))
|
|
|
|
return;
|
2012-08-17 02:33:47 +08:00
|
|
|
if (const PointerType *SrcPtrTy = SrcType->getAs<PointerType>())
|
|
|
|
if (SrcPtrTy->isObjCSelType()) {
|
|
|
|
QualType DT = DestType;
|
|
|
|
if (isa<PointerType>(DestType))
|
|
|
|
DT = DestType->getPointeeType();
|
|
|
|
if (!DT.getUnqualifiedType()->isVoidType())
|
|
|
|
Self.Diag(SrcExpr.get()->getExprLoc(),
|
|
|
|
diag::warn_cast_pointer_from_sel)
|
|
|
|
<< SrcType << DestType << SrcExpr.get()->getSourceRange();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-17 02:53:14 +08:00
|
|
|
static void checkIntToPointerCast(bool CStyle, SourceLocation Loc,
|
|
|
|
const Expr *SrcExpr, QualType DestType,
|
|
|
|
Sema &Self) {
|
|
|
|
QualType SrcType = SrcExpr->getType();
|
|
|
|
|
|
|
|
// Not warning on reinterpret_cast, boolean, constant expressions, etc
|
|
|
|
// are not explicit design choices, but consistent with GCC's behavior.
|
|
|
|
// Feel free to modify them if you've reason/evidence for an alternative.
|
|
|
|
if (CStyle && SrcType->isIntegralType(Self.Context)
|
|
|
|
&& !SrcType->isBooleanType()
|
|
|
|
&& !SrcType->isEnumeralType()
|
|
|
|
&& !SrcExpr->isIntegerConstantExpr(Self.Context)
|
2013-05-30 05:50:46 +08:00
|
|
|
&& Self.Context.getTypeSize(DestType) >
|
|
|
|
Self.Context.getTypeSize(SrcType)) {
|
|
|
|
// Separate between casts to void* and non-void* pointers.
|
|
|
|
// Some APIs use (abuse) void* for something like a user context,
|
|
|
|
// and often that value is an integer even if it isn't a pointer itself.
|
|
|
|
// Having a separate warning flag allows users to control the warning
|
|
|
|
// for their workflow.
|
|
|
|
unsigned Diag = DestType->isVoidPointerType() ?
|
|
|
|
diag::warn_int_to_void_pointer_cast
|
|
|
|
: diag::warn_int_to_pointer_cast;
|
|
|
|
Self.Diag(Loc, Diag) << SrcType << DestType;
|
|
|
|
}
|
2012-10-17 02:53:14 +08:00
|
|
|
}
|
|
|
|
|
2011-04-09 02:41:53 +08:00
|
|
|
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
2009-07-25 23:41:38 +08:00
|
|
|
QualType DestType, bool CStyle,
|
2015-10-04 12:53:55 +08:00
|
|
|
SourceRange OpRange,
|
2009-09-26 08:12:34 +08:00
|
|
|
unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind) {
|
2010-07-14 07:17:26 +08:00
|
|
|
bool IsLValueCast = false;
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
DestType = Self.Context.getCanonicalType(DestType);
|
2011-04-09 02:41:53 +08:00
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
2010-11-08 11:40:48 +08:00
|
|
|
|
|
|
|
// Is the source an overloaded name? (i.e. &foo)
|
2011-02-20 05:32:49 +08:00
|
|
|
// If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ...
|
|
|
|
if (SrcType == Self.Context.OverloadTy) {
|
2011-10-12 07:14:30 +08:00
|
|
|
// ... unless foo<int> resolves to an lvalue unambiguously.
|
|
|
|
// TODO: what if this fails because of DiagnoseUseOfDecl or something
|
|
|
|
// like it?
|
|
|
|
ExprResult SingleFunctionExpr = SrcExpr;
|
|
|
|
if (Self.ResolveAndFixSingleFunctionTemplateSpecialization(
|
|
|
|
SingleFunctionExpr,
|
2011-02-20 05:32:49 +08:00
|
|
|
Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr
|
2011-10-12 07:14:30 +08:00
|
|
|
) && SingleFunctionExpr.isUsable()) {
|
2012-08-24 05:35:17 +08:00
|
|
|
SrcExpr = SingleFunctionExpr;
|
2011-04-09 02:41:53 +08:00
|
|
|
SrcType = SrcExpr.get()->getType();
|
2011-10-12 07:14:30 +08:00
|
|
|
} else {
|
2011-02-20 05:32:49 +08:00
|
|
|
return TC_NotApplicable;
|
2011-10-12 07:14:30 +08:00
|
|
|
}
|
2011-02-20 05:32:49 +08:00
|
|
|
}
|
2010-11-08 11:40:48 +08:00
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
|
2012-04-29 16:24:44 +08:00
|
|
|
if (!SrcExpr.get()->isGLValue()) {
|
|
|
|
// Cannot cast non-glvalue to (lvalue or rvalue) reference type. See the
|
|
|
|
// similar comment in const_cast.
|
2009-07-25 23:41:38 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_rvalue;
|
|
|
|
return TC_NotApplicable;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2011-05-03 02:21:19 +08:00
|
|
|
if (!CStyle) {
|
|
|
|
Self.CheckCompatibleReinterpretCast(SrcType, DestType,
|
|
|
|
/*isDereference=*/false, OpRange);
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the
|
|
|
|
// same effect as the conversion *reinterpret_cast<T*>(&x) with the
|
|
|
|
// built-in & and * operators.
|
2011-04-23 06:31:13 +08:00
|
|
|
|
2014-05-26 14:22:03 +08:00
|
|
|
const char *inappropriate = nullptr;
|
2011-04-23 07:57:57 +08:00
|
|
|
switch (SrcExpr.get()->getObjectKind()) {
|
2011-04-23 09:10:24 +08:00
|
|
|
case OK_Ordinary:
|
|
|
|
break;
|
2011-04-23 07:57:57 +08:00
|
|
|
case OK_BitField: inappropriate = "bit-field"; break;
|
|
|
|
case OK_VectorComponent: inappropriate = "vector element"; break;
|
|
|
|
case OK_ObjCProperty: inappropriate = "property expression"; break;
|
2012-03-07 04:05:56 +08:00
|
|
|
case OK_ObjCSubscript: inappropriate = "container subscripting expression";
|
|
|
|
break;
|
2011-04-23 07:57:57 +08:00
|
|
|
}
|
|
|
|
if (inappropriate) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference)
|
|
|
|
<< inappropriate << DestType
|
|
|
|
<< OpRange << SrcExpr.get()->getSourceRange();
|
|
|
|
msg = 0; SrcExpr = ExprError();
|
2011-04-23 06:31:13 +08:00
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// This code does this transformation for the checked types.
|
|
|
|
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
|
|
|
|
SrcType = Self.Context.getPointerType(SrcType);
|
2010-11-08 11:40:48 +08:00
|
|
|
|
2010-07-14 07:17:26 +08:00
|
|
|
IsLValueCast = true;
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Canonicalize source for comparison.
|
|
|
|
SrcType = Self.Context.getCanonicalType(SrcType);
|
|
|
|
|
2009-07-30 05:53:49 +08:00
|
|
|
const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(),
|
|
|
|
*SrcMemPtr = SrcType->getAs<MemberPointerType>();
|
2009-07-25 23:41:38 +08:00
|
|
|
if (DestMemPtr && SrcMemPtr) {
|
|
|
|
// C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1"
|
|
|
|
// can be explicitly converted to an rvalue of type "pointer to member
|
|
|
|
// of Y of type T2" if T1 and T2 are both function types or both object
|
|
|
|
// types.
|
2015-04-24 09:25:08 +08:00
|
|
|
if (DestMemPtr->isMemberFunctionPointer() !=
|
|
|
|
SrcMemPtr->isMemberFunctionPointer())
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_NotApplicable;
|
|
|
|
|
|
|
|
// C++ 5.2.10p2: The reinterpret_cast operator shall not cast away
|
|
|
|
// constness.
|
|
|
|
// A reinterpret_cast followed by a const_cast can, though, so in C-style,
|
|
|
|
// we accept it.
|
2011-06-16 07:02:42 +08:00
|
|
|
if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
|
|
|
|
/*CheckObjCLifetime=*/CStyle)) {
|
Implement appropriate semantics for C++ casting and conversion when
dealing with address-space- and GC-qualified pointers. Previously,
these qualifiers were being treated just like cvr-qualifiers (in some
cases) or were completely ignored, leading to uneven behavior. For
example, const_cast would allow conversion between pointers to
different address spaces.
The new semantics are fairly simple: reinterpret_cast can be used to
explicitly cast between pointers to different address spaces
(including adding/removing addresss spaces), while
static_cast/dynamic_cast/const_cast do not tolerate any changes in the
address space. C-style casts can add/remove/change address spaces
through the reinterpret_cast mechanism. Other non-CVR qualifiers
(e.g., Objective-C GC qualifiers) work similarly.
As part of this change, I tweaked the "casts away constness"
diagnostic to use the term "casts away qualifiers". The term
"constness" actually comes from the C++ standard, despite the fact
that removing "volatile" also falls under that category. In Clang, we
also have restrict, address spaces, ObjC GC attributes, etc., so the
more general "qualifiers" is clearer.
llvm-svn: 129583
2011-04-16 01:59:54 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_qualifiers_away;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Failed;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2014-01-17 17:01:00 +08:00
|
|
|
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
|
|
|
|
// We need to determine the inheritance model that the class will use if
|
|
|
|
// haven't yet.
|
|
|
|
Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0);
|
|
|
|
Self.RequireCompleteType(OpRange.getBegin(), DestType, 0);
|
|
|
|
}
|
|
|
|
|
2010-08-16 13:30:44 +08:00
|
|
|
// Don't allow casting between member pointers of different sizes.
|
|
|
|
if (Self.Context.getTypeSize(DestMemPtr) !=
|
|
|
|
Self.Context.getTypeSize(SrcMemPtr)) {
|
|
|
|
msg = diag::err_bad_cxx_cast_member_pointer_size;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// A valid member pointer cast.
|
2012-02-15 09:22:51 +08:00
|
|
|
assert(!IsLValueCast);
|
|
|
|
Kind = CK_ReinterpretMemberPointer;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// See below for the enumeral issue.
|
2010-06-16 08:35:25 +08:00
|
|
|
if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) {
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++0x 5.2.10p4: A pointer can be explicitly converted to any integral
|
|
|
|
// type large enough to hold it. A value of std::nullptr_t can be
|
|
|
|
// converted to an integral type; the conversion has the same meaning
|
|
|
|
// and validity as a conversion of (void*)0 to the integral type.
|
|
|
|
if (Self.Context.getTypeSize(SrcType) >
|
|
|
|
Self.Context.getTypeSize(DestType)) {
|
|
|
|
msg = diag::err_bad_reinterpret_cast_small_int;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_PointerToIntegral;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2015-07-24 07:54:07 +08:00
|
|
|
// Allow reinterpret_casts between vectors of the same size and
|
|
|
|
// between vectors and integers of the same size.
|
2009-09-17 03:19:43 +08:00
|
|
|
bool destIsVector = DestType->isVectorType();
|
|
|
|
bool srcIsVector = SrcType->isVectorType();
|
|
|
|
if (srcIsVector || destIsVector) {
|
2015-07-24 07:54:07 +08:00
|
|
|
// The non-vector type, if any, must have integral type. This is
|
|
|
|
// the same rule that C vector casts use; note, however, that enum
|
|
|
|
// types are not integral in C++.
|
|
|
|
if ((!destIsVector && !DestType->isIntegralType(Self.Context)) ||
|
|
|
|
(!srcIsVector && !SrcType->isIntegralType(Self.Context)))
|
2009-09-17 03:19:43 +08:00
|
|
|
return TC_NotApplicable;
|
|
|
|
|
2015-07-24 07:54:07 +08:00
|
|
|
// The size we want to consider is eltCount * eltSize.
|
|
|
|
// That's exactly what the lax-conversion rules will check.
|
|
|
|
if (Self.areLaxCompatibleVectorTypes(SrcType, DestType)) {
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_BitCast;
|
2009-09-17 03:19:43 +08:00
|
|
|
return TC_Success;
|
2009-12-23 06:47:22 +08:00
|
|
|
}
|
2015-07-24 07:54:07 +08:00
|
|
|
|
|
|
|
// Otherwise, pick a reasonable diagnostic.
|
|
|
|
if (!destIsVector)
|
2009-09-17 03:19:43 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
|
2015-07-24 07:54:07 +08:00
|
|
|
else if (!srcIsVector)
|
2009-09-17 03:19:43 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size;
|
|
|
|
else
|
|
|
|
msg = diag::err_bad_cxx_cast_vector_to_vector_different_size;
|
|
|
|
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2012-02-03 10:54:37 +08:00
|
|
|
|
|
|
|
if (SrcType == DestType) {
|
|
|
|
// C++ 5.2.10p2 has a note that mentions that, subject to all other
|
|
|
|
// restrictions, a cast to the same type is allowed so long as it does not
|
|
|
|
// cast away constness. In C++98, the intent was not entirely clear here,
|
|
|
|
// since all other paragraphs explicitly forbid casts to the same type.
|
|
|
|
// C++11 clarifies this case with p2.
|
|
|
|
//
|
|
|
|
// The only allowed types are: integral, enumeration, pointer, or
|
|
|
|
// pointer-to-member types. We also won't restrict Obj-C pointers either.
|
|
|
|
Kind = CK_NoOp;
|
|
|
|
TryCastResult Result = TC_NotApplicable;
|
|
|
|
if (SrcType->isIntegralOrEnumerationType() ||
|
|
|
|
SrcType->isAnyPointerType() ||
|
|
|
|
SrcType->isMemberPointerType() ||
|
|
|
|
SrcType->isBlockPointerType()) {
|
|
|
|
Result = TC_Success;
|
|
|
|
}
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2010-07-09 04:27:32 +08:00
|
|
|
bool destIsPtr = DestType->isAnyPointerType() ||
|
|
|
|
DestType->isBlockPointerType();
|
|
|
|
bool srcIsPtr = SrcType->isAnyPointerType() ||
|
|
|
|
SrcType->isBlockPointerType();
|
2009-07-25 23:41:38 +08:00
|
|
|
if (!destIsPtr && !srcIsPtr) {
|
|
|
|
// Except for std::nullptr_t->integer and lvalue->reference, which are
|
|
|
|
// handled above, at least one of the two arguments must be a pointer.
|
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2010-06-16 08:35:25 +08:00
|
|
|
if (DestType->isIntegralType(Self.Context)) {
|
2009-07-25 23:41:38 +08:00
|
|
|
assert(srcIsPtr && "One type must be a pointer");
|
|
|
|
// C++ 5.2.10p4: A pointer can be explicitly converted to any integral
|
2011-05-12 06:13:54 +08:00
|
|
|
// type large enough to hold it; except in Microsoft mode, where the
|
2013-06-06 17:16:36 +08:00
|
|
|
// integral type size doesn't matter (except we don't allow bool).
|
|
|
|
bool MicrosoftException = Self.getLangOpts().MicrosoftExt &&
|
|
|
|
!DestType->isBooleanType();
|
2011-05-12 06:13:54 +08:00
|
|
|
if ((Self.Context.getTypeSize(SrcType) >
|
|
|
|
Self.Context.getTypeSize(DestType)) &&
|
2013-06-06 17:16:36 +08:00
|
|
|
!MicrosoftException) {
|
2009-07-25 23:41:38 +08:00
|
|
|
msg = diag::err_bad_reinterpret_cast_small_int;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_PointerToIntegral;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2010-06-16 08:17:44 +08:00
|
|
|
if (SrcType->isIntegralOrEnumerationType()) {
|
2009-07-25 23:41:38 +08:00
|
|
|
assert(destIsPtr && "One type must be a pointer");
|
2012-10-17 02:53:14 +08:00
|
|
|
checkIntToPointerCast(CStyle, OpRange.getBegin(), SrcExpr.get(), DestType,
|
|
|
|
Self);
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.10p5: A value of integral or enumeration type can be explicitly
|
|
|
|
// converted to a pointer.
|
2010-11-13 09:35:44 +08:00
|
|
|
// C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not
|
|
|
|
// necessarily converted to a null pointer value.]
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_IntegralToPointer;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
if (!destIsPtr || !srcIsPtr) {
|
|
|
|
// With the valid non-pointer conversions out of the way, we can be even
|
|
|
|
// more stringent.
|
|
|
|
return TC_NotApplicable;
|
2008-11-06 23:59:35 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
|
|
|
|
// The C-style cast operator can.
|
2011-06-16 07:02:42 +08:00
|
|
|
if (CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
|
|
|
|
/*CheckObjCLifetime=*/CStyle)) {
|
Implement appropriate semantics for C++ casting and conversion when
dealing with address-space- and GC-qualified pointers. Previously,
these qualifiers were being treated just like cvr-qualifiers (in some
cases) or were completely ignored, leading to uneven behavior. For
example, const_cast would allow conversion between pointers to
different address spaces.
The new semantics are fairly simple: reinterpret_cast can be used to
explicitly cast between pointers to different address spaces
(including adding/removing addresss spaces), while
static_cast/dynamic_cast/const_cast do not tolerate any changes in the
address space. C-style casts can add/remove/change address spaces
through the reinterpret_cast mechanism. Other non-CVR qualifiers
(e.g., Objective-C GC qualifiers) work similarly.
As part of this change, I tweaked the "casts away constness"
diagnostic to use the term "casts away qualifiers". The term
"constness" actually comes from the C++ standard, despite the fact
that removing "volatile" also falls under that category. In Clang, we
also have restrict, address spaces, ObjC GC attributes, etc., so the
more general "qualifiers" is clearer.
llvm-svn: 129583
2011-04-16 01:59:54 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_qualifiers_away;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Failed;
|
|
|
|
}
|
2010-07-09 04:27:32 +08:00
|
|
|
|
|
|
|
// Cannot convert between block pointers and Objective-C object pointers.
|
|
|
|
if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) ||
|
|
|
|
(DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType()))
|
|
|
|
return TC_NotApplicable;
|
|
|
|
|
2011-09-09 13:25:32 +08:00
|
|
|
if (IsLValueCast) {
|
|
|
|
Kind = CK_LValueBitCast;
|
|
|
|
} else if (DestType->isObjCObjectPointerType()) {
|
2011-09-10 09:16:55 +08:00
|
|
|
Kind = Self.PrepareCastToObjCObjectPointer(SrcExpr);
|
2011-09-09 13:25:32 +08:00
|
|
|
} else if (DestType->isBlockPointerType()) {
|
|
|
|
if (!SrcType->isBlockPointerType()) {
|
|
|
|
Kind = CK_AnyPointerToBlockPointerCast;
|
|
|
|
} else {
|
|
|
|
Kind = CK_BitCast;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Kind = CK_BitCast;
|
|
|
|
}
|
|
|
|
|
2010-07-09 04:27:32 +08:00
|
|
|
// Any pointer can be cast to an Objective-C pointer type with a C-style
|
|
|
|
// cast.
|
2009-12-09 07:09:15 +08:00
|
|
|
if (CStyle && DestType->isObjCObjectPointerType()) {
|
|
|
|
return TC_Success;
|
|
|
|
}
|
2012-08-17 02:33:47 +08:00
|
|
|
if (CStyle)
|
|
|
|
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// Not casting away constness, so the only remaining check is for compatible
|
|
|
|
// pointer categories.
|
|
|
|
|
|
|
|
if (SrcType->isFunctionPointerType()) {
|
|
|
|
if (DestType->isFunctionPointerType()) {
|
|
|
|
// C++ 5.2.10p6: A pointer to a function can be explicitly converted to
|
|
|
|
// a pointer to a function of a different type.
|
|
|
|
return TC_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
// C++0x 5.2.10p8: Converting a pointer to a function into a pointer to
|
|
|
|
// an object type or vice versa is conditionally-supported.
|
|
|
|
// Compilers support it in C++03 too, though, because it's necessary for
|
|
|
|
// casting the return value of dlsym() and GetProcAddress().
|
|
|
|
// FIXME: Conditionally-supported behavior should be configurable in the
|
|
|
|
// TargetInfo or similar.
|
2011-10-19 04:49:44 +08:00
|
|
|
Self.Diag(OpRange.getBegin(),
|
2013-01-02 19:42:31 +08:00
|
|
|
Self.getLangOpts().CPlusPlus11 ?
|
2011-10-19 04:49:44 +08:00
|
|
|
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
|
|
|
|
<< OpRange;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DestType->isFunctionPointerType()) {
|
|
|
|
// See above.
|
2011-10-19 04:49:44 +08:00
|
|
|
Self.Diag(OpRange.getBegin(),
|
2013-01-02 19:42:31 +08:00
|
|
|
Self.getLangOpts().CPlusPlus11 ?
|
2011-10-19 04:49:44 +08:00
|
|
|
diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj)
|
|
|
|
<< OpRange;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Success;
|
|
|
|
}
|
2010-07-09 04:27:32 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ 5.2.10p7: A pointer to an object can be explicitly converted to
|
|
|
|
// a pointer to an object of different type.
|
|
|
|
// Void pointers are not specified, but supported by every compiler out there.
|
|
|
|
// So we finish by allowing everything that remains - it's got to be two
|
|
|
|
// object pointers.
|
|
|
|
return TC_Success;
|
2011-02-15 02:34:10 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2012-02-13 02:41:05 +08:00
|
|
|
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
|
|
|
|
bool ListInitialization) {
|
2011-10-07 07:25:11 +08:00
|
|
|
// Handle placeholders.
|
|
|
|
if (isPlaceholder()) {
|
|
|
|
// C-style casts can resolve __unknown_any types.
|
|
|
|
if (claimPlaceholder(BuiltinType::UnknownAny)) {
|
|
|
|
SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType,
|
|
|
|
SrcExpr.get(), Kind,
|
|
|
|
ValueKind, BasePath);
|
|
|
|
return;
|
|
|
|
}
|
2011-10-05 15:41:44 +08:00
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
checkNonOverloadPlaceholders();
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2011-10-18 01:42:19 +08:00
|
|
|
}
|
2011-10-07 07:25:11 +08:00
|
|
|
|
|
|
|
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
|
2009-07-25 23:41:38 +08:00
|
|
|
// This test is outside everything else because it's the only case where
|
|
|
|
// a non-lvalue-reference target type does not lead to decay.
|
2011-10-05 15:41:44 +08:00
|
|
|
if (DestType->isVoidType()) {
|
2011-04-11 03:13:55 +08:00
|
|
|
Kind = CK_ToVoid;
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
if (claimPlaceholder(BuiltinType::Overload)) {
|
2011-10-12 07:14:30 +08:00
|
|
|
Self.ResolveAndFixSingleFunctionTemplateSpecialization(
|
|
|
|
SrcExpr, /* Decay Function to ptr */ false,
|
2011-10-05 15:41:44 +08:00
|
|
|
/* Complain */ true, DestRange, DestType,
|
2011-03-12 09:48:56 +08:00
|
|
|
diag::err_bad_cstyle_cast_overload);
|
2011-10-05 15:41:44 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2011-02-20 05:32:49 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.IgnoredValueConversions(SrcExpr.get());
|
2011-10-05 15:41:44 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-11-30 10:05:44 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// If the type is dependent, we won't do any other semantic analysis now.
|
2013-09-19 09:12:33 +08:00
|
|
|
if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
|
|
|
|
SrcExpr.get()->isValueDependent()) {
|
2011-10-05 15:41:44 +08:00
|
|
|
assert(Kind == CK_Dependent);
|
|
|
|
return;
|
2010-11-15 17:13:47 +08:00
|
|
|
}
|
2011-07-09 04:20:17 +08:00
|
|
|
|
2011-10-12 07:14:30 +08:00
|
|
|
if (ValueKind == VK_RValue && !DestType->isRecordType() &&
|
|
|
|
!isPlaceholder(BuiltinType::Overload)) {
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
|
2011-10-05 15:41:44 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2011-04-09 02:41:53 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2011-04-11 03:13:55 +08:00
|
|
|
// AltiVec vector initialization with a single literal.
|
2011-10-05 15:41:44 +08:00
|
|
|
if (const VectorType *vecTy = DestType->getAs<VectorType>())
|
2011-04-11 03:13:55 +08:00
|
|
|
if (vecTy->getVectorKind() == VectorType::AltiVecVector
|
2011-10-05 15:41:44 +08:00
|
|
|
&& (SrcExpr.get()->getType()->isIntegerType()
|
|
|
|
|| SrcExpr.get()->getType()->isFloatingType())) {
|
2011-04-11 03:13:55 +08:00
|
|
|
Kind = CK_VectorSplat;
|
2011-10-05 15:41:44 +08:00
|
|
|
return;
|
2011-04-11 03:13:55 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
// C++ [expr.cast]p5: The conversions performed by
|
|
|
|
// - a const_cast,
|
|
|
|
// - a static_cast,
|
|
|
|
// - a static_cast followed by a const_cast,
|
|
|
|
// - a reinterpret_cast, or
|
|
|
|
// - a reinterpret_cast followed by a const_cast,
|
|
|
|
// can be performed using the cast notation of explicit type conversion.
|
|
|
|
// [...] If a conversion can be interpreted in more than one of the ways
|
|
|
|
// listed above, the interpretation that appears first in the list is used,
|
|
|
|
// even if a cast resulting from that interpretation is ill-formed.
|
|
|
|
// In plain language, this means trying a const_cast ...
|
|
|
|
unsigned msg = diag::err_bad_cxx_cast_generic;
|
2013-06-15 06:27:52 +08:00
|
|
|
TryCastResult tcr = TryConstCast(Self, SrcExpr, DestType,
|
2011-10-05 15:41:44 +08:00
|
|
|
/*CStyle*/true, msg);
|
2013-06-15 06:27:52 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2009-10-20 02:14:28 +08:00
|
|
|
if (tcr == TC_Success)
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_NoOp;
|
2009-10-20 02:14:28 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
Sema::CheckedConversionKind CCK
|
|
|
|
= FunctionalStyle? Sema::CCK_FunctionalCast
|
|
|
|
: Sema::CCK_CStyleCast;
|
2009-07-25 23:41:38 +08:00
|
|
|
if (tcr == TC_NotApplicable) {
|
|
|
|
// ... or if that is not possible, a static_cast, ignoring const, ...
|
2011-10-05 15:41:44 +08:00
|
|
|
tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
|
2012-02-13 02:41:05 +08:00
|
|
|
msg, Kind, BasePath, ListInitialization);
|
2011-10-05 15:41:44 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
if (tcr == TC_NotApplicable) {
|
|
|
|
// ... and finally a reinterpret_cast, ignoring const.
|
2011-10-05 15:41:44 +08:00
|
|
|
tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/true,
|
|
|
|
OpRange, msg, Kind);
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (Self.getLangOpts().ObjCAutoRefCount && tcr == TC_Success)
|
2011-10-05 15:41:44 +08:00
|
|
|
checkObjCARCConversion(CCK);
|
2011-06-16 07:02:42 +08:00
|
|
|
|
2010-11-09 08:19:31 +08:00
|
|
|
if (tcr != TC_Success && msg != 0) {
|
2011-10-05 15:41:44 +08:00
|
|
|
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
|
2010-11-08 11:40:48 +08:00
|
|
|
DeclAccessPair Found;
|
2011-10-05 15:41:44 +08:00
|
|
|
FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
|
|
|
|
DestType,
|
|
|
|
/*Complain*/ true,
|
2010-11-08 11:40:48 +08:00
|
|
|
Found);
|
2014-04-14 00:08:24 +08:00
|
|
|
if (Fn) {
|
|
|
|
// If DestType is a function type (not to be confused with the function
|
|
|
|
// pointer type), it will be possible to resolve the function address,
|
|
|
|
// but the type cast should be considered as failure.
|
|
|
|
OverloadExpr *OE = OverloadExpr::find(SrcExpr.get()).Expression;
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bad_cstyle_cast_overload)
|
|
|
|
<< OE->getName() << DestType << OpRange
|
|
|
|
<< OE->getQualifierLoc().getSourceRange();
|
|
|
|
Self.NoteAllOverloadCandidates(SrcExpr.get());
|
|
|
|
}
|
2010-11-09 08:19:31 +08:00
|
|
|
} else {
|
2011-10-05 15:41:44 +08:00
|
|
|
diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
|
2012-02-14 03:55:43 +08:00
|
|
|
OpRange, SrcExpr.get(), DestType, ListInitialization);
|
2010-11-08 11:40:48 +08:00
|
|
|
}
|
2011-10-05 15:41:44 +08:00
|
|
|
} else if (Kind == CK_BitCast) {
|
|
|
|
checkCastAlign();
|
2010-11-08 11:40:48 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
// Clear out SrcExpr if there was a fatal error.
|
2011-04-09 02:41:53 +08:00
|
|
|
if (tcr != TC_Success)
|
2011-10-05 15:41:44 +08:00
|
|
|
SrcExpr = ExprError();
|
|
|
|
}
|
|
|
|
|
2012-08-18 01:22:34 +08:00
|
|
|
/// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a
|
|
|
|
/// non-matching type. Such as enum function call to int, int call to
|
|
|
|
/// pointer; etc. Cast to 'void' is an exception.
|
|
|
|
static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr,
|
|
|
|
QualType DestType) {
|
2014-06-16 07:30:39 +08:00
|
|
|
if (Self.Diags.isIgnored(diag::warn_bad_function_cast,
|
|
|
|
SrcExpr.get()->getExprLoc()))
|
2012-08-18 01:22:34 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (!isa<CallExpr>(SrcExpr.get()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
|
|
|
if (DestType.getUnqualifiedType()->isVoidType())
|
|
|
|
return;
|
|
|
|
if ((SrcType->isAnyPointerType() || SrcType->isBlockPointerType())
|
|
|
|
&& (DestType->isAnyPointerType() || DestType->isBlockPointerType()))
|
|
|
|
return;
|
|
|
|
if (SrcType->isIntegerType() && DestType->isIntegerType() &&
|
|
|
|
(SrcType->isBooleanType() == DestType->isBooleanType()) &&
|
|
|
|
(SrcType->isEnumeralType() == DestType->isEnumeralType()))
|
|
|
|
return;
|
|
|
|
if (SrcType->isRealFloatingType() && DestType->isRealFloatingType())
|
|
|
|
return;
|
|
|
|
if (SrcType->isEnumeralType() && DestType->isEnumeralType())
|
|
|
|
return;
|
|
|
|
if (SrcType->isComplexType() && DestType->isComplexType())
|
|
|
|
return;
|
|
|
|
if (SrcType->isComplexIntegerType() && DestType->isComplexIntegerType())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Self.Diag(SrcExpr.get()->getExprLoc(),
|
|
|
|
diag::warn_bad_function_cast)
|
|
|
|
<< SrcType << DestType << SrcExpr.get()->getSourceRange();
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
/// Check the semantics of a C-style cast operation, in C.
|
|
|
|
void CastOperation::CheckCStyleCast() {
|
2012-03-11 15:00:24 +08:00
|
|
|
assert(!Self.getLangOpts().CPlusPlus);
|
2011-10-07 07:25:11 +08:00
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
// C-style casts can resolve __unknown_any types.
|
|
|
|
if (claimPlaceholder(BuiltinType::UnknownAny)) {
|
|
|
|
SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType,
|
|
|
|
SrcExpr.get(), Kind,
|
|
|
|
ValueKind, BasePath);
|
|
|
|
return;
|
|
|
|
}
|
2011-10-07 07:25:11 +08:00
|
|
|
|
|
|
|
// C99 6.5.4p2: the cast type needs to be void or scalar and the expression
|
|
|
|
// type needs to be scalar.
|
|
|
|
if (DestType->isVoidType()) {
|
|
|
|
// We don't necessarily do lvalue-to-rvalue conversions on this.
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.IgnoredValueConversions(SrcExpr.get());
|
2011-10-07 07:25:11 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Cast to void allows any expr type.
|
|
|
|
Kind = CK_ToVoid;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get());
|
2011-10-07 07:25:11 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
2012-01-17 01:27:18 +08:00
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
assert(!SrcType->isPlaceholderType());
|
2011-10-07 07:25:11 +08:00
|
|
|
|
2014-01-14 20:47:29 +08:00
|
|
|
// OpenCL v1 s6.5: Casting a pointer to address space A to a pointer to
|
|
|
|
// address space B is illegal.
|
|
|
|
if (Self.getLangOpts().OpenCL && DestType->isPointerType() &&
|
|
|
|
SrcType->isPointerType()) {
|
2014-11-26 23:36:41 +08:00
|
|
|
const PointerType *DestPtr = DestType->getAs<PointerType>();
|
|
|
|
if (!DestPtr->isAddressSpaceOverlapping(*SrcType->getAs<PointerType>())) {
|
2014-01-14 20:47:29 +08:00
|
|
|
Self.Diag(OpRange.getBegin(),
|
|
|
|
diag::err_typecheck_incompatible_address_space)
|
|
|
|
<< SrcType << DestType << Sema::AA_Casting
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
|
|
|
|
diag::err_typecheck_cast_to_incomplete)) {
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!DestType->isScalarType() && !DestType->isVectorType()) {
|
|
|
|
const RecordType *DestRecordTy = DestType->getAs<RecordType>();
|
|
|
|
|
|
|
|
if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){
|
|
|
|
// GCC struct/union extension: allow cast to self.
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar)
|
|
|
|
<< DestType << SrcExpr.get()->getSourceRange();
|
|
|
|
Kind = CK_NoOp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// GCC's cast to union extension.
|
|
|
|
if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) {
|
|
|
|
RecordDecl *RD = DestRecordTy->getDecl();
|
|
|
|
RecordDecl::field_iterator Field, FieldEnd;
|
|
|
|
for (Field = RD->field_begin(), FieldEnd = RD->field_end();
|
|
|
|
Field != FieldEnd; ++Field) {
|
|
|
|
if (Self.Context.hasSameUnqualifiedType(Field->getType(), SrcType) &&
|
|
|
|
!Field->isUnnamedBitfield()) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union)
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (Field == FieldEnd) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type)
|
|
|
|
<< SrcType << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Kind = CK_ToUnion;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reject any other conversions to non-scalar types.
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_typecheck_cond_expect_scalar)
|
|
|
|
<< DestType << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The type we're casting to is known to be a scalar or vector.
|
|
|
|
|
|
|
|
// Require the operand to be a scalar or vector.
|
|
|
|
if (!SrcType->isScalarType() && !SrcType->isVectorType()) {
|
|
|
|
Self.Diag(SrcExpr.get()->getExprLoc(),
|
|
|
|
diag::err_typecheck_expect_scalar_operand)
|
|
|
|
<< SrcType << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DestType->isExtVectorType()) {
|
2014-05-29 18:55:11 +08:00
|
|
|
SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.get(), Kind);
|
2011-10-07 07:25:11 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) {
|
|
|
|
if (DestVecTy->getVectorKind() == VectorType::AltiVecVector &&
|
|
|
|
(SrcType->isIntegerType() || SrcType->isFloatingType())) {
|
|
|
|
Kind = CK_VectorSplat;
|
|
|
|
} else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) {
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (SrcType->isVectorType()) {
|
|
|
|
if (Self.CheckVectorCast(OpRange, SrcType, DestType, Kind))
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The source and target types are both scalars, i.e.
|
|
|
|
// - arithmetic types (fundamental, enum, and complex)
|
|
|
|
// - all kinds of pointers
|
|
|
|
// Note that member pointers were filtered out with C++, above.
|
|
|
|
|
|
|
|
if (isa<ObjCSelectorExpr>(SrcExpr.get())) {
|
|
|
|
Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_selector_expr);
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If either type is a pointer, the other type has to be either an
|
|
|
|
// integer or a pointer.
|
|
|
|
if (!DestType->isArithmeticType()) {
|
|
|
|
if (!SrcType->isIntegralType(Self.Context) && SrcType->isArithmeticType()) {
|
|
|
|
Self.Diag(SrcExpr.get()->getExprLoc(),
|
|
|
|
diag::err_cast_pointer_from_non_pointer_int)
|
|
|
|
<< SrcType << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
2012-10-17 02:53:14 +08:00
|
|
|
checkIntToPointerCast(/* CStyle */ true, OpRange.getBegin(), SrcExpr.get(),
|
|
|
|
DestType, Self);
|
2011-10-07 07:25:11 +08:00
|
|
|
} else if (!SrcType->isArithmeticType()) {
|
|
|
|
if (!DestType->isIntegralType(Self.Context) &&
|
|
|
|
DestType->isArithmeticType()) {
|
|
|
|
Self.Diag(SrcExpr.get()->getLocStart(),
|
|
|
|
diag::err_cast_pointer_to_non_pointer_int)
|
2011-11-15 19:25:38 +08:00
|
|
|
<< DestType << SrcExpr.get()->getSourceRange();
|
2011-10-07 07:25:11 +08:00
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-23 19:56:20 +08:00
|
|
|
if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) {
|
|
|
|
if (DestType->isHalfType()) {
|
|
|
|
Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
|
|
|
|
<< DestType << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
// ARC imposes extra restrictions on casts.
|
2012-03-11 15:00:24 +08:00
|
|
|
if (Self.getLangOpts().ObjCAutoRefCount) {
|
2011-10-07 07:25:11 +08:00
|
|
|
checkObjCARCConversion(Sema::CCK_CStyleCast);
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (const PointerType *CastPtr = DestType->getAs<PointerType>()) {
|
|
|
|
if (const PointerType *ExprPtr = SrcType->getAs<PointerType>()) {
|
|
|
|
Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers();
|
|
|
|
Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers();
|
|
|
|
if (CastPtr->getPointeeType()->isObjCLifetimeType() &&
|
|
|
|
ExprPtr->getPointeeType()->isObjCLifetimeType() &&
|
|
|
|
!CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) {
|
|
|
|
Self.Diag(SrcExpr.get()->getLocStart(),
|
|
|
|
diag::err_typecheck_incompatible_ownership)
|
|
|
|
<< SrcType << DestType << Sema::AA_Casting
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) {
|
|
|
|
Self.Diag(SrcExpr.get()->getLocStart(),
|
|
|
|
diag::err_arc_convesion_of_weak_unavailable)
|
|
|
|
<< 1 << SrcType << DestType << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2013-11-21 08:39:36 +08:00
|
|
|
|
2012-08-17 02:33:47 +08:00
|
|
|
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
|
2012-08-18 01:22:34 +08:00
|
|
|
DiagnoseBadFunctionCast(Self, SrcExpr, DestType);
|
2011-10-07 07:25:11 +08:00
|
|
|
Kind = Self.PrepareScalarCast(SrcExpr, DestType);
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Kind == CK_BitCast)
|
|
|
|
checkCastAlign();
|
2014-11-22 05:03:10 +08:00
|
|
|
|
|
|
|
// -Wcast-qual
|
|
|
|
QualType TheOffendingSrcType, TheOffendingDestType;
|
|
|
|
Qualifiers CastAwayQualifiers;
|
|
|
|
if (SrcType->isAnyPointerType() && DestType->isAnyPointerType() &&
|
|
|
|
CastsAwayConstness(Self, SrcType, DestType, true, false,
|
|
|
|
&TheOffendingSrcType, &TheOffendingDestType,
|
|
|
|
&CastAwayQualifiers)) {
|
|
|
|
int qualifiers = -1;
|
|
|
|
if (CastAwayQualifiers.hasConst() && CastAwayQualifiers.hasVolatile()) {
|
|
|
|
qualifiers = 0;
|
|
|
|
} else if (CastAwayQualifiers.hasConst()) {
|
|
|
|
qualifiers = 1;
|
|
|
|
} else if (CastAwayQualifiers.hasVolatile()) {
|
|
|
|
qualifiers = 2;
|
|
|
|
}
|
|
|
|
// This is a variant of int **x; const int **y = (const int **)x;
|
|
|
|
if (qualifiers == -1)
|
|
|
|
Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual2) <<
|
|
|
|
SrcType << DestType;
|
|
|
|
else
|
|
|
|
Self.Diag(SrcExpr.get()->getLocStart(), diag::warn_cast_qual) <<
|
|
|
|
TheOffendingSrcType << TheOffendingDestType << qualifiers;
|
|
|
|
}
|
2011-10-07 07:25:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
|
|
|
|
TypeSourceInfo *CastTypeInfo,
|
|
|
|
SourceLocation RPLoc,
|
|
|
|
Expr *CastExpr) {
|
2011-10-05 15:41:44 +08:00
|
|
|
CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
|
|
|
|
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
|
|
|
|
Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd());
|
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus) {
|
2012-02-13 02:41:05 +08:00
|
|
|
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false,
|
|
|
|
isa<InitListExpr>(CastExpr));
|
2011-10-07 07:25:11 +08:00
|
|
|
} else {
|
|
|
|
Op.CheckCStyleCast();
|
|
|
|
}
|
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
if (Op.SrcExpr.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType,
|
2014-05-29 18:55:11 +08:00
|
|
|
Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
2011-10-18 02:40:02 +08:00
|
|
|
&Op.BasePath, CastTypeInfo, LPLoc, RPLoc));
|
2011-10-05 15:41:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
|
|
|
|
SourceLocation LPLoc,
|
|
|
|
Expr *CastExpr,
|
|
|
|
SourceLocation RPLoc) {
|
2012-02-14 03:55:43 +08:00
|
|
|
assert(LPLoc.isValid() && "List-initialization shouldn't get here.");
|
2011-10-05 15:41:44 +08:00
|
|
|
CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
|
|
|
|
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
|
|
|
|
Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
|
|
|
|
|
2012-02-14 03:55:43 +08:00
|
|
|
Op.CheckCXXCStyleCast(/*FunctionalStyle=*/true, /*ListInit=*/false);
|
2011-10-05 15:41:44 +08:00
|
|
|
if (Op.SrcExpr.isInvalid())
|
2011-04-09 02:41:53 +08:00
|
|
|
return ExprError();
|
2015-09-04 18:17:10 +08:00
|
|
|
|
|
|
|
auto *SubExpr = Op.SrcExpr.get();
|
|
|
|
if (auto *BindExpr = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
|
|
|
|
SubExpr = BindExpr->getSubExpr();
|
|
|
|
if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr))
|
2013-09-07 13:49:53 +08:00
|
|
|
ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
|
2011-04-09 02:41:53 +08:00
|
|
|
|
2011-10-18 02:40:02 +08:00
|
|
|
return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
|
2013-08-16 06:02:56 +08:00
|
|
|
Op.ValueKind, CastTypeInfo, Op.Kind,
|
2014-05-29 18:55:11 +08:00
|
|
|
Op.SrcExpr.get(), &Op.BasePath, LPLoc, RPLoc));
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|