//===--- SemaNamedCast.cpp - Semantic Analysis for Named Casts ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements semantic analysis for C++ named casts.
//
//===----------------------------------------------------------------------===//
#include "Sema.h"
#include "SemaInherit.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/SmallVector.h"
#include <set>
using namespace clang;
enum TryStaticCastResult {
TSC_NotApplicable, ///< The cast method is not applicable.
TSC_Success, ///< The cast method is appropriate and successful.
TSC_Failed ///< The cast method is appropriate, but failed. A
///< diagnostic has been emitted.
};
static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange);
static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange);
static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange);
static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange,
const SourceRange &DestRange);
static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType);
static TryStaticCastResult TryLValueToRValueCast(
Sema &Self, Expr *SrcExpr, QualType DestType, const SourceRange &OpRange);
static TryStaticCastResult TryStaticReferenceDowncast(
Sema &Self, Expr *SrcExpr, QualType DestType, const SourceRange &OpRange);
static TryStaticCastResult TryStaticPointerDowncast(
Sema &Self, QualType SrcType, QualType DestType, const SourceRange &OpRange);
static TryStaticCastResult TryStaticMemberPointerUpcast(
Sema &Self, QualType SrcType, QualType DestType, const SourceRange &OpRange);
static TryStaticCastResult TryStaticDowncast(Sema &Self, QualType SrcType,
QualType DestType,
const SourceRange &OpRange,
QualType OrigSrcType,
QualType OrigDestType);
static TryStaticCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr,
QualType DestType,
const SourceRange &OpRange);
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
Action::OwningExprResult
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
SourceLocation LAngleBracketLoc, TypeTy *Ty,
SourceLocation RAngleBracketLoc,
SourceLocation LParenLoc, ExprArg E,
SourceLocation RParenLoc) {
Expr *Ex = E.takeAs<Expr>();
QualType DestType = QualType::getFromOpaquePtr(Ty);
SourceRange OpRange(OpLoc, RParenLoc);
SourceRange DestRange(LAngleBracketLoc, RAngleBracketLoc);
// If the type is dependent, we won't do the semantic analysis now.
// FIXME: should we check this in a more fine-grained manner?
bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent();
switch (Kind) {
default: assert(0 && "Unknown C++ cast!");
case tok::kw_const_cast:
if (!TypeDependent)
CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
return Owned(new (Context) CXXConstCastExpr(DestType.getNonReferenceType(),
Ex, DestType, OpLoc));
case tok::kw_dynamic_cast:
if (!TypeDependent)
CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange);
return Owned(new (Context)CXXDynamicCastExpr(DestType.getNonReferenceType(),
Ex, DestType, OpLoc));
case tok::kw_reinterpret_cast:
if (!TypeDependent)
CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange);
return Owned(new (Context) CXXReinterpretCastExpr(
DestType.getNonReferenceType(),
Ex, DestType, OpLoc));
case tok::kw_static_cast:
if (!TypeDependent)
CheckStaticCast(*this, Ex, DestType, OpRange);
return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(),
Ex, DestType, OpLoc));
}
return ExprError();
}
/// 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));
void
CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
const SourceRange &OpRange, const SourceRange &DestRange)
{
QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
DestType = Self.Context.getCanonicalType