aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-11-18 06:31:45 +0000
committerJohn McCall <rjmccall@apple.com>2010-11-18 06:31:45 +0000
commitf89e55ab1bfb3ea997f8b02997c611a02254eb2d (patch)
treecacb763638dfa30e56adfe71a8ab73cd8b19eb64 /lib/Sema
parent6a02b609c2e23b28d24f9db4c8006137c6b55ae4 (diff)
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
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaCXXCast.cpp55
-rw-r--r--lib/Sema/SemaChecking.cpp5
-rw-r--r--lib/Sema/SemaDeclCXX.cpp35
-rw-r--r--lib/Sema/SemaExpr.cpp218
-rw-r--r--lib/Sema/SemaExprCXX.cpp76
-rw-r--r--lib/Sema/SemaExprObjC.cpp57
-rw-r--r--lib/Sema/SemaObjCProperty.cpp12
-rw-r--r--lib/Sema/SemaOverload.cpp108
-rw-r--r--lib/Sema/SemaTemplate.cpp20
-rw-r--r--lib/Sema/TreeTransform.h54
10 files changed, 416 insertions, 224 deletions
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index e57e89e4a4..06c2758a9b 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -44,17 +44,21 @@ enum CastType {
static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
const SourceRange &OpRange,
const SourceRange &DestRange);
static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
const SourceRange &OpRange,
const SourceRange &DestRange,
CastKind &Kind);
static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
const SourceRange &OpRange,
CastKind &Kind,
CXXCastPath &BasePath);
static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+ ExprValueKind &VK,
const SourceRange &OpRange,
const SourceRange &DestRange,
CastKind &Kind,
@@ -156,44 +160,46 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
Diag(Ex->getLocStart(), diag::err_invalid_use_of_bound_member_func)
<< Ex->getSourceRange();
+ ExprValueKind VK = VK_RValue;
switch (Kind) {
default: llvm_unreachable("Unknown C++ cast!");
case tok::kw_const_cast:
if (!TypeDependent)
- CheckConstCast(*this, Ex, DestType, OpRange, DestRange);
+ CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange);
return Owned(CXXConstCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Ex, DestTInfo, OpLoc));
+ VK, Ex, DestTInfo, OpLoc));
case tok::kw_dynamic_cast: {
CastKind Kind = CK_Dependent;
CXXCastPath BasePath;
if (!TypeDependent)
- CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath);
+ CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange,
+ Kind, BasePath);
return Owned(CXXDynamicCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, &BasePath, DestTInfo,
+ VK, Kind, Ex, &BasePath, DestTInfo,
OpLoc));
}
case tok::kw_reinterpret_cast: {
CastKind Kind = CK_Dependent;
if (!TypeDependent)
- CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
+ CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind);
return Owned(CXXReinterpretCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, 0,
+ VK, Kind, Ex, 0,
DestTInfo, OpLoc));
}
case tok::kw_static_cast: {
CastKind Kind = CK_Dependent;
CXXCastPath BasePath;
if (!TypeDependent)
- CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath);
+ CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath);
return Owned(CXXStaticCastExpr::Create(Context,
DestType.getNonLValueExprType(Context),
- Kind, Ex, &BasePath,
+ VK, Kind, Ex, &BasePath,
DestTInfo, OpLoc));
}
}
@@ -315,7 +321,7 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {
/// checked downcasts in class hierarchies.
static void
CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
- const SourceRange &OpRange,
+ ExprValueKind &VK, const SourceRange &OpRange,
const SourceRange &DestRange, CastKind &Kind,
CXXCastPath &BasePath) {
QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType();
@@ -326,11 +332,12 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
QualType DestPointee;
const PointerType *DestPointer = DestType->getAs<PointerType>();
- const ReferenceType *DestReference = DestType->getAs<ReferenceType>();
+ const ReferenceType *DestReference = 0;
if (DestPointer) {
DestPointee = DestPointer->getPointeeType();
- } else if (DestReference) {
+ } else if ((DestReference = DestType->getAs<ReferenceType>())) {
DestPointee = DestReference->getPointeeType();
+ VK = isa<LValueReferenceType>(DestReference) ? VK_LValue : VK_RValue;
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
<< OrigDestType << DestRange;
@@ -447,9 +454,10 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// const char *str = "literal";
/// legacy_function(const_cast\<char*\>(str));
void
-CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
+CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, ExprValueKind &VK,
const SourceRange &OpRange, const SourceRange &DestRange) {
- if (!DestType->isLValueReferenceType())
+ VK = Expr::getValueKindForType(DestType);
+ if (VK == VK_RValue)
Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
@@ -466,9 +474,10 @@ CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
void
CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
- const SourceRange &OpRange, const SourceRange &DestRange,
- CastKind &Kind) {
- if (!DestType->isLValueReferenceType())
+ ExprValueKind &VK, const SourceRange &OpRange,
+ const SourceRange &DestRange, CastKind &Kind) {
+ VK = Expr::getValueKindForType(DestType);
+ if (VK == VK_RValue)
Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
@@ -498,8 +507,8 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/// implicit conversions explicit and getting rid of data loss warnings.
void
CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
- const SourceRange &OpRange, CastKind &Kind,
- CXXCastPath &BasePath) {
+ ExprValueKind &VK, const SourceRange &OpRange,
+ CastKind &Kind, CXXCastPath &BasePath) {
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -508,7 +517,8 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
return;
}
- if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
+ VK = Expr::getValueKindForType(DestType);
+ if (VK == VK_RValue && !DestType->isRecordType())
Self.DefaultFunctionArrayLvalueConversion(SrcExpr);
unsigned msg = diag::err_bad_cxx_cast_generic;
@@ -1345,8 +1355,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
}
bool
-Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
- CastKind &Kind,
+Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
+ Expr *&CastExpr, CastKind &Kind,
CXXCastPath &BasePath,
bool FunctionalStyle) {
if (CastExpr->isBoundMemberFunction(Context))
@@ -1368,7 +1378,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
return false;
}
- if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
+ VK = Expr::getValueKindForType(CastTy);
+ if (VK == VK_RValue && !CastTy->isRecordType())
DefaultFunctionArrayLvalueConversion(CastExpr);
// C++ [expr.cast]p5: The conversions performed by
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index d04addd210..ed45de53f2 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -487,8 +487,9 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// GCC does an implicit conversion to the pointer or integer ValType. This
// can fail in some cases (1i -> int**), check for this error case now.
CastKind Kind = CK_Invalid;
+ ExprValueKind VK = VK_RValue;
CXXCastPath BasePath;
- if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath))
+ if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, VK, BasePath))
return ExprError();
// Okay, we have something that *can* be converted to the right type. Check
@@ -497,7 +498,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// pass in 42. The 42 gets converted to char. This is even more strange
// for things like 45.123 -> char, etc.
// FIXME: Do this check.
- ImpCastExprToType(Arg, ValType, Kind, VK_RValue, &BasePath);
+ ImpCastExprToType(Arg, ValType, Kind, VK, &BasePath);
TheCall->setArg(i+1, Arg);
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index f7638f80d9..77f604a653 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1515,7 +1515,8 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
Expr *CopyCtorArg =
DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param,
- Constructor->getLocation(), ParamType, 0);
+ Constructor->getLocation(), ParamType,
+ VK_LValue, 0);
// Cast to the base class to avoid ambiguities.
QualType ArgTy =
@@ -1577,7 +1578,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
Expr *MemberExprBase =
DeclRefExpr::Create(SemaRef.Context, 0, SourceRange(), Param,
- Loc, ParamType, 0);
+ Loc, ParamType, VK_LValue, 0);
// Build a reference to this field within the parameter.
CXXScopeSpec SS;
@@ -1622,7 +1623,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
// Create a reference to the iteration variable.
ExprResult IterationVarRef
- = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, Loc);
+ = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc);
assert(!IterationVarRef.isInvalid() &&
"Reference to invented variable cannot fail!");
@@ -4635,7 +4636,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
// Create a reference to the iteration variable; we'll use this several
// times throughout.
Expr *IterationVarRef
- = S.BuildDeclRefExpr(IterationVar, SizeType, Loc).takeAs<Expr>();
+ = S.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc).take();
assert(IterationVarRef && "Reference to invented variable cannot fail!");
// Create the DeclStmt that holds the iteration variable.
@@ -4646,15 +4647,14 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
Upper.zextOrTrunc(S.Context.getTypeSize(SizeType));
Expr *Comparison
= new (S.Context) BinaryOperator(IterationVarRef,
- IntegerLiteral::Create(S.Context,
- Upper, SizeType, Loc),
- BO_NE, S.Context.BoolTy, Loc);
+ IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
+ BO_NE, S.Context.BoolTy,
+ VK_RValue, OK_Ordinary, Loc);
// Create the pre-increment of the iteration variable.
Expr *Increment
- = new (S.Context) UnaryOperator(IterationVarRef,
- UO_PreInc,
- SizeType, Loc);
+ = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType,
+ VK_LValue, OK_Ordinary, Loc);
// Subscript the "from" and "to" expressions with the iteration variable.
From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc,
@@ -4663,10 +4663,9 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
IterationVarRef, Loc));
// Build the copy for an individual element of the array.
- StmtResult Copy = BuildSingleCopyAssign(S, Loc,
- ArrayTy->getElementType(),
- To, From,
- CopyingBaseSubobject, Depth+1);
+ StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(),
+ To, From, CopyingBaseSubobject,
+ Depth + 1);
if (Copy.isInvalid())
return StmtError();
@@ -4907,7 +4906,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
// Construct a reference to the "other" object. We'll be using this
// throughout the generated ASTs.
- Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, Loc).takeAs<Expr>();
+ Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_RValue, Loc).take();
assert(OtherRef && "Reference to parameter cannot fail!");
// Construct the "this" pointer. We'll be using this throughout the generated
@@ -5068,7 +5067,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy,
CollectableMemCpy->getType(),
- Loc, 0).takeAs<Expr>();
+ VK_LValue, Loc, 0).take();
assert(CollectableMemCpyRef && "Builtin reference cannot fail");
}
}
@@ -5088,7 +5087,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy,
BuiltinMemCpy->getType(),
- Loc, 0).takeAs<Expr>();
+ VK_LValue, Loc, 0).take();
assert(BuiltinMemCpyRef && "Builtin reference cannot fail");
}
@@ -6105,7 +6104,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
// it can be destroyed later.
InitializedEntity Entity = InitializedEntity::InitializeVariable(ExDecl);
Expr *ExDeclRef = DeclRefExpr::Create(Context, 0, SourceRange(), ExDecl,
- Loc, ExDeclType, 0);
+ Loc, ExDeclType, VK_LValue, 0);
InitializationKind Kind = InitializationKind::CreateCopy(Loc,
SourceLocation());
InitializationSequence InitSeq(*this, Entity, Kind, &ExDeclRef, 1);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 2cb92b6db6..25c27fe628 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -743,15 +743,16 @@ static bool ShouldSnapshotBlockValueReference(Sema &S, BlockScopeInfo *CurBlock,
ExprResult
-Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc,
- const CXXScopeSpec *SS) {
+Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK,
+ SourceLocation Loc, const CXXScopeSpec *SS) {
DeclarationNameInfo NameInfo(D->getDeclName(), Loc);
- return BuildDeclRefExpr(D, Ty, NameInfo, SS);
+ return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS);
}
/// BuildDeclRefExpr - Build a DeclRefExpr.
ExprResult
Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,
+ ExprValueKind VK,
const DeclarationNameInfo &NameInfo,
const CXXScopeSpec *SS) {
if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
@@ -785,7 +786,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty,
return Owned(DeclRefExpr::Create(Context,
SS? (NestedNameSpecifier *)SS->getScopeRep() : 0,
SS? SS->getRange() : SourceRange(),
- D, NameInfo, Ty));
+ D, NameInfo, Ty, VK));
}
/// \brief Given a field that represents a member of an anonymous
@@ -845,8 +846,9 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
// BaseObject is an anonymous struct/union variable (and is,
// therefore, not part of another non-anonymous record).
MarkDeclarationReferenced(Loc, BaseObject);
- BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(),
- Loc);
+ BaseObjectExpr =
+ new (Context) DeclRefExpr(BaseObject, BaseObject->getType(),
+ VK_LValue, Loc);
BaseQuals
= Context.getCanonicalType(BaseObject->getType()).getQualifiers();
} else if (BaseObjectExpr) {
@@ -899,13 +901,14 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
for (llvm::SmallVector<FieldDecl *, 4>::reverse_iterator
FI = AnonFields.rbegin(), FIEnd = AnonFields.rend();
FI != FIEnd; ++FI) {
- QualType MemberType = (*FI)->getType();
+ FieldDecl *Field = *FI;
+ QualType MemberType = Field->getType();
Qualifiers MemberTypeQuals =
Context.getCanonicalType(MemberType).getQualifiers();
// CVR attributes from the base are picked up by members,
// except that 'mutable' members don't pick up 'const'.
- if ((*FI)->isMutable())
+ if (Field->isMutable())
ResultQuals.removeConst();
// GC attributes are never picked up by members.
@@ -922,7 +925,9 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc,
PerformObjectMemberConversion(Result, /*FIXME:Qualifier=*/0, *FI, *FI);
// FIXME: Might this end up being a qualified name?
Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI,
- OpLoc, MemberType);
+ OpLoc, MemberType, VK_LValue,
+ Field->isBitField() ?
+ OK_BitField : OK_Ordinary);
BaseObjectIsPointer = false;
ResultQuals = NewQuals;
}
@@ -1526,7 +1531,8 @@ ExprResult Sema::ActOnIdExpression(Scope *S,
if (const FunctionProtoType *Proto = T->getAs<FunctionProtoType>())
NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType(),
Proto->getExtInfo());
- return BuildDeclRefExpr(Func, NoProtoType, NameLoc, &SS);
+ // Note that functions are r-values in C.
+ return BuildDeclRefExpr(Func, NoProtoType, VK_RValue, NameLoc, &SS);
}
}
@@ -1916,6 +1922,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
DeclAccessPair FoundDecl,
const DeclarationNameInfo &MemberNameInfo,
QualType Ty,
+ ExprValueKind VK, ExprObjectKind OK,
const TemplateArgumentListInfo *TemplateArgs = 0) {
NestedNameSpecifier *Qualifier = 0;
SourceRange QualifierRange;
@@ -1926,7 +1933,7 @@ static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
return MemberExpr::Create(C, Base, isArrow, Qualifier, QualifierRange,
Member, FoundDecl, MemberNameInfo,
- TemplateArgs, Ty);
+ TemplateArgs, Ty, VK, OK);
}
/// Builds an implicit member access expression. The current context
@@ -2083,6 +2090,18 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
return Owned(ULE);
}
+static ExprValueKind getValueKindForDecl(ASTContext &Context,
+ const ValueDecl *D) {
+ if (isa<VarDecl>(D) || isa<FieldDecl>(D)) return VK_LValue;
+ if (!Context.getLangOptions().CPlusPlus) return VK_RValue;
+ if (isa<FunctionDecl>(D)) {
+ if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance())
+ return VK_RValue;
+ return VK_LValue;
+ }
+ return Expr::getValueKindForType(D->getType());
+}
+
/// \brief Complete semantic analysis for a reference to the given declaration.
ExprResult
@@ -2126,6 +2145,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
if (VD->isInvalidDecl())
return ExprError();
+ ExprValueKind VK = getValueKindForDecl(Context, VD);
+
// If the identifier reference is inside a block, and it refers to a value
// that is outside the block, create a BlockDeclRefExpr instead of a
// DeclRefExpr. This ensures the value is treated as a copy-in snapshot when
@@ -2150,6 +2171,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
MarkDeclarationReferenced(Loc, VD);
QualType ExprTy = VD->getType().getNonReferenceType();
+
// The BlocksAttr indicates the variable is bound by-reference.
bool byrefVar = (VD->getAttr<BlocksAttr>() != 0);
QualType T = VD->getType();
@@ -2160,17 +2182,17 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
bool constAdded = !ExprTy.isConstQualified();
// Variable will be bound by-copy, make it const within the closure.
ExprTy.addConst();
- BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false,
- constAdded);
+ BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, VK,
+ Loc, false, constAdded);
}
else
- BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true);
+ BDRE = new (Context) BlockDeclRefExpr(VD, ExprTy, VK, Loc, true);
if (getLangOptions().CPlusPlus) {
if (!T->isDependentType() && !T->isReferenceType()) {
Expr *E = new (Context)
DeclRefExpr(const_cast<ValueDecl*>(BDRE->getDecl()), T,
- SourceLocation());
+ VK, SourceLocation());
if (T->getAs<RecordType>())
if (!T->isUnionType()) {
ExprResult Res = PerformCopyInitialization(
@@ -2191,7 +2213,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS,
// If this reference is not in a block or if the referenced variable is
// within the block, create a normal DeclRefExpr.
- return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
+ return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), VK,
NameInfo, &SS);
}
@@ -2624,7 +2646,9 @@ Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
if (getLangOptions().CPlusPlus &&
(LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) {
return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
- Context.DependentTy, RLoc));
+ Context.DependentTy,
+ VK_LValue, OK_Ordinary,
+ RLoc));
}
if (getLangOptions().CPlusPlus &&
@@ -2651,6 +2675,8 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
DefaultFunctionArrayLvalueConversion(RHSExp);
QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType();
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_Ordinary;
// C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
// to the expression *((e1)+(e2)). This means the array "Base" may actually be
@@ -2685,6 +2711,9 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
} else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) {
BaseExpr = LHSExp; // vectors: V[123]
IndexExpr = RHSExp;
+ VK = LHSExp->getValueKind();
+ if (VK != VK_RValue)
+ OK = OK_VectorComponent;
// FIXME: need to deal with const...
ResultType = VTy->getElementType();
@@ -2756,7 +2785,7 @@ Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
}
return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
- ResultType, RLoc));
+ ResultType, VK, OK, RLoc));
}
QualType Sema::
@@ -3240,11 +3269,17 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
return BuildAnonymousStructUnionMemberReference(MemberLoc, FD,
BaseExpr, OpLoc);
+ // x.a is an l-value if 'a' has a reference type. Otherwise:
+ // x.a is an l-value/x-value/pr-value if the base is (and note
+ // that *x is always an l-value).
+ ExprValueKind VK = IsArrow ? VK_LValue : BaseExpr->getValueKind();
+
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
QualType MemberType = FD->getType();
- if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>())
+ if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) {
MemberType = Ref->getPointeeType();
- else {
+ VK = VK_LValue;
+ } else {
Qualifiers BaseQuals = BaseType.getQualifiers();
BaseQuals.removeObjCGCAttr();
if (FD->isMutable()) BaseQuals.removeConst();
@@ -3262,28 +3297,34 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
return ExprError();
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
FD, FoundDecl, MemberNameInfo,
- MemberType));
+ MemberType, VK,
+ FD->isBitField() ? OK_BitField : OK_Ordinary));
}
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, Var);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
Var, FoundDecl, MemberNameInfo,
- Var->getType().getNonReferenceType()));
+ Var->getType().getNonReferenceType(),
+ Expr::getValueKindForType(Var->getType()),
+ OK_Ordinary));
}
- if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
+ if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
MemberFn, FoundDecl, MemberNameInfo,
- MemberFn->getType()));
+ MemberFn->getType(),
+ MemberFn->isInstance() ? VK_RValue : VK_LValue,
+ OK_Ordinary));
}
+ assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
Enum, FoundDecl, MemberNameInfo,
- Enum->getType()));
+ Enum->getType(), VK_RValue, OK_Ordinary));
}
Owned(BaseExpr);
@@ -3435,7 +3476,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
PType = (*(Setter->param_end() -1))->getType();
// FIXME: we must check that the setter has property type.
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter,
- PType,
+ PType, VK_LValue,
+ OK_ObjCProperty,
Setter, MemberLoc, BaseExpr));
}
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
@@ -3599,6 +3641,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
return ExprError();
return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(),
+ VK_LValue, OK_ObjCProperty,
MemberLoc,
BaseExpr));
}
@@ -3615,6 +3658,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
SMD = dyn_cast<ObjCMethodDecl>(SDecl);
QualType PType = OMD->getSendResultType();
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(OMD, PType,
+ VK_LValue,
+ OK_ObjCProperty,
SMD,
MemberLoc,
BaseExpr));
@@ -3647,7 +3692,9 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
QualType ret = CheckExtVectorComponent(BaseType, OpLoc, Member, MemberLoc);
if (ret.isNull())
return ExprError();
- return Owned(new (Context) ExtVectorElementExpr(ret, BaseExpr, *Member,
+ return Owned(new (Context) ExtVectorElementExpr(ret,
+ BaseExpr->getValueKind(),
+ BaseExpr, *Member,
MemberLoc));
}
@@ -3959,7 +4006,7 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
}
return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy,
- RParenLoc));
+ VK_RValue, RParenLoc));
}
// Determine whether this is a dependent call inside a C++ template,
@@ -3974,7 +4021,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (Dependent)
return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs,
- Context.DependentTy, RParenLoc));
+ Context.DependentTy, VK_RValue,
+ RParenLoc));
// Determine whether this is a call to an object (C++ [over.call.object]).
if (Fn->getType()->isRecordType())
@@ -4014,10 +4062,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (const FunctionProtoType *FPT
= BO->getType()->getAs<FunctionProtoType>()) {
QualType ResultTy = FPT->getCallResultType(Context);
+ ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType());
CXXMemberCallExpr *TheCall
= new (Context) CXXMemberCallExpr(Context, BO, Args,
- NumArgs, ResultTy,
+ NumArgs, ResultTy, VK,
RParenLoc);
if (CheckCallReturnType(FPT->getResultType(),
@@ -4081,6 +4130,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
CallExpr *TheCall = new (Context) CallExpr(Context, Fn,
Args, NumArgs,
Context.BoolTy,
+ VK_RValue,
RParenLoc);
const FunctionType *FuncT;
@@ -4108,6 +4158,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
// We know the result type of the call, set it.
TheCall->setType(FuncT->getCallResultType(Context));
+ TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType()));
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) {
if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs,
@@ -4243,8 +4294,11 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
return ExprError();
}
+ // In C, compound literals are l-values for some reason.
+ ExprValueKind VK = getLangOptions().CPlusPlus ? VK_RValue : VK_LValue;
+
return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType,
- literalExpr, isFileScope));
+ VK, literalExpr, isFileScope));
}
ExprResult
@@ -4388,16 +4442,18 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
}
/// CheckCastTypes - Check type constraints for casting between types.
-bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,
- CastKind& Kind,
- CXXCastPath &BasePath,
- bool FunctionalStyle) {
+bool Sema::CheckCastTypes(SourceRange TyR, QualType castType,
+ Expr *&castExpr, CastKind& Kind, ExprValueKind &VK,
+ CXXCastPath &BasePath, bool FunctionalStyle) {
if (getLangOptions().CPlusPlus)
return CXXCheckCStyleCast(SourceRange(TyR.getBegin(),
castExpr->getLocEnd()),
- castType, castExpr, Kind, BasePath,
+ castType, VK, castExpr, Kind, BasePath,
FunctionalStyle);
+ // We only support r-value casts in C.
+ VK = VK_RValue;
+
DefaultFunctionArrayLvalueConversion(castExpr);
// C99 6.5.4p2: the cast type needs to be void or scalar and the expression
@@ -4574,14 +4630,15 @@ ExprResult
Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
SourceLocation RParenLoc, Expr *castExpr) {
CastKind Kind = CK_Invalid;
+ ExprValueKind VK = VK_RValue;
CXXCastPath BasePath;
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
- Kind, BasePath))
+ Kind, VK, BasePath))
return ExprError();
return Owned(CStyleCastExpr::Create(Context,
Ty->getType().getNonLValueExprType(Context),
- Kind, castExpr, &BasePath, Ty,
+ VK, Kind, castExpr, &BasePath, Ty,
LParenLoc, RParenLoc));
}
@@ -4669,7 +4726,7 @@ ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L,
/// In that case, lhs = cond.
/// C99 6.5.15
QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
- Expr *&SAVE,
+ Expr *&SAVE, ExprValueKind &VK,
SourceLocation QuestionLoc) {
// If both LHS and RHS are overloaded functions, try to resolve them.
if (Context.hasSameType(LHS->getType(), RHS->getType()) &&
@@ -4688,7 +4745,9 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
// C++ is sufficiently different to merit its own checker.
if (getLangOptions().CPlusPlus)
- return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE, QuestionLoc);
+ return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE, VK, QuestionLoc);
+
+ VK = VK_RValue;
UsualUnaryConversions(Cond);
if (SAVE) {
@@ -5053,15 +5112,16 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc,
LHSExpr = SAVEExpr = CondExpr;
}
+ ExprValueKind VK = VK_RValue;
QualType result = CheckCon