зеркало из https://github.com/microsoft/clang-1.git
Revert r142914 and r142915, due to possibly missing file.
r142914: "Introduce a placeholder type for "pseudo object"" r142915: "Pull the pseudo-object stuff into its own file." git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142921 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
9d06ba82d8
Коммит
327a50f464
|
@ -496,7 +496,7 @@ public:
|
|||
CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy;
|
||||
CanQualType VoidPtrTy, NullPtrTy;
|
||||
CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy;
|
||||
CanQualType PseudoObjectTy, ARCUnbridgedCastTy;
|
||||
CanQualType ARCUnbridgedCastTy;
|
||||
CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy;
|
||||
|
||||
// Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand.
|
||||
|
|
|
@ -179,24 +179,6 @@ PLACEHOLDER_TYPE(Overload, OverloadTy)
|
|||
// x->foo # if only contains non-static members
|
||||
PLACEHOLDER_TYPE(BoundMember, BoundMemberTy)
|
||||
|
||||
// The type of an expression which refers to a pseudo-object,
|
||||
// such as those introduced by Objective C's @property or
|
||||
// VS.NET's __property declarations. A placeholder type. The
|
||||
// pseudo-object is actually accessed by emitting a call to
|
||||
// some sort of function or method; typically there is a pair
|
||||
// of a setter and a getter, with the setter used if the
|
||||
// pseudo-object reference is used syntactically as the
|
||||
// left-hand-side of an assignment operator.
|
||||
//
|
||||
// A pseudo-object reference naming an Objective-C @property is
|
||||
// always a dot access with a base of object-pointer type,
|
||||
// e.g. 'x.foo'.
|
||||
//
|
||||
// In VS.NET, a __property declaration creates an implicit
|
||||
// member with an associated name, which can then be named
|
||||
// in any of the normal ways an ordinary member could be.
|
||||
PLACEHOLDER_TYPE(PseudoObject, PseudoObjectTy)
|
||||
|
||||
// __builtin_any_type. A placeholder type. Useful for clients
|
||||
// like debuggers that don't know what type to give something.
|
||||
// Only a small number of operations are valid on expressions of
|
||||
|
|
|
@ -1456,26 +1456,12 @@ public:
|
|||
|
||||
bool isPrefix() const { return isPrefix(getOpcode()); }
|
||||
bool isPostfix() const { return isPostfix(getOpcode()); }
|
||||
|
||||
static bool isIncrementOp(Opcode Op) {
|
||||
return Op == UO_PreInc || Op == UO_PostInc;
|
||||
}
|
||||
bool isIncrementOp() const {
|
||||
return isIncrementOp(getOpcode());
|
||||
return Opc == UO_PreInc || Opc == UO_PostInc;
|
||||
}
|
||||
|
||||
static bool isDecrementOp(Opcode Op) {
|
||||
return Op == UO_PreDec || Op == UO_PostDec;
|
||||
}
|
||||
bool isDecrementOp() const {
|
||||
return isDecrementOp(getOpcode());
|
||||
}
|
||||
|
||||
static bool isIncrementDecrementOp(Opcode Op) { return Op <= UO_PreDec; }
|
||||
bool isIncrementDecrementOp() const {
|
||||
return isIncrementDecrementOp(getOpcode());
|
||||
return Opc <= UO_PreDec;
|
||||
}
|
||||
|
||||
static bool isArithmeticOp(Opcode Op) {
|
||||
return Op >= UO_Plus && Op <= UO_LNot;
|
||||
}
|
||||
|
|
|
@ -227,6 +227,7 @@ public:
|
|||
|
||||
/// ObjCPropertyRefExpr - A dot-syntax expression to access an ObjC
|
||||
/// property.
|
||||
///
|
||||
class ObjCPropertyRefExpr : public Expr {
|
||||
private:
|
||||
/// If the bool is true, this is an implicit property reference; the
|
||||
|
@ -236,11 +237,6 @@ private:
|
|||
llvm::PointerIntPair<NamedDecl*, 1, bool> PropertyOrGetter;
|
||||
ObjCMethodDecl *Setter;
|
||||
|
||||
// FIXME: Maybe we should store the property identifier here,
|
||||
// because it's not rederivable from the other data when there's an
|
||||
// implicit property with no getter (because the 'foo' -> 'setFoo:'
|
||||
// transformation is lossy on the first character).
|
||||
|
||||
SourceLocation IdLoc;
|
||||
|
||||
/// \brief When the receiver in property access is 'super', this is
|
||||
|
@ -259,7 +255,6 @@ public:
|
|||
base->containsUnexpandedParameterPack()),
|
||||
PropertyOrGetter(PD, false), Setter(0),
|
||||
IdLoc(l), ReceiverLoc(), Receiver(base) {
|
||||
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
||||
}
|
||||
|
||||
ObjCPropertyRefExpr(ObjCPropertyDecl *PD, QualType t,
|
||||
|
@ -270,7 +265,6 @@ public:
|
|||
st->containsUnexpandedParameterPack()),
|
||||
PropertyOrGetter(PD, false), Setter(0),
|
||||
IdLoc(l), ReceiverLoc(sl), Receiver(st.getTypePtr()) {
|
||||
assert(t->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
||||
}
|
||||
|
||||
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
||||
|
@ -281,7 +275,6 @@ public:
|
|||
Base->containsUnexpandedParameterPack()),
|
||||
PropertyOrGetter(Getter, true), Setter(Setter),
|
||||
IdLoc(IdLoc), ReceiverLoc(), Receiver(Base) {
|
||||
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
||||
}
|
||||
|
||||
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
||||
|
@ -291,7 +284,6 @@ public:
|
|||
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
|
||||
PropertyOrGetter(Getter, true), Setter(Setter),
|
||||
IdLoc(IdLoc), ReceiverLoc(SuperLoc), Receiver(SuperTy.getTypePtr()) {
|
||||
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
||||
}
|
||||
|
||||
ObjCPropertyRefExpr(ObjCMethodDecl *Getter, ObjCMethodDecl *Setter,
|
||||
|
@ -301,7 +293,6 @@ public:
|
|||
: Expr(ObjCPropertyRefExprClass, T, VK, OK, false, false, false, false),
|
||||
PropertyOrGetter(Getter, true), Setter(Setter),
|
||||
IdLoc(IdLoc), ReceiverLoc(ReceiverLoc), Receiver(Receiver) {
|
||||
assert(T->isSpecificPlaceholderType(BuiltinType::PseudoObject));
|
||||
}
|
||||
|
||||
explicit ObjCPropertyRefExpr(EmptyShell Empty)
|
||||
|
@ -357,15 +348,14 @@ public:
|
|||
if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl())
|
||||
ResultType = Getter->getResultType();
|
||||
else
|
||||
ResultType = PDecl->getType();
|
||||
ResultType = getType();
|
||||
} else {
|
||||
const ObjCMethodDecl *Getter = getImplicitPropertyGetter();
|
||||
if (Getter)
|
||||
ResultType = Getter->getResultType(); // with reference!
|
||||
ResultType = Getter->getResultType(); // with reference!
|
||||
}
|
||||
return ResultType;
|
||||
}
|
||||
|
||||
|
||||
QualType getSetterArgType() const {
|
||||
QualType ArgType;
|
||||
if (isImplicitProperty()) {
|
||||
|
|
|
@ -3612,22 +3612,16 @@ def ext_gnu_ptr_func_arith : Extension<
|
|||
"arithmetic on%select{ a|}0 pointer%select{|s}0 to%select{ the|}2 function "
|
||||
"type%select{|s}2 %1%select{| and %3}2 is a GNU extension">,
|
||||
InGroup<PointerArith>;
|
||||
def error_readonly_property_assignment : Error<
|
||||
"assigning to property with 'readonly' attribute not allowed">;
|
||||
def error_readonly_message_assignment : Error<
|
||||
"assigning to 'readonly' return result of an objective-c message not allowed">;
|
||||
def ext_integer_increment_complex : Extension<
|
||||
"ISO C does not support '++'/'--' on complex integer type %0">;
|
||||
def ext_integer_complement_complex : Extension<
|
||||
"ISO C does not support '~' for complex conjugation of %0">;
|
||||
def err_nosetter_property_assignment : Error<
|
||||
"%select{assignment to readonly property|"
|
||||
"no setter method %1 for assignment to property}0">;
|
||||
def err_nosetter_property_incdec : Error<
|
||||
"%select{%select{increment|decrement}1 of readonly property|"
|
||||
"no setter method %2 for %select{increment|decrement}1 of property}0">;
|
||||
def err_nogetter_property_compound_assignment : Error<
|
||||
"a getter method is needed to perform a compound assignment on a property">;
|
||||
def err_nogetter_property_incdec : Error<
|
||||
"no getter method %1 for %select{increment|decrement} of property">;
|
||||
def error_nosetter_property_assignment : Error<
|
||||
"setter method is needed to assign to object using property" " assignment syntax">;
|
||||
def error_no_subobject_property_setting : Error<
|
||||
"expression is not assignable">;
|
||||
def err_qualified_objc_access : Error<
|
||||
|
|
|
@ -5319,8 +5319,6 @@ public:
|
|||
ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel,
|
||||
const ObjCObjectPointerType *OPT,
|
||||
bool IsInstance);
|
||||
ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
|
||||
bool IsInstance);
|
||||
|
||||
bool inferObjCARCLifetime(ValueDecl *decl);
|
||||
|
||||
|
@ -5779,13 +5777,10 @@ public:
|
|||
// For compound assignment, pass both expressions and the converted type.
|
||||
QualType CheckAssignmentOperands( // C99 6.5.16.[1,2]
|
||||
Expr *LHSExpr, ExprResult &RHS, SourceLocation Loc, QualType CompoundType);
|
||||
|
||||
ExprResult checkPseudoObjectIncDec(Scope *S, SourceLocation OpLoc,
|
||||
UnaryOperatorKind Opcode, Expr *Op);
|
||||
ExprResult checkPseudoObjectAssignment(Scope *S, SourceLocation OpLoc,
|
||||
BinaryOperatorKind Opcode,
|
||||
Expr *LHS, Expr *RHS);
|
||||
ExprResult checkPseudoObjectRValue(Expr *E);
|
||||
|
||||
void ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS,
|
||||
QualType& LHSTy);
|
||||
ExprResult ConvertPropertyForRValue(Expr *E);
|
||||
|
||||
QualType CheckConditionalOperands( // C99 6.5.15
|
||||
ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
|
||||
|
|
|
@ -556,9 +556,7 @@ namespace clang {
|
|||
/// \brief The OpenCL 'half' / ARM NEON __fp16 type.
|
||||
PREDEF_TYPE_HALF_ID = 33,
|
||||
/// \brief ARC's unbridged-cast placeholder type.
|
||||
PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34,
|
||||
/// \brief The pseudo-object placeholder type.
|
||||
PREDEF_TYPE_PSEUDO_OBJECT = 35
|
||||
PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34
|
||||
};
|
||||
|
||||
/// \brief The number of predefined type IDs that are reserved for
|
||||
|
|
|
@ -461,9 +461,6 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) {
|
|||
// Placeholder type for bound members.
|
||||
InitBuiltinType(BoundMemberTy, BuiltinType::BoundMember);
|
||||
|
||||
// Placeholder type for pseudo-objects.
|
||||
InitBuiltinType(PseudoObjectTy, BuiltinType::PseudoObject);
|
||||
|
||||
// "any" type; useful for debugger-like clients.
|
||||
InitBuiltinType(UnknownAnyTy, BuiltinType::UnknownAny);
|
||||
|
||||
|
|
|
@ -1493,7 +1493,6 @@ const char *BuiltinType::getName(const PrintingPolicy &Policy) const {
|
|||
case NullPtr: return "nullptr_t";
|
||||
case Overload: return "<overloaded function type>";
|
||||
case BoundMember: return "<bound member function type>";
|
||||
case PseudoObject: return "<pseudo-object type>";
|
||||
case Dependent: return "<dependent type>";
|
||||
case UnknownAny: return "<unknown type>";
|
||||
case ARCUnbridgedCast: return "<ARC unbridged cast type>";
|
||||
|
|
|
@ -238,7 +238,6 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
|
|||
case BuiltinType::BoundMember:
|
||||
case BuiltinType::UnknownAny:
|
||||
case BuiltinType::ARCUnbridgedCast:
|
||||
case BuiltinType::PseudoObject:
|
||||
case BuiltinType::ObjCId:
|
||||
case BuiltinType::ObjCClass:
|
||||
case BuiltinType::ObjCSel:
|
||||
|
|
|
@ -326,8 +326,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
|
|||
}
|
||||
|
||||
case CK_GetObjCProperty: {
|
||||
LValue LV =
|
||||
CGF.EmitObjCPropertyRefLValue(E->getSubExpr()->getObjCProperty());
|
||||
LValue LV = CGF.EmitLValue(E->getSubExpr());
|
||||
assert(LV.isPropertyRef());
|
||||
RValue RV = CGF.EmitLoadOfPropertyRefLValue(LV, getReturnValueSlot());
|
||||
EmitMoveFromReturnSlot(E, RV);
|
||||
|
|
|
@ -363,7 +363,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op,
|
|||
case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
|
||||
|
||||
case CK_GetObjCProperty: {
|
||||
LValue LV = CGF.EmitObjCPropertyRefLValue(Op->getObjCProperty());
|
||||
LValue LV = CGF.EmitLValue(Op);
|
||||
assert(LV.isPropertyRef() && "Unknown LValue type!");
|
||||
return CGF.EmitLoadOfPropertyRefLValue(LV).getComplexVal();
|
||||
}
|
||||
|
|
|
@ -1167,10 +1167,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) {
|
|||
break;
|
||||
|
||||
case CK_GetObjCProperty: {
|
||||
assert(CGF.getContext().hasSameUnqualifiedType(E->getType(), DestTy));
|
||||
assert(E->isGLValue() && E->getObjectKind() == OK_ObjCProperty &&
|
||||
"CK_GetObjCProperty for non-lvalue or non-ObjCProperty");
|
||||
LValue LV = CGF.EmitObjCPropertyRefLValue(E->getObjCProperty());
|
||||
RValue RV = CGF.EmitLoadOfPropertyRefLValue(LV);
|
||||
RValue RV = CGF.EmitLoadOfLValue(CGF.EmitLValue(E));
|
||||
return RV.getScalarVal();
|
||||
}
|
||||
|
||||
|
|
|
@ -1304,7 +1304,7 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *
|
|||
} else {
|
||||
OMD = PropRefExpr->getImplicitPropertySetter();
|
||||
Sel = OMD->getSelector();
|
||||
Ty = (*OMD->param_begin())->getType();
|
||||
Ty = PropRefExpr->getType();
|
||||
}
|
||||
Super = PropRefExpr->isSuperReceiver();
|
||||
if (!Super) {
|
||||
|
@ -1380,7 +1380,7 @@ Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) {
|
|||
} else {
|
||||
OMD = PropRefExpr->getImplicitPropertyGetter();
|
||||
Sel = OMD->getSelector();
|
||||
Ty = OMD->getResultType();
|
||||
Ty = PropRefExpr->getType();
|
||||
}
|
||||
Super = PropRefExpr->isSuperReceiver();
|
||||
if (!Super)
|
||||
|
|
|
@ -31,7 +31,6 @@ add_clang_library(clangSema
|
|||
SemaLookup.cpp
|
||||
SemaObjCProperty.cpp
|
||||
SemaOverload.cpp
|
||||
SemaPseudoObject.cpp
|
||||
SemaStmt.cpp
|
||||
SemaTemplate.cpp
|
||||
SemaTemplateDeduction.cpp
|
||||
|
|
|
@ -4256,8 +4256,7 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
|
|||
if (LT != Qualifiers::OCL_None)
|
||||
return;
|
||||
|
||||
if (ObjCPropertyRefExpr *PRE
|
||||
= dyn_cast<ObjCPropertyRefExpr>(LHS->IgnoreParens())) {
|
||||
if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(LHS)) {
|
||||
if (PRE->isImplicitProperty())
|
||||
return;
|
||||
const ObjCPropertyDecl *PD = PRE->getExplicitProperty();
|
||||
|
|
|
@ -363,9 +363,19 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) {
|
|||
assert(!T.isNull() && "r-value conversion on typeless expression?");
|
||||
|
||||
// We can't do lvalue-to-rvalue on atomics yet.
|
||||
if (T->isAtomicType())
|
||||
if (T->getAs<AtomicType>())
|
||||
return Owned(E);
|
||||
|
||||
// Create a load out of an ObjCProperty l-value, if necessary.
|
||||
if (E->getObjectKind() == OK_ObjCProperty) {
|
||||
ExprResult Res = ConvertPropertyForRValue(E);
|
||||
if (Res.isInvalid())
|
||||
return Owned(E);
|
||||
E = Res.take();
|
||||
if (!E->isGLValue())
|
||||
return Owned(E);
|
||||
}
|
||||
|
||||
// We don't want to throw lvalue-to-rvalue casts on top of
|
||||
// expressions of certain types in C++.
|
||||
if (getLangOptions().CPlusPlus &&
|
||||
|
@ -3959,23 +3969,6 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList,
|
|||
unsigned NumInit = InitArgList.size();
|
||||
Expr **InitList = InitArgList.release();
|
||||
|
||||
// Immediately handle non-overload placeholders. Overloads can be
|
||||
// resolved contextually, but everything else here can't.
|
||||
for (unsigned I = 0; I != NumInit; ++I) {
|
||||
if (const BuiltinType *pty
|
||||
= InitList[I]->getType()->getAsPlaceholderType()) {
|
||||
if (pty->getKind() == BuiltinType::Overload) continue;
|
||||
|
||||
ExprResult result = CheckPlaceholderExpr(InitList[I]);
|
||||
|
||||
// Ignore failures; dropping the entire initializer list because
|
||||
// of one failure would be terrible for indexing/etc.
|
||||
if (result.isInvalid()) continue;
|
||||
|
||||
InitList[I] = result.take();
|
||||
}
|
||||
}
|
||||
|
||||
// Semantic analysis for initializers is done by ActOnDeclarator() and
|
||||
// CheckInitializer() - it requires knowledge of the object being intialized.
|
||||
|
||||
|
@ -6960,41 +6953,51 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]
|
|||
/// depends on various declarations and thus must be treated specially.
|
||||
///
|
||||
static bool IsReadonlyProperty(Expr *E, Sema &S) {
|
||||
const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E);
|
||||
if (!PropExpr) return false;
|
||||
if (PropExpr->isImplicitProperty()) return false;
|
||||
if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
|
||||
const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
|
||||
if (PropExpr->isImplicitProperty()) return false;
|
||||
|
||||
ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
|
||||
QualType BaseType = PropExpr->isSuperReceiver() ?
|
||||
ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
|
||||
QualType BaseType = PropExpr->isSuperReceiver() ?
|
||||
PropExpr->getSuperReceiverType() :
|
||||
PropExpr->getBase()->getType();
|
||||
|
||||
if (const ObjCObjectPointerType *OPT =
|
||||
BaseType->getAsObjCInterfacePointerType())
|
||||
if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
|
||||
if (S.isPropertyReadonly(PDecl, IFace))
|
||||
return true;
|
||||
if (const ObjCObjectPointerType *OPT =
|
||||
BaseType->getAsObjCInterfacePointerType())
|
||||
if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl())
|
||||
if (S.isPropertyReadonly(PDecl, IFace))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsConstProperty(Expr *E, Sema &S) {
|
||||
const ObjCPropertyRefExpr *PropExpr = dyn_cast<ObjCPropertyRefExpr>(E);
|
||||
if (!PropExpr) return false;
|
||||
if (PropExpr->isImplicitProperty()) return false;
|
||||
if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) {
|
||||
const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E);
|
||||
if (PropExpr->isImplicitProperty()) return false;
|
||||
|
||||
ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
|
||||
QualType T = PDecl->getType().getNonReferenceType();
|
||||
return T.isConstQualified();
|
||||
ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty();
|
||||
QualType T = PDecl->getType();
|
||||
if (T->isReferenceType())
|
||||
T = T->getAs<ReferenceType>()->getPointeeType();
|
||||
CanQualType CT = S.Context.getCanonicalType(T);
|
||||
return CT.isConstQualified();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsReadonlyMessage(Expr *E, Sema &S) {
|
||||
const MemberExpr *ME = dyn_cast<MemberExpr>(E);
|
||||
if (!ME) return false;
|
||||
if (!isa<FieldDecl>(ME->getMemberDecl())) return false;
|
||||
ObjCMessageExpr *Base =
|
||||
dyn_cast<ObjCMessageExpr>(ME->getBase()->IgnoreParenImpCasts());
|
||||
if (!Base) return false;
|
||||
return Base->getMethodDecl() != 0;
|
||||
if (E->getStmtClass() != Expr::MemberExprClass)
|
||||
return false;
|
||||
const MemberExpr *ME = cast<MemberExpr>(E);
|
||||
NamedDecl *Member = ME->getMemberDecl();
|
||||
if (isa<FieldDecl>(Member)) {
|
||||
Expr *Base = ME->getBase()->IgnoreParenImpCasts();
|
||||
if (Base->getStmtClass() != Expr::ObjCMessageExprClass)
|
||||
return false;
|
||||
return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not,
|
||||
|
@ -7082,8 +7085,10 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
|
|||
Diag = diag::err_block_decl_ref_not_modifiable_lvalue;
|
||||
break;
|
||||
case Expr::MLV_ReadonlyProperty:
|
||||
Diag = diag::error_readonly_property_assignment;
|
||||
break;
|
||||
case Expr::MLV_NoSetterProperty:
|
||||
llvm_unreachable("readonly properties should be processed differently");
|
||||
Diag = diag::error_nosetter_property_assignment;
|
||||
break;
|
||||
case Expr::MLV_InvalidMessageExpression:
|
||||
Diag = diag::error_readonly_message_assignment;
|
||||
|
@ -7109,8 +7114,6 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) {
|
|||
QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
|
||||
SourceLocation Loc,
|
||||
QualType CompoundType) {
|
||||
assert(!LHSExpr->hasPlaceholderType(BuiltinType::PseudoObject));
|
||||
|
||||
// Verify that LHS is a modifiable lvalue, and emit error if not.
|
||||
if (CheckForModifiableLvalue(LHSExpr, Loc, *this))
|
||||
return QualType();
|
||||
|
@ -7121,6 +7124,14 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS,
|
|||
AssignConvertType ConvTy;
|
||||
if (CompoundType.isNull()) {
|
||||
QualType LHSTy(LHSType);
|
||||
// Simple assignment "x = y".
|
||||
if (LHSExpr->getObjectKind() == OK_ObjCProperty) {
|
||||
ExprResult LHSResult = Owned(LHSExpr);
|
||||
ConvertPropertyForLValue(LHSResult, RHS, LHSTy);
|
||||
if (LHSResult.isInvalid())
|
||||
return QualType();
|
||||
LHSExpr = LHSResult.take();
|
||||
}
|
||||
ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS);
|
||||
if (RHS.isInvalid())
|
||||
return QualType();
|
||||
|
@ -7281,6 +7292,104 @@ static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op,
|
|||
return ResType.getUnqualifiedType();
|
||||
}
|
||||
}
|
||||
|
||||
ExprResult Sema::ConvertPropertyForRValue(Expr *E) {
|
||||
assert(E->getValueKind() == VK_LValue &&
|
||||
E->getObjectKind() == OK_ObjCProperty);
|
||||
const ObjCPropertyRefExpr *PRE = E->getObjCProperty();
|
||||
|
||||
QualType T = E->getType();
|
||||
QualType ReceiverType;
|
||||
if (PRE->isObjectReceiver())
|
||||
ReceiverType = PRE->getBase()->getType();
|
||||
else if (PRE->isSuperReceiver())
|
||||
ReceiverType = PRE->getSuperReceiverType();
|
||||
else
|
||||
ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver());
|
||||
|
||||
ExprValueKind VK = VK_RValue;
|
||||
if (PRE->isImplicitProperty()) {
|
||||
if (ObjCMethodDecl *GetterMethod =
|
||||
PRE->getImplicitPropertyGetter()) {
|
||||
T = getMessageSendResultType(ReceiverType, GetterMethod,
|
||||
PRE->isClassReceiver(),
|
||||
PRE->isSuperReceiver());
|
||||
VK = Expr::getValueKindForType(GetterMethod->getResultType());
|
||||
}
|
||||
else {
|
||||
Diag(PRE->getLocation(), diag::err_getter_not_found)
|
||||
<< PRE->getBase()->getType();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// lvalue-ness of an explicit property is determined by
|
||||
// getter type.
|
||||
QualType ResT = PRE->getGetterResultType();
|
||||
VK = Expr::getValueKindForType(ResT);
|
||||
}
|
||||
|
||||
E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty,
|
||||
E, 0, VK);
|
||||
|
||||
ExprResult Result = MaybeBindToTemporary(E);
|
||||
if (!Result.isInvalid())
|
||||
E = Result.take();
|
||||
|
||||
return Owned(E);
|
||||
}
|
||||
|
||||
void Sema::ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS,
|
||||
QualType &LHSTy) {
|
||||
assert(LHS.get()->getValueKind() == VK_LValue &&
|
||||
LHS.get()->getObjectKind() == OK_ObjCProperty);
|
||||
const ObjCPropertyRefExpr *PropRef = LHS.get()->getObjCProperty();
|
||||
|
||||
bool Consumed = false;
|
||||
|
||||
if (PropRef->isImplicitProperty()) {
|
||||
// If using property-dot syntax notation for assignment, and there is a
|
||||
// setter, RHS expression is being passed to the setter argument. So,
|
||||
// type conversion (and comparison) is RHS to setter's argument type.
|
||||
if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) {
|
||||
ObjCMethodDecl::param_const_iterator P = SetterMD->param_begin();
|
||||
LHSTy = (*P)->getType();
|
||||
Consumed = (getLangOptions().ObjCAutoRefCount &&
|
||||
(*P)->hasAttr<NSConsumedAttr>());
|
||||
|
||||
// Otherwise, if the getter returns an l-value, just call that.
|
||||
} else {
|
||||
QualType Result = PropRef->getImplicitPropertyGetter()->getResultType();
|
||||
ExprValueKind VK = Expr::getValueKindForType(Result);
|
||||
if (VK == VK_LValue) {
|
||||
LHS = ImplicitCastExpr::Create(Context, LHS.get()->getType(),
|
||||
CK_GetObjCProperty, LHS.take(), 0, VK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const ObjCMethodDecl *setter
|
||||
= PropRef->getExplicitProperty()->getSetterMethodDecl();
|
||||
if (setter) {
|
||||
ObjCMethodDecl::param_const_iterator P = setter->param_begin();
|
||||
LHSTy = (*P)->getType();
|
||||
if (getLangOptions().ObjCAutoRefCount)
|
||||
Consumed = (*P)->hasAttr<NSConsumedAttr>();
|
||||
}
|
||||
}
|
||||
|
||||
if ((getLangOptions().CPlusPlus && LHSTy->isRecordType()) ||
|
||||
getLangOptions().ObjCAutoRefCount) {
|
||||
InitializedEntity Entity =
|
||||
InitializedEntity::InitializeParameter(Context, LHSTy, Consumed);
|
||||
ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), RHS);
|
||||
if (!ArgE.isInvalid()) {
|
||||
RHS = ArgE;
|
||||
if (getLangOptions().ObjCAutoRefCount && !PropRef->isSuperReceiver())
|
||||
checkRetainCycles(const_cast<Expr*>(PropRef->getBase()), RHS.get());
|
||||
}
|
||||
}
|
||||
LHSTy = LHSTy.getNonReferenceType();
|
||||
}
|
||||
|
||||
|
||||
/// getPrimaryDecl - Helper function for CheckAddressOfOperand().
|
||||
|
@ -7364,39 +7473,31 @@ static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
|
|||
/// 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.
|
||||
static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
|
||||
static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
|
||||
SourceLocation OpLoc) {
|
||||
if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){
|
||||
if (PTy->getKind() == BuiltinType::Overload) {
|
||||
if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) {
|
||||
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
|
||||
<< OrigOp.get()->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
return S.Context.OverloadTy;
|
||||
}
|
||||
|
||||
if (PTy->getKind() == BuiltinType::UnknownAny)
|
||||
return S.Context.UnknownAnyTy;
|
||||
|
||||
if (PTy->getKind() == BuiltinType::BoundMember) {
|
||||
S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
|
||||
<< OrigOp.get()->getSourceRange();
|
||||
if (OrigOp->isTypeDependent())
|
||||
return S.Context.DependentTy;
|
||||
if (OrigOp->getType() == S.Context.OverloadTy) {
|
||||
if (!isa<OverloadExpr>(OrigOp->IgnoreParens())) {
|
||||
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
|
||||
<< OrigOp->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
OrigOp = S.CheckPlaceholderExpr(OrigOp.take());
|
||||
if (OrigOp.isInvalid()) return QualType();
|
||||
|
||||
return S.Context.OverloadTy;
|
||||
}
|
||||
if (OrigOp->getType() == S.Context.UnknownAnyTy)
|
||||
return S.Context.UnknownAnyTy;
|
||||
if (OrigOp->getType() == S.Context.BoundMemberTy) {
|
||||
S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
|
||||
<< OrigOp->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
if (OrigOp.get()->isTypeDependent())
|
||||
return S.Context.DependentTy;
|
||||
|
||||
assert(!OrigOp.get()->getType()->isPlaceholderType());
|
||||
assert(!OrigOp->getType()->isPlaceholderType());
|
||||
|
||||
// Make sure to ignore parentheses in subsequent checks
|
||||
Expr *op = OrigOp.get()->IgnoreParens();
|
||||
Expr *op = OrigOp->IgnoreParens();
|
||||
|
||||
if (S.getLangOptions().C99) {
|
||||
// Implement C99-only parts of addressof rules.
|
||||
|
@ -7429,16 +7530,16 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
|
|||
// If the underlying expression isn't a decl ref, give up.
|
||||
if (!isa<DeclRefExpr>(op)) {
|
||||
S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
|
||||
<< OrigOp.get()->getSourceRange();
|
||||
<< OrigOp->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
DeclRefExpr *DRE = cast<DeclRefExpr>(op);
|
||||
CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl());
|
||||
|
||||
// The id-expression was parenthesized.
|
||||
if (OrigOp.get() != DRE) {
|
||||
if (OrigOp != DRE) {
|
||||
S.Diag(OpLoc, diag::err_parens_pointer_member_function)
|
||||
<< OrigOp.get()->getSourceRange();
|
||||
<< OrigOp->getSourceRange();
|
||||
|
||||
// The method was named without a qualifier.
|
||||
} else if (!DRE->getQualifier()) {
|
||||
|
@ -7452,15 +7553,10 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp,
|
|||
// C99 6.5.3.2p1
|
||||
// The operand must be either an l-value or a function designator
|
||||
if (!op->getType()->isFunctionType()) {
|
||||
// Use a special diagnostic for loads from property references.
|
||||
if (isa<ObjCPropertyRefExpr>(op->IgnoreImplicit()->IgnoreParens())) {
|
||||
AddressOfError = AO_Property_Expansion;
|
||||
} else {
|
||||
// FIXME: emit more specific diag...
|
||||
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
|
||||
<< op->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
// FIXME: emit more specific diag...
|
||||
S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof)
|
||||
<< op->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
} else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1
|
||||
// The operand cannot be a bit-field
|
||||
|
@ -7685,6 +7781,23 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
|
|||
ExprValueKind VK = VK_RValue;
|
||||
ExprObjectKind OK = OK_Ordinary;
|
||||
|
||||
// Check if a 'foo<int>' involved in a binary op, identifies a single
|
||||
// function unambiguously (i.e. an lvalue ala 13.4)
|
||||
// But since an assignment can trigger target based overload, exclude it in
|
||||
// our blind search. i.e:
|
||||
// template<class T> void f(); template<class T, class U> void f(U);
|
||||
// f<int> == 0; // resolve f<int> blindly
|
||||
// void (*p)(int); p = f<int>; // resolve f<int> using target
|
||||
if (Opc != BO_Assign) {
|
||||
ExprResult resolvedLHS = CheckPlaceholderExpr(LHS.get());
|
||||
if (!resolvedLHS.isUsable()) return ExprError();
|
||||
LHS = move(resolvedLHS);
|
||||
|
||||
ExprResult resolvedRHS = CheckPlaceholderExpr(RHS.get());
|
||||
if (!resolvedRHS.isUsable()) return ExprError();
|
||||
RHS = move(resolvedRHS);
|
||||
}
|
||||
|
||||
switch (Opc) {
|
||||
case BO_Assign:
|
||||
ResultTy = CheckAssignmentOperands(LHS.get(), RHS, OpLoc, QualType());
|
||||
|
@ -7980,83 +8093,38 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
|
|||
return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
|
||||
}
|
||||
|
||||
/// Build an overloaded binary operator expression in the given scope.
|
||||
static ExprResult BuildOverloadedBinOp(Sema &S, Scope *Sc, SourceLocation OpLoc,
|
||||
BinaryOperatorKind Opc,
|
||||
Expr *LHS, Expr *RHS) {
|
||||
// Find all of the overloaded operators visible from this
|
||||
// point. We perform both an operator-name lookup from the local
|
||||
// scope and an argument-dependent lookup based on the types of
|
||||
// the arguments.
|
||||
UnresolvedSet<16> Functions;
|
||||
OverloadedOperatorKind OverOp
|
||||
= BinaryOperator::getOverloadedOperator(Opc);
|
||||
if (Sc && OverOp != OO_None)
|
||||
S.LookupOverloadedOperatorName(OverOp, Sc, LHS->getType(),
|
||||
RHS->getType(), Functions);
|
||||
|
||||
// Build the (potentially-overloaded, potentially-dependent)
|
||||
// binary operation.
|
||||
return S.CreateOverloadedBinOp(OpLoc, Opc, Functions, LHS, RHS);
|
||||
}
|
||||
|
||||
ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc,
|
||||
BinaryOperatorKind Opc,
|
||||
Expr *LHSExpr, Expr *RHSExpr) {
|
||||
// Handle pseudo-objects in the LHS.
|
||||
if (const BuiltinType *pty = LHSExpr->getType()->getAsPlaceholderType()) {
|
||||
// Assignments with a pseudo-object l-value need special analysis.
|
||||
if (pty->getKind() == BuiltinType::PseudoObject &&
|
||||
BinaryOperator::isAssignmentOp(Opc))
|
||||
return checkPseudoObjectAssignment(S, OpLoc, Opc, LHSExpr, RHSExpr);
|
||||
|
||||
// Don't resolve overloads if the other type is overloadable.
|
||||
if (pty->getKind() == BuiltinType::Overload) {
|
||||
// We can't actually test that if we still have a placeholder,
|
||||
// though. Fortunately, none of the exceptions we see in that
|
||||
// code below are valid when the LHS is an overload set.
|
||||
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
|
||||
if (resolvedRHS.isInvalid()) return ExprError();
|
||||
RHSExpr = resolvedRHS.take();
|
||||
|
||||
if (RHSExpr->getType()->isOverloadableType())
|
||||
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
|
||||
}
|
||||
|
||||
ExprResult LHS = CheckPlaceholderExpr(LHSExpr);
|
||||
if (LHS.isInvalid()) return ExprError();
|
||||
LHSExpr = LHS.take();
|
||||
}
|
||||
|
||||
// Handle pseudo-objects in the RHS.
|
||||
if (const BuiltinType *pty = RHSExpr->getType()->getAsPlaceholderType()) {
|
||||
// An overload in the RHS can potentially be resolved by the type
|
||||
// being assigned to.
|
||||
if (Opc == BO_Assign && pty->getKind() == BuiltinType::Overload)
|
||||
return CreateBuiltinBinOp(OpLoc, Opc, LHSExpr, RHSExpr);
|
||||
|
||||
// Don't resolve overloads if the other type is overloadable.
|
||||
if (pty->getKind() == BuiltinType::Overload &&
|
||||
LHSExpr->getType()->isOverloadableType())
|
||||
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
|
||||
|
||||
ExprResult resolvedRHS = CheckPlaceholderExpr(RHSExpr);
|
||||
if (!resolvedRHS.isUsable()) return ExprError();
|
||||
RHSExpr = resolvedRHS.take();
|
||||
}
|
||||
|
||||
if (getLangOptions().CPlusPlus) {
|
||||
bool UseBuiltinOperator;
|
||||
|
||||
if (LHSExpr->isTypeDependent() || RHSExpr->isTypeDependent()) {
|
||||
UseBuiltinOperator = false;
|
||||
} else if (Opc == BO_Assign &&
|
||||
LHSExpr->getObjectKind() == OK_ObjCProperty) {
|
||||
UseBuiltinOperator = true;
|
||||
} else {
|
||||
UseBuiltinOperator = !LHSExpr->getType()->isOverloadableType() &&
|
||||
!RHSExpr->getType()->isOverloadableType();
|
||||
}
|
||||
|
||||
if (!UseBuiltinOperator)
|
||||
return BuildOverloadedBinOp(*this, S, OpLoc, Opc, LHSExpr, RHSExpr);
|
||||
if (!UseBuiltinOperator) {
|
||||
// Find all of the overloaded operators visible from this
|
||||
// point. We perform both an operator-name lookup from the local
|
||||
// scope and an argument-dependent lookup based on the types of
|
||||
// the arguments.
|
||||
UnresolvedSet<16> Functions;
|
||||
OverloadedOperatorKind OverOp
|
||||
= BinaryOperator::getOverloadedOperator(Opc);
|
||||
if (S && OverOp != OO_None)
|
||||
LookupOverloadedOperatorName(OverOp, S, LHSExpr->getType(),
|
||||
RHSExpr->getType(), Functions);
|
||||
|
||||
// Build the (potentially-overloaded, potentially-dependent)
|
||||
// binary operation.
|
||||
return CreateOverloadedBinOp(OpLoc, Opc, Functions, LHSExpr, RHSExpr);
|
||||
}
|
||||
}
|
||||
|
||||
// Build a built-in binary operation.
|
||||
|
@ -8082,9 +8150,12 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
Opc == UO_PreDec);
|
||||
break;
|
||||
case UO_AddrOf:
|
||||
resultType = CheckAddressOfOperand(*this, Input, OpLoc);
|
||||
resultType = CheckAddressOfOperand(*this, Input.get(), OpLoc);
|
||||
break;
|
||||
case UO_Deref: {
|
||||
ExprResult resolved = CheckPlaceholderExpr(Input.get());
|
||||
if (!resolved.isUsable()) return ExprError();
|
||||
Input = move(resolved);
|
||||
Input = DefaultFunctionArrayLvalueConversion(Input.take());
|
||||
resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc);
|
||||
break;
|
||||
|
@ -8106,6 +8177,11 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
Opc == UO_Plus &&
|
||||
resultType->isPointerType())
|
||||
break;
|
||||
else if (resultType->isPlaceholderType()) {
|
||||
Input = CheckPlaceholderExpr(Input.take());
|
||||
if (Input.isInvalid()) return ExprError();
|
||||
return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
|
||||
}
|
||||
|
||||
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
|
||||
<< resultType << Input.get()->getSourceRange());
|
||||
|
@ -8123,7 +8199,11 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
<< resultType << Input.get()->getSourceRange();
|
||||
else if (resultType->hasIntegerRepresentation())
|
||||
break;
|
||||
else {
|
||||
else if (resultType->isPlaceholderType()) {
|
||||
Input = CheckPlaceholderExpr(Input.take());
|
||||
if (Input.isInvalid()) return ExprError();
|
||||
return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
|
||||
} else {
|
||||
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
|
||||
<< resultType << Input.get()->getSourceRange());
|
||||
}
|
||||
|
@ -8151,6 +8231,10 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
Input = ImpCastExprToType(Input.take(), Context.BoolTy,
|
||||
ScalarTypeToBooleanCastKind(resultType));
|
||||
}
|
||||
} else if (resultType->isPlaceholderType()) {
|
||||
Input = CheckPlaceholderExpr(Input.take());
|
||||
if (Input.isInvalid()) return ExprError();
|
||||
return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take());
|
||||
} else {
|
||||
return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
|
||||
<< resultType << Input.get()->getSourceRange());
|
||||
|
@ -8191,32 +8275,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
|
||||
ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc,
|
||||
UnaryOperatorKind Opc, Expr *Input) {
|
||||
// First things first: handle placeholders so that the
|
||||
// overloaded-operator check considers the right type.
|
||||
if (const BuiltinType *pty = Input->getType()->getAsPlaceholderType()) {
|
||||
// Increment and decrement of pseudo-object references.
|
||||
if (pty->getKind() == BuiltinType::PseudoObject &&
|
||||
UnaryOperator::isIncrementDecrementOp(Opc))
|
||||
return checkPseudoObjectIncDec(S, OpLoc, Opc, Input);
|
||||
|
||||
// extension is always a builtin operator.
|
||||
if (Opc == UO_Extension)
|
||||
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
|
||||
|
||||
// & gets special logic for several kinds of placeholder.
|
||||
// The builtin code knows what to do.
|
||||
if (Opc == UO_AddrOf &&
|
||||
(pty->getKind() == BuiltinType::Overload ||
|
||||
pty->getKind() == BuiltinType::UnknownAny ||
|
||||
pty->getKind() == BuiltinType::BoundMember))
|
||||
return CreateBuiltinUnaryOp(OpLoc, Opc, Input);
|
||||
|
||||
// Anything else needs to be handled now.
|
||||
ExprResult Result = CheckPlaceholderExpr(Input);
|
||||
if (Result.isInvalid()) return ExprError();
|
||||
Input = Result.take();
|
||||
}
|
||||
|
||||
if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() &&
|
||||
UnaryOperator::getOverloadedOperator(Opc) != OO_None) {
|
||||
// Find all of the overloaded operators visible from this
|
||||
|
@ -10093,10 +10151,6 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
|
|||
case BuiltinType::UnknownAny:
|
||||
return diagnoseUnknownAnyExpr(*this, E);
|
||||
|
||||
// Pseudo-objects.
|
||||
case BuiltinType::PseudoObject:
|
||||
return checkPseudoObjectRValue(E);
|
||||
|
||||
// Everything else should be impossible.
|
||||
#define BUILTIN_TYPE(Id, SingletonId) \
|
||||
case BuiltinType::Id:
|
||||
|
|
|
@ -2260,7 +2260,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
|
|||
break;
|
||||
|
||||
case ICK_Lvalue_To_Rvalue:
|
||||
assert(From->getObjectKind() != OK_ObjCProperty);
|
||||
// Should this get its own ICK?
|
||||
if (From->getObjectKind() == OK_ObjCProperty) {
|
||||
ExprResult FromRes = ConvertPropertyForRValue(From);
|
||||
if (FromRes.isInvalid())
|
||||
return ExprError();
|
||||
From = FromRes.take();
|
||||
if (!From->isGLValue()) break;
|
||||
}
|
||||
|
||||
FromType = FromType.getUnqualifiedType();
|
||||
From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue,
|
||||
From, 0, VK_RValue);
|
||||
|
@ -4186,10 +4194,6 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
|
|||
if (Result.isInvalid()) return ExprError();
|
||||
Base = Result.get();
|
||||
|
||||
Result = CheckPlaceholderExpr(Base);
|
||||
if (Result.isInvalid()) return ExprError();
|
||||
Base = Result.take();
|
||||
|
||||
QualType BaseType = Base->getType();
|
||||
MayBePseudoDestructor = false;
|
||||
if (BaseType->isDependentType()) {
|
||||
|
@ -4588,12 +4592,6 @@ ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
|
|||
/// Perform the conversions required for an expression used in a
|
||||
/// context that ignores the result.
|
||||
ExprResult Sema::IgnoredValueConversions(Expr *E) {
|
||||
if (E->hasPlaceholderType()) {
|
||||
ExprResult result = CheckPlaceholderExpr(E);
|
||||
if (result.isInvalid()) return Owned(E);
|
||||
E = result.take();
|
||||
}
|
||||
|
||||
// C99 6.3.2.1:
|
||||
// [Except in specific positions,] an lvalue that does not have
|
||||
// array type is converted to the value stored in the
|
||||
|
@ -4609,6 +4607,14 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) {
|
|||
return Owned(E);
|
||||
}
|
||||
|
||||
// We always want to do this on ObjC property references.
|
||||
if (E->getObjectKind() == OK_ObjCProperty) {
|
||||
ExprResult Res = ConvertPropertyForRValue(E);
|
||||
if (Res.isInvalid()) return Owned(E);
|
||||
E = Res.take();
|
||||
if (E->isRValue()) return Owned(E);
|
||||
}
|
||||
|
||||
// Otherwise, this rule does not apply in C++, at least not for the moment.
|
||||
if (getLangOptions().CPlusPlus) return Owned(E);
|
||||
|
||||
|
|
|
@ -777,7 +777,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
|
|||
QualType BaseType = BaseExprType;
|
||||
if (IsArrow) {
|
||||
assert(BaseType->isPointerType());
|
||||
BaseType = BaseType->castAs<PointerType>()->getPointeeType();
|
||||
BaseType = BaseType->getAs<PointerType>()->getPointeeType();
|
||||
}
|
||||
R.setBaseObjectType(BaseType);
|
||||
|
||||
|
@ -814,6 +814,15 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
|
|||
CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R))
|
||||
return ExprError();
|
||||
|
||||
// Perform a property load on the base regardless of whether we
|
||||
// actually need it for the declaration.
|
||||
if (BaseExpr && BaseExpr->getObjectKind() == OK_ObjCProperty) {
|
||||
ExprResult Result = ConvertPropertyForRValue(BaseExpr);
|
||||
if (Result.isInvalid())
|
||||
return ExprError();
|
||||
BaseExpr = Result.take();
|
||||
}
|
||||
|
||||
// Construct an unresolved result if we in fact got an unresolved
|
||||
// result.
|
||||
if (R.isOverloadedResult() || R.isUnresolvableResult()) {
|
||||
|
@ -1200,8 +1209,11 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
|
|||
if (DiagnoseUseOfDecl(PD, MemberLoc))
|
||||
return ExprError();
|
||||
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD,
|
||||
Context.PseudoObjectTy,
|
||||
QualType T = PD->getType();
|
||||
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
||||
T = getMessageSendResultType(BaseType, Getter, false, false);
|
||||
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, T,
|
||||
VK_LValue,
|
||||
OK_ObjCProperty,
|
||||
MemberLoc,
|
||||
|
@ -1219,10 +1231,16 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
|
|||
if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0,
|
||||
SetterSel, Context))
|
||||
SMD = dyn_cast<ObjCMethodDecl>(SDecl);
|
||||
QualType PType = getMessageSendResultType(BaseType, OMD, false,
|
||||
false);
|
||||
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD,
|
||||
Context.PseudoObjectTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
ExprValueKind VK = VK_LValue;
|
||||
if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType())
|
||||
VK = VK_RValue;
|
||||
ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty);
|
||||
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType,
|
||||
VK, OK,
|
||||
MemberLoc, BaseExpr.take()));
|
||||
}
|
||||
}
|
||||
|
@ -1277,9 +1295,23 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
|
|||
return ExprError();
|
||||
|
||||
if (Getter || Setter) {
|
||||
QualType PType;
|
||||
|
||||
ExprValueKind VK = VK_LValue;
|
||||
if (Getter) {
|
||||
PType = getMessageSendResultType(QualType(OT, 0), Getter, true,
|
||||
false);
|
||||
if (!getLangOptions().CPlusPlus && PType.isCForbiddenLValueType())
|
||||
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) ObjCPropertyRefExpr(Getter, Setter,
|
||||
Context.PseudoObjectTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
PType, VK, OK,
|
||||
MemberLoc, BaseExpr.take()));
|
||||
}
|
||||
|
||||
|
|
|
@ -527,35 +527,6 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel,
|
|||
return Method;
|
||||
}
|
||||
|
||||
/// LookupMethodInType - Look up a method in an ObjCObjectType.
|
||||
ObjCMethodDecl *Sema::LookupMethodInObjectType(Selector sel, QualType type,
|
||||
bool isInstance) {
|
||||
const ObjCObjectType *objType = type->castAs<ObjCObjectType>();
|
||||
if (ObjCInterfaceDecl *iface = objType->getInterface()) {
|
||||
// Look it up in the main interface (and categories, etc.)
|
||||
if (ObjCMethodDecl *method = iface->lookupMethod(sel, isInstance))
|
||||
return method;
|
||||
|
||||
// Okay, look for "private" methods declared in any
|
||||
// @implementations we've seen.
|
||||
if (isInstance) {
|
||||
if (ObjCMethodDecl *method = LookupPrivateInstanceMethod(sel, iface))
|
||||
return method;
|
||||
} else {
|
||||
if (ObjCMethodDecl *method = LookupPrivateClassMethod(sel, iface))
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
// Check qualifiers.
|
||||
for (ObjCObjectType::qual_iterator
|
||||
i = objType->qual_begin(), e = objType->qual_end(); i != e; ++i)
|
||||
if (ObjCMethodDecl *method = (*i)->lookupMethod(sel, isInstance))
|
||||
return method;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier
|
||||
/// list of a qualified objective pointer type.
|
||||
ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel,
|
||||
|
@ -604,14 +575,23 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
// Check whether we can reference this property.
|
||||
if (DiagnoseUseOfDecl(PD, MemberLoc))
|
||||
return ExprError();
|
||||
QualType ResTy = PD->getType();
|
||||
ResTy = ResTy.getNonLValueExprType(Context);
|
||||
Selector Sel = PP.getSelectorTable().getNullarySelector(Member);
|
||||
ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel);
|
||||
if (Getter &&
|
||||
(Getter->hasRelatedResultType()
|
||||
|| DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)))
|
||||
ResTy = getMessageSendResultType(QualType(OPT, 0), Getter, false,
|
||||
Super);
|
||||
|
||||
if (Super)
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
MemberLoc,
|
||||
SuperLoc, SuperType));
|
||||
else
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy,
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
MemberLoc, BaseExpr));
|
||||
}
|
||||
|
@ -623,16 +603,17 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
if (DiagnoseUseOfDecl(PD, MemberLoc))
|
||||
return ExprError();
|
||||
|
||||
QualType T = PD->getType();
|
||||
if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl())
|
||||
T = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super);
|
||||
if (Super)
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD,
|
||||
Context.PseudoObjectTy,
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, T,
|
||||
VK_LValue,
|
||||
OK_ObjCProperty,
|
||||
MemberLoc,
|
||||
SuperLoc, SuperType));
|
||||
else
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD,
|
||||
Context.PseudoObjectTy,
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(PD, T,
|
||||
VK_LValue,
|
||||
OK_ObjCProperty,
|
||||
MemberLoc,
|
||||
|
@ -687,16 +668,28 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT,
|
|||
return ExprError();
|
||||
|
||||
if (Getter || Setter) {
|
||||
QualType PType;
|
||||
if (Getter)
|
||||
PType = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super);
|
||||
else {
|
||||
ParmVarDecl *ArgDecl = *Setter->param_begin();
|
||||
PType = ArgDecl->getType().getUnqualifiedType(); // can't be an array
|
||||
}
|
||||
|
||||
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) ObjCPropertyRefExpr(Getter, Setter,
|
||||
Context.PseudoObjectTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
PType, VK, OK,
|
||||
MemberLoc,
|
||||
SuperLoc, SuperType));
|
||||
else
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
|
||||
Context.PseudoObjectTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
PType, VK, OK,
|
||||
MemberLoc, BaseExpr));
|
||||
|
||||
}
|
||||
|
@ -832,17 +825,34 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
|
|||
return ExprError();
|
||||
|
||||
if (Getter || Setter) {
|
||||
QualType PType;
|
||||
|
||||
ExprValueKind VK = VK_LValue;
|
||||
if (Getter) {
|
||||
PType = getMessageSendResultType(Context.getObjCInterfaceType(IFace),
|
||||
Getter, true,
|
||||
receiverNamePtr->isStr("super"));
|
||||
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);
|
||||
|
||||
if (IsSuper)
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
|
||||
Context.PseudoObjectTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
PType, VK, OK,
|
||||
propertyNameLoc,
|
||||
receiverNameLoc,
|
||||
Context.getObjCInterfaceType(IFace)));
|
||||
|
||||
return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter,
|
||||
Context.PseudoObjectTy,
|
||||
VK_LValue, OK_ObjCProperty,
|
||||
PType, VK, OK,
|
||||
propertyNameLoc,
|
||||
receiverNameLoc, IFace));
|
||||
}
|
||||
|
|
|
@ -3795,8 +3795,15 @@ InitializationSequence::InitializationSequence(Sema &S,
|
|||
setSequenceKind(NormalSequence);
|
||||
|
||||
for (unsigned I = 0; I != NumArgs; ++I)
|
||||
if (const BuiltinType *PlaceholderTy
|
||||
= Args[I]->getType()->getAsPlaceholderType()) {
|
||||
if (Args[I]->getObjectKind() == OK_ObjCProperty) {
|
||||
ExprResult Result = S.ConvertPropertyForRValue(Args[I]);
|
||||
if (Result.isInvalid()) {
|
||||
SetFailed(FK_ConversionFromPropertyFailed);
|
||||
return;
|
||||
}
|
||||
Args[I] = Result.take();
|
||||
} else if (const BuiltinType *PlaceholderTy
|
||||
= Args[I]->getType()->getAsPlaceholderType()) {
|
||||
// FIXME: should we be doing this here?
|
||||
if (PlaceholderTy->getKind() != BuiltinType::Overload) {
|
||||
ExprResult result = S.CheckPlaceholderExpr(Args[I]);
|
||||
|
@ -4486,6 +4493,13 @@ InitializationSequence::Perform(Sema &S,
|
|||
assert(Args.size() == 1);
|
||||
CurInit = Args.get()[0];
|
||||
if (!CurInit.get()) return ExprError();
|
||||
|
||||
// Read from a property when initializing something with it.
|
||||
if (CurInit.get()->getObjectKind() == OK_ObjCProperty) {
|
||||
CurInit = S.ConvertPropertyForRValue(CurInit.take());
|
||||
if (CurInit.isInvalid())
|
||||
return ExprError();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -800,7 +800,9 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
|
|||
SelfExpr, true, true);
|
||||
ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
|
||||
ParmVarDecl *Param = (*P);
|
||||
QualType T = Param->getType().getNonReferenceType();
|
||||
QualType T = Param->getType();
|
||||
if (T->isReferenceType())
|
||||
T = T->getAs<ReferenceType>()->getPointeeType();
|
||||
Expr *rhs = new (Context) DeclRefExpr(Param, T,
|
||||
VK_LValue, SourceLocation());
|
||||
ExprResult Res = BuildBinOp(S, lhs->getLocEnd(),
|
||||
|
@ -952,8 +954,8 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
|
|||
ObjCMethodDecl *GetterMethod,
|
||||
SourceLocation Loc) {
|
||||
if (GetterMethod &&
|
||||
!Context.hasSameType(GetterMethod->getResultType().getNonReferenceType(),
|
||||
property->getType().getNonReferenceType())) {
|
||||
GetterMethod->getResultType().getNonReferenceType()
|
||||
!= property->getType().getNonReferenceType()) {
|
||||
AssignConvertType result = Incompatible;
|
||||
if (property->getType()->isObjCObjectPointerType())
|
||||
result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(),
|
||||
|
|
|
@ -575,6 +575,17 @@ namespace {
|
|||
/// Return true on unrecoverable error.
|
||||
static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
|
||||
UnbridgedCastsSet *unbridgedCasts = 0) {
|
||||
// ObjCProperty l-values are placeholder-like.
|
||||
if (E->getObjectKind() == OK_ObjCProperty) {
|
||||
ExprResult result = S.ConvertPropertyForRValue(E);
|
||||
if (result.isInvalid())
|
||||
return true;
|
||||
|
||||
E = result.take();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle true placeholders.
|
||||
if (const BuiltinType *placeholder = E->getType()->getAsPlaceholderType()) {
|
||||
// We can't handle overloaded expressions here because overload
|
||||
// resolution might reasonably tweak them.
|
||||
|
@ -992,9 +1003,6 @@ ExprResult
|
|||
Sema::PerformImplicitConversion(Expr *From, QualType ToType,
|
||||
AssignmentAction Action, bool AllowExplicit,
|
||||
ImplicitConversionSequence& ICS) {
|
||||
if (checkPlaceholderForOverload(*this, From))
|
||||
return ExprError();
|
||||
|
||||
// Objective-C ARC: Determine whether we will allow the writeback conversion.
|
||||
bool AllowObjCWritebackConversion
|
||||
= getLangOptions().ObjCAutoRefCount &&
|
||||
|
@ -4078,9 +4086,6 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) {
|
|||
/// PerformContextuallyConvertToBool - Perform a contextual conversion
|
||||
/// of the expression From to bool (C++0x [conv]p3).
|
||||
ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
|
||||
if (checkPlaceholderForOverload(*this, From))
|
||||
return ExprError();
|
||||
|
||||
ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From);
|
||||
if (!ICS.isBad())
|
||||
return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
|
||||
|
@ -4140,9 +4145,6 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) {
|
|||
/// PerformContextuallyConvertToObjCPointer - Perform a contextual
|
||||
/// conversion of the expression From to an Objective-C pointer type.
|
||||
ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) {
|
||||
if (checkPlaceholderForOverload(*this, From))
|
||||
return ExprError();
|
||||
|
||||
QualType Ty = Context.getObjCIdType();
|
||||
ImplicitConversionSequence ICS =
|
||||
TryContextuallyConvertToObjCPointer(*this, From);
|
||||
|
@ -9007,9 +9009,39 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
|
|||
if (checkPlaceholderForOverload(*this, Args[1]))
|
||||
return ExprError();
|
||||
|
||||
// Do placeholder-like conversion on the LHS; note that we should
|
||||
// not get here with a PseudoObject LHS.
|
||||
assert(Args[0]->getObjectKind() != OK_ObjCProperty);
|
||||
// The LHS is more complicated.
|
||||
if (Args[0]->getObjectKind() == OK_ObjCProperty) {
|
||||
|
||||
// There's a tension for assignment operators between primitive
|
||||
// property assignment and the overloaded operators.
|
||||
if (BinaryOperator::isAssignmentOp(Opc)) {
|
||||
const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty();
|
||||
|
||||
// Is the property "logically" settable?
|
||||
bool Settable = (PRE->isExplicitProperty() ||
|
||||
PRE->getImplicitPropertySetter());
|
||||
|
||||
// To avoid gratuitously inventing semantics, use the primitive
|
||||
// unless it isn't. Thoughts in case we ever really care:
|
||||
// - If the property isn't logically settable, we have to
|
||||
// load and hope.
|
||||
// - If the property is settable and this is simple assignment,
|
||||
// we really should use the primitive.
|
||||
// - If the property is settable, then we could try overloading
|
||||
// on a generic lvalue of the appropriate type; if it works
|
||||
// out to a builtin candidate, we would do that same operation
|
||||
// on the property, and otherwise just error.
|
||||
if (Settable)
|
||||
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
|
||||
}
|
||||
|
||||
ExprResult Result = ConvertPropertyForRValue(Args[0]);
|
||||
if (Result.isInvalid())
|
||||
return ExprError();
|
||||
Args[0] = Result.take();
|
||||
}
|
||||
|
||||
// Handle all the other placeholders.
|
||||
if (checkPlaceholderForOverload(*this, Args[0]))
|
||||
return ExprError();
|
||||
|
||||
|
|
|
@ -492,10 +492,6 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
|
|||
if (!Cond)
|
||||
return StmtError();
|
||||
|
||||
CondResult = CheckPlaceholderExpr(Cond);
|
||||
if (CondResult.isInvalid())
|
||||
return StmtError();
|
||||
|
||||
CondResult
|
||||
= ConvertToIntegralOrEnumerationType(SwitchLoc, Cond,
|
||||
PDiag(diag::err_typecheck_statement_requires_integer),
|
||||
|
|
|
@ -2249,8 +2249,8 @@ public:
|
|||
/// By default, performs semantic analysis to build the new expression.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
ExprResult RebuildObjCPropertyRefExpr(Expr *BaseArg,
|
||||
ObjCPropertyDecl *Property,
|
||||
SourceLocation PropertyLoc) {
|
||||
ObjCPropertyDecl *Property,
|
||||
SourceLocation PropertyLoc) {
|
||||
CXXScopeSpec SS;
|
||||
ExprResult Base = getSema().Owned(BaseArg);
|
||||
LookupResult R(getSema(), Property->getDeclName(), PropertyLoc,
|
||||
|
@ -8049,7 +8049,7 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
|
|||
E->getLocation());
|
||||
|
||||
return getDerived().RebuildObjCPropertyRefExpr(Base.get(),
|
||||
SemaRef.Context.PseudoObjectTy,
|
||||
E->getType(),
|
||||
E->getImplicitPropertyGetter(),
|
||||
E->getImplicitPropertySetter(),
|
||||
E->getLocation());
|
||||
|
|
|
@ -52,7 +52,6 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
|
|||
case BuiltinType::Char32: ID = PREDEF_TYPE_CHAR32_ID; break;
|
||||
case BuiltinType::Overload: ID = PREDEF_TYPE_OVERLOAD_ID; break;
|
||||
case BuiltinType::BoundMember:ID = PREDEF_TYPE_BOUND_MEMBER; break;
|
||||
case BuiltinType::PseudoObject:ID = PREDEF_TYPE_PSEUDO_OBJECT;break;
|
||||
case BuiltinType::Dependent: ID = PREDEF_TYPE_DEPENDENT_ID; break;
|
||||
case BuiltinType::UnknownAny: ID = PREDEF_TYPE_UNKNOWN_ANY; break;
|
||||
case BuiltinType::ARCUnbridgedCast:
|
||||
|
|
|
@ -3857,7 +3857,6 @@ QualType ASTReader::GetType(TypeID ID) {
|
|||
case PREDEF_TYPE_LONGDOUBLE_ID: T = Context.LongDoubleTy; break;
|
||||
case PREDEF_TYPE_OVERLOAD_ID: T = Context.OverloadTy; break;
|
||||
case PREDEF_TYPE_BOUND_MEMBER: T = Context.BoundMemberTy; break;
|
||||
case PREDEF_TYPE_PSEUDO_OBJECT: T = Context.PseudoObjectTy; break;
|
||||
case PREDEF_TYPE_DEPENDENT_ID: T = Context.DependentTy; break;
|
||||
case PREDEF_TYPE_UNKNOWN_ANY: T = Context.UnknownAnyTy; break;
|
||||
case PREDEF_TYPE_NULLPTR_ID: T = Context.NullPtrTy; break;
|
||||
|
|
|
@ -48,6 +48,6 @@ int main(int argc, char **argv) {
|
|||
|
||||
@implementation I0 // expected-warning {{property 'p0' requires method 'p0' to be define}}
|
||||
- (void) foo {
|
||||
self.p0 = 0; // expected-error {{assignment to readonly property}}
|
||||
self.p0 = 0; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
@end
|
||||
|
||||
void f0(A *a, B* b) {
|
||||
a.x = 10; // expected-error {{assignment to readonly property}}
|
||||
a.x = 10; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
|
||||
a.ok = 20;
|
||||
b.x = 10; // expected-error {{no setter method 'setX:' for assignment to property}}
|
||||
b.x = 10; // expected-error {{setter method is needed to assign to object using property assignment syntax}}
|
||||
b.ok = 20;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,6 @@ NSRect NSMakeRect();
|
|||
@implementation NSWindow (Category)
|
||||
-(void)methodToMakeClangCrash
|
||||
{
|
||||
self.frame = NSMakeRect(); // expected-error {{no setter method 'setFrame:' for assignment to property}}
|
||||
self.frame = NSMakeRect(); // expected-error {{setter method is needed to assign to object using property assignment syntax}}
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
void FUNC () {
|
||||
Foo *foo;
|
||||
foo.bar = 0; // expected-error {{assignment to readonly property}}
|
||||
foo.bar = 0; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
|
||||
}
|
||||
|
||||
// rdar://8747333
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
-(void) im0 {
|
||||
self.x = 0;
|
||||
self.y = 2;
|
||||
self.z = 2; // expected-error {{assignment to readonly property}}
|
||||
self.z = 2; // expected-error {{assigning to property with 'readonly' attribute not allowed}}
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -85,7 +85,7 @@ static int g_val;
|
|||
- (void)setFoo:(int)value;
|
||||
@end
|
||||
|
||||
void g(int); // expected-note {{passing argument to parameter here}}
|
||||
void g(int);
|
||||
|
||||
void f(C *c) {
|
||||
c.Foo = 17; // OK
|
||||
|
|
|
@ -20,7 +20,7 @@ struct X {
|
|||
@end
|
||||
|
||||
void f(A* a) {
|
||||
a.x = X(); // expected-error {{no setter method 'setX:' for assignment to property}}
|
||||
a.x = X(); // expected-error {{setter method is needed to assign to object using property assignment syntax}}
|
||||
}
|
||||
|
||||
struct Y : X { };
|
||||
|
|
Загрузка…
Ссылка в новой задаче