forked from OSchip/llvm-project
Template instantiation for cast expressions.
llvm-svn: 72119
This commit is contained in:
parent
8370964257
commit
71b6a37bc4
|
@ -114,6 +114,11 @@ protected:
|
|||
public:
|
||||
const char *getCastName() const;
|
||||
|
||||
/// \brief Retrieve the location of the cast operator keyword, e.g.,
|
||||
/// "static_cast".
|
||||
SourceLocation getOperatorLoc() const { return Loc; }
|
||||
void setOperatorLoc(SourceLocation L) { Loc = L; }
|
||||
|
||||
virtual SourceRange getSourceRange() const {
|
||||
return SourceRange(Loc, getSubExpr()->getSourceRange().getEnd());
|
||||
}
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace {
|
|||
OwningExprResult VisitUnaryOperator(UnaryOperator *E);
|
||||
OwningExprResult VisitArraySubscriptExpr(ArraySubscriptExpr *E);
|
||||
OwningExprResult VisitCallExpr(CallExpr *E);
|
||||
// FIXME: VisitMemberExpr
|
||||
// FIXME: CompoundLiteralExpr
|
||||
OwningExprResult VisitBinaryOperator(BinaryOperator *E);
|
||||
OwningExprResult VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E);
|
||||
OwningExprResult VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E);
|
||||
|
@ -54,7 +56,15 @@ namespace {
|
|||
OwningExprResult VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
|
||||
OwningExprResult VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E);
|
||||
OwningExprResult VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E);
|
||||
OwningExprResult VisitCastExpr(CastExpr *E);
|
||||
OwningExprResult VisitImplicitCastExpr(ImplicitCastExpr *E);
|
||||
OwningExprResult VisitExplicitCastExpr(ExplicitCastExpr *E);
|
||||
OwningExprResult VisitCStyleCastExpr(CStyleCastExpr *E);
|
||||
OwningExprResult VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
|
||||
OwningExprResult VisitCXXStaticCastExpr(CXXStaticCastExpr *E);
|
||||
OwningExprResult VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E);
|
||||
OwningExprResult VisitCXXReinterpretCastExpr(CXXReinterpretCastExpr *E);
|
||||
OwningExprResult VisitCXXConstCastExpr(CXXConstCastExpr *E);
|
||||
OwningExprResult VisitCXXThisExpr(CXXThisExpr *E);
|
||||
OwningExprResult VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E);
|
||||
OwningExprResult VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E);
|
||||
|
@ -546,6 +556,11 @@ TemplateExprInstantiator::VisitCXXTemporaryObjectExpr(
|
|||
return SemaRef.ExprError();
|
||||
}
|
||||
|
||||
Sema::OwningExprResult TemplateExprInstantiator::VisitCastExpr(CastExpr *E) {
|
||||
assert(false && "Cannot instantiate abstract CastExpr");
|
||||
return SemaRef.ExprError();
|
||||
}
|
||||
|
||||
Sema::OwningExprResult TemplateExprInstantiator::VisitImplicitCastExpr(
|
||||
ImplicitCastExpr *E) {
|
||||
assert(!E->isTypeDependent() && "Implicit casts must have known types");
|
||||
|
@ -561,6 +576,112 @@ Sema::OwningExprResult TemplateExprInstantiator::VisitImplicitCastExpr(
|
|||
return SemaRef.Owned(ICE);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitExplicitCastExpr(ExplicitCastExpr *E) {
|
||||
assert(false && "Cannot instantiate abstract ExplicitCastExpr");
|
||||
return SemaRef.ExprError();
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCStyleCastExpr(CStyleCastExpr *E) {
|
||||
// Instantiate the type that we're casting to.
|
||||
SourceLocation TypeStartLoc
|
||||
= SemaRef.PP.getLocForEndOfToken(E->getLParenLoc());
|
||||
QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(),
|
||||
TemplateArgs,
|
||||
TypeStartLoc,
|
||||
DeclarationName());
|
||||
if (ExplicitTy.isNull())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
// Instantiate the subexpression.
|
||||
OwningExprResult SubExpr = Visit(E->getSubExpr());
|
||||
if (SubExpr.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
return SemaRef.ActOnCastExpr(E->getLParenLoc(),
|
||||
ExplicitTy.getAsOpaquePtr(),
|
||||
E->getRParenLoc(),
|
||||
move(SubExpr));
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) {
|
||||
// Figure out which cast operator we're dealing with.
|
||||
tok::TokenKind Kind;
|
||||
switch (E->getStmtClass()) {
|
||||
case Stmt::CXXStaticCastExprClass:
|
||||
Kind = tok::kw_static_cast;
|
||||
break;
|
||||
|
||||
case Stmt::CXXDynamicCastExprClass:
|
||||
Kind = tok::kw_dynamic_cast;
|
||||
break;
|
||||
|
||||
case Stmt::CXXReinterpretCastExprClass:
|
||||
Kind = tok::kw_reinterpret_cast;
|
||||
break;
|
||||
|
||||
case Stmt::CXXConstCastExprClass:
|
||||
Kind = tok::kw_const_cast;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false && "Invalid C++ named cast");
|
||||
return SemaRef.ExprError();
|
||||
}
|
||||
|
||||
// Instantiate the type that we're casting to.
|
||||
SourceLocation TypeStartLoc
|
||||
= SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
|
||||
QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(),
|
||||
TemplateArgs,
|
||||
TypeStartLoc,
|
||||
DeclarationName());
|
||||
if (ExplicitTy.isNull())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
// Instantiate the subexpression.
|
||||
OwningExprResult SubExpr = Visit(E->getSubExpr());
|
||||
if (SubExpr.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
SourceLocation FakeLAngleLoc
|
||||
= SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc());
|
||||
SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin();
|
||||
SourceLocation FakeRParenLoc
|
||||
= SemaRef.PP.getLocForEndOfToken(
|
||||
E->getSubExpr()->getSourceRange().getEnd());
|
||||
return SemaRef.ActOnCXXNamedCast(E->getOperatorLoc(), Kind,
|
||||
/*FIXME:*/FakeLAngleLoc,
|
||||
ExplicitTy.getAsOpaquePtr(),
|
||||
/*FIXME:*/FakeRAngleLoc,
|
||||
/*FIXME:*/FakeRAngleLoc,
|
||||
move(SubExpr),
|
||||
/*FIXME:*/FakeRParenLoc);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) {
|
||||
return VisitCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) {
|
||||
return VisitCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXReinterpretCastExpr(
|
||||
CXXReinterpretCastExpr *E) {
|
||||
return VisitCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXConstCastExpr(CXXConstCastExpr *E) {
|
||||
return VisitCXXNamedCastExpr(E);
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
TemplateExprInstantiator::VisitCXXThisExpr(CXXThisExpr *E) {
|
||||
QualType ThisType =
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
struct A { int x; };
|
||||
|
||||
class Base {
|
||||
public:
|
||||
virtual void f();
|
||||
};
|
||||
|
||||
class Derived : public Base { };
|
||||
|
||||
struct ConvertibleToInt {
|
||||
operator int() const;
|
||||
};
|
||||
|
||||
struct Constructible {
|
||||
Constructible(int, float);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// C-style casts
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename U>
|
||||
struct CStyleCast0 {
|
||||
void f(T t) {
|
||||
(void)((U)t); // FIXME:ugly expected-error{{operand}}
|
||||
}
|
||||
};
|
||||
|
||||
template struct CStyleCast0<int, float>;
|
||||
template struct CStyleCast0<A, int>; // expected-note{{instantiation}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// static_cast
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename U>
|
||||
struct StaticCast0 {
|
||||
void f(T t) {
|
||||
(void)static_cast<U>(t); // expected-error{{static_cast}}
|
||||
}
|
||||
};
|
||||
|
||||
template struct StaticCast0<ConvertibleToInt, bool>;
|
||||
template struct StaticCast0<int, float>;
|
||||
template struct StaticCast0<int, A>; // expected-note{{instantiation}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// dynamic_cast
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename U>
|
||||
struct DynamicCast0 {
|
||||
void f(T t) {
|
||||
(void)dynamic_cast<U>(t); // expected-error{{not a reference or pointer}}
|
||||
}
|
||||
};
|
||||
|
||||
template struct DynamicCast0<Base*, Derived*>;
|
||||
template struct DynamicCast0<Base*, A>; // expected-note{{instantiation}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// reinterpret_cast
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename U>
|
||||
struct ReinterpretCast0 {
|
||||
void f(T t) {
|
||||
(void)reinterpret_cast<U>(t); // expected-error{{constness}}
|
||||
}
|
||||
};
|
||||
|
||||
template struct ReinterpretCast0<void (*)(int), void (*)(float)>;
|
||||
template struct ReinterpretCast0<int const *, float *>; // expected-note{{instantiation}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// const_cast
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename U>
|
||||
struct ConstCast0 {
|
||||
void f(T t) {
|
||||
(void)const_cast<U>(t); // expected-error{{not allowed}}
|
||||
}
|
||||
};
|
||||
|
||||
template struct ConstCast0<int const * *, int * *>;
|
||||
template struct ConstCast0<int const *, float *>; // expected-note{{instantiation}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// C++ functional cast
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename U>
|
||||
struct FunctionalCast1 {
|
||||
void f(T t) {
|
||||
(void)U(t); // FIXME:ugly expected-error{{operand}}
|
||||
}
|
||||
};
|
||||
|
||||
template struct FunctionalCast1<int, float>;
|
||||
template struct FunctionalCast1<A, int>; // expected-note{{instantiation}}
|
||||
|
||||
#if 0
|
||||
// Generates temporaries, which we cannot handle yet.
|
||||
template<int N, long M>
|
||||
struct FunctionalCast2 {
|
||||
void f() {
|
||||
(void)Constructible(N, M);
|
||||
}
|
||||
};
|
||||
|
||||
template struct FunctionalCast2<1, 3>;
|
||||
#endif
|
Loading…
Reference in New Issue