/// getInfixData - If the specified expression is an infix binary /// operator, return its infix operator attributes. static InfixData getInfixData(TypeChecker &TC, DeclContext *DC, Expr *E) { if (auto *ifExpr = dyn_cast<IfExpr>(E)) { // Ternary has fixed precedence. assert(!ifExpr->isFolded() && "already folded if expr in sequence?!"); (void)ifExpr; return InfixData(IntrinsicPrecedences::IfExpr, Associativity::Right, /*assignment*/ false); } if (auto *assign = dyn_cast<AssignExpr>(E)) { // Assignment has fixed precedence. assert(!assign->isFolded() && "already folded assign expr in sequence?!"); (void)assign; return InfixData(IntrinsicPrecedences::AssignExpr, Associativity::Right, /*assignment*/ true); } if (auto *as = dyn_cast<ExplicitCastExpr>(E)) { // 'as' and 'is' casts have fixed precedence. assert(!as->isFolded() && "already folded 'as' expr in sequence?!"); (void)as; return InfixData(IntrinsicPrecedences::ExplicitCastExpr, Associativity::None, /*assignment*/ false); } if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { SourceFile *SF = DC->getParentSourceFile(); Identifier name = DRE->getDecl()->getName(); bool isCascading = DC->isCascadingContextForLookup(true); if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading, E->getLoc())) return op->getInfixData(); } if (OverloadedDeclRefExpr *OO = dyn_cast<OverloadedDeclRefExpr>(E)) { SourceFile *SF = DC->getParentSourceFile(); Identifier name = OO->getDecls()[0]->getName(); bool isCascading = DC->isCascadingContextForLookup(true); if (InfixOperatorDecl *op = SF->lookupInfixOperator(name, isCascading, E->getLoc())) return op->getInfixData(); } // If E is already an ErrorExpr, then we've diagnosed it as invalid already, // otherwise emit an error. if (!isa<ErrorExpr>(E)) TC.diagnose(E->getLoc(), diag::unknown_binop); // Recover with an infinite-precedence left-associative operator. return InfixData((unsigned char)~0U, Associativity::Left, /*assignment*/ false); }
static PrecedenceGroupDecl * lookupPrecedenceGroupForOperator(TypeChecker &TC, DeclContext *DC, Identifier name, SourceLoc loc) { SourceFile *SF = DC->getParentSourceFile(); bool isCascading = DC->isCascadingContextForLookup(true); if (auto op = SF->lookupInfixOperator(name, isCascading, loc)) { TC.validateDecl(op); return op->getPrecedenceGroup(); } else { TC.diagnose(loc, diag::unknown_binop); } return nullptr; }