зеркало из https://github.com/microsoft/clang-1.git
Fix handling of the GNU "t ? : f" extension to the conditional
operator in C++, and verify that template instantiation for the condition operator does the right thing. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72127 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
6731c31150
Коммит
d5f3a0fde4
|
@ -828,16 +828,16 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
|
|||
// casts should be wrapped by ImplicitCastExprs. There's just the special
|
||||
// case involving throws to work out.
|
||||
const ConditionalOperator *Cond = cast<ConditionalOperator>(this);
|
||||
Expr *LHS = Cond->getLHS();
|
||||
Expr *RHS = Cond->getRHS();
|
||||
Expr *True = Cond->getTrueExpr();
|
||||
Expr *False = Cond->getFalseExpr();
|
||||
// C++0x 5.16p2
|
||||
// If either the second or the third operand has type (cv) void, [...]
|
||||
// the result [...] is an rvalue.
|
||||
if (LHS->getType()->isVoidType() || RHS->getType()->isVoidType())
|
||||
if (True->getType()->isVoidType() || False->getType()->isVoidType())
|
||||
return LV_InvalidExpression;
|
||||
|
||||
// Both sides must be lvalues for the result to be an lvalue.
|
||||
if (LHS->isLvalue(Ctx) != LV_Valid || RHS->isLvalue(Ctx) != LV_Valid)
|
||||
if (True->isLvalue(Ctx) != LV_Valid || False->isLvalue(Ctx) != LV_Valid)
|
||||
return LV_InvalidExpression;
|
||||
|
||||
// That's it.
|
||||
|
|
|
@ -427,13 +427,13 @@ TemplateExprInstantiator::VisitConditionalOperator(ConditionalOperator *E) {
|
|||
if (Cond.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
// FIXME: use getLHS() and cope with NULLness
|
||||
Sema::OwningExprResult True = Visit(E->getTrueExpr());
|
||||
if (True.isInvalid())
|
||||
Sema::OwningExprResult LHS = SemaRef.InstantiateExpr(E->getLHS(),
|
||||
TemplateArgs);
|
||||
if (LHS.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
Sema::OwningExprResult False = Visit(E->getFalseExpr());
|
||||
if (False.isInvalid())
|
||||
Sema::OwningExprResult RHS = Visit(E->getRHS());
|
||||
if (RHS.isInvalid())
|
||||
return SemaRef.ExprError();
|
||||
|
||||
if (!E->isTypeDependent()) {
|
||||
|
@ -442,15 +442,15 @@ TemplateExprInstantiator::VisitConditionalOperator(ConditionalOperator *E) {
|
|||
// Instead, we just build the new conditional operator call expression.
|
||||
return SemaRef.Owned(new (SemaRef.Context) ConditionalOperator(
|
||||
Cond.takeAs<Expr>(),
|
||||
True.takeAs<Expr>(),
|
||||
False.takeAs<Expr>(),
|
||||
LHS.takeAs<Expr>(),
|
||||
RHS.takeAs<Expr>(),
|
||||
E->getType()));
|
||||
}
|
||||
|
||||
|
||||
return SemaRef.ActOnConditionalOp(/*FIXME*/E->getCond()->getLocEnd(),
|
||||
/*FIXME*/E->getFalseExpr()->getLocStart(),
|
||||
move(Cond), move(True), move(False));
|
||||
move(Cond), move(LHS), move(RHS));
|
||||
}
|
||||
|
||||
Sema::OwningExprResult
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// RUN: clang-cc -fsyntax-only -verify %s
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Imaginary literals
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T>
|
||||
struct ImaginaryLiteral0 {
|
||||
void f(T &x) {
|
||||
|
@ -10,6 +13,9 @@ struct ImaginaryLiteral0 {
|
|||
template struct ImaginaryLiteral0<_Complex float>;
|
||||
template struct ImaginaryLiteral0<int*>; // expected-note{{instantiation}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Compound assignment operator
|
||||
// ---------------------------------------------------------------------
|
||||
namespace N1 {
|
||||
struct X { };
|
||||
|
||||
|
@ -38,3 +44,15 @@ template struct N2::PlusEquals0<N1::X, long, long&>;
|
|||
template struct N2::PlusEquals0<N3::Y, long, short&>;
|
||||
template struct N2::PlusEquals0<int, int, int&>;
|
||||
template struct N2::PlusEquals0<N3::Y, int, short&>; // expected-note{{instantiation}}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Conditional operator
|
||||
// ---------------------------------------------------------------------
|
||||
template<typename T, typename U, typename Result>
|
||||
struct Conditional0 {
|
||||
void f(T t, U u) {
|
||||
Result result = t? : u;
|
||||
}
|
||||
};
|
||||
|
||||
template struct Conditional0<int, int, int>;
|
||||
|
|
Загрузка…
Ссылка в новой задаче