diff options
author | NAKAMURA Takumi <geek4civic@gmail.com> | 2011-10-25 14:32:25 +0000 |
---|---|---|
committer | NAKAMURA Takumi <geek4civic@gmail.com> | 2011-10-25 14:32:25 +0000 |
commit | 9a8f13961cc6fc9471ff9c916c7576c0bc13de39 (patch) | |
tree | 05e45eb81660bf306a4b068e96d69c5dff21de5c /clang/lib/Sema | |
parent | 6ca458e49a3addfa7436a0c02e2a84c4a174f13a (diff) | |
download | bcm5719-llvm-9a8f13961cc6fc9471ff9c916c7576c0bc13de39.tar.gz bcm5719-llvm-9a8f13961cc6fc9471ff9c916c7576c0bc13de39.zip |
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."
llvm-svn: 142921
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 410 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprMember.cpp | 48 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 96 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 56 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 6 |
11 files changed, 411 insertions, 267 deletions
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 06d02252d68..dbbb980de85 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -31,7 +31,6 @@ add_clang_library(clangSema SemaLookup.cpp SemaObjCProperty.cpp SemaOverload.cpp - SemaPseudoObject.cpp SemaStmt.cpp SemaTemplate.cpp SemaTemplateDeduction.cpp diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6e81c3c9661..daab1cd4877 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.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(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 885b9664d62..3b4a40b51ab 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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: diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index c96ab42b880..9267860d157 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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); diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 25d3c2a4254..16c17fb8909 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -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())); } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index ceff1de3d49..527983805c9 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -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)); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 77cfe6c2de5..59901cb11b0 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 617dbefadaf..7e9bb46cd60 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -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(), diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f5494dee173..44395c59df1 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -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(); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 887dd398940..3297c0641fe 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -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), diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 59c132caccd..3c118cb423d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -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()); |