Calculate the value kind of an expression when it's created and
store it on the expression node. Also store an "object kind",
which distinguishes ordinary "addressed" l-values (like
variable references and pointer dereferences) and bitfield,
@property, and vector-component l-values.
Currently we're not using these for much, but I aim to switch
pretty much everything calculating l-valueness over to them.
For now they shouldn't necessarily be trusted.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119685 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 70e9a97..fbd36fd 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -605,9 +605,10 @@
//
if (NumExprs == 1) {
CastKind Kind = CK_Invalid;
+ ExprValueKind VK = VK_RValue;
CXXCastPath BasePath;
if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0],
- Kind, BasePath,
+ Kind, VK, BasePath,
/*FunctionalStyle=*/true))
return ExprError();
@@ -615,7 +616,7 @@
return Owned(CXXFunctionalCastExpr::Create(Context,
Ty.getNonLValueExprType(Context),
- TInfo, TyBeginLoc, Kind,
+ VK, TInfo, TyBeginLoc, Kind,
Exprs[0], &BasePath,
RParenLoc));
}
@@ -1582,8 +1583,8 @@
/// \brief Check the use of the given variable as a C++ condition in an if,
/// while, do-while, or switch statement.
ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar,
- SourceLocation StmtLoc,
- bool ConvertToBoolean) {
+ SourceLocation StmtLoc,
+ bool ConvertToBoolean) {
QualType T = ConditionVar->getType();
// C++ [stmt.select]p2:
@@ -1599,7 +1600,8 @@
Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
ConditionVar->getLocation(),
- ConditionVar->getType().getNonReferenceType());
+ ConditionVar->getType().getNonReferenceType(),
+ Expr::getValueKindForType(ConditionVar->getType()));
if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc))
return ExprError();
@@ -2331,8 +2333,10 @@
RParen, Context.BoolTy));
}
-QualType Sema::CheckPointerToMemberOperands(
- Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect) {
+QualType Sema::CheckPointerToMemberOperands(Expr *&lex, Expr *&rex,
+ ExprValueKind &VK,
+ SourceLocation Loc,
+ bool isIndirect) {
const char *OpSpelling = isIndirect ? "->*" : ".*";
// C++ 5.5p2
// The binary operator .* [p3: ->*] binds its second operand, which shall
@@ -2361,7 +2365,7 @@
QualType LType = lex->getType();
if (isIndirect) {
if (const PointerType *Ptr = LType->getAs<PointerType>())
- LType = Ptr->getPointeeType().getNonReferenceType();
+ LType = Ptr->getPointeeType();
else {
Diag(Loc, diag::err_bad_memptr_lhs)
<< OpSpelling << 1 << LType
@@ -2402,6 +2406,7 @@
Diag(Loc, diag::err_pointer_to_member_type) << isIndirect;
return QualType();
}
+
// C++ 5.5p2
// The result is an object or a function of the type specified by the
// second operand.
@@ -2416,6 +2421,21 @@
// We probably need a "MemberFunctionClosureType" or something like that.
QualType Result = MemPtr->getPointeeType();
Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
+
+ // C++ [expr.mptr.oper]p6:
+ // The result of a .* expression whose second operand is a pointer
+ // to a data member is of the same value category as its
+ // first operand. The result of a .* expression whose second
+ // operand is a pointer to a member function is a prvalue. The
+ // result of an ->* expression is an lvalue if its second operand
+ // is a pointer to data member and a prvalue otherwise.
+ if (Result->isFunctionType())
+ VK = VK_RValue;
+ else if (isIndirect)
+ VK = VK_LValue;
+ else
+ VK = lex->getValueKind();
+
return Result;
}
@@ -2573,7 +2593,7 @@
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
- Expr *&SAVE,
+ Expr *&SAVE, ExprValueKind &VK,
SourceLocation QuestionLoc) {
// FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
// interface pointers.
@@ -2591,6 +2611,9 @@
return QualType();
}
+ // Assume r-value.
+ VK = VK_RValue;
+
// Either of the arguments dependent?
if (LHS->isTypeDependent() || RHS->isTypeDependent())
return Context.DependentTy;
@@ -2670,19 +2693,20 @@
}
// C++0x 5.16p4
- // If the second and third operands are lvalues and have the same type,
- // the result is of that type [...]
+ // If the second and third operands are glvalues of the same value
+ // category and have the same type, the result is of that type and
+ // value category and it is a bit-field if the second or the third
+ // operand is a bit-field, or if both are bit-fields.
+ // We can't support the bitfield parts of that correctly right now,
+ // though, so we just require both sides to be ordinary values.
bool Same = Context.hasSameType(LTy, RTy);
- if (Same && LHS->isLvalue(Context) == Expr::LV_Valid &&
- RHS->isLvalue(Context) == Expr::LV_Valid) {
- // In this context, property reference is really a message call and
- // is not considered an l-value.
- bool lhsProperty = (isa<ObjCPropertyRefExpr>(LHS) ||
- isa<ObjCImplicitSetterGetterRefExpr>(LHS));
- bool rhsProperty = (isa<ObjCPropertyRefExpr>(RHS) ||
- isa<ObjCImplicitSetterGetterRefExpr>(RHS));
- if (!lhsProperty && !rhsProperty)
- return LTy;
+ if (Same &&
+ LHS->getValueKind() != VK_RValue &&
+ LHS->getValueKind() == RHS->getValueKind() &&
+ LHS->getObjectKind() == OK_Ordinary &&
+ RHS->getObjectKind() == OK_Ordinary) {
+ VK = LHS->getValueKind();
+ return LTy;
}
// C++0x 5.16p5
@@ -3456,11 +3480,15 @@
MemberExpr *ME =
new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method,
- SourceLocation(), Method->getType());
- QualType ResultType = Method->getCallResultType();
+ SourceLocation(), Method->getType(),
+ VK_RValue, OK_Ordinary);
+ QualType ResultType = Method->getResultType();
+ ExprValueKind VK = Expr::getValueKindForType(ResultType);
+ ResultType = ResultType.getNonLValueExprType(Context);
+
MarkDeclarationReferenced(Exp->getLocStart(), Method);
CXXMemberCallExpr *CE =
- new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType,
+ new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK,
Exp->getLocEnd());
return CE;
}