[cfe-commits] r119722 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/ExprCXX.h include/clang/Sema/Sema.h lib/AST/ExprCXX.cpp lib/AST/ExprClassification.cpp lib/Rewrite/RewriteObjC.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaExprObjC.cpp test/CodeGenObjCXX/property-derived-to-base-conv.mm test/SemaObjCXX/propert-dot-error.mm
John McCall
rjmccall at apple.com
Thu Nov 18 11:01:18 PST 2010
Author: rjmccall
Date: Thu Nov 18 13:01:18 2010
New Revision: 119722
URL: http://llvm.org/viewvc/llvm-project?rev=119722&view=rev
Log:
Add an assertion, fix a whole bunch of bugs, comment the assertion
out because there are still bugs left.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/ExprCXX.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/ExprCXX.cpp
cfe/trunk/lib/AST/ExprClassification.cpp
cfe/trunk/lib/Rewrite/RewriteObjC.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/test/CodeGenObjCXX/property-derived-to-base-conv.mm
cfe/trunk/test/SemaObjCXX/propert-dot-error.mm
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Thu Nov 18 13:01:18 2010
@@ -267,7 +267,10 @@
/// give its value kind.
static ExprValueKind getValueKindForType(QualType T) {
if (const ReferenceType *RT = T->getAs<ReferenceType>())
- return isa<LValueReferenceType>(RT) ? VK_LValue : VK_XValue;
+ return (isa<LValueReferenceType>(RT)
+ ? VK_LValue
+ : (RT->getPointeeType()->isFunctionType()
+ ? VK_LValue : VK_XValue));
return VK_RValue;
}
@@ -2455,8 +2458,8 @@
public:
ConditionalOperator(Expr *cond, SourceLocation QLoc, Expr *lhs,
SourceLocation CLoc, Expr *rhs, Expr *save,
- QualType t, ExprValueKind VK)
- : Expr(ConditionalOperatorClass, t, VK, OK_Ordinary,
+ QualType t, ExprValueKind VK, ExprObjectKind OK)
+ : Expr(ConditionalOperatorClass, t, VK, OK,
// FIXME: the type of the conditional operator doesn't
// depend on the type of the conditional, but the standard
// seems to imply that it could. File a bug!
@@ -3422,7 +3425,8 @@
public:
ExtVectorElementExpr(QualType ty, ExprValueKind VK, Expr *base,
IdentifierInfo &accessor, SourceLocation loc)
- : Expr(ExtVectorElementExprClass, ty, VK, OK_VectorComponent,
+ : Expr(ExtVectorElementExprClass, ty, VK,
+ (VK == VK_RValue ? OK_Ordinary : OK_VectorComponent),
base->isTypeDependent(), base->isValueDependent()),
Base(base), Accessor(&accessor), AccessorLoc(loc) {}
Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Thu Nov 18 13:01:18 2010
@@ -423,7 +423,7 @@
Operand(Operand), Range(R) { }
CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R)
- : Expr(CXXUuidofExprClass, Ty, /*FIXME*/ VK_LValue, OK_Ordinary,
+ : Expr(CXXUuidofExprClass, Ty, VK_RValue, OK_Ordinary,
false, Operand->isTypeDependent()),
Operand(Operand), Range(R) { }
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Nov 18 13:01:18 2010
@@ -4204,14 +4204,12 @@
void ConvertPropertyAssignment(Expr *LHS, Expr *&RHS, QualType& LHSTy);
- QualType CheckCommaOperands( // C99 6.5.17
- Expr *lex, Expr *&rex, SourceLocation OpLoc);
QualType CheckConditionalOperands( // C99 6.5.15
Expr *&cond, Expr *&lhs, Expr *&rhs, Expr *&save,
- ExprValueKind &VK, SourceLocation questionLoc);
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
QualType CXXCheckConditionalOperands( // C++ 5.16
- Expr *&cond, Expr *&lhs, Expr *&rhs, Expr *&save, ExprValueKind &VK,
- SourceLocation questionLoc);
+ Expr *&cond, Expr *&lhs, Expr *&rhs, Expr *&save,
+ ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc);
QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2,
bool *NonStandardCompositeType = 0);
@@ -4223,19 +4221,6 @@
QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx,
SourceLocation l, bool isRel);
- /// type checking unary operators (subroutines of ActOnUnaryOp).
- /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
- QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
- bool isInc, bool isPrefix);
- QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
- QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);
- QualType CheckRealImagOperand(Expr *&Op, SourceLocation OpLoc, bool isReal);
-
- /// type checking primary expressions.
- QualType CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
- const IdentifierInfo *Comp,
- SourceLocation CmpLoc);
-
/// type checking declaration initializers (C99 6.7.8)
bool CheckInitList(const InitializedEntity &Entity,
InitListExpr *&InitList, QualType &DeclType);
Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Thu Nov 18 13:01:18 2010
@@ -677,7 +677,7 @@
SourceLocation RParenLoc)
: Expr(CXXUnresolvedConstructExprClass,
Type->getType().getNonReferenceType(),
- VK_RValue, OK_Ordinary,
+ VK_LValue, OK_Ordinary,
Type->getType()->isDependentType(), true),
Type(Type),
LParenLoc(LParenLoc),
Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Thu Nov 18 13:01:18 2010
@@ -64,6 +64,21 @@
kind = Cl::CL_Void;
}
+#if 0
+ // Enable this assertion for testing.
+ switch (kind) {
+ case Cl::CL_LValue: assert(getValueKind() == VK_LValue); break;
+ case Cl::CL_XValue: assert(getValueKind() == VK_XValue); break;
+ case Cl::CL_Function:
+ case Cl::CL_Void:
+ case Cl::CL_DuplicateVectorComponents:
+ case Cl::CL_MemberFunction:
+ case Cl::CL_SubObjCPropertySetting:
+ case Cl::CL_ClassTemporary:
+ case Cl::CL_PRValue: assert(getValueKind() == VK_RValue); break;
+ }
+#endif
+
Cl::ModifiableType modifiable = Cl::CM_Untested;
if (Loc)
modifiable = IsModifiable(Ctx, this, kind, *Loc);
@@ -380,6 +395,10 @@
// *E1 is an lvalue
if (E->isArrow())
return Cl::CL_LValue;
+ Expr *Base = E->getBase()->IgnoreParenImpCasts();
+ if (isa<ObjCPropertyRefExpr>(Base) ||
+ isa<ObjCImplicitSetterGetterRefExpr>(Base))
+ return Cl::CL_SubObjCPropertySetting;
return ClassifyInternal(Ctx, E->getBase());
}
Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Thu Nov 18 13:01:18 2010
@@ -3151,7 +3151,7 @@
new (Context) ConditionalOperator(lessThanExpr,
SourceLocation(), CE,
SourceLocation(), STCE, (Expr*)0,
- returnType, VK_RValue);
+ returnType, VK_RValue, OK_Ordinary);
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
CondExpr);
}
@@ -4687,7 +4687,7 @@
SourceLocation(), cast<Expr>(LHSStmt),
SourceLocation(), cast<Expr>(RHSStmt),
(Expr*)0,
- Exp->getType(), VK_RValue);
+ Exp->getType(), VK_RValue, OK_Ordinary);
return CondExpr;
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
CPT = IRE->getType()->getAs<BlockPointerType>();
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Nov 18 13:01:18 2010
@@ -4906,7 +4906,7 @@
// Construct a reference to the "other" object. We'll be using this
// throughout the generated ASTs.
- Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_RValue, Loc).take();
+ Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take();
assert(OtherRef && "Reference to parameter cannot fail!");
// Construct the "this" pointer. We'll be using this throughout the generated
@@ -5012,11 +5012,11 @@
MemberLookup.addDecl(*Field);
MemberLookup.resolveKind();
ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType,
- Loc, /*IsArrow=*/false,
- SS, 0, MemberLookup, 0);
+ Loc, /*IsArrow=*/false,
+ SS, 0, MemberLookup, 0);
ExprResult To = BuildMemberReferenceExpr(This, This->getType(),
- Loc, /*IsArrow=*/true,
- SS, 0, MemberLookup, 0);
+ Loc, /*IsArrow=*/true,
+ SS, 0, MemberLookup, 0);
assert(!From.isInvalid() && "Implicit field reference cannot fail");
assert(!To.isInvalid() && "Implicit field reference cannot fail");
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Thu Nov 18 13:01:18 2010
@@ -778,6 +778,12 @@
return ExprError();
}
}
+
+ // This ridiculousness brought to you by 'extern void x;' and the
+ // GNU compiler collection.
+ } else if (!getLangOptions().CPlusPlus && !Ty.hasQualifiers() &&
+ Ty->isVoidType()) {
+ VK = VK_RValue;
}
}
@@ -2092,7 +2098,9 @@
static ExprValueKind getValueKindForDecl(ASTContext &Context,
const ValueDecl *D) {
- if (isa<VarDecl>(D) || isa<FieldDecl>(D)) return VK_LValue;
+ // FIXME: It's not clear to me why NonTypeTemplateParmDecl is a VarDecl.
+ if (isa<VarDecl>(D) && !isa<NonTypeTemplateParmDecl>(D)) return VK_LValue;
+ if (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())
@@ -2592,9 +2600,10 @@
return move(Result);
}
-QualType Sema::CheckRealImagOperand(Expr *&V, SourceLocation Loc, bool isReal) {
+static QualType CheckRealImagOperand(Sema &S, Expr *&V, SourceLocation Loc,
+ bool isReal) {
if (V->isTypeDependent())
- return Context.DependentTy;
+ return S.Context.DependentTy;
// These operators return the element type of a complex type.
if (const ComplexType *CT = V->getType()->getAs<ComplexType>())
@@ -2605,15 +2614,15 @@
return V->getType();
// Test for placeholders.
- ExprResult PR = CheckPlaceholderExpr(V, Loc);
+ ExprResult PR = S.CheckPlaceholderExpr(V, Loc);
if (PR.isInvalid()) return QualType();
if (PR.take() != V) {
V = PR.take();
- return CheckRealImagOperand(V, Loc, isReal);
+ return CheckRealImagOperand(S, V, Loc, isReal);
}
// Reject anything else.
- Diag(Loc, diag::err_realimag_invalid_type) << V->getType()
+ S.Diag(Loc, diag::err_realimag_invalid_type) << V->getType()
<< (isReal ? "__real" : "__imag");
return QualType();
}
@@ -2633,6 +2642,19 @@
return BuildUnaryOp(S, OpLoc, Opc, Input);
}
+/// Expressions of certain arbitrary types are forbidden by C from
+/// having l-value type. These are:
+/// - 'void', but not qualified void
+/// - function types
+///
+/// The exact rule here is C99 6.3.2.1:
+/// An lvalue is an expression with an object type or an incomplete
+/// type other than void.
+static bool IsCForbiddenLValueType(ASTContext &C, QualType T) {
+ return ((T->isVoidType() && !T.hasQualifiers()) ||
+ T->isFunctionType());
+}
+
ExprResult
Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
@@ -2771,6 +2793,10 @@
// GNU extension: subscripting on pointer to void
Diag(LLoc, diag::ext_gnu_void_ptr)
<< BaseExpr->getSourceRange();
+
+ // C forbids expressions of unqualified void type from being l-values.
+ // See IsCForbiddenLValueType.
+ if (!ResultType.hasQualifiers()) VK = VK_RValue;
} else if (!ResultType->isDependentType() &&
RequireCompleteType(LLoc, ResultType,
PDiag(diag::err_subscript_incomplete_type)
@@ -2784,13 +2810,20 @@
return ExprError();
}
+ assert(VK == VK_RValue || LangOpts.CPlusPlus ||
+ !IsCForbiddenLValueType(Context, ResultType));
+
return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp,
ResultType, VK, OK, RLoc));
}
-QualType Sema::
-CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
- const IdentifierInfo *CompName,
+/// Check an ext-vector component access expression.
+///
+/// VK should be set in advance to the value kind of the base
+/// expression.
+static QualType
+CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK,
+ SourceLocation OpLoc, const IdentifierInfo *CompName,
SourceLocation CompLoc) {
// FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements,
// see FIXME there.
@@ -2811,25 +2844,36 @@
// indicating that it is a string of hex values to be used as vector indices.
bool HexSwizzle = *compStr == 's' || *compStr == 'S';
+ bool HasRepeated = false;
+ bool HasIndex[16] = {};
+
+ int Idx;
+
// Check that we've found one of the special components, or that the component
// names must come from the same set.
if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") ||
!strcmp(compStr, "even") || !strcmp(compStr, "odd")) {
HalvingSwizzle = true;
- } else if (vecType->getPointAccessorIdx(*compStr) != -1) {
- do
+ } else if (!HexSwizzle &&
+ (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) {
+ do {
+ if (HasIndex[Idx]) HasRepeated = true;
+ HasIndex[Idx] = true;
compStr++;
- while (*compStr && vecType->getPointAccessorIdx(*compStr) != -1);
- } else if (HexSwizzle || vecType->getNumericAccessorIdx(*compStr) != -1) {
- do
+ } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1);
+ } else {
+ if (HexSwizzle) compStr++;
+ while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) {
+ if (HasIndex[Idx]) HasRepeated = true;
+ HasIndex[Idx] = true;
compStr++;
- while (*compStr && vecType->getNumericAccessorIdx(*compStr) != -1);
+ }
}
if (!HalvingSwizzle && *compStr) {
// We didn't get to the end of the string. This means the component names
// didn't come from the same set *or* we encountered an illegal name.
- Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
+ S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal)
<< llvm::StringRef(compStr, 1) << SourceRange(CompLoc);
return QualType();
}
@@ -2844,7 +2888,7 @@
while (*compStr) {
if (!vecType->isAccessorWithinNumElements(*compStr++)) {
- Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
+ S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length)
<< baseType << SourceRange(CompLoc);
return QualType();
}
@@ -2864,12 +2908,14 @@
if (CompSize == 1)
return vecType->getElementType();
- QualType VT = Context.getExtVectorType(vecType->getElementType(), CompSize);
+ if (HasRepeated) VK = VK_RValue;
+
+ QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize);
// Now look up the TypeDefDecl from the vector type. Without this,
// diagostics look bad. We want extended vector types to appear built-in.
- for (unsigned i = 0, E = ExtVectorDecls.size(); i != E; ++i) {
- if (ExtVectorDecls[i]->getUnderlyingType() == VT)
- return Context.getTypedefType(ExtVectorDecls[i]);
+ for (unsigned i = 0, E = S.ExtVectorDecls.size(); i != E; ++i) {
+ if (S.ExtVectorDecls[i]->getUnderlyingType() == VT)
+ return S.Context.getTypedefType(S.ExtVectorDecls[i]);
}
return VT; // should never get here (a typedef type should always be found).
}
@@ -3271,8 +3317,18 @@
// 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();
+ // that *x is always an l-value), except that if the base isn't
+ // an ordinary object then we must have an rvalue.
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_Ordinary;
+ if (!IsArrow) {
+ if (BaseExpr->getObjectKind() == OK_Ordinary)
+ VK = BaseExpr->getValueKind();
+ else
+ VK = VK_RValue;
+ }
+ if (VK != VK_RValue && FD->isBitField())
+ OK = OK_BitField;
// Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref]
QualType MemberType = FD->getType();
@@ -3297,8 +3353,7 @@
return ExprError();
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
FD, FoundDecl, MemberNameInfo,
- MemberType, VK,
- FD->isBitField() ? OK_BitField : OK_Ordinary));
+ MemberType, VK, OK));
}
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
@@ -3306,8 +3361,7 @@
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
Var, FoundDecl, MemberNameInfo,
Var->getType().getNonReferenceType(),
- Expr::getValueKindForType(Var->getType()),
- OK_Ordinary));
+ VK_LValue, OK_Ordinary));
}
if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
@@ -3469,15 +3523,21 @@
if (Getter || Setter) {
QualType PType;
- if (Getter)
+ ExprValueKind VK = VK_LValue;
+ if (Getter) {
PType = Getter->getSendResultType();
- else
+ if (!getLangOptions().CPlusPlus &&
+ IsCForbiddenLValueType(Context, PType))
+ VK = VK_RValue;
+ } else {
// Get the expression type from Setter's incoming parameter.
PType = (*(Setter->param_end() -1))->getType();
+ }
+ ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
+
// FIXME: we must check that the setter has property type.
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter,
- PType, VK_LValue,
- OK_ObjCProperty,
+ PType, VK, OK,
Setter, MemberLoc, BaseExpr));
}
return ExprError(Diag(MemberLoc, diag::err_property_not_found)
@@ -3657,10 +3717,15 @@
SetterSel, Context))
SMD = dyn_cast<ObjCMethodDecl>(SDecl);
QualType PType = OMD->getSendResultType();
+
+ ExprValueKind VK = VK_LValue;
+ if (!getLangOptions().CPlusPlus &&
+ IsCForbiddenLValueType(Context, PType))
+ VK = VK_RValue;
+ ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
+
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(OMD, PType,
- VK_LValue,
- OK_ObjCProperty,
- SMD,
+ VK, OK, SMD,
MemberLoc,
BaseExpr));
}
@@ -3689,13 +3754,14 @@
// Handle 'field access' to vectors, such as 'V.xx'.
if (BaseType->isExtVectorType()) {
IdentifierInfo *Member = MemberName.getAsIdentifierInfo();
- QualType ret = CheckExtVectorComponent(BaseType, OpLoc, Member, MemberLoc);
+ ExprValueKind VK = BaseExpr->getValueKind();
+ QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc,
+ Member, MemberLoc);
if (ret.isNull())
return ExprError();
- return Owned(new (Context) ExtVectorElementExpr(ret,
- BaseExpr->getValueKind(),
- BaseExpr, *Member,
- MemberLoc));
+
+ return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr,
+ *Member, MemberLoc));
}
Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union)
@@ -4727,6 +4793,7 @@
/// C99 6.5.15
QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
Expr *&SAVE, ExprValueKind &VK,
+ ExprObjectKind &OK,
SourceLocation QuestionLoc) {
// If both LHS and RHS are overloaded functions, try to resolve them.
if (Context.hasSameType(LHS->getType(), RHS->getType()) &&
@@ -4745,9 +4812,11 @@
// C++ is sufficiently different to merit its own checker.
if (getLangOptions().CPlusPlus)
- return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE, VK, QuestionLoc);
+ return CXXCheckConditionalOperands(Cond, LHS, RHS, SAVE,
+ VK, OK, QuestionLoc);
VK = VK_RValue;
+ OK = OK_Ordinary;
UsualUnaryConversions(Cond);
if (SAVE) {
@@ -5113,15 +5182,16 @@
}
ExprValueKind VK = VK_RValue;
+ ExprObjectKind OK = OK_Ordinary;
QualType result = CheckConditionalOperands(CondExpr, LHSExpr, RHSExpr,
- SAVEExpr, VK, QuestionLoc);
+ SAVEExpr, VK, OK, QuestionLoc);
if (result.isNull())
return ExprError();
return Owned(new (Context) ConditionalOperator(CondExpr, QuestionLoc,
LHSExpr, ColonLoc,
RHSExpr, SAVEExpr,
- result, VK));
+ result, VK, OK));
}
// CheckPointerTypesForAssignment - This is a very tricky routine (despite
@@ -6774,14 +6844,15 @@
}
// C99 6.5.17
-QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) {
- DiagnoseUnusedExprResult(LHS);
+static QualType CheckCommaOperands(Sema &S, Expr *LHS, Expr *&RHS,
+ SourceLocation Loc) {
+ S.DiagnoseUnusedExprResult(LHS);
- ExprResult LHSResult = CheckPlaceholderExpr(LHS, Loc);
+ ExprResult LHSResult = S.CheckPlaceholderExpr(LHS, Loc);
if (LHSResult.isInvalid())
return QualType();
- ExprResult RHSResult = CheckPlaceholderExpr(RHS, Loc);
+ ExprResult RHSResult = S.CheckPlaceholderExpr(RHS, Loc);
if (RHSResult.isInvalid())
return QualType();
RHS = RHSResult.take();
@@ -6789,14 +6860,14 @@
// C's comma performs lvalue conversion (C99 6.3.2.1) on both its
// operands, but not unary promotions.
// C++'s comma does not do any conversions at all (C++ [expr.comma]p1).
- if (!getLangOptions().CPlusPlus) {
- DefaultFunctionArrayLvalueConversion(LHS);
+ if (!S.getLangOptions().CPlusPlus) {
+ S.DefaultFunctionArrayLvalueConversion(LHS);
if (!LHS->getType()->isVoidType())
- RequireCompleteType(Loc, LHS->getType(), diag::err_incomplete_type);
+ S.RequireCompleteType(Loc, LHS->getType(), diag::err_incomplete_type);
- DefaultFunctionArrayLvalueConversion(RHS);
+ S.DefaultFunctionArrayLvalueConversion(RHS);
if (!RHS->getType()->isVoidType())
- RequireCompleteType(Loc, RHS->getType(), diag::err_incomplete_type);
+ S.RequireCompleteType(Loc, RHS->getType(), diag::err_incomplete_type);
}
return RHS->getType();
@@ -6804,22 +6875,24 @@
/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine
/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions.
-QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc,
- bool isInc, bool isPrefix) {
+static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
+ ExprValueKind &VK,
+ SourceLocation OpLoc,
+ bool isInc, bool isPrefix) {
if (Op->isTypeDependent())
- return Context.DependentTy;
+ return S.Context.DependentTy;
QualType ResType = Op->getType();
assert(!ResType.isNull() && "no type for increment/decrement expression");
- if (getLangOptions().CPlusPlus && ResType->isBooleanType()) {
+ if (S.getLangOptions().CPlusPlus && ResType->isBooleanType()) {
// Decrement of bool is not allowed.
if (!isInc) {
- Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange();
+ S.Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange();
return QualType();
}
// Increment of bool sets it to true, but is deprecated.
- Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
+ S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange();
} else if (ResType->isRealType()) {
// OK!
} else if (ResType->isAnyPointerType()) {
@@ -6827,56 +6900,62 @@
// C99 6.5.2.4p2, 6.5.6p2
if (PointeeTy->isVoidType()) {
- if (getLangOptions().CPlusPlus) {
- Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type)
+ if (S.getLangOptions().CPlusPlus) {
+ S.Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type)
<< Op->getSourceRange();
return QualType();
}
// Pointer to void is a GNU extension in C.
- Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
+ S.Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange();
} else if (PointeeTy->isFunctionType()) {
- if (getLangOptions().CPlusPlus) {
- Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
+ if (S.getLangOptions().CPlusPlus) {
+ S.Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type)
<< Op->getType() << Op->getSourceRange();
return QualType();
}
- Diag(OpLoc, diag::ext_gnu_ptr_func_arith)
+ S.Diag(OpLoc, diag::ext_gnu_ptr_func_arith)
<< ResType << Op->getSourceRange();
- } else if (RequireCompleteType(OpLoc, PointeeTy,
- PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+ } else if (S.RequireCompleteType(OpLoc, PointeeTy,
+ S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
<< Op->getSourceRange()
<< ResType))
return QualType();
// Diagnose bad cases where we step over interface counts.
- else if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) {
- Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
+ else if (PointeeTy->isObjCObjectType() && S.LangOpts.ObjCNonFragileABI) {
+ S.Diag(OpLoc, diag::err_arithmetic_nonfragile_interface)
<< PointeeTy << Op->getSourceRange();
return QualType();
}
} else if (ResType->isAnyComplexType()) {
// C99 does not support ++/-- on complex types, we allow as an extension.
- Diag(OpLoc, diag::ext_integer_increment_complex)
+ S.Diag(OpLoc, diag::ext_integer_increment_complex)
<< ResType << Op->getSourceRange();
} else if (ResType->isPlaceholderType()) {
- ExprResult PR = CheckPlaceholderExpr(Op, OpLoc);
+ ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc);
if (PR.isInvalid()) return QualType();
- return CheckIncrementDecrementOperand(PR.take(), OpLoc, isInc, isPrefix);
+ return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc,
+ isInc, isPrefix);
} else {
- Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
+ S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement)
<< ResType << int(isInc) << Op->getSourceRange();
return QualType();
}
// At this point, we know we have a real, complex or pointer type.
// Now make sure the operand is a modifiable lvalue.
- if (CheckForModifiableLvalue(Op, OpLoc, *this))
+ if (CheckForModifiableLvalue(Op, OpLoc, S))
return QualType();
// In C++, a prefix increment is the same type as the operand. Otherwise
// (in C or with postfix), the increment is the unqualified type of the
// operand.
- return isPrefix && getLangOptions().CPlusPlus
- ? ResType : ResType.getUnqualifiedType();
+ if (isPrefix && S.getLangOptions().CPlusPlus) {
+ VK = VK_LValue;
+ return ResType;
+ } else {
+ VK = VK_RValue;
+ return ResType.getUnqualifiedType();
+ }
}
void Sema::ConvertPropertyAssignment(Expr *LHS, Expr *&RHS, QualType& LHSTy) {
@@ -6971,20 +7050,21 @@
/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
/// In C++, the operand might be an overloaded function name, in which case
/// we allow the '&' but retain the overloaded-function type.
-QualType Sema::CheckAddressOfOperand(Expr *OrigOp, SourceLocation OpLoc) {
+static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
+ SourceLocation OpLoc) {
if (OrigOp->isTypeDependent())
- return Context.DependentTy;
- if (OrigOp->getType() == Context.OverloadTy)
- return Context.OverloadTy;
+ return S.Context.DependentTy;
+ if (OrigOp->getType() == S.Context.OverloadTy)
+ return S.Context.OverloadTy;
- ExprResult PR = CheckPlaceholderExpr(OrigOp, OpLoc);
+ ExprResult PR = S.CheckPlaceholderExpr(OrigOp, OpLoc);
if (PR.isInvalid()) return QualType();
OrigOp = PR.take();
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp->IgnoreParens();
- if (getLangOptions().C99) {
+ if (S.getLangOptions().C99) {
// Implement C99-only parts of addressof rules.
if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
if (uOp->getOpcode() == UO_Deref)
@@ -6996,23 +7076,24 @@
// expressions here, but the result of one is always an lvalue anyway.
}
NamedDecl *dcl = getPrimaryDecl(op);
- Expr::isLvalueResult lval = op->isLvalue(Context);
+ Expr::isLvalueResult lval = op->isLvalue(S.Context);
if (lval == Expr::LV_ClassTemporary) {
- Diag(OpLoc, isSFINAEContext()? diag::err_typecheck_addrof_class_temporary
- : diag::ext_typecheck_addrof_class_temporary)
+ bool sfinae = S.isSFINAEContext();
+ S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary
+ : diag::ext_typecheck_addrof_class_temporary)
<< op->getType() << op->getSourceRange();
- if (isSFINAEContext())
+ if (sfinae)
return QualType();
} else if (isa<ObjCSelectorExpr>(op)) {
- return Context.getPointerType(op->getType());
+ return S.Context.getPointerType(op->getType());
} else if (lval == Expr::LV_MemberFunction) {
// If it's an instance method, make a member pointer.
// The expression must have exactly the form &A::foo.
// If the underlying expression isn't a decl ref, give up.
if (!isa<DeclRefExpr>(op)) {
- Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
<< OrigOp->getSourceRange();
return QualType();
}
@@ -7021,45 +7102,45 @@
// The id-expression was parenthesized.
if (OrigOp != DRE) {
- Diag(OpLoc, diag::err_parens_pointer_member_function)
+ S.Diag(OpLoc, diag::err_parens_pointer_member_function)
<< OrigOp->getSourceRange();
// The method was named without a qualifier.
} else if (!DRE->getQualifier()) {
- Diag(OpLoc, diag::err_unqualified_pointer_member_function)
+ S.Diag(OpLoc, diag::err_unqualified_pointer_member_function)
<< op->getSourceRange();
}
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(MD->getParent()).getTypePtr());
+ return S.Context.getMemberPointerType(op->getType(),
+ S.Context.getTypeDeclType(MD->getParent()).getTypePtr());
} else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) {
// C99 6.5.3.2p1
// The operand must be either an l-value or a function designator
if (!op->getType()->isFunctionType()) {
// FIXME: emit more specific diag...
- Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
+ S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
<< op->getSourceRange();
return QualType();
}
} else if (op->getBitField()) { // C99 6.5.3.2p1
// The operand cannot be a bit-field
- Diag(OpLoc, diag::err_typecheck_address_of)
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
<< "bit-field" << op->getSourceRange();
return QualType();
} else if (op->refersToVectorElement()) {
// The operand cannot be an element of a vector
- Diag(OpLoc, diag::err_typecheck_address_of)
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
<< "vector element" << op->getSourceRange();
return QualType();
} else if (isa<ObjCPropertyRefExpr>(op)) {
// cannot take address of a property expression.
- Diag(OpLoc, diag::err_typecheck_address_of)
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
<< "property expression" << op->getSourceRange();
return QualType();
} else if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(op)) {
// FIXME: Can LHS ever be null here?
- if (!CheckAddressOfOperand(CO->getTrueExpr(), OpLoc).isNull())
- return CheckAddressOfOperand(CO->getFalseExpr(), OpLoc);
+ if (!CheckAddressOfOperand(S, CO->getTrueExpr(), OpLoc).isNull())
+ return CheckAddressOfOperand(S, CO->getFalseExpr(), OpLoc);
} else if (dcl) { // C99 6.5.3.2p1
// We have an lvalue with a decl. Make sure the decl is not declared
// with the register storage-class specifier.
@@ -7067,13 +7148,13 @@
// in C++ it is not error to take address of a register
// variable (c++03 7.1.1P3)
if (vd->getStorageClass() == SC_Register &&
- !getLangOptions().CPlusPlus) {
- Diag(OpLoc, diag::err_typecheck_address_of)
+ !S.getLangOptions().CPlusPlus) {
+ S.Diag(OpLoc, diag::err_typecheck_address_of)
<< "register variable" << op->getSourceRange();
return QualType();
}
} else if (isa<FunctionTemplateDecl>(dcl)) {
- return Context.OverloadTy;
+ return S.Context.OverloadTy;
} else if (FieldDecl *FD = dyn_cast<FieldDecl>(dcl)) {
// Okay: we can take the address of a field.
// Could be a pointer to member, though, if there is an explicit
@@ -7082,14 +7163,14 @@
DeclContext *Ctx = dcl->getDeclContext();
if (Ctx && Ctx->isRecord()) {
if (FD->getType()->isReferenceType()) {
- Diag(OpLoc,
- diag::err_cannot_form_pointer_to_member_of_reference_type)
+ S.Diag(OpLoc,
+ diag::err_cannot_form_pointer_to_member_of_reference_type)
<< FD->getDeclName() << FD->getType();
return QualType();
}
- return Context.getMemberPointerType(op->getType(),
- Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+ return S.Context.getMemberPointerType(op->getType(),
+ S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
}
}
} else if (!isa<FunctionDecl>(dcl))
@@ -7100,21 +7181,22 @@
// Taking the address of a void variable is technically illegal, but we
// allow it in cases which are otherwise valid.
// Example: "extern void x; void* y = &x;".
- Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
+ S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange();
}
// If the operand has type "type", the result has type "pointer to type".
if (op->getType()->isObjCObjectType())
- return Context.getObjCObjectPointerType(op->getType());
- return Context.getPointerType(op->getType());
+ return S.Context.getObjCObjectPointerType(op->getType());
+ return S.Context.getPointerType(op->getType());
}
/// CheckIndirectionOperand - Type check unary indirection (prefix '*').
-QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) {
+static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
+ SourceLocation OpLoc) {
if (Op->isTypeDependent())
- return Context.DependentTy;
+ return S.Context.DependentTy;
- UsualUnaryConversions(Op);
+ S.UsualUnaryConversions(Op);
QualType OpTy = Op->getType();
QualType Result;
@@ -7128,16 +7210,25 @@
OpTy->getAs<ObjCObjectPointerType>())
Result = OPT->getPointeeType();
else {
- ExprResult PR = CheckPlaceholderExpr(Op, OpLoc);
+ ExprResult PR = S.CheckPlaceholderExpr(Op, OpLoc);
if (PR.isInvalid()) return QualType();
- if (PR.take() != Op) return CheckIndirectionOperand(PR.take(), OpLoc);
+ if (PR.take() != Op)
+ return CheckIndirectionOperand(S, PR.take(), VK, OpLoc);
}
if (Result.isNull()) {
- Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
+ S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
<< OpTy << Op->getSourceRange();
return QualType();
}
+
+ // Dereferences are usually l-values...
+ VK = VK_LValue;
+
+ // ...except that certain expressions are never l-values in C.
+ if (!S.getLangOptions().CPlusPlus &&
+ IsCForbiddenLValueType(S.Context, Result))
+ VK = VK_RValue;
return Result;
}
@@ -7221,8 +7312,8 @@
case BO_Assign:
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
if (getLangOptions().CPlusPlus) {
- VK = rhs->getValueKind();
- OK = rhs->getObjectKind();
+ VK = lhs->getValueKind();
+ OK = lhs->getObjectKind();
}
break;
case BO_PtrMemD:
@@ -7307,7 +7398,7 @@
ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, CompResultTy);
break;
case BO_Comma:
- ResultTy = CheckCommaOperands(lhs, rhs, OpLoc);
+ ResultTy = CheckCommaOperands(*this, lhs, rhs, OpLoc);
if (getLangOptions().CPlusPlus) {
VK = rhs->getValueKind();
OK = rhs->getObjectKind();
@@ -7552,24 +7643,20 @@
switch (Opc) {
case UO_PreInc:
case UO_PreDec:
- VK = VK_LValue;
- OK = Input->getObjectKind();
- // fallthrough
case UO_PostInc:
case UO_PostDec:
- resultType = CheckIncrementDecrementOperand(Input, OpLoc,
+ resultType = CheckIncrementDecrementOperand(*this, Input, VK, OpLoc,
Opc == UO_PreInc ||
Opc == UO_PostInc,
Opc == UO_PreInc ||
Opc == UO_PreDec);
break;
case UO_AddrOf:
- resultType = CheckAddressOfOperand(Input, OpLoc);
+ resultType = CheckAddressOfOperand(*this, Input, OpLoc);
break;
case UO_Deref:
DefaultFunctionArrayLvalueConversion(Input);
- resultType = CheckIndirectionOperand(Input, OpLoc);
- VK = VK_LValue;
+ resultType = CheckIndirectionOperand(*this, Input, VK, OpLoc);
break;
case UO_Plus:
case UO_Minus:
@@ -7639,7 +7726,7 @@
break;
case UO_Real:
case UO_Imag:
- resultType = CheckRealImagOperand(Input, OpLoc, Opc == UO_Real);
+ resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real);
// _Real and _Imag map ordinary l-values into ordinary l-values.
if (Input->getValueKind() != VK_RValue &&
Input->getObjectKind() == OK_Ordinary)
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Nov 18 13:01:18 2010
@@ -1601,7 +1601,7 @@
Expr *Condition = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
ConditionVar->getLocation(),
ConditionVar->getType().getNonReferenceType(),
- Expr::getValueKindForType(ConditionVar->getType()));
+ VK_LValue);
if (ConvertToBoolean && CheckBooleanCondition(Condition, StmtLoc))
return ExprError();
@@ -2594,6 +2594,7 @@
/// extension. In this case, LHS == Cond. (But they're not aliases.)
QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
Expr *&SAVE, ExprValueKind &VK,
+ ExprObjectKind &OK,
SourceLocation QuestionLoc) {
// FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
// interface pointers.
@@ -2613,6 +2614,7 @@
// Assume r-value.
VK = VK_RValue;
+ OK = OK_Ordinary;
// Either of the arguments dependent?
if (LHS->isTypeDependent() || RHS->isTypeDependent())
@@ -2697,15 +2699,20 @@
// 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.
+ // We only extend this to bitfields, not to the crazy other kinds of
+ // l-values.
bool Same = Context.hasSameType(LTy, RTy);
if (Same &&
LHS->getValueKind() != VK_RValue &&
LHS->getValueKind() == RHS->getValueKind() &&
- LHS->getObjectKind() == OK_Ordinary &&
- RHS->getObjectKind() == OK_Ordinary) {
+ (LHS->getObjectKind() == OK_Ordinary ||
+ LHS->getObjectKind() == OK_BitField) &&
+ (RHS->getObjectKind() == OK_Ordinary ||
+ RHS->getObjectKind() == OK_BitField)) {
VK = LHS->getValueKind();
+ if (LHS->getObjectKind() == OK_BitField ||
+ RHS->getObjectKind() == OK_BitField)
+ OK = OK_BitField;
return LTy;
}
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Thu Nov 18 13:01:18 2010
@@ -431,16 +431,20 @@
return ExprError();
if (Getter) {
- QualType PType;
- PType = Getter->getSendResultType();
+ QualType PType = Getter->getSendResultType();
+ ExprValueKind VK = VK_LValue;
+ ExprObjectKind OK = OK_ObjCProperty;
+ if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() &&
+ PType->isVoidType())
+ VK = VK_RValue, OK = OK_Ordinary;
+
if (Super)
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
- VK_LValue, OK_ObjCProperty,
- Setter, MemberLoc, SuperLoc, SuperType));
+ VK, OK, Setter, MemberLoc,
+ SuperLoc, SuperType));
else
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType,
- VK_LValue, OK_ObjCProperty,
- Setter, MemberLoc, BaseExpr));
+ VK, OK, Setter, MemberLoc, BaseExpr));
}
@@ -547,16 +551,23 @@
if (Getter || Setter) {
QualType PType;
- if (Getter)
+ ExprValueKind VK = VK_LValue;
+ if (Getter) {
PType = Getter->getSendResultType();
- else {
+ if (!getLangOptions().CPlusPlus &&
+ !PType.hasQualifiers() && PType->isVoidType())
+ VK = VK_RValue;
+ } else {
for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(),
E = Setter->param_end(); PI != E; ++PI)
PType = (*PI)->getType();
+ VK = VK_LValue;
}
+
+ ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
+
return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(
- Getter, PType, VK_LValue, OK_ObjCProperty,
- Setter,
+ Getter, PType, VK, OK, Setter,
propertyNameLoc, IFace, receiverNameLoc));
}
return ExprError(Diag(propertyNameLoc, diag::err_property_not_found)
Modified: cfe/trunk/test/CodeGenObjCXX/property-derived-to-base-conv.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/property-derived-to-base-conv.mm?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/property-derived-to-base-conv.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/property-derived-to-base-conv.mm Thu Nov 18 13:01:18 2010
@@ -1,7 +1,11 @@
// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -emit-llvm -o - %s
// rdar: // 7501812
-struct A { int member; };
+struct A {
+ int member;
+ void foo();
+ A *operator->();
+};
struct B : A { };
@interface BInt {
@@ -14,6 +18,8 @@
@end
void g(BInt *bint) {
- bint.value.member = 17;
+ bint.value.foo();
+ bint.value->member = 17;
+ int x = bint.value.member;
}
Modified: cfe/trunk/test/SemaObjCXX/propert-dot-error.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/propert-dot-error.mm?rev=119722&r1=119721&r2=119722&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/propert-dot-error.mm (original)
+++ cfe/trunk/test/SemaObjCXX/propert-dot-error.mm Thu Nov 18 13:01:18 2010
@@ -5,6 +5,10 @@
X();
X(const X&);
~X();
+
+ static int staticData;
+ int data;
+ void method();
};
@interface A {
@@ -19,3 +23,19 @@
a.x = X(); // expected-error {{setter method is needed to assign to object using property assignment syntax}}
}
+struct Y : X { };
+
+ at interface B {
+ at private
+ Y *y;
+}
+- (Y)value;
+- (void)setValue : (Y) arg;
+ at property Y value;
+ at end
+
+void g(B *b) {
+ b.value.data = 17; // expected-error {{not assignable}}
+ b.value.staticData = 17;
+ b.value.method();
+}
More information about the cfe-commits
mailing list