2011-10-12 01:38:55 +08:00
|
|
|
//===--- SemaCast.cpp - Semantic Analysis for Casts -----------------------===//
|
2008-11-06 05:50:06 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2008-11-06 05:50:06 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
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
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2021-03-25 07:03:13 +08:00
|
|
|
#include "clang/AST/ASTStructuralEquivalence.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"
|
2016-05-11 05:00:03 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/Initialization.h"
|
2021-03-25 07:03:13 +08:00
|
|
|
#include "clang/Sema/SemaInternal.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.
|
2018-07-11 07:04:35 +08:00
|
|
|
TC_Extension, ///< The cast method is appropriate and accepted as a
|
|
|
|
///< language extension.
|
2009-07-25 23:41:38 +08:00
|
|
|
TC_Failed ///< The cast method is appropriate, but failed. A
|
|
|
|
///< diagnostic has been emitted.
|
|
|
|
};
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
static bool isValidCast(TryCastResult TCR) {
|
|
|
|
return TCR == TC_Success || TCR == TC_Extension;
|
|
|
|
}
|
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
enum CastType {
|
|
|
|
CT_Const, ///< const_cast
|
|
|
|
CT_Static, ///< static_cast
|
|
|
|
CT_Reinterpret, ///< reinterpret_cast
|
|
|
|
CT_Dynamic, ///< dynamic_cast
|
|
|
|
CT_CStyle, ///< (Type)expr
|
2020-05-18 18:02:01 +08:00
|
|
|
CT_Functional, ///< Type(expr)
|
|
|
|
CT_Addrspace ///< addrspace_cast
|
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();
|
2019-07-03 02:28:13 +08:00
|
|
|
void CheckBuiltinBitCast();
|
2020-05-18 18:02:01 +08:00
|
|
|
void CheckAddrspaceCast();
|
2011-10-07 07:25:11 +08:00
|
|
|
|
[Sema] Mark implicitly-inserted ICE's as being part of explicit cast (PR38166)
Summary:
As discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=38166 | PR38166 ]], we need to be able to distinqush whether the cast
we are visiting is actually a cast, or part of an `ExplicitCast`.
There are at least four ways to get there:
1. Introduce a new `CastKind`, and use it instead of `IntegralCast` if we are in `ExplicitCast`.
Would work, but does not scale - what if we will need more of these cast kinds?
2. Introduce a flag in `CastExprBits`, whether this cast is part of `ExplicitCast` or not.
Would work, but it isn't immediately clear where it needs to be set.
2. Fix `ScalarExprEmitter::VisitCastExpr()` to visit these `NoOp` casts.
As pointed out by @rsmith, CodeGenFunction::EmitMaterializeTemporaryExpr calls
skipRValueSubobjectAdjustments, which steps over the CK_NoOp cast`,
which explains why we currently don't visit those.
This is probably impossible, as @efriedma points out, that is intentional as per `[class.temporary]` in the standard
3. And the simplest one, just record which NoOp casts we skip.
It just kinda works as-is afterwards.
But, the approach with a flag is the least intrusive one, and is probably the best one overall.
Reviewers: rsmith, rjmccall, majnemer, efriedma
Reviewed By: rsmith
Subscribers: cfe-commits, aaron.ballman, vsk, llvm-commits, rsmith
Differential Revision: https://reviews.llvm.org/D49508
llvm-svn: 337815
2018-07-24 16:16:50 +08:00
|
|
|
void updatePartOfExplicitCastFlags(CastExpr *CE) {
|
|
|
|
// Walk down from the CE to the OrigSrcExpr, and mark all immediate
|
|
|
|
// ImplicitCastExpr's as being part of ExplicitCastExpr. The original CE
|
|
|
|
// (which is a ExplicitCastExpr), and the OrigSrcExpr are not touched.
|
[AST] Sink 'part of explicit cast' down into ImplicitCastExpr
Summary:
As discussed in IRC with @rsmith, it is slightly not good to keep that in the `CastExpr` itself:
Given the explicit cast, which is represented in AST as an `ExplicitCastExpr` + `ImplicitCastExpr`'s,
only the `ImplicitCastExpr`'s will be marked as `PartOfExplicitCast`, but not the `ExplicitCastExpr` itself.
Thus, it is only ever `true` for `ImplicitCastExpr`'s, so we don't need to write/read/dump it for `ExplicitCastExpr`'s.
We don't need to worry that we write the `PartOfExplicitCast` in PCH after `CastExpr::path_iterator`,
since the `ExprImplicitCastAbbrev` is only used when the `NumBaseSpecs == 0`, i.e. there is no 'path'.
Reviewers: rsmith, rjmccall, erichkeane, aaron.ballman
Reviewed By: rsmith, erichkeane
Subscribers: vsk, cfe-commits, rsmith
Tags: #clang
Differential Revision: https://reviews.llvm.org/D49838
llvm-svn: 338108
2018-07-27 15:27:14 +08:00
|
|
|
for (; auto *ICE = dyn_cast<ImplicitCastExpr>(CE->getSubExpr()); CE = ICE)
|
|
|
|
ICE->setIsPartOfExplicitCast(true);
|
[Sema] Mark implicitly-inserted ICE's as being part of explicit cast (PR38166)
Summary:
As discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=38166 | PR38166 ]], we need to be able to distinqush whether the cast
we are visiting is actually a cast, or part of an `ExplicitCast`.
There are at least four ways to get there:
1. Introduce a new `CastKind`, and use it instead of `IntegralCast` if we are in `ExplicitCast`.
Would work, but does not scale - what if we will need more of these cast kinds?
2. Introduce a flag in `CastExprBits`, whether this cast is part of `ExplicitCast` or not.
Would work, but it isn't immediately clear where it needs to be set.
2. Fix `ScalarExprEmitter::VisitCastExpr()` to visit these `NoOp` casts.
As pointed out by @rsmith, CodeGenFunction::EmitMaterializeTemporaryExpr calls
skipRValueSubobjectAdjustments, which steps over the CK_NoOp cast`,
which explains why we currently don't visit those.
This is probably impossible, as @efriedma points out, that is intentional as per `[class.temporary]` in the standard
3. And the simplest one, just record which NoOp casts we skip.
It just kinda works as-is afterwards.
But, the approach with a flag is the least intrusive one, and is probably the best one overall.
Reviewers: rsmith, rjmccall, majnemer, efriedma
Reviewed By: rsmith
Subscribers: cfe-commits, aaron.ballman, vsk, llvm-commits, rsmith
Differential Revision: https://reviews.llvm.org/D49508
llvm-svn: 337815
2018-07-24 16:16:50 +08:00
|
|
|
}
|
|
|
|
|
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) {
|
2020-09-12 22:54:14 +08:00
|
|
|
castExpr = ImplicitCastExpr::Create(
|
|
|
|
Self.Context, Self.Context.ARCUnbridgedCastTy, CK_Dependent,
|
|
|
|
castExpr, nullptr, castExpr->getValueKind(),
|
|
|
|
Self.CurFPFeatureOverrides());
|
2011-10-18 02:40:02 +08:00
|
|
|
}
|
[Sema] Mark implicitly-inserted ICE's as being part of explicit cast (PR38166)
Summary:
As discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=38166 | PR38166 ]], we need to be able to distinqush whether the cast
we are visiting is actually a cast, or part of an `ExplicitCast`.
There are at least four ways to get there:
1. Introduce a new `CastKind`, and use it instead of `IntegralCast` if we are in `ExplicitCast`.
Would work, but does not scale - what if we will need more of these cast kinds?
2. Introduce a flag in `CastExprBits`, whether this cast is part of `ExplicitCast` or not.
Would work, but it isn't immediately clear where it needs to be set.
2. Fix `ScalarExprEmitter::VisitCastExpr()` to visit these `NoOp` casts.
As pointed out by @rsmith, CodeGenFunction::EmitMaterializeTemporaryExpr calls
skipRValueSubobjectAdjustments, which steps over the CK_NoOp cast`,
which explains why we currently don't visit those.
This is probably impossible, as @efriedma points out, that is intentional as per `[class.temporary]` in the standard
3. And the simplest one, just record which NoOp casts we skip.
It just kinda works as-is afterwards.
But, the approach with a flag is the least intrusive one, and is probably the best one overall.
Reviewers: rsmith, rjmccall, majnemer, efriedma
Reviewed By: rsmith
Subscribers: cfe-commits, aaron.ballman, vsk, llvm-commits, rsmith
Differential Revision: https://reviews.llvm.org/D49508
llvm-svn: 337815
2018-07-24 16:16:50 +08:00
|
|
|
updatePartOfExplicitCastFlags(castExpr);
|
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
|
|
|
|
2018-10-11 00:05:22 +08:00
|
|
|
// Language specific cast restrictions for address spaces.
|
|
|
|
void checkAddressSpaceCast(QualType SrcType, QualType DestType);
|
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
void checkCastAlign() {
|
|
|
|
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
|
|
|
|
}
|
|
|
|
|
2017-03-30 02:09:02 +08:00
|
|
|
void checkObjCConversion(Sema::CheckedConversionKind CCK) {
|
|
|
|
assert(Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers());
|
2011-10-18 02:40:02 +08:00
|
|
|
|
2011-10-05 15:41:44 +08:00
|
|
|
Expr *src = SrcExpr.get();
|
2017-03-30 02:09:02 +08:00
|
|
|
if (Self.CheckObjCConversion(OpRange, DestType, src, CCK) ==
|
|
|
|
Sema::ACR_unbridged)
|
2011-10-18 02:40:02 +08:00
|
|
|
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
|
|
|
};
|
2020-06-11 03:20:54 +08:00
|
|
|
|
|
|
|
void CheckNoDeref(Sema &S, const QualType FromType, const QualType ToType,
|
|
|
|
SourceLocation OpLoc) {
|
|
|
|
if (const auto *PtrType = dyn_cast<PointerType>(FromType)) {
|
|
|
|
if (PtrType->getPointeeType()->hasAttr(attr::NoDeref)) {
|
|
|
|
if (const auto *DestType = dyn_cast<PointerType>(ToType)) {
|
|
|
|
if (!DestType->getPointeeType()->hasAttr(attr::NoDeref)) {
|
|
|
|
S.Diag(OpLoc, diag::warn_noderef_to_dereferenceable_pointer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CheckNoDerefRAII {
|
|
|
|
CheckNoDerefRAII(CastOperation &Op) : Op(Op) {}
|
|
|
|
~CheckNoDerefRAII() {
|
|
|
|
if (!Op.SrcExpr.isInvalid())
|
|
|
|
CheckNoDeref(Op.Self, Op.SrcExpr.get()->getType(), Op.ResultType,
|
|
|
|
Op.OpRange.getBegin());
|
|
|
|
}
|
|
|
|
|
|
|
|
CastOperation &Op;
|
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2008-11-08 21:00:26 +08:00
|
|
|
|
2017-07-04 01:59:22 +08:00
|
|
|
static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr,
|
|
|
|
QualType DestType);
|
|
|
|
|
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,
|
2018-07-31 03:24:48 +08:00
|
|
|
QualType DestType,
|
2011-06-16 07:02:42 +08:00
|
|
|
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,
|
2018-07-31 03:24:48 +08:00
|
|
|
QualType DestType,
|
2011-06-16 07:02:42 +08:00
|
|
|
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,
|
2020-05-18 18:02:01 +08:00
|
|
|
SourceRange OpRange, unsigned &msg,
|
2010-08-25 19:45:40 +08:00
|
|
|
CastKind &Kind);
|
2020-05-18 18:02:01 +08:00
|
|
|
static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
|
|
|
QualType DestType, bool CStyle,
|
|
|
|
unsigned &msg, CastKind &Kind);
|
2008-11-08 21:00:26 +08:00
|
|
|
|
2020-05-18 18:02:01 +08:00
|
|
|
/// ActOnCXXNamedCast - Parse
|
|
|
|
/// {dynamic,static,reinterpret,const,addrspace}_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
|
|
|
|
2020-05-18 18:02:01 +08:00
|
|
|
case tok::kw_addrspace_cast:
|
|
|
|
if (!TypeDependent) {
|
|
|
|
Op.CheckAddrspaceCast();
|
|
|
|
if (Op.SrcExpr.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
return Op.complete(CXXAddrspaceCastExpr::Create(
|
|
|
|
Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
|
|
|
DestTInfo, OpLoc, Parens.getEnd(), AngleBrackets));
|
|
|
|
|
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();
|
2016-08-12 16:04:13 +08:00
|
|
|
DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
|
2011-04-09 02:41:53 +08:00
|
|
|
}
|
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: {
|
2019-07-18 18:02:35 +08:00
|
|
|
// dynamic_cast is not supported in C++ for OpenCL.
|
[OpenCL] Restrict various keywords in OpenCL C++ mode
Restrict the following keywords in the OpenCL C++ language mode,
according to Sections 2.2 & 2.9 of the OpenCL C++ 1.0 Specification.
- dynamic_cast
- typeid
- register (already restricted in OpenCL C, update the diagnostic)
- thread_local
- exceptions (try/catch/throw)
- access qualifiers read_only, write_only, read_write
Support the `__global`, `__local`, `__constant`, `__private`, and
`__generic` keywords in OpenCL C++. Leave the unprefixed address
space qualifiers such as global available, i.e., do not mark them as
reserved keywords in OpenCL C++. libclcxx provides explicit address
space pointer classes such as `global_ptr` and `global<T>` that are
implemented using the `__`-prefixed qualifiers.
Differential Revision: https://reviews.llvm.org/D46022
llvm-svn: 331874
2018-05-09 21:16:17 +08:00
|
|
|
if (getLangOpts().OpenCLCPlusPlus) {
|
|
|
|
return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported)
|
|
|
|
<< "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();
|
2016-08-12 16:04:13 +08:00
|
|
|
DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
|
2011-04-09 02:41:53 +08:00
|
|
|
}
|
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();
|
2016-08-12 16:04:13 +08:00
|
|
|
DiscardMisalignedMemberAddress(DestType.getTypePtr(), E);
|
2011-04-09 02:41:53 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2020-09-12 22:54:14 +08:00
|
|
|
return Op.complete(CXXStaticCastExpr::Create(
|
|
|
|
Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
|
|
|
&Op.BasePath, DestTInfo, CurFPFeatureOverrides(), OpLoc,
|
|
|
|
Parens.getEnd(), AngleBrackets));
|
2009-08-08 06:21:05 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-03 02:28:13 +08:00
|
|
|
ExprResult Sema::ActOnBuiltinBitCastExpr(SourceLocation KWLoc, Declarator &D,
|
|
|
|
ExprResult Operand,
|
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
assert(!D.isInvalidType());
|
|
|
|
|
|
|
|
TypeSourceInfo *TInfo = GetTypeForDeclaratorCast(D, Operand.get()->getType());
|
|
|
|
if (D.isInvalidType())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
return BuildBuiltinBitCastExpr(KWLoc, TInfo, Operand.get(), RParenLoc);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildBuiltinBitCastExpr(SourceLocation KWLoc,
|
|
|
|
TypeSourceInfo *TSI, Expr *Operand,
|
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
CastOperation Op(*this, TSI->getType(), Operand);
|
|
|
|
Op.OpRange = SourceRange(KWLoc, RParenLoc);
|
|
|
|
TypeLoc TL = TSI->getTypeLoc();
|
|
|
|
Op.DestRange = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
|
|
|
|
|
|
|
|
if (!Operand->isTypeDependent() && !TSI->getType()->isDependentType()) {
|
|
|
|
Op.CheckBuiltinBitCast();
|
|
|
|
if (Op.SrcExpr.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
BuiltinBitCastExpr *BCE =
|
|
|
|
new (Context) BuiltinBitCastExpr(Op.ResultType, Op.ValueKind, Op.Kind,
|
|
|
|
Op.SrcExpr.get(), TSI, KWLoc, RParenLoc);
|
|
|
|
return Op.complete(BCE);
|
|
|
|
}
|
|
|
|
|
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:
|
2020-05-18 18:02:01 +08:00
|
|
|
case CT_Addrspace:
|
2011-02-15 02:34:10 +08:00
|
|
|
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;
|
2019-10-24 08:54:10 +08:00
|
|
|
howManyCandidates = OCD_AmbiguousCandidates;
|
2011-02-15 02:34:10 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case OR_Deleted:
|
|
|
|
msg = diag::err_ovl_deleted_conversion_in_cast;
|
|
|
|
howManyCandidates = OCD_ViableCandidates;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-05-03 08:44:50 +08:00
|
|
|
candidates.NoteCandidates(
|
|
|
|
PartialDiagnosticAt(range.getBegin(),
|
|
|
|
S.PDiag(msg) << CT << srcType << destType << range
|
|
|
|
<< src->getSourceRange()),
|
|
|
|
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())
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
S.Diag(DeclFrom->getLocation(), diag::note_type_incomplete) << DeclFrom;
|
2015-01-29 05:31:26 +08:00
|
|
|
auto DeclTo = RecTo->getAsCXXRecordDecl();
|
|
|
|
if (!DeclTo->isCompleteDefinition())
|
[clang] Pass the NamedDecl* instead of the DeclarationName into many diagnostics.
Background:
-----------
There are two related argument types which can be sent into a diagnostic to
display the name of an entity: DeclarationName (ak_declarationname) or
NamedDecl* (ak_nameddecl) (there is also ak_identifierinfo for
IdentifierInfo*, but we are not concerned with it here).
A DeclarationName in a diagnostic will just be streamed to the output,
which will directly result in a call to DeclarationName::print.
A NamedDecl* in a diagnostic will also ultimately result in a call to
DeclarationName::print, but with two customisation points along the way:
The first customisation point is NamedDecl::getNameForDiagnostic which is
overloaded by FunctionDecl, ClassTemplateSpecializationDecl and
VarTemplateSpecializationDecl to print the template arguments, if any.
The second customisation point is NamedDecl::printName. By default it just
streams the stored DeclarationName into the output but it can be customised
to provide a user-friendly name for an entity. It is currently overloaded by
DecompositionDecl and MSGuidDecl.
What this patch does:
---------------------
For many diagnostics a DeclarationName is used instead of the NamedDecl*.
This bypasses the two customisation points mentioned above. This patches fix
this for diagnostics in Sema.cpp, SemaCast.cpp, SemaChecking.cpp, SemaDecl.cpp,
SemaDeclAttr.cpp, SemaDecl.cpp, SemaOverload.cpp and SemaStmt.cpp.
I have only modified diagnostics where I could construct a test-case which
demonstrates that the change is appropriate (either with this patch or the next
one).
Reviewed By: erichkeane, aaron.ballman
Differential Revision: https://reviews.llvm.org/D84656
2020-07-28 06:22:21 +08:00
|
|
|
S.Diag(DeclTo->getLocation(), diag::note_type_incomplete) << DeclTo;
|
2015-01-29 05:31:26 +08:00
|
|
|
}
|
|
|
|
}
|
2011-02-15 02:34:10 +08:00
|
|
|
}
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
namespace {
|
|
|
|
/// The kind of unwrapping we did when determining whether a conversion casts
|
|
|
|
/// away constness.
|
|
|
|
enum CastAwayConstnessKind {
|
|
|
|
/// The conversion does not cast away constness.
|
|
|
|
CACK_None = 0,
|
|
|
|
/// We unwrapped similar types.
|
|
|
|
CACK_Similar = 1,
|
|
|
|
/// We unwrapped dissimilar types with similar representations (eg, a pointer
|
|
|
|
/// versus an Objective-C object pointer).
|
|
|
|
CACK_SimilarKind = 2,
|
|
|
|
/// We unwrapped representationally-unrelated types, such as a pointer versus
|
|
|
|
/// a pointer-to-member.
|
|
|
|
CACK_Incoherent = 3,
|
|
|
|
};
|
|
|
|
}
|
2017-07-04 01:59:22 +08:00
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
/// Unwrap one level of types for CastsAwayConstness.
|
|
|
|
///
|
2018-07-11 08:19:19 +08:00
|
|
|
/// Like Sema::UnwrapSimilarTypes, this removes one level of indirection from
|
|
|
|
/// both types, provided that they're both pointer-like or array-like. Unlike
|
|
|
|
/// the Sema function, doesn't care if the unwrapped pieces are related.
|
2018-07-19 04:13:36 +08:00
|
|
|
///
|
|
|
|
/// This function may remove additional levels as necessary for correctness:
|
|
|
|
/// the resulting T1 is unwrapped sufficiently that it is never an array type,
|
|
|
|
/// so that its qualifiers can be directly compared to those of T2 (which will
|
|
|
|
/// have the combined set of qualifiers from all indermediate levels of T2),
|
|
|
|
/// as (effectively) required by [expr.const.cast]p7 replacing T1's qualifiers
|
|
|
|
/// with those from T2.
|
2018-07-11 07:04:35 +08:00
|
|
|
static CastAwayConstnessKind
|
|
|
|
unwrapCastAwayConstnessLevel(ASTContext &Context, QualType &T1, QualType &T2) {
|
2018-07-19 04:13:36 +08:00
|
|
|
enum { None, Ptr, MemPtr, BlockPtr, Array };
|
2018-07-11 07:04:35 +08:00
|
|
|
auto Classify = [](QualType T) {
|
2018-07-19 04:13:36 +08:00
|
|
|
if (T->isAnyPointerType()) return Ptr;
|
|
|
|
if (T->isMemberPointerType()) return MemPtr;
|
|
|
|
if (T->isBlockPointerType()) return BlockPtr;
|
2018-07-11 08:19:19 +08:00
|
|
|
// We somewhat-arbitrarily don't look through VLA types here. This is at
|
|
|
|
// least consistent with the behavior of UnwrapSimilarTypes.
|
2018-07-19 04:13:36 +08:00
|
|
|
if (T->isConstantArrayType() || T->isIncompleteArrayType()) return Array;
|
|
|
|
return None;
|
2018-07-11 07:04:35 +08:00
|
|
|
};
|
2017-07-04 01:59:22 +08:00
|
|
|
|
2018-07-11 08:19:19 +08:00
|
|
|
auto Unwrap = [&](QualType T) {
|
|
|
|
if (auto *AT = Context.getAsArrayType(T))
|
|
|
|
return AT->getElementType();
|
|
|
|
return T->getPointeeType();
|
|
|
|
};
|
|
|
|
|
2018-07-19 04:13:36 +08:00
|
|
|
CastAwayConstnessKind Kind;
|
|
|
|
|
|
|
|
if (T2->isReferenceType()) {
|
|
|
|
// Special case: if the destination type is a reference type, unwrap it as
|
|
|
|
// the first level. (The source will have been an lvalue expression in this
|
|
|
|
// case, so there is no corresponding "reference to" in T1 to remove.) This
|
|
|
|
// simulates removing a "pointer to" from both sides.
|
|
|
|
T2 = T2->getPointeeType();
|
|
|
|
Kind = CastAwayConstnessKind::CACK_Similar;
|
|
|
|
} else if (Context.UnwrapSimilarTypes(T1, T2)) {
|
|
|
|
Kind = CastAwayConstnessKind::CACK_Similar;
|
|
|
|
} else {
|
|
|
|
// Try unwrapping mismatching levels.
|
|
|
|
int T1Class = Classify(T1);
|
|
|
|
if (T1Class == None)
|
|
|
|
return CastAwayConstnessKind::CACK_None;
|
|
|
|
|
|
|
|
int T2Class = Classify(T2);
|
|
|
|
if (T2Class == None)
|
|
|
|
return CastAwayConstnessKind::CACK_None;
|
|
|
|
|
|
|
|
T1 = Unwrap(T1);
|
|
|
|
T2 = Unwrap(T2);
|
|
|
|
Kind = T1Class == T2Class ? CastAwayConstnessKind::CACK_SimilarKind
|
|
|
|
: CastAwayConstnessKind::CACK_Incoherent;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We've unwrapped at least one level. If the resulting T1 is a (possibly
|
|
|
|
// multidimensional) array type, any qualifier on any matching layer of
|
|
|
|
// T2 is considered to correspond to T1. Decompose down to the element
|
|
|
|
// type of T1 so that we can compare properly.
|
|
|
|
while (true) {
|
|
|
|
Context.UnwrapSimilarArrayTypes(T1, T2);
|
|
|
|
|
|
|
|
if (Classify(T1) != Array)
|
|
|
|
break;
|
|
|
|
|
|
|
|
auto T2Class = Classify(T2);
|
|
|
|
if (T2Class == None)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (T2Class != Array)
|
|
|
|
Kind = CastAwayConstnessKind::CACK_Incoherent;
|
|
|
|
else if (Kind != CastAwayConstnessKind::CACK_Incoherent)
|
|
|
|
Kind = CastAwayConstnessKind::CACK_SimilarKind;
|
|
|
|
|
|
|
|
T1 = Unwrap(T1);
|
|
|
|
T2 = Unwrap(T2).withCVRQualifiers(T2.getCVRQualifiers());
|
|
|
|
}
|
|
|
|
|
|
|
|
return Kind;
|
2009-11-19 02:10:53 +08:00
|
|
|
}
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
/// Check if the pointer conversion from SrcType to DestType casts away
|
|
|
|
/// constness as defined in C++ [expr.const.cast]. 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.
|
2018-07-11 07:04:35 +08:00
|
|
|
static CastAwayConstnessKind
|
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,
|
Define weak and __weak to mean ARC-style weak references, even in MRC.
Previously, __weak was silently accepted and ignored in MRC mode.
That makes this a potentially source-breaking change that we have to
roll out cautiously. Accordingly, for the time being, actual support
for __weak references in MRC is experimental, and the compiler will
reject attempts to actually form such references. The intent is to
eventually enable the feature by default in all non-GC modes.
(It is, of course, incompatible with ObjC GC's interpretation of
__weak.)
If you like, you can enable this feature with
-Xclang -fobjc-weak
but like any -Xclang option, this option may be removed at any point,
e.g. if/when it is eventually enabled by default.
This patch also enables the use of the ARC __unsafe_unretained qualifier
in MRC. Unlike __weak, this is being enabled immediately. Since
variables are essentially __unsafe_unretained by default in MRC,
the only practical uses are (1) communication and (2) changing the
default behavior of by-value block capture.
As an implementation matter, this means that the ObjC ownership
qualifiers may appear in any ObjC language mode, and so this patch
removes a number of checks for getLangOpts().ObjCAutoRefCount
that were guarding the processing of these qualifiers. I don't
expect this to be a significant drain on performance; it may even
be faster to just check for these qualifiers directly on a type
(since it's probably in a register anyway) than to do N dependent
loads to grab the LangOptions.
rdar://9674298
llvm-svn: 251041
2015-10-23 02:38:17 +08:00
|
|
|
// and we're not in ObjC mode, there's nothing to check.
|
2018-10-31 04:31:30 +08:00
|
|
|
if (!CheckCVR && CheckObjCLifetime && !Self.Context.getLangOpts().ObjC)
|
2018-07-11 07:04:35 +08:00
|
|
|
return CastAwayConstnessKind::CACK_None;
|
|
|
|
|
|
|
|
if (!DestType->isReferenceType()) {
|
|
|
|
assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() ||
|
|
|
|
SrcType->isBlockPointerType()) &&
|
|
|
|
"Source type is not pointer or pointer to member.");
|
|
|
|
assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() ||
|
|
|
|
DestType->isBlockPointerType()) &&
|
|
|
|
"Destination type is not pointer or pointer to member.");
|
|
|
|
}
|
2009-01-27 06:19:12 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType),
|
2009-11-15 17:20:52 +08:00
|
|
|
UnwrappedDestType = Self.Context.getCanonicalType(DestType);
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
// Find the qualifiers. We only care about cvr-qualifiers for the
|
|
|
|
// purpose of this check, because other qualifiers (address spaces,
|
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
|
|
|
// 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;
|
2018-07-11 07:04:35 +08:00
|
|
|
auto WorstKind = CastAwayConstnessKind::CACK_Similar;
|
|
|
|
bool AllConstSoFar = true;
|
|
|
|
while (auto Kind = unwrapCastAwayConstnessLevel(
|
|
|
|
Self.Context, UnwrappedSrcType, UnwrappedDestType)) {
|
|
|
|
// Track the worst kind of unwrap we needed to do before we found a
|
|
|
|
// problem.
|
|
|
|
if (Kind > WorstKind)
|
|
|
|
WorstKind = Kind;
|
|
|
|
|
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);
|
2017-08-11 08:06:49 +08:00
|
|
|
|
|
|
|
// We do not meaningfully track object const-ness of Objective-C object
|
|
|
|
// types. Remove const from the source type if either the source or
|
|
|
|
// the destination is an Objective-C object type.
|
|
|
|
if (UnwrappedSrcType->isObjCObjectType() ||
|
|
|
|
UnwrappedDestType->isObjCObjectType())
|
|
|
|
SrcQuals.removeConst();
|
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
if (CheckCVR) {
|
2018-07-11 07:04:35 +08:00
|
|
|
Qualifiers SrcCvrQuals =
|
|
|
|
Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers());
|
|
|
|
Qualifiers DestCvrQuals =
|
|
|
|
Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers());
|
|
|
|
|
|
|
|
if (SrcCvrQuals != DestCvrQuals) {
|
|
|
|
if (CastAwayQualifiers)
|
|
|
|
*CastAwayQualifiers = SrcCvrQuals - DestCvrQuals;
|
|
|
|
|
|
|
|
// If we removed a cvr-qualifier, this is casting away 'constness'.
|
|
|
|
if (!DestCvrQuals.compatiblyIncludes(SrcCvrQuals)) {
|
|
|
|
if (TheOffendingSrcType)
|
|
|
|
*TheOffendingSrcType = PrevUnwrappedSrcType;
|
|
|
|
if (TheOffendingDestType)
|
|
|
|
*TheOffendingDestType = PrevUnwrappedDestType;
|
|
|
|
return WorstKind;
|
|
|
|
}
|
2014-11-22 05:03:10 +08:00
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
// If any prior level was not 'const', this is also casting away
|
|
|
|
// 'constness'. We noted the outermost type missing a 'const' already.
|
|
|
|
if (!AllConstSoFar)
|
|
|
|
return WorstKind;
|
2014-11-22 05:03:10 +08:00
|
|
|
}
|
2011-06-16 07:02:42 +08:00
|
|
|
}
|
2018-07-11 07:04:35 +08:00
|
|
|
|
2011-06-16 07:02:42 +08:00
|
|
|
if (CheckObjCLifetime &&
|
|
|
|
!DestQuals.compatiblyIncludesObjCLifetime(SrcQuals))
|
2018-07-11 07:04:35 +08:00
|
|
|
return WorstKind;
|
|
|
|
|
|
|
|
// If we found our first non-const-qualified type, this may be the place
|
|
|
|
// where things start to go wrong.
|
|
|
|
if (AllConstSoFar && !DestQuals.hasConst()) {
|
|
|
|
AllConstSoFar = false;
|
|
|
|
if (TheOffendingSrcType)
|
|
|
|
*TheOffendingSrcType = PrevUnwrappedSrcType;
|
|
|
|
if (TheOffendingDestType)
|
|
|
|
*TheOffendingDestType = PrevUnwrappedDestType;
|
|
|
|
}
|
2014-11-22 05:03:10 +08:00
|
|
|
|
|
|
|
PrevUnwrappedSrcType = UnwrappedSrcType;
|
|
|
|
PrevUnwrappedDestType = UnwrappedDestType;
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
return CastAwayConstnessKind::CACK_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TryCastResult getCastAwayConstnessCastKind(CastAwayConstnessKind CACK,
|
|
|
|
unsigned &DiagID) {
|
|
|
|
switch (CACK) {
|
|
|
|
case CastAwayConstnessKind::CACK_None:
|
|
|
|
llvm_unreachable("did not cast away constness");
|
|
|
|
|
|
|
|
case CastAwayConstnessKind::CACK_Similar:
|
|
|
|
// FIXME: Accept these as an extension too?
|
|
|
|
case CastAwayConstnessKind::CACK_SimilarKind:
|
|
|
|
DiagID = diag::err_bad_cxx_cast_qualifiers_away;
|
|
|
|
return TC_Failed;
|
|
|
|
|
|
|
|
case CastAwayConstnessKind::CACK_Incoherent:
|
|
|
|
DiagID = diag::ext_bad_cxx_cast_qualifiers_away_incoherent;
|
|
|
|
return TC_Extension;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("unexpected cast away constness kind");
|
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() {
|
2020-06-11 03:20:54 +08:00
|
|
|
CheckNoDerefRAII NoderefCheck(*this);
|
|
|
|
|
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,
|
2019-12-17 10:26:19 +08:00
|
|
|
diag::err_bad_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
|
2018-07-31 03:24:48 +08:00
|
|
|
// an lvalue of a complete class type, [...]. If T is an rvalue reference
|
2011-01-22 08:06:57 +08:00
|
|
|
// 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)
|
2019-11-04 23:26:21 +08:00
|
|
|
<< OrigSrcType << this->DestType << 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())
|
2016-06-22 04:29:17 +08:00
|
|
|
SrcExpr = Self.CreateMaterializeTemporaryExpr(
|
|
|
|
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,
|
2019-12-17 10:26:19 +08:00
|
|
|
diag::err_bad_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.
|
2015-12-19 05:45:41 +08:00
|
|
|
if (DestRecord &&
|
|
|
|
Self.IsDerivedFrom(OpRange.getBegin(), SrcPointee, DestPointee)) {
|
2010-04-25 03:06:50 +08:00
|
|
|
if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
|
2018-07-31 03:24:48 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-09-16 04:44:22 +08:00
|
|
|
// Warns when dynamic_cast is used with RTTI data disabled.
|
|
|
|
if (!Self.getLangOpts().RTTIData) {
|
|
|
|
bool MicrosoftABI =
|
|
|
|
Self.getASTContext().getTargetInfo().getCXXABI().isMicrosoft();
|
|
|
|
bool isClangCL = Self.getDiagnostics().getDiagnosticOptions().getFormat() ==
|
|
|
|
DiagnosticOptions::MSVC;
|
|
|
|
if (MicrosoftABI || !DestPointee->isVoidType())
|
|
|
|
Self.Diag(OpRange.getBegin(),
|
|
|
|
diag::warn_no_dynamic_cast_with_rtti_disabled)
|
|
|
|
<< isClangCL;
|
|
|
|
}
|
|
|
|
|
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() {
|
2020-06-11 03:20:54 +08:00
|
|
|
CheckNoDerefRAII NoderefCheck(*this);
|
|
|
|
|
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;
|
2018-07-11 07:04:35 +08:00
|
|
|
auto TCR = TryConstCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg);
|
|
|
|
if (TCR != TC_Success && 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
|
|
|
}
|
2018-07-11 07:04:35 +08:00
|
|
|
if (!isValidCast(TCR))
|
|
|
|
SrcExpr = ExprError();
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
2008-11-06 05:50:06 +08:00
|
|
|
|
2020-05-18 18:02:01 +08:00
|
|
|
void CastOperation::CheckAddrspaceCast() {
|
|
|
|
unsigned msg = diag::err_bad_cxx_cast_generic;
|
|
|
|
auto TCR =
|
|
|
|
TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ false, msg, Kind);
|
|
|
|
if (TCR != TC_Success && msg != 0) {
|
|
|
|
Self.Diag(OpRange.getBegin(), msg)
|
|
|
|
<< CT_Addrspace << SrcExpr.get()->getType() << DestType << OpRange;
|
|
|
|
}
|
|
|
|
if (!isValidCast(TCR))
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-03-25 07:03:13 +08:00
|
|
|
static bool argTypeIsABIEquivalent(QualType SrcType, QualType DestType,
|
|
|
|
ASTContext &Context) {
|
|
|
|
if (SrcType->isPointerType() && DestType->isPointerType())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Allow integral type mismatch if their size are equal.
|
|
|
|
if (SrcType->isIntegralType(Context) && DestType->isIntegralType(Context))
|
|
|
|
if (Context.getTypeInfoInChars(SrcType).Width ==
|
|
|
|
Context.getTypeInfoInChars(DestType).Width)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return Context.hasSameUnqualifiedType(SrcType, DestType);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool checkCastFunctionType(Sema &Self, const ExprResult &SrcExpr,
|
|
|
|
QualType DestType) {
|
|
|
|
if (Self.Diags.isIgnored(diag::warn_cast_function_type,
|
|
|
|
SrcExpr.get()->getExprLoc()))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
|
|
|
const FunctionType *SrcFTy = nullptr;
|
|
|
|
const FunctionType *DstFTy = nullptr;
|
|
|
|
if (((SrcType->isBlockPointerType() || SrcType->isFunctionPointerType()) &&
|
|
|
|
DestType->isFunctionPointerType()) ||
|
|
|
|
(SrcType->isMemberFunctionPointerType() &&
|
|
|
|
DestType->isMemberFunctionPointerType())) {
|
|
|
|
SrcFTy = SrcType->getPointeeType()->castAs<FunctionType>();
|
|
|
|
DstFTy = DestType->getPointeeType()->castAs<FunctionType>();
|
|
|
|
} else if (SrcType->isFunctionType() && DestType->isFunctionReferenceType()) {
|
|
|
|
SrcFTy = SrcType->castAs<FunctionType>();
|
|
|
|
DstFTy = DestType.getNonReferenceType()->castAs<FunctionType>();
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
assert(SrcFTy && DstFTy);
|
|
|
|
|
|
|
|
auto IsVoidVoid = [](const FunctionType *T) {
|
|
|
|
if (!T->getReturnType()->isVoidType())
|
|
|
|
return false;
|
|
|
|
if (const auto *PT = T->getAs<FunctionProtoType>())
|
|
|
|
return !PT->isVariadic() && PT->getNumParams() == 0;
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Skip if either function type is void(*)(void)
|
|
|
|
if (IsVoidVoid(SrcFTy) || IsVoidVoid(DstFTy))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Check return type.
|
|
|
|
if (!argTypeIsABIEquivalent(SrcFTy->getReturnType(), DstFTy->getReturnType(),
|
|
|
|
Self.Context))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check if either has unspecified number of parameters
|
|
|
|
if (SrcFTy->isFunctionNoProtoType() || DstFTy->isFunctionNoProtoType())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Check parameter types.
|
|
|
|
|
|
|
|
const auto *SrcFPTy = cast<FunctionProtoType>(SrcFTy);
|
|
|
|
const auto *DstFPTy = cast<FunctionProtoType>(DstFTy);
|
|
|
|
|
|
|
|
// In a cast involving function types with a variable argument list only the
|
|
|
|
// types of initial arguments that are provided are considered.
|
|
|
|
unsigned NumParams = SrcFPTy->getNumParams();
|
|
|
|
unsigned DstNumParams = DstFPTy->getNumParams();
|
|
|
|
if (NumParams > DstNumParams) {
|
|
|
|
if (!DstFPTy->isVariadic())
|
|
|
|
return false;
|
|
|
|
NumParams = DstNumParams;
|
|
|
|
} else if (NumParams < DstNumParams) {
|
|
|
|
if (!SrcFPTy->isVariadic())
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < NumParams; ++i)
|
|
|
|
if (!argTypeIsABIEquivalent(SrcFPTy->getParamType(i),
|
|
|
|
DstFPTy->getParamType(i), Self.Context))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
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;
|
2018-07-31 03:24:48 +08:00
|
|
|
TryCastResult tcr =
|
|
|
|
TryReinterpretCast(Self, SrcExpr, DestType,
|
2011-06-16 07:02:42 +08:00
|
|
|
/*CStyle*/false, OpRange, msg, Kind);
|
2018-07-11 07:04:35 +08:00
|
|
|
if (tcr != TC_Success && msg != 0) {
|
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) {
|
2018-07-31 03:24: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
|
|
|
}
|
2018-07-11 07:04:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isValidCast(tcr)) {
|
2017-03-30 02:16:38 +08:00
|
|
|
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
|
2017-03-30 02:09:02 +08:00
|
|
|
checkObjCConversion(Sema::CCK_OtherCast);
|
2013-03-22 10:58:14 +08:00
|
|
|
DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange);
|
2021-03-25 07:03:13 +08:00
|
|
|
|
|
|
|
if (!checkCastFunctionType(Self, SrcExpr, DestType))
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type)
|
|
|
|
<< SrcExpr.get()->getType() << DestType << OpRange;
|
2018-07-11 07:04:35 +08:00
|
|
|
} else {
|
|
|
|
SrcExpr = ExprError();
|
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() {
|
2020-06-11 03:20:54 +08:00
|
|
|
CheckNoDerefRAII NoderefCheck(*this);
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
if (isPlaceholder()) {
|
|
|
|
checkNonOverloadPlaceholders();
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-05-09 15:17:10 +08:00
|
|
|
if (DestType->getAs<MatrixType>() ||
|
|
|
|
SrcExpr.get()->getType()->getAs<MatrixType>()) {
|
|
|
|
if (Self.CheckMatrixCast(OpRange, DestType, SrcExpr.get()->getType(), Kind))
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
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)) {
|
2018-07-31 03:24:48 +08:00
|
|
|
Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr,
|
|
|
|
false, // Decay Function to ptr
|
2011-02-20 05:32:49 +08:00
|
|
|
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)
|
2018-07-31 03:24:48 +08:00
|
|
|
<< oe->getName() << DestType << OpRange
|
2011-03-01 04:01:57 +08:00
|
|
|
<< 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
|
|
|
}
|
2018-07-11 07:04:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (isValidCast(tcr)) {
|
2011-06-16 07:02:42 +08:00
|
|
|
if (Kind == CK_BitCast)
|
2011-10-05 15:41:44 +08:00
|
|
|
checkCastAlign();
|
2017-03-30 02:16:38 +08:00
|
|
|
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
|
2017-03-30 02:09:02 +08:00
|
|
|
checkObjCConversion(Sema::CCK_OtherCast);
|
2018-07-11 07:04:35 +08:00
|
|
|
} else {
|
|
|
|
SrcExpr = ExprError();
|
2010-11-08 11:40:48 +08:00
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
|
2018-08-03 11:18:56 +08:00
|
|
|
static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) {
|
|
|
|
auto *SrcPtrType = SrcType->getAs<PointerType>();
|
|
|
|
if (!SrcPtrType)
|
|
|
|
return false;
|
|
|
|
auto *DestPtrType = DestType->getAs<PointerType>();
|
|
|
|
if (!DestPtrType)
|
|
|
|
return false;
|
|
|
|
return SrcPtrType->getPointeeType().getAddressSpace() !=
|
|
|
|
DestPtrType->getPointeeType().getAddressSpace();
|
|
|
|
}
|
|
|
|
|
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,
|
2018-07-31 03:24:48 +08:00
|
|
|
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, CXXCastPath &BasePath,
|
|
|
|
bool ListInitialization) {
|
2011-06-16 07:02:42 +08:00
|
|
|
// Determine whether we have the semantics of a C-style cast.
|
2018-07-31 03:24:48 +08:00
|
|
|
bool CStyle
|
2011-06-16 07:02:42 +08:00
|
|
|
= (CCK == Sema::CCK_CStyleCast || CCK == Sema::CCK_FunctionalCast);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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
|
|
|
|
2018-07-31 03:24:48 +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".
|
2016-11-03 10:13:17 +08:00
|
|
|
tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
|
2012-02-13 02:41:05 +08:00
|
|
|
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;
|
2018-07-31 03:24:48 +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
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +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()) {
|
2019-12-17 10:26:19 +08:00
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
|
|
|
|
diag::err_bad_cast_incomplete)) {
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2011-09-03 01:38:59 +08:00
|
|
|
if (SrcType->isIntegralOrEnumerationType()) {
|
2020-08-17 00:40:08 +08:00
|
|
|
// [expr.static.cast]p10 If the enumeration type has a fixed underlying
|
|
|
|
// type, the value is first converted to that type by integral conversion
|
|
|
|
const EnumType *Enum = DestType->getAs<EnumType>();
|
|
|
|
Kind = Enum->getDecl()->isFixed() &&
|
|
|
|
Enum->getDecl()->getIntegerType()->isBooleanType()
|
|
|
|
? CK_IntegralToBoolean
|
|
|
|
: 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
|
|
|
}
|
2018-08-03 11:18:56 +08:00
|
|
|
Kind = IsAddressSpaceConversion(SrcType, DestType)
|
|
|
|
? CK_AddressSpaceConversion
|
|
|
|
: 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()) {
|
2018-07-31 03:24:48 +08:00
|
|
|
// allow both c-style cast and static_cast of objective-c pointers as
|
2010-05-11 07:46:53 +08:00
|
|
|
// 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
|
|
|
}
|
|
|
|
}
|
2018-04-06 23:14:32 +08:00
|
|
|
// Allow arbitrary objective-c pointer conversion with static casts.
|
2010-05-13 02:16:59 +08:00
|
|
|
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;
|
2018-07-31 03:24:48 +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.
|
2016-11-03 10:13:17 +08:00
|
|
|
TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
|
|
|
|
QualType DestType, bool CStyle,
|
|
|
|
CastKind &Kind, CXXCastPath &BasePath,
|
|
|
|
unsigned &msg) {
|
2015-07-13 06:10:56 +08:00
|
|
|
// C++11 [expr.static.cast]p3:
|
2016-11-03 10:13:17 +08:00
|
|
|
// A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
|
2011-01-22 08:06:57 +08:00
|
|
|
// 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.
|
2011-01-27 05:04:06 +08:00
|
|
|
QualType FromType = SrcExpr->getType();
|
|
|
|
QualType ToType = R->getPointeeType();
|
|
|
|
if (CStyle) {
|
|
|
|
FromType = FromType.getUnqualifiedType();
|
|
|
|
ToType = ToType.getUnqualifiedType();
|
|
|
|
}
|
2016-11-03 10:13:17 +08:00
|
|
|
|
2019-12-19 06:01:40 +08:00
|
|
|
Sema::ReferenceConversions RefConv;
|
2016-11-03 10:13:17 +08:00
|
|
|
Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship(
|
2019-12-19 06:01:40 +08:00
|
|
|
SrcExpr->getBeginLoc(), ToType, FromType, &RefConv);
|
2016-11-03 10:13:17 +08:00
|
|
|
if (RefResult != Sema::Ref_Compatible) {
|
|
|
|
if (CStyle || RefResult == Sema::Ref_Incompatible)
|
2015-07-13 06:10:56 +08:00
|
|
|
return TC_NotApplicable;
|
2016-11-03 10:13:17 +08:00
|
|
|
// Diagnose types which are reference-related but not compatible here since
|
|
|
|
// we can provide better diagnostics. In these cases forwarding to
|
|
|
|
// [expr.static.cast]p4 should never result in a well-formed cast.
|
|
|
|
msg = SrcExpr->isLValue() ? diag::err_bad_lvalue_to_rvalue_cast
|
|
|
|
: diag::err_bad_rvalue_to_rvalue_cast;
|
2009-07-25 23:41:38 +08:00
|
|
|
return TC_Failed;
|
2009-03-23 06:30:06 +08:00
|
|
|
}
|
|
|
|
|
2019-12-19 06:01:40 +08:00
|
|
|
if (RefConv & Sema::ReferenceConversions::DerivedToBase) {
|
2011-01-26 00:13:26 +08:00
|
|
|
Kind = CK_DerivedToBase;
|
|
|
|
CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
|
|
|
|
/*DetectVirtual=*/true);
|
2018-08-10 05:08:08 +08:00
|
|
|
if (!Self.IsDerivedFrom(SrcExpr->getBeginLoc(), SrcExpr->getType(),
|
2015-12-19 05:45:41 +08:00
|
|
|
R->getPointeeType(), Paths))
|
2011-01-26 00:13:26 +08:00
|
|
|
return TC_NotApplicable;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-01-26 00:13:26 +08:00
|
|
|
Self.BuildBasePathArray(Paths, BasePath);
|
|
|
|
} else
|
|
|
|
Kind = CK_NoOp;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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.
|
2018-07-31 03:24:48 +08:00
|
|
|
return TryStaticDowncast(Self,
|
|
|
|
Self.Context.getCanonicalType(SrcExpr->getType()),
|
2009-11-15 17:20:52 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
return TryStaticDowncast(Self,
|
2009-11-15 17:20:52 +08:00
|
|
|
Self.Context.getCanonicalType(SrcPointer->getPointeeType()),
|
2018-07-31 03:24:48 +08:00
|
|
|
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,
|
2018-07-31 03:24:48 +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
|
2015-12-19 06:40:25 +08:00
|
|
|
if (!Self.isCompleteType(OpRange.getBegin(), SrcType) ||
|
|
|
|
!Self.isCompleteType(OpRange.getBegin(), DestType))
|
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);
|
2015-12-19 05:45:41 +08:00
|
|
|
if (!Self.IsDerivedFrom(OpRange.getBegin(), 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);
|
2015-12-19 05:45:41 +08:00
|
|
|
Self.IsDerivedFrom(OpRange.getBegin(), DestType, SrcType, Paths);
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
2008-11-08 07:29:29 +08:00
|
|
|
std::string PathDisplayStr;
|
|
|
|
std::set<unsigned> DisplayedPaths;
|
2016-06-23 08:15:04 +08:00
|
|
|
for (clang::CXXBasePath &Path : Paths) {
|
|
|
|
if (DisplayedPaths.insert(Path.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 ";
|
2016-06-23 08:15:04 +08:00
|
|
|
for (CXXBasePathElement &PE : llvm::reverse(Path))
|
|
|
|
PathDisplayStr += PE.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)
|
2018-07-31 03:24:48 +08:00
|
|
|
<< QualType(SrcType).getUnqualifiedType()
|
2009-11-15 17:20:52 +08:00
|
|
|
<< 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) {
|
2016-04-28 17:56:22 +08:00
|
|
|
switch (Self.CheckBaseClassAccess(OpRange.getBegin(),
|
|
|
|
SrcType, DestType,
|
|
|
|
Paths.front(),
|
|
|
|
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
|
2018-07-31 03:24:48 +08:00
|
|
|
TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
|
|
|
|
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
|
|
|
}
|
2018-07-31 03:24:48 +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-12-19 06:40:25 +08:00
|
|
|
|
|
|
|
// Lock down the inheritance model right now in MS ABI, whether or not the
|
|
|
|
// pointee types are the same.
|
2016-03-23 00:44:39 +08:00
|
|
|
if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
|
2015-12-19 06:40:25 +08:00
|
|
|
(void)Self.isCompleteType(OpRange.getBegin(), SrcType);
|
2016-03-23 00:44:39 +08:00
|
|
|
(void)Self.isCompleteType(OpRange.getBegin(), DestType);
|
|
|
|
}
|
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);
|
2015-12-19 05:45:41 +08:00
|
|
|
if (!Self.IsDerivedFrom(OpRange.getBegin(), 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);
|
2015-12-19 05:45:41 +08:00
|
|
|
bool StillOkay =
|
|
|
|
Self.IsDerivedFrom(OpRange.getBegin(), SrcClass, DestClass, Paths);
|
2009-01-29 02:33:18 +08:00
|
|
|
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.
|
2018-07-31 03:24:48 +08:00
|
|
|
FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
|
|
|
|
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,
|
2018-07-31 03:24:48 +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,
|
2019-12-17 10:26:19 +08:00
|
|
|
diag::err_bad_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();
|
2016-12-10 02:49:13 +08:00
|
|
|
// FIXME: Per DR242, we should check for an implicit conversion sequence
|
|
|
|
// or for a constructor that could be invoked by direct-initialization
|
|
|
|
// here, not for an initialization sequence.
|
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,
|
2018-07-31 03:24:48 +08:00
|
|
|
// or the expression is an overload expression this has to work.
|
2010-11-08 11:40:48 +08:00
|
|
|
// 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.
|
2018-07-31 03:24:48 +08:00
|
|
|
bool CStyle
|
2011-06-16 07:02:42 +08:00
|
|
|
= (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;
|
2018-07-31 03:24:48 +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;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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;
|
2018-07-31 03:24:48 +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
|
|
|
}
|
|
|
|
|
2018-07-11 08:19:19 +08:00
|
|
|
// C++ [expr.const.cast]p3:
|
|
|
|
// "For two similar types T1 and T2, [...]"
|
|
|
|
//
|
|
|
|
// We only allow a const_cast to change cvr-qualifiers, not other kinds of
|
|
|
|
// type qualifiers. (Likewise, we ignore other changes when determining
|
|
|
|
// whether a cast casts away constness.)
|
|
|
|
if (!Self.Context.hasCvrSimilarType(SrcType, DestType))
|
2009-07-25 23:41:38 +08:00
|
|
|
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.
|
2016-12-10 02:49:13 +08:00
|
|
|
SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcExpr.get()->getType(),
|
|
|
|
SrcExpr.get(),
|
2016-06-22 04:29:17 +08:00
|
|
|
/*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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:00:03 +08:00
|
|
|
/// Diagnose casts that change the calling convention of a pointer to a function
|
|
|
|
/// defined in the current TU.
|
|
|
|
static void DiagnoseCallingConvCast(Sema &Self, const ExprResult &SrcExpr,
|
|
|
|
QualType DstType, SourceRange OpRange) {
|
|
|
|
// Check if this cast would change the calling convention of a function
|
|
|
|
// pointer type.
|
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
|
|
|
if (Self.Context.hasSameType(SrcType, DstType) ||
|
|
|
|
!SrcType->isFunctionPointerType() || !DstType->isFunctionPointerType())
|
|
|
|
return;
|
|
|
|
const auto *SrcFTy =
|
|
|
|
SrcType->castAs<PointerType>()->getPointeeType()->castAs<FunctionType>();
|
|
|
|
const auto *DstFTy =
|
|
|
|
DstType->castAs<PointerType>()->getPointeeType()->castAs<FunctionType>();
|
|
|
|
CallingConv SrcCC = SrcFTy->getCallConv();
|
|
|
|
CallingConv DstCC = DstFTy->getCallConv();
|
|
|
|
if (SrcCC == DstCC)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// We have a calling convention cast. Check if the source is a pointer to a
|
|
|
|
// known, specific function that has already been defined.
|
|
|
|
Expr *Src = SrcExpr.get()->IgnoreParenImpCasts();
|
|
|
|
if (auto *UO = dyn_cast<UnaryOperator>(Src))
|
|
|
|
if (UO->getOpcode() == UO_AddrOf)
|
|
|
|
Src = UO->getSubExpr()->IgnoreParenImpCasts();
|
|
|
|
auto *DRE = dyn_cast<DeclRefExpr>(Src);
|
|
|
|
if (!DRE)
|
|
|
|
return;
|
|
|
|
auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl());
|
2017-02-01 03:37:45 +08:00
|
|
|
if (!FD)
|
2016-05-11 05:00:03 +08:00
|
|
|
return;
|
|
|
|
|
2016-05-12 01:43:13 +08:00
|
|
|
// Only warn if we are casting from the default convention to a non-default
|
|
|
|
// convention. This can happen when the programmer forgot to apply the calling
|
2017-02-01 03:37:45 +08:00
|
|
|
// convention to the function declaration and then inserted this cast to
|
2016-05-12 01:43:13 +08:00
|
|
|
// satisfy the type system.
|
|
|
|
CallingConv DefaultCC = Self.getASTContext().getDefaultCallingConvention(
|
|
|
|
FD->isVariadic(), FD->isCXXInstanceMember());
|
|
|
|
if (DstCC == DefaultCC || SrcCC != DefaultCC)
|
|
|
|
return;
|
|
|
|
|
2016-05-11 05:00:03 +08:00
|
|
|
// Diagnose this cast, as it is probably bad.
|
|
|
|
StringRef SrcCCName = FunctionType::getNameForCallConv(SrcCC);
|
|
|
|
StringRef DstCCName = FunctionType::getNameForCallConv(DstCC);
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::warn_cast_calling_conv)
|
|
|
|
<< SrcCCName << DstCCName << OpRange;
|
|
|
|
|
|
|
|
// The checks above are cheaper than checking if the diagnostic is enabled.
|
|
|
|
// However, it's worth checking if the warning is enabled before we construct
|
|
|
|
// a fixit.
|
|
|
|
if (Self.Diags.isIgnored(diag::warn_cast_calling_conv, OpRange.getBegin()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Try to suggest a fixit to change the calling convention of the function
|
|
|
|
// whose address was taken. Try to use the latest macro for the convention.
|
|
|
|
// For example, users probably want to write "WINAPI" instead of "__stdcall"
|
|
|
|
// to match the Windows header declarations.
|
2017-02-01 03:37:45 +08:00
|
|
|
SourceLocation NameLoc = FD->getFirstDecl()->getNameInfo().getLoc();
|
2016-05-11 05:00:03 +08:00
|
|
|
Preprocessor &PP = Self.getPreprocessor();
|
|
|
|
SmallVector<TokenValue, 6> AttrTokens;
|
|
|
|
SmallString<64> CCAttrText;
|
|
|
|
llvm::raw_svector_ostream OS(CCAttrText);
|
|
|
|
if (Self.getLangOpts().MicrosoftExt) {
|
|
|
|
// __stdcall or __vectorcall
|
|
|
|
OS << "__" << DstCCName;
|
|
|
|
IdentifierInfo *II = PP.getIdentifierInfo(OS.str());
|
|
|
|
AttrTokens.push_back(II->isKeyword(Self.getLangOpts())
|
|
|
|
? TokenValue(II->getTokenID())
|
|
|
|
: TokenValue(II));
|
|
|
|
} else {
|
|
|
|
// __attribute__((stdcall)) or __attribute__((vectorcall))
|
|
|
|
OS << "__attribute__((" << DstCCName << "))";
|
|
|
|
AttrTokens.push_back(tok::kw___attribute);
|
|
|
|
AttrTokens.push_back(tok::l_paren);
|
|
|
|
AttrTokens.push_back(tok::l_paren);
|
|
|
|
IdentifierInfo *II = PP.getIdentifierInfo(DstCCName);
|
|
|
|
AttrTokens.push_back(II->isKeyword(Self.getLangOpts())
|
|
|
|
? TokenValue(II->getTokenID())
|
|
|
|
: TokenValue(II));
|
|
|
|
AttrTokens.push_back(tok::r_paren);
|
|
|
|
AttrTokens.push_back(tok::r_paren);
|
|
|
|
}
|
|
|
|
StringRef AttrSpelling = PP.getLastMacroWithSpelling(NameLoc, AttrTokens);
|
|
|
|
if (!AttrSpelling.empty())
|
|
|
|
CCAttrText = AttrSpelling;
|
|
|
|
OS << ' ';
|
|
|
|
Self.Diag(NameLoc, diag::note_change_calling_conv_fixit)
|
|
|
|
<< FD << DstCCName << FixItHint::CreateInsertion(NameLoc, CCAttrText);
|
|
|
|
}
|
|
|
|
|
2020-02-16 22:01:25 +08:00
|
|
|
static void checkIntToPointerCast(bool CStyle, const SourceRange &OpRange,
|
2012-10-17 02:53:14 +08:00
|
|
|
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;
|
2020-02-16 22:01:25 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange;
|
2013-05-30 05:50:46 +08:00
|
|
|
}
|
2012-10-17 02:53:14 +08:00
|
|
|
}
|
|
|
|
|
2016-03-20 05:36:10 +08:00
|
|
|
static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType,
|
|
|
|
ExprResult &Result) {
|
|
|
|
// We can only fix an overloaded reinterpret_cast if
|
|
|
|
// - it is a template with explicit arguments that resolves to an lvalue
|
|
|
|
// unambiguously, or
|
|
|
|
// - it is the only function in an overload set that may have its address
|
|
|
|
// taken.
|
|
|
|
|
|
|
|
Expr *E = Result.get();
|
|
|
|
// TODO: what if this fails because of DiagnoseUseOfDecl or something
|
|
|
|
// like it?
|
|
|
|
if (Self.ResolveAndFixSingleFunctionTemplateSpecialization(
|
|
|
|
Result,
|
|
|
|
Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr
|
|
|
|
) &&
|
|
|
|
Result.isUsable())
|
|
|
|
return true;
|
|
|
|
|
2016-06-08 08:34:22 +08:00
|
|
|
// No guarantees that ResolveAndFixSingleFunctionTemplateSpecialization
|
|
|
|
// preserves Result.
|
|
|
|
Result = E;
|
2020-01-09 21:07:51 +08:00
|
|
|
if (!Self.resolveAndFixAddressOfSingleOverloadCandidate(
|
2017-05-09 12:06:24 +08:00
|
|
|
Result, /*DoFunctionPointerConversion=*/true))
|
2016-03-20 05:36:10 +08:00
|
|
|
return false;
|
2016-06-08 08:34:22 +08:00
|
|
|
return Result.isUsable();
|
2016-03-20 05:36:10 +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;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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)
|
2016-03-20 05:36:10 +08:00
|
|
|
// If so, reinterpret_cast generally can not help us here (13.4, p1, bullet 5)
|
2011-02-20 05:32:49 +08:00
|
|
|
if (SrcType == Self.Context.OverloadTy) {
|
2016-03-20 05:36:10 +08:00
|
|
|
ExprResult FixedExpr = SrcExpr;
|
|
|
|
if (!fixOverloadedReinterpretCastExpr(Self, DestType, FixedExpr))
|
2011-02-20 05:32:49 +08:00
|
|
|
return TC_NotApplicable;
|
2016-03-20 05:36:10 +08:00
|
|
|
|
|
|
|
assert(FixedExpr.isUsable() && "Invalid result fixing overloaded expr");
|
|
|
|
SrcExpr = FixedExpr;
|
|
|
|
SrcType = SrcExpr.get()->getType();
|
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,
|
2019-07-16 12:46:31 +08:00
|
|
|
/*IsDereference=*/false, OpRange);
|
2011-05-03 02:21:19 +08:00
|
|
|
}
|
|
|
|
|
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;
|
2016-12-10 02:49:13 +08:00
|
|
|
case OK_BitField:
|
|
|
|
msg = diag::err_bad_cxx_cast_bitfield;
|
|
|
|
return TC_NotApplicable;
|
|
|
|
// FIXME: Use a specific diagnostic for the rest of these cases.
|
2011-04-23 07:57:57 +08:00
|
|
|
case OK_VectorComponent: inappropriate = "vector element"; break;
|
[Matrix] Implement matrix index expressions ([][]).
This patch implements matrix index expressions
(matrix[RowIdx][ColumnIdx]).
It does so by introducing a new MatrixSubscriptExpr(Base, RowIdx, ColumnIdx).
MatrixSubscriptExprs are built in 2 steps in ActOnMatrixSubscriptExpr. First,
if the base of a subscript is of matrix type, we create a incomplete
MatrixSubscriptExpr(base, idx, nullptr). Second, if the base is an incomplete
MatrixSubscriptExpr, we create a complete
MatrixSubscriptExpr(base->getBase(), base->getRowIdx(), idx)
Similar to vector elements, it is not possible to take the address of
a MatrixSubscriptExpr.
For CodeGen, a new MatrixElt type is added to LValue, which is very
similar to VectorElt. The only difference is that we may need to cast
the type of the base from an array to a vector type when accessing it.
Reviewers: rjmccall, anemet, Bigcheese, rsmith, martong
Reviewed By: rjmccall
Differential Revision: https://reviews.llvm.org/D76791
2020-06-02 02:42:03 +08:00
|
|
|
case OK_MatrixComponent:
|
|
|
|
inappropriate = "matrix element";
|
|
|
|
break;
|
2011-04-23 07:57:57 +08:00
|
|
|
case OK_ObjCProperty: inappropriate = "property expression"; break;
|
2018-07-31 03:24:48 +08:00
|
|
|
case OK_ObjCSubscript: inappropriate = "container subscripting expression";
|
2012-03-07 04:05:56 +08:00
|
|
|
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);
|
2018-07-31 03:24: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;
|
|
|
|
|
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.
|
2015-12-19 06:40:25 +08:00
|
|
|
(void)Self.isCompleteType(OpRange.getBegin(), SrcType);
|
|
|
|
(void)Self.isCompleteType(OpRange.getBegin(), DestType);
|
2014-01-17 17:01:00 +08:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
// 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.
|
|
|
|
if (auto CACK =
|
|
|
|
CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
|
|
|
|
/*CheckObjCLifetime=*/CStyle))
|
|
|
|
return getCastAwayConstnessCastKind(CACK, msg);
|
|
|
|
|
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) {
|
2020-11-17 20:33:56 +08:00
|
|
|
// Allow bitcasting between SVE VLATs and VLSTs, and vice-versa.
|
|
|
|
if (Self.isValidSveBitcast(SrcType, DestType)) {
|
|
|
|
Kind = CK_BitCast;
|
|
|
|
return TC_Success;
|
|
|
|
}
|
|
|
|
|
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;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2009-09-17 03:19:43 +08:00
|
|
|
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
|
2018-07-31 03:24:48 +08:00
|
|
|
// cast away constness. In C++98, the intent was not entirely clear here,
|
2012-02-03 10:54:37 +08:00
|
|
|
// since all other paragraphs explicitly forbid casts to the same type.
|
|
|
|
// C++11 clarifies this case with p2.
|
|
|
|
//
|
2018-07-31 03:24:48 +08:00
|
|
|
// The only allowed types are: integral, enumeration, pointer, or
|
2012-02-03 10:54:37 +08:00
|
|
|
// 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).
|
2011-05-12 06:13:54 +08:00
|
|
|
if ((Self.Context.getTypeSize(SrcType) >
|
2020-03-06 07:07:07 +08:00
|
|
|
Self.Context.getTypeSize(DestType))) {
|
|
|
|
bool MicrosoftException =
|
|
|
|
Self.getLangOpts().MicrosoftExt && !DestType->isBooleanType();
|
|
|
|
if (MicrosoftException) {
|
|
|
|
unsigned Diag = SrcType->isVoidPointerType()
|
|
|
|
? diag::warn_void_pointer_to_int_cast
|
|
|
|
: diag::warn_pointer_to_int_cast;
|
|
|
|
Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange;
|
|
|
|
} else {
|
|
|
|
msg = diag::err_bad_reinterpret_cast_small_int;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
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");
|
2020-02-16 22:01:25 +08:00
|
|
|
checkIntToPointerCast(CStyle, OpRange, 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
|
|
|
|
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;
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
// C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness.
|
|
|
|
// The C-style cast operator can.
|
|
|
|
TryCastResult SuccessResult = TC_Success;
|
|
|
|
if (auto CACK =
|
|
|
|
CastsAwayConstness(Self, SrcType, DestType, /*CheckCVR=*/!CStyle,
|
|
|
|
/*CheckObjCLifetime=*/CStyle))
|
|
|
|
SuccessResult = getCastAwayConstnessCastKind(CACK, msg);
|
|
|
|
|
2019-03-08 01:06:30 +08:00
|
|
|
if (IsAddressSpaceConversion(SrcType, DestType)) {
|
|
|
|
Kind = CK_AddressSpaceConversion;
|
|
|
|
assert(SrcType->isPointerType() && DestType->isPointerType());
|
|
|
|
if (!CStyle &&
|
|
|
|
!DestType->getPointeeType().getQualifiers().isAddressSpaceSupersetOf(
|
|
|
|
SrcType->getPointeeType().getQualifiers())) {
|
|
|
|
SuccessResult = TC_Failed;
|
|
|
|
}
|
|
|
|
} else if (IsLValueCast) {
|
2011-09-09 13:25:32 +08:00
|
|
|
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()) {
|
2018-07-11 07:04:35 +08:00
|
|
|
return SuccessResult;
|
2009-12-09 07:09:15 +08:00
|
|
|
}
|
2012-08-17 02:33:47 +08:00
|
|
|
if (CStyle)
|
|
|
|
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
|
2016-05-11 05:00:03 +08:00
|
|
|
|
|
|
|
DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange);
|
|
|
|
|
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.
|
2018-07-11 07:04:35 +08:00
|
|
|
return SuccessResult;
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
2018-07-11 07:04:35 +08:00
|
|
|
return SuccessResult;
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2018-07-11 07:04:35 +08:00
|
|
|
return SuccessResult;
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2020-02-06 19:56:21 +08:00
|
|
|
// Diagnose address space conversion in nested pointers.
|
|
|
|
QualType DestPtee = DestType->getPointeeType().isNull()
|
|
|
|
? DestType->getPointeeType()
|
|
|
|
: DestType->getPointeeType()->getPointeeType();
|
|
|
|
QualType SrcPtee = SrcType->getPointeeType().isNull()
|
|
|
|
? SrcType->getPointeeType()
|
|
|
|
: SrcType->getPointeeType()->getPointeeType();
|
|
|
|
while (!DestPtee.isNull() && !SrcPtee.isNull()) {
|
|
|
|
if (DestPtee.getAddressSpace() != SrcPtee.getAddressSpace()) {
|
|
|
|
Self.Diag(OpRange.getBegin(),
|
|
|
|
diag::warn_bad_cxx_cast_nested_pointer_addr_space)
|
|
|
|
<< CStyle << SrcType << DestType << SrcExpr.get()->getSourceRange();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
DestPtee = DestPtee->getPointeeType();
|
|
|
|
SrcPtee = SrcPtee->getPointeeType();
|
|
|
|
}
|
|
|
|
|
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.
|
2018-07-11 07:04:35 +08:00
|
|
|
return SuccessResult;
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2019-03-08 01:06:30 +08:00
|
|
|
static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
|
|
|
|
QualType DestType, bool CStyle,
|
2020-05-18 18:02:01 +08:00
|
|
|
unsigned &msg, CastKind &Kind) {
|
2019-03-08 01:06:30 +08:00
|
|
|
if (!Self.getLangOpts().OpenCL)
|
|
|
|
// FIXME: As compiler doesn't have any information about overlapping addr
|
|
|
|
// spaces at the moment we have to be permissive here.
|
|
|
|
return TC_NotApplicable;
|
|
|
|
// Even though the logic below is general enough and can be applied to
|
|
|
|
// non-OpenCL mode too, we fast-path above because no other languages
|
|
|
|
// define overlapping address spaces currently.
|
|
|
|
auto SrcType = SrcExpr.get()->getType();
|
2020-05-18 18:02:01 +08:00
|
|
|
// FIXME: Should this be generalized to references? The reference parameter
|
|
|
|
// however becomes a reference pointee type here and therefore rejected.
|
|
|
|
// Perhaps this is the right behavior though according to C++.
|
2019-03-08 01:06:30 +08:00
|
|
|
auto SrcPtrType = SrcType->getAs<PointerType>();
|
|
|
|
if (!SrcPtrType)
|
|
|
|
return TC_NotApplicable;
|
|
|
|
auto DestPtrType = DestType->getAs<PointerType>();
|
|
|
|
if (!DestPtrType)
|
|
|
|
return TC_NotApplicable;
|
|
|
|
auto SrcPointeeType = SrcPtrType->getPointeeType();
|
|
|
|
auto DestPointeeType = DestPtrType->getPointeeType();
|
2020-05-21 03:22:30 +08:00
|
|
|
if (!DestPointeeType.isAddressSpaceOverlapping(SrcPointeeType)) {
|
2019-03-08 01:06:30 +08:00
|
|
|
msg = diag::err_bad_cxx_cast_addr_space_mismatch;
|
|
|
|
return TC_Failed;
|
|
|
|
}
|
|
|
|
auto SrcPointeeTypeWithoutAS =
|
|
|
|
Self.Context.removeAddrSpaceQualType(SrcPointeeType.getCanonicalType());
|
|
|
|
auto DestPointeeTypeWithoutAS =
|
|
|
|
Self.Context.removeAddrSpaceQualType(DestPointeeType.getCanonicalType());
|
2020-05-18 18:02:01 +08:00
|
|
|
if (Self.Context.hasSameType(SrcPointeeTypeWithoutAS,
|
|
|
|
DestPointeeTypeWithoutAS)) {
|
|
|
|
Kind = SrcPointeeType.getAddressSpace() == DestPointeeType.getAddressSpace()
|
|
|
|
? CK_NoOp
|
|
|
|
: CK_AddressSpaceConversion;
|
|
|
|
return TC_Success;
|
|
|
|
} else {
|
|
|
|
return TC_NotApplicable;
|
|
|
|
}
|
2019-03-08 01:06:30 +08:00
|
|
|
}
|
|
|
|
|
2018-10-11 00:05:22 +08:00
|
|
|
void CastOperation::checkAddressSpaceCast(QualType SrcType, QualType DestType) {
|
|
|
|
// In OpenCL only conversions between pointers to objects in overlapping
|
|
|
|
// addr spaces are allowed. v2.0 s6.5.5 - Generic addr space overlaps
|
|
|
|
// with any named one, except for constant.
|
2019-05-08 22:23:49 +08:00
|
|
|
|
|
|
|
// Converting the top level pointee addrspace is permitted for compatible
|
|
|
|
// addrspaces (such as 'generic int *' to 'local int *' or vice versa), but
|
|
|
|
// if any of the nested pointee addrspaces differ, we emit a warning
|
|
|
|
// regardless of addrspace compatibility. This makes
|
|
|
|
// local int ** p;
|
|
|
|
// return (generic int **) p;
|
|
|
|
// warn even though local -> generic is permitted.
|
2018-10-11 00:05:22 +08:00
|
|
|
if (Self.getLangOpts().OpenCL) {
|
2019-05-08 22:23:49 +08:00
|
|
|
const Type *DestPtr, *SrcPtr;
|
|
|
|
bool Nested = false;
|
|
|
|
unsigned DiagID = diag::err_typecheck_incompatible_address_space;
|
|
|
|
DestPtr = Self.getASTContext().getCanonicalType(DestType.getTypePtr()),
|
|
|
|
SrcPtr = Self.getASTContext().getCanonicalType(SrcType.getTypePtr());
|
|
|
|
|
|
|
|
while (isa<PointerType>(DestPtr) && isa<PointerType>(SrcPtr)) {
|
|
|
|
const PointerType *DestPPtr = cast<PointerType>(DestPtr);
|
|
|
|
const PointerType *SrcPPtr = cast<PointerType>(SrcPtr);
|
|
|
|
QualType DestPPointee = DestPPtr->getPointeeType();
|
|
|
|
QualType SrcPPointee = SrcPPtr->getPointeeType();
|
2020-05-21 03:22:30 +08:00
|
|
|
if (Nested
|
|
|
|
? DestPPointee.getAddressSpace() != SrcPPointee.getAddressSpace()
|
|
|
|
: !DestPPointee.isAddressSpaceOverlapping(SrcPPointee)) {
|
2019-05-08 22:23:49 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), DiagID)
|
|
|
|
<< SrcType << DestType << Sema::AA_Casting
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
|
|
|
if (!Nested)
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DestPtr = DestPPtr->getPointeeType().getTypePtr();
|
|
|
|
SrcPtr = SrcPPtr->getPointeeType().getTypePtr();
|
|
|
|
Nested = true;
|
|
|
|
DiagID = diag::ext_nested_pointer_qualifier_mismatch;
|
2018-10-11 00:05:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-13 02:41:05 +08:00
|
|
|
void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
|
|
|
|
bool ListInitialization) {
|
2017-07-04 01:59:22 +08:00
|
|
|
assert(Self.getLangOpts().CPlusPlus);
|
|
|
|
|
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(
|
2018-07-31 03:24:48 +08:00
|
|
|
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
|
|
|
|
2021-05-04 20:44:58 +08:00
|
|
|
if (DestType->getAs<MatrixType>() ||
|
|
|
|
SrcExpr.get()->getType()->getAs<MatrixType>()) {
|
|
|
|
if (Self.CheckMatrixCast(OpRange, DestType, SrcExpr.get()->getType(), Kind))
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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;
|
2016-01-13 09:52:39 +08:00
|
|
|
SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
|
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 ...
|
2019-03-08 01:06:30 +08:00
|
|
|
// Note that for address space we check compatibility after const_cast.
|
2009-07-25 23:41:38 +08:00
|
|
|
unsigned msg = diag::err_bad_cxx_cast_generic;
|
2013-06-15 06:27:52 +08:00
|
|
|
TryCastResult tcr = TryConstCast(Self, SrcExpr, DestType,
|
2019-03-08 01:06:30 +08:00
|
|
|
/*CStyle*/ true, msg);
|
2013-06-15 06:27:52 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2018-07-11 07:04:35 +08:00
|
|
|
if (isValidCast(tcr))
|
2010-08-25 19:45:40 +08:00
|
|
|
Kind = CK_NoOp;
|
2009-10-20 02:14:28 +08:00
|
|
|
|
2019-03-08 01:06:30 +08:00
|
|
|
Sema::CheckedConversionKind CCK =
|
|
|
|
FunctionalStyle ? Sema::CCK_FunctionalCast : Sema::CCK_CStyleCast;
|
2009-07-25 23:41:38 +08:00
|
|
|
if (tcr == TC_NotApplicable) {
|
2020-05-18 18:02:01 +08:00
|
|
|
tcr = TryAddressSpaceCast(Self, SrcExpr, DestType, /*CStyle*/ true, msg,
|
|
|
|
Kind);
|
2011-10-05 15:41:44 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2019-06-03 23:42:36 +08:00
|
|
|
|
2009-07-25 23:41:38 +08:00
|
|
|
if (tcr == TC_NotApplicable) {
|
2020-05-18 18:02:01 +08:00
|
|
|
// ... or if that is not possible, a static_cast, ignoring const and
|
|
|
|
// addr space, ...
|
2019-03-08 01:06:30 +08:00
|
|
|
tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange, msg, Kind,
|
|
|
|
BasePath, ListInitialization);
|
2011-10-05 15:41:44 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2019-03-08 01:06:30 +08:00
|
|
|
|
|
|
|
if (tcr == TC_NotApplicable) {
|
2020-05-18 18:02:01 +08:00
|
|
|
// ... and finally a reinterpret_cast, ignoring const and addr space.
|
2019-03-08 01:06:30 +08:00
|
|
|
tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/ true,
|
|
|
|
OpRange, msg, Kind);
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-30 02:09:02 +08:00
|
|
|
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers() &&
|
2018-07-11 07:04:35 +08:00
|
|
|
isValidCast(tcr))
|
2017-03-30 02:09:02 +08:00
|
|
|
checkObjCConversion(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
|
|
|
}
|
|
|
|
}
|
2009-07-25 23:41:38 +08:00
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
if (isValidCast(tcr)) {
|
|
|
|
if (Kind == CK_BitCast)
|
|
|
|
checkCastAlign();
|
2021-03-25 07:03:13 +08:00
|
|
|
|
|
|
|
if (!checkCastFunctionType(Self, SrcExpr, DestType))
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type)
|
|
|
|
<< SrcExpr.get()->getType() << DestType << OpRange;
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
} else {
|
2011-10-05 15:41:44 +08:00
|
|
|
SrcExpr = ExprError();
|
2018-07-11 07:04:35 +08:00
|
|
|
}
|
2011-10-05 15:41:44 +08:00
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
/// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a
|
2012-08-18 01:22:34 +08:00
|
|
|
/// 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;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-08-18 01:22:34 +08:00
|
|
|
if (!isa<CallExpr>(SrcExpr.get()))
|
|
|
|
return;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-08-18 01:22:34 +08:00
|
|
|
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;
|
2020-08-04 04:37:59 +08:00
|
|
|
if (SrcType->isFixedPointType() && DestType->isFixedPointType())
|
|
|
|
return;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-08-18 01:22:34 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-10-08 16:00:29 +08:00
|
|
|
// If the type is dependent, we won't do any other semantic analysis now.
|
|
|
|
if (Self.getASTContext().isDependenceAllowed() &&
|
|
|
|
(DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
|
|
|
|
SrcExpr.get()->isValueDependent())) {
|
|
|
|
assert((DestType->containsErrors() || SrcExpr.get()->containsErrors() ||
|
|
|
|
SrcExpr.get()->containsErrors()) &&
|
|
|
|
"should only occur in error-recovery path.");
|
|
|
|
assert(Kind == CK_Dependent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-13 03:57:04 +08:00
|
|
|
// Overloads are allowed with C extensions, so we need to support them.
|
|
|
|
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
|
|
|
|
DeclAccessPair DAP;
|
|
|
|
if (FunctionDecl *FD = Self.ResolveAddressOfOverloadedFunction(
|
|
|
|
SrcExpr.get(), DestType, /*Complain=*/true, DAP))
|
|
|
|
SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr.get(), DAP, FD);
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
assert(SrcExpr.isUsable());
|
|
|
|
}
|
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
|
|
|
|
2018-10-11 00:05:22 +08:00
|
|
|
checkAddressSpaceCast(SrcType, DestType);
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2014-01-14 20:47:29 +08:00
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
|
|
|
|
diag::err_typecheck_cast_to_incomplete)) {
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-06 04:33:19 +08:00
|
|
|
// Allow casting a sizeless built-in type to itself.
|
|
|
|
if (DestType->isSizelessBuiltinType() &&
|
|
|
|
Self.Context.hasSameUnqualifiedType(DestType, SrcType)) {
|
|
|
|
Kind = CK_NoOp;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-11-17 20:33:56 +08:00
|
|
|
// Allow bitcasting between compatible SVE vector types.
|
|
|
|
if ((SrcType->isVectorType() || DestType->isVectorType()) &&
|
|
|
|
Self.isValidSveBitcast(SrcType, DestType)) {
|
|
|
|
Kind = CK_BitCast;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-04-10 17:25:34 +08:00
|
|
|
if (!DestType->isScalarType() && !DestType->isVectorType() &&
|
|
|
|
!DestType->isMatrixType()) {
|
2011-10-07 07:25:11 +08:00
|
|
|
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();
|
2017-08-16 05:42:47 +08:00
|
|
|
if (CastExpr::getTargetFieldForToUnionCast(RD, SrcType)) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union)
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
|
|
|
Kind = CK_ToUnion;
|
|
|
|
return;
|
|
|
|
} else {
|
2011-10-07 07:25:11 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type)
|
|
|
|
<< SrcType << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-21 01:18:16 +08:00
|
|
|
// OpenCL v2.0 s6.13.10 - Allow casts from '0' to event_t type.
|
|
|
|
if (Self.getLangOpts().OpenCL && DestType->isEventT()) {
|
2018-12-01 07:41:18 +08:00
|
|
|
Expr::EvalResult Result;
|
|
|
|
if (SrcExpr.get()->EvaluateAsInt(Result, Self.Context)) {
|
|
|
|
llvm::APSInt CastInt = Result.Val.getInt();
|
2016-05-21 01:18:16 +08:00
|
|
|
if (0 == CastInt) {
|
2018-10-23 23:19:20 +08:00
|
|
|
Kind = CK_ZeroToOCLOpaqueType;
|
2016-05-21 01:18:16 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Self.Diag(OpRange.getBegin(),
|
2016-12-03 06:38:31 +08:00
|
|
|
diag::err_opencl_cast_non_zero_to_event_t)
|
2016-05-21 01:18:16 +08:00
|
|
|
<< CastInt.toString(10) << SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2021-04-10 17:25:34 +08:00
|
|
|
// The type we're casting to is known to be a scalar, a vector, or a matrix.
|
2011-10-07 07:25:11 +08:00
|
|
|
|
2021-04-10 17:25:34 +08:00
|
|
|
// Require the operand to be a scalar, a vector, or a matrix.
|
|
|
|
if (!SrcType->isScalarType() && !SrcType->isVectorType() &&
|
|
|
|
!SrcType->isMatrixType()) {
|
2011-10-07 07:25:11 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-04-10 17:25:34 +08:00
|
|
|
if (DestType->getAs<MatrixType>() || SrcType->getAs<MatrixType>()) {
|
|
|
|
if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind))
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) {
|
|
|
|
if (DestVecTy->getVectorKind() == VectorType::AltiVecVector &&
|
|
|
|
(SrcType->isIntegerType() || SrcType->isFloatingType())) {
|
|
|
|
Kind = CK_VectorSplat;
|
2016-01-13 09:52:39 +08:00
|
|
|
SrcExpr = Self.prepareVectorSplat(DestType, SrcExpr.get());
|
2011-10-07 07:25:11 +08:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
[ARM] Add __bf16 as new Bfloat16 C Type
Summary:
This patch upstreams support for a new storage only bfloat16 C type.
This type is used to implement primitive support for bfloat16 data, in
line with the Bfloat16 extension of the Armv8.6-a architecture, as
detailed here:
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/arm-architecture-developments-armv8-6-a
The bfloat type, and its properties are specified in the Arm Architecture
Reference Manual:
https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile
In detail this patch:
- introduces an opaque, storage-only C-type __bf16, which introduces a new bfloat IR type.
This is part of a patch series, starting with command-line and Bfloat16
assembly support. The subsequent patches will upstream intrinsics
support for BFloat16, followed by Matrix Multiplication and the
remaining Virtualization features of the armv8.6-a architecture.
The following people contributed to this patch:
- Luke Cheeseman
- Momchil Velikov
- Alexandros Lamprineas
- Luke Geeson
- Simon Tatham
- Ties Stuij
Reviewers: SjoerdMeijer, rjmccall, rsmith, liutianle, RKSimon, craig.topper, jfb, LukeGeeson, fpetrogalli
Reviewed By: SjoerdMeijer
Subscribers: labrinea, majnemer, asmith, dexonsmith, kristof.beyls, arphaman, danielkiss, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D76077
2020-06-05 07:20:02 +08:00
|
|
|
// Can't cast to or from bfloat
|
|
|
|
if (DestType->isBFloat16Type() && !SrcType->isBFloat16Type()) {
|
|
|
|
Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_to_bfloat16)
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (SrcType->isBFloat16Type() && !DestType->isBFloat16Type()) {
|
|
|
|
Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_from_bfloat16)
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
// 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;
|
|
|
|
}
|
2020-02-16 22:01:25 +08:00
|
|
|
checkIntToPointerCast(/* CStyle */ true, OpRange, SrcExpr.get(), DestType,
|
|
|
|
Self);
|
2011-10-07 07:25:11 +08:00
|
|
|
} else if (!SrcType->isArithmeticType()) {
|
|
|
|
if (!DestType->isIntegralType(Self.Context) &&
|
|
|
|
DestType->isArithmeticType()) {
|
2018-08-10 05:08:08 +08:00
|
|
|
Self.Diag(SrcExpr.get()->getBeginLoc(),
|
|
|
|
diag::err_cast_pointer_to_non_pointer_int)
|
|
|
|
<< DestType << SrcExpr.get()->getSourceRange();
|
2011-10-07 07:25:11 +08:00
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
2020-02-16 22:01:25 +08:00
|
|
|
|
|
|
|
if ((Self.Context.getTypeSize(SrcType) >
|
2020-02-22 17:37:41 +08:00
|
|
|
Self.Context.getTypeSize(DestType)) &&
|
|
|
|
!DestType->isBooleanType()) {
|
2020-02-16 22:01:25 +08:00
|
|
|
// C 6.3.2.3p6: Any pointer type may be converted to an integer type.
|
|
|
|
// Except as previously specified, the result is implementation-defined.
|
|
|
|
// If the result cannot be represented in the integer type, the behavior
|
|
|
|
// is undefined. The result need not be in the range of values of any
|
|
|
|
// integer type.
|
2020-03-08 08:37:44 +08:00
|
|
|
unsigned Diag;
|
2020-03-05 05:18:59 +08:00
|
|
|
if (SrcType->isVoidPointerType())
|
2020-03-08 08:37:44 +08:00
|
|
|
Diag = DestType->isEnumeralType() ? diag::warn_void_pointer_to_enum_cast
|
|
|
|
: diag::warn_void_pointer_to_int_cast;
|
|
|
|
else if (DestType->isEnumeralType())
|
|
|
|
Diag = diag::warn_pointer_to_enum_cast;
|
|
|
|
else
|
|
|
|
Diag = diag::warn_pointer_to_int_cast;
|
2020-02-16 22:01:25 +08:00
|
|
|
Self.Diag(OpRange.getBegin(), Diag) << SrcType << DestType << OpRange;
|
|
|
|
}
|
2011-10-07 07:25:11 +08:00
|
|
|
}
|
|
|
|
|
2021-03-05 21:23:49 +08:00
|
|
|
if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().isAvailableOption(
|
|
|
|
"cl_khr_fp16", Self.getLangOpts())) {
|
2013-01-23 19:56:20 +08:00
|
|
|
if (DestType->isHalfType()) {
|
2018-08-10 05:08:08 +08:00
|
|
|
Self.Diag(SrcExpr.get()->getBeginLoc(), diag::err_opencl_cast_to_half)
|
|
|
|
<< DestType << SrcExpr.get()->getSourceRange();
|
2013-01-23 19:56:20 +08:00
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-07 07:25:11 +08:00
|
|
|
// ARC imposes extra restrictions on casts.
|
2017-03-30 02:09:02 +08:00
|
|
|
if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers()) {
|
|
|
|
checkObjCConversion(Sema::CCK_CStyleCast);
|
2011-10-07 07:25:11 +08:00
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
2017-03-30 02:09:02 +08:00
|
|
|
|
|
|
|
const PointerType *CastPtr = DestType->getAs<PointerType>();
|
|
|
|
if (Self.getLangOpts().ObjCAutoRefCount && CastPtr) {
|
2011-10-07 07:25:11 +08:00
|
|
|
if (const PointerType *ExprPtr = SrcType->getAs<PointerType>()) {
|
|
|
|
Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers();
|
|
|
|
Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers();
|
2018-07-31 03:24:48 +08:00
|
|
|
if (CastPtr->getPointeeType()->isObjCLifetimeType() &&
|
2011-10-07 07:25:11 +08:00
|
|
|
ExprPtr->getPointeeType()->isObjCLifetimeType() &&
|
|
|
|
!CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) {
|
2018-08-10 05:08:08 +08:00
|
|
|
Self.Diag(SrcExpr.get()->getBeginLoc(),
|
2011-10-07 07:25:11 +08:00
|
|
|
diag::err_typecheck_incompatible_ownership)
|
2018-08-10 05:08:08 +08:00
|
|
|
<< SrcType << DestType << Sema::AA_Casting
|
|
|
|
<< SrcExpr.get()->getSourceRange();
|
2011-10-07 07:25:11 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
}
|
2011-10-07 07:25:11 +08:00
|
|
|
else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) {
|
2018-08-10 05:08:08 +08:00
|
|
|
Self.Diag(SrcExpr.get()->getBeginLoc(),
|
2011-10-07 07:25:11 +08:00
|
|
|
diag::err_arc_convesion_of_weak_unavailable)
|
2018-08-10 05:08:08 +08:00
|
|
|
<< 1 << SrcType << DestType << SrcExpr.get()->getSourceRange();
|
2011-10-07 07:25:11 +08:00
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2021-03-25 07:03:13 +08:00
|
|
|
if (!checkCastFunctionType(Self, SrcExpr, DestType))
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type)
|
|
|
|
<< SrcType << DestType << OpRange;
|
|
|
|
|
2012-08-17 02:33:47 +08:00
|
|
|
DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType);
|
2016-05-11 05:00:03 +08:00
|
|
|
DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange);
|
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();
|
2017-07-04 01:59:22 +08:00
|
|
|
}
|
|
|
|
|
2019-07-03 02:28:13 +08:00
|
|
|
void CastOperation::CheckBuiltinBitCast() {
|
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
|
|
|
|
2019-08-13 02:31:27 +08:00
|
|
|
if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
|
|
|
|
diag::err_typecheck_cast_to_incomplete) ||
|
|
|
|
Self.RequireCompleteType(OpRange.getBegin(), SrcType,
|
|
|
|
diag::err_incomplete_type)) {
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-08-13 03:29:43 +08:00
|
|
|
if (SrcExpr.get()->isRValue())
|
|
|
|
SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcType, SrcExpr.get(),
|
|
|
|
/*IsLValueReference=*/false);
|
|
|
|
|
2019-07-03 02:28:13 +08:00
|
|
|
CharUnits DestSize = Self.Context.getTypeSizeInChars(DestType);
|
|
|
|
CharUnits SourceSize = Self.Context.getTypeSizeInChars(SrcType);
|
|
|
|
if (DestSize != SourceSize) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bit_cast_type_size_mismatch)
|
|
|
|
<< (int)SourceSize.getQuantity() << (int)DestSize.getQuantity();
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!DestType.isTriviallyCopyableType(Self.Context)) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bit_cast_non_trivially_copyable)
|
|
|
|
<< 1;
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SrcType.isTriviallyCopyableType(Self.Context)) {
|
|
|
|
Self.Diag(OpRange.getBegin(), diag::err_bit_cast_non_trivially_copyable)
|
|
|
|
<< 0;
|
|
|
|
SrcExpr = ExprError();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Kind = CK_LValueToRValueBitCast;
|
|
|
|
}
|
|
|
|
|
2017-07-04 01:59:22 +08:00
|
|
|
/// DiagnoseCastQual - Warn whenever casts discards a qualifiers, be it either
|
|
|
|
/// const, volatile or both.
|
|
|
|
static void DiagnoseCastQual(Sema &Self, const ExprResult &SrcExpr,
|
|
|
|
QualType DestType) {
|
|
|
|
if (SrcExpr.isInvalid())
|
|
|
|
return;
|
|
|
|
|
|
|
|
QualType SrcType = SrcExpr.get()->getType();
|
|
|
|
if (!((SrcType->isAnyPointerType() && DestType->isAnyPointerType()) ||
|
|
|
|
DestType->isLValueReferenceType()))
|
|
|
|
return;
|
2014-11-22 05:03:10 +08:00
|
|
|
|
|
|
|
QualType TheOffendingSrcType, TheOffendingDestType;
|
|
|
|
Qualifiers CastAwayQualifiers;
|
2018-07-11 07:04:35 +08:00
|
|
|
if (CastsAwayConstness(Self, SrcType, DestType, true, false,
|
|
|
|
&TheOffendingSrcType, &TheOffendingDestType,
|
|
|
|
&CastAwayQualifiers) !=
|
|
|
|
CastAwayConstnessKind::CACK_Similar)
|
2017-07-04 01:59:22 +08:00
|
|
|
return;
|
|
|
|
|
2018-07-11 07:04:35 +08:00
|
|
|
// FIXME: 'restrict' is not properly handled here.
|
2017-07-04 01:59:22 +08:00
|
|
|
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)
|
2018-08-10 05:08:08 +08:00
|
|
|
Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual2)
|
2017-07-04 01:59:22 +08:00
|
|
|
<< SrcType << DestType;
|
|
|
|
else
|
2018-08-10 05:08:08 +08:00
|
|
|
Self.Diag(SrcExpr.get()->getBeginLoc(), diag::warn_cast_qual)
|
2017-07-04 01:59:22 +08:00
|
|
|
<< TheOffendingSrcType << TheOffendingDestType << qualifiers;
|
2011-10-07 07:25:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
|
|
|
|
TypeSourceInfo *CastTypeInfo,
|
|
|
|
SourceLocation RPLoc,
|
|
|
|
Expr *CastExpr) {
|
2018-07-31 03:24:48 +08:00
|
|
|
CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
|
2011-10-05 15:41:44 +08:00
|
|
|
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
|
2018-08-10 05:09:38 +08:00
|
|
|
Op.OpRange = SourceRange(LPLoc, CastExpr->getEndLoc());
|
2011-10-05 15:41:44 +08:00
|
|
|
|
2012-03-11 15:00:24 +08:00
|
|
|
if (getLangOpts().CPlusPlus) {
|
2019-07-16 12:46:31 +08:00
|
|
|
Op.CheckCXXCStyleCast(/*FunctionalCast=*/ false,
|
2012-02-13 02:41:05 +08:00
|
|
|
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();
|
|
|
|
|
2017-07-04 01:59:22 +08:00
|
|
|
// -Wcast-qual
|
|
|
|
DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType);
|
|
|
|
|
2020-09-12 22:54:14 +08:00
|
|
|
return Op.complete(CStyleCastExpr::Create(
|
|
|
|
Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.get(),
|
|
|
|
&Op.BasePath, CurFPFeatureOverrides(), CastTypeInfo, LPLoc, RPLoc));
|
2011-10-05 15:41:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
|
2017-02-10 03:17:44 +08:00
|
|
|
QualType Type,
|
2011-10-05 15:41:44 +08:00
|
|
|
SourceLocation LPLoc,
|
|
|
|
Expr *CastExpr,
|
|
|
|
SourceLocation RPLoc) {
|
2012-02-14 03:55:43 +08:00
|
|
|
assert(LPLoc.isValid() && "List-initialization shouldn't get here.");
|
2017-02-10 03:17:44 +08:00
|
|
|
CastOperation Op(*this, Type, CastExpr);
|
2011-10-05 15:41:44 +08:00
|
|
|
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
|
2018-08-10 05:09:38 +08:00
|
|
|
Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getEndLoc());
|
2011-10-05 15:41:44 +08:00
|
|
|
|
2019-07-16 12:46:31 +08:00
|
|
|
Op.CheckCXXCStyleCast(/*FunctionalCast=*/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
|
|
|
|
2020-09-12 22:54:14 +08:00
|
|
|
return Op.complete(CXXFunctionalCastExpr::Create(
|
|
|
|
Context, Op.ResultType, Op.ValueKind, CastTypeInfo, Op.Kind,
|
|
|
|
Op.SrcExpr.get(), &Op.BasePath, CurFPFeatureOverrides(), LPLoc, RPLoc));
|
2008-11-06 05:50:06 +08:00
|
|
|
}
|