Improve our handling of (C++) references within Clang. Specifically:
- Do not allow expressions to ever have reference type
- Extend Expr::isLvalue to handle more cases where having written a
reference into the source implies that the expression is an lvalue
(e.g., function calls, C++ casts).
- Make GRExprEngine::VisitCall treat the call arguments as lvalues when
they are being bound to a reference parameter.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58306 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 1380264..f330444 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -393,6 +393,20 @@
break;
case ParenExprClass: // C99 6.5.1p5
return cast<ParenExpr>(this)->getSubExpr()->isLvalue(Ctx);
+ case CallExprClass: {
+ // C++ [expr.call]p10:
+ // A function call is an lvalue if and only if the result type
+ // is a reference.
+ QualType CalleeType
+ = dyn_cast<CallExpr>(this)->getCallee()->IgnoreParens()->getType();
+ if (const PointerType *FnTypePtr = CalleeType->getAsPointerType())
+ if (const FunctionType *FnType
+ = FnTypePtr->getPointeeType()->getAsFunctionType())
+ if (FnType->getResultType()->isReferenceType())
+ return LV_Valid;
+
+ break;
+ }
case CompoundLiteralExprClass: // C99 6.5.2.5p5
return LV_Valid;
case ExtVectorElementExprClass:
@@ -407,10 +421,25 @@
return (cast<PredefinedExpr>(this)->getIdentType()
== PredefinedExpr::CXXThis
? LV_InvalidExpression : LV_Valid);
+ case VAArgExprClass:
+ return LV_Valid;
case CXXDefaultArgExprClass:
return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);
case CXXConditionDeclExprClass:
return LV_Valid;
+ case ExplicitCCastExprClass:
+ case CXXFunctionalCastExprClass:
+ case CXXStaticCastExprClass:
+ case CXXDynamicCastExprClass:
+ case CXXReinterpretCastExprClass:
+ case CXXConstCastExprClass:
+ // The result of an explicit cast is an lvalue if the type we are
+ // casting to is a reference type. See C++ [expr.cast]p1,
+ // C++ [expr.static.cast]p2, C++ [expr.dynamic.cast]p2,
+ // C++ [expr.reinterpret.cast]p1, C++ [expr.const.cast]p1.
+ if (cast<ExplicitCastExpr>(this)->getTypeAsWritten()->isReferenceType())
+ return LV_Valid;
+ break;
default:
break;
}