bool SemaAnnotator:: passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data) { TypeDecl *CtorTyRef = nullptr; ExtensionDecl *ExtDecl = nullptr; if (auto *TD = dyn_cast<TypeDecl>(D)) { if (!CtorRefs.empty() && Loc.isValid()) { Expr *Fn = CtorRefs.back()->getFn(); if (Fn->getLoc() == Loc.getBaseNameLoc()) { D = extractDecl(Fn); CtorTyRef = TD; } } if (!ExtDecls.empty() && Loc.isValid()) { auto ExtTyLoc = ExtDecls.back()->getExtendedTypeLoc().getLoc(); if (ExtTyLoc.isValid() && ExtTyLoc == Loc.getBaseNameLoc()) { ExtDecl = ExtDecls.back(); } } } CharSourceRange Range = Lexer::getCharSourceRangeFromSourceRange(D->getASTContext().SourceMgr, Loc.getSourceRange()); bool Continue = SEWalker.visitDeclReference(D, Range, CtorTyRef, ExtDecl, Ty, Data); if (!Continue) Cancelled = true; return Continue; }
bool SemaAnnotator::passReference(ValueDecl *D, Type Ty, SourceLoc Loc) { unsigned NameLen = D->getName().getLength(); TypeDecl *CtorTyRef = nullptr; if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { if (!CtorRefs.empty() && Loc.isValid()) { Expr *Fn = CtorRefs.back()->getFn(); if (Fn->getLoc() == Loc) { D = extractDecl(Fn); CtorTyRef = TD; } } } CharSourceRange Range = (Loc.isValid()) ? CharSourceRange(Loc, NameLen) : CharSourceRange(); bool Continue = SEWalker.visitDeclReference(D, Range, CtorTyRef, Ty); if (!Continue) Cancelled = true; return Continue; }
bool SemaAnnotator::passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc) { TypeDecl *CtorTyRef = nullptr; if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { if (!CtorRefs.empty() && Loc.isValid()) { Expr *Fn = CtorRefs.back()->getFn(); if (Fn->getLoc() == Loc.getBaseNameLoc()) { D = extractDecl(Fn); CtorTyRef = TD; } } } CharSourceRange Range = Lexer::getCharSourceRangeFromSourceRange(D->getASTContext().SourceMgr, Loc.getSourceRange()); bool Continue = SEWalker.visitDeclReference(D, Range, CtorTyRef, Ty); if (!Continue) Cancelled = true; return Continue; }
bool RValueTreatedAsLValueFailure::diagnoseAsError() { Diag<StringRef> subElementDiagID; Diag<Type> rvalueDiagID = diag::assignment_lhs_not_lvalue; Expr *diagExpr = getLocator()->getAnchor(); SourceLoc loc = diagExpr->getLoc(); if (auto assignExpr = dyn_cast<AssignExpr>(diagExpr)) { diagExpr = assignExpr->getDest(); } if (auto callExpr = dyn_cast<ApplyExpr>(diagExpr)) { Expr *argExpr = callExpr->getArg(); loc = callExpr->getFn()->getLoc(); if (isa<PrefixUnaryExpr>(callExpr) || isa<PostfixUnaryExpr>(callExpr)) { subElementDiagID = diag::cannot_apply_lvalue_unop_to_subelement; rvalueDiagID = diag::cannot_apply_lvalue_unop_to_rvalue; diagExpr = argExpr; } else if (isa<BinaryExpr>(callExpr)) { subElementDiagID = diag::cannot_apply_lvalue_binop_to_subelement; rvalueDiagID = diag::cannot_apply_lvalue_binop_to_rvalue; auto argTuple = dyn_cast<TupleExpr>(argExpr); diagExpr = argTuple->getElement(0); } else if (getLocator()->getPath().size() > 0) { auto lastPathElement = getLocator()->getPath().back(); assert(lastPathElement.getKind() == ConstraintLocator::PathElementKind::ApplyArgToParam); subElementDiagID = diag::cannot_pass_rvalue_inout_subelement; rvalueDiagID = diag::cannot_pass_rvalue_inout; if (auto argTuple = dyn_cast<TupleExpr>(argExpr)) diagExpr = argTuple->getElement(lastPathElement.getValue()); else if (auto parens = dyn_cast<ParenExpr>(argExpr)) diagExpr = parens->getSubExpr(); } else { subElementDiagID = diag::assignment_lhs_is_apply_expression; } } else if (auto inoutExpr = dyn_cast<InOutExpr>(diagExpr)) { if (auto restriction = getRestrictionForType(getType(inoutExpr))) { PointerTypeKind pointerKind; if (restriction->second == ConversionRestrictionKind::ArrayToPointer && restriction->first->getAnyPointerElementType(pointerKind) && (pointerKind == PTK_UnsafePointer || pointerKind == PTK_UnsafeRawPointer)) { // If we're converting to an UnsafePointer, then the programmer // specified an & unnecessarily. Produce a fixit hint to remove it. emitDiagnostic(inoutExpr->getLoc(), diag::extra_address_of_unsafepointer, restriction->first) .highlight(inoutExpr->getSourceRange()) .fixItRemove(inoutExpr->getStartLoc()); return true; } } subElementDiagID = diag::cannot_pass_rvalue_inout_subelement; rvalueDiagID = diag::cannot_pass_rvalue_inout; diagExpr = inoutExpr->getSubExpr(); } else if (isa<DeclRefExpr>(diagExpr)) { subElementDiagID = diag::assignment_lhs_is_immutable_variable; } else if (isa<ForceValueExpr>(diagExpr)) { subElementDiagID = diag::assignment_bang_has_immutable_subcomponent; } else if (isa<MemberRefExpr>(diagExpr)) { subElementDiagID = diag::assignment_lhs_is_immutable_property; } else if (auto member = dyn_cast<UnresolvedDotExpr>(diagExpr)) { subElementDiagID = diag::assignment_lhs_is_immutable_property; if (auto *ctor = dyn_cast<ConstructorDecl>(getDC())) { if (auto *baseRef = dyn_cast<DeclRefExpr>(member->getBase())) { if (baseRef->getDecl() == ctor->getImplicitSelfDecl() && ctor->getDelegatingOrChainedInitKind(nullptr) == ConstructorDecl::BodyInitKind::Delegating) { emitDiagnostic(loc, diag::assignment_let_property_delegating_init, member->getName()); if (auto *ref = getResolvedMemberRef(member)) { emitDiagnostic(ref, diag::decl_declared_here, member->getName()); } return true; } } } if (auto resolvedOverload = getResolvedOverload(getLocator())) if (resolvedOverload->Choice.getKind() == OverloadChoiceKind::DynamicMemberLookup) subElementDiagID = diag::assignment_dynamic_property_has_immutable_base; } else if (auto sub = dyn_cast<SubscriptExpr>(diagExpr)) { subElementDiagID = diag::assignment_subscript_has_immutable_base; } else { subElementDiagID = diag::assignment_lhs_is_immutable_variable; } AssignmentFailure failure(diagExpr, getConstraintSystem(), loc, subElementDiagID, rvalueDiagID); return failure.diagnose(); }