From d5f3a0fde43bca9f3738aed931b0f13ca73a9f11 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 19 May 2009 20:13:50 +0000 Subject: [PATCH] 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 --- lib/AST/Expr.cpp | 8 ++++---- lib/Sema/SemaTemplateInstantiateExpr.cpp | 16 ++++++++-------- test/SemaTemplate/instantiate-expr-3.cpp | 18 ++++++++++++++++++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6bafdf278d..2df76a2904 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -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(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. diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 9dda383342..2589e301e0 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -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(), - True.takeAs(), - False.takeAs(), + LHS.takeAs(), + RHS.takeAs(), 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 diff --git a/test/SemaTemplate/instantiate-expr-3.cpp b/test/SemaTemplate/instantiate-expr-3.cpp index 892f649ef7..7f54c5de3c 100644 --- a/test/SemaTemplate/instantiate-expr-3.cpp +++ b/test/SemaTemplate/instantiate-expr-3.cpp @@ -1,5 +1,8 @@ // RUN: clang-cc -fsyntax-only -verify %s +// --------------------------------------------------------------------- +// Imaginary literals +// --------------------------------------------------------------------- template struct ImaginaryLiteral0 { void f(T &x) { @@ -10,6 +13,9 @@ struct ImaginaryLiteral0 { template struct ImaginaryLiteral0<_Complex float>; template struct ImaginaryLiteral0; // expected-note{{instantiation}} +// --------------------------------------------------------------------- +// Compound assignment operator +// --------------------------------------------------------------------- namespace N1 { struct X { }; @@ -38,3 +44,15 @@ template struct N2::PlusEquals0; template struct N2::PlusEquals0; template struct N2::PlusEquals0; template struct N2::PlusEquals0; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// Conditional operator +// --------------------------------------------------------------------- +template +struct Conditional0 { + void f(T t, U u) { + Result result = t? : u; + } +}; + +template struct Conditional0; -- 2.40.0