aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-05-19 20:13:50 +0000
committerDouglas Gregor <dgregor@apple.com>2009-05-19 20:13:50 +0000
commitd5f3a0fde43bca9f3738aed931b0f13ca73a9f11 (patch)
tree587d9da355a2cd9fbd8e7e3082e812f587ea54cc
parent6731c31150524b365138e5b8f46e6a4751a7c391 (diff)
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
-rw-r--r--lib/AST/Expr.cpp8
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp16
-rw-r--r--test/SemaTemplate/instantiate-expr-3.cpp18
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<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.
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<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
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<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>;