/// \brief If a member function call is the at() accessor on the container with /// IndexVar as the single argument, include it as a valid usage and prune /// the traversal. /// /// Member calls on other objects will not be permitted. /// Calls on the iterator object are not permitted, unless done through /// operator->(). The one exception is allowing vector::at() for pseudoarrays. bool ForLoopIndexUseVisitor::TraverseCXXMemberCallExpr( CXXMemberCallExpr *MemberCall) { MemberExpr *Member = dyn_cast<MemberExpr>(MemberCall->getCallee()->IgnoreParenImpCasts()); if (!Member) return VisitorBase::TraverseCXXMemberCallExpr(MemberCall); // We specifically allow an accessor named "at" to let STL in, though // this is restricted to pseudo-arrays by requiring a single, integer // argument. const IdentifierInfo *Ident = Member->getMemberDecl()->getIdentifier(); if (Ident && Ident->isStr("at") && MemberCall->getNumArgs() == 1) { if (isIndexInSubscriptExpr(Context, MemberCall->getArg(0), IndexVar, Member->getBase(), ContainerExpr, ContainerNeedsDereference)) { Usages.push_back(Usage(MemberCall)); return true; } } if (containsExpr(Context, &DependentExprs, Member->getBase())) ConfidenceLevel.lowerTo(TCK_Risky); return VisitorBase::TraverseCXXMemberCallExpr(MemberCall); }
int FileScope::checkUserType(Type* type, Expr* id, bool used_public) { // TODO refactor const Package* pkg = 0; switch (id->getKind()) { case EXPR_IDENTIFIER: // unqualified { IdentifierExpr* I = cast<IdentifierExpr>(id); ScopeResult res = findSymbol(I->getName()); if (!res.decl) { Diags.Report(I->getLocation(), diag::err_unknown_typename) << I->getName(); return 1; } if (res.ambiguous) { Diags.Report(I->getLocation(), diag::err_ambiguous_symbol) << I->getName(); // TODO show alternatives return 1; } if (res.external && !res.decl->isPublic()) { Diags.Report(I->getLocation(), diag::err_not_public) << I->getName(); return 1; } TypeDecl* td = dyncast<TypeDecl>(res.decl); if (!td) { Diags.Report(I->getLocation(), diag::err_not_a_typename) << I->getName(); return 1; } if (used_public && !res.external && !td->isPublic()) { Diags.Report(I->getLocation(), diag::err_non_public_type) << I->getName(); return 1; } // ok assert(res.pkg && "pkg should be set"); I->setPackage(res.pkg); I->setDecl(res.decl); type->setRefType(td->getType()); } break; case EXPR_MEMBER: // fully qualified { MemberExpr* M = cast<MemberExpr>(id); Expr* base = M->getBase(); IdentifierExpr* pkg_id = cast<IdentifierExpr>(base); const std::string& pkgName = pkg_id->getName(); // check if package exists pkg = findPackage(pkgName); if (!pkg) { // check if used with alias (then fullname is forbidden) for (PackagesConstIter iter = packages.begin(); iter != packages.end(); ++iter) { const Package* p = iter->second; if (p->getName() == pkgName) { Diags.Report(pkg_id->getLocation(), diag::err_package_has_alias) << pkgName << iter->first; return 1; } } // TODO use function PkgsConstIter iter = allPackages.find(pkgName); if (iter == allPackages.end()) { Diags.Report(pkg_id->getLocation(), diag::err_unknown_package) << pkgName; } else { Diags.Report(pkg_id->getLocation(), diag::err_package_not_used) << pkgName; } return 1; } // check member Expr* member = M->getMember(); IdentifierExpr* member_id = cast<IdentifierExpr>(member); // check Type Decl* symbol = pkg->findSymbol(member_id->getName()); if (!symbol) { Diags.Report(member_id->getLocation(), diag::err_unknown_typename) << M->getFullName(); return 1; } TypeDecl* td = dyncast<TypeDecl>(symbol); if (!td) { Diags.Report(member_id->getLocation(), diag::err_not_a_typename) << M->getFullName(); return 1; } // if external package, check visibility if (isExternal(pkg) && !td->isPublic()) { Diags.Report(member_id->getLocation(), diag::err_not_public) << M->getFullName(); return 1; } if (used_public && !isExternal(pkg) && !td->isPublic()) { Diags.Report(member_id->getLocation(), diag::err_non_public_type) << M->getFullName(); return 1; } // ok member_id->setPackage(pkg); type->setRefType(td->getType()); } break; default: assert(0); } return 0; }
bool TransferFunctions::checkImageAccess(Expr *E, MemoryAccess curMemAcc) { // discard implicit casts and paren expressions E = E->IgnoreParenImpCasts(); // match Image(), Accessor(), Mask(), and Domain() calls if (isa<CXXOperatorCallExpr>(E)) { CXXOperatorCallExpr *COCE = dyn_cast<CXXOperatorCallExpr>(E); if (isa<MemberExpr>(COCE->getArg(0))) { MemberExpr *ME = dyn_cast<MemberExpr>(COCE->getArg(0)); if (isa<FieldDecl>(ME->getMemberDecl())) { FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()); MemoryAccess memAcc = KS.imagesToAccess[FD]; MemoryAccessDetail memAccDetail = KS.imagesToAccessDetail[FD]; memAcc = (MemoryAccess) (memAcc|curMemAcc); KS.imagesToAccess[FD] = memAcc; // access to Image if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(), KS.compilerClasses.Image)) { KS.Diags.Report(E->getLocStart(), KS.DiagIDImageAccess) << FD->getNameAsString(); exit(EXIT_FAILURE); } // access to Accessor if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(), KS.compilerClasses.Accessor)) { if (curMemAcc & READ_ONLY) KS.num_img_loads++; if (curMemAcc & WRITE_ONLY) KS.num_img_stores++; switch (COCE->getNumArgs()) { default: break; case 1: memAccDetail = (MemoryAccessDetail) (memAccDetail|NO_STRIDE); if (KS.kernelType < PointOperator) KS.kernelType = PointOperator; break; case 2: // TODO: check for Mask or Domain as parameter and check if we // need only STRIDE_X or STRIDE_Y memAccDetail = (MemoryAccessDetail) (memAccDetail|STRIDE_XY); if (KS.kernelType < LocalOperator) KS.kernelType = LocalOperator; break; case 3: memAccDetail = (MemoryAccessDetail) (memAccDetail|checkStride(COCE->getArg(1), COCE->getArg(2))); if (memAccDetail > NO_STRIDE && KS.kernelType < LocalOperator) { KS.kernelType = LocalOperator; } break; } KS.imagesToAccessDetail[FD] = memAccDetail; return true; } // access to Mask if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(), KS.compilerClasses.Mask)) { if (curMemAcc & READ_ONLY) KS.num_mask_loads++; if (curMemAcc & WRITE_ONLY) KS.num_mask_stores++; if (KS.inLambdaFunction) { // TODO: check for Mask as parameter and check if we need only // STRIDE_X or STRIDE_Y memAccDetail = (MemoryAccessDetail) (memAccDetail|STRIDE_XY); if (KS.kernelType < LocalOperator) KS.kernelType = LocalOperator; } else { assert(COCE->getNumArgs()==3 && "Mask access requires x and y parameters!"); memAccDetail = (MemoryAccessDetail) (memAccDetail|checkStride(COCE->getArg(1), COCE->getArg(2))); if (memAccDetail > NO_STRIDE && KS.kernelType < LocalOperator) { KS.kernelType = LocalOperator; } } KS.imagesToAccessDetail[FD] = memAccDetail; return false; } // access to Domain if (KS.compilerClasses.isTypeOfClass(FD->getType(), KS.compilerClasses.Domain)) { if (curMemAcc & READ_ONLY) KS.num_mask_loads++; if (curMemAcc & WRITE_ONLY) KS.num_mask_stores++; if (KS.inLambdaFunction) { // TODO: check for Domain as parameter and check if we need only // STRIDE_X or STRIDE_Y memAccDetail = (MemoryAccessDetail) (memAccDetail|STRIDE_XY); if (KS.kernelType < LocalOperator) KS.kernelType = LocalOperator; } else { assert(COCE->getNumArgs()==3 && "Domain access requires x and y parameters!"); memAccDetail = (MemoryAccessDetail) (memAccDetail|checkStride(COCE->getArg(1), COCE->getArg(2))); if (memAccDetail > NO_STRIDE && KS.kernelType < LocalOperator) { KS.kernelType = LocalOperator; } } KS.imagesToAccessDetail[FD] = memAccDetail; return false; } } } } // match Image->getPixel(), output(), and outputAtPixel() calls if (isa<CXXMemberCallExpr>(E)) { CXXMemberCallExpr *CMCE = dyn_cast<CXXMemberCallExpr>(E); if (isa<MemberExpr>(CMCE->getCallee())) { MemberExpr *ME = dyn_cast<MemberExpr>(CMCE->getCallee()); if (isa<MemberExpr>(ME->getBase())) { MemberExpr *MEAcc = dyn_cast<MemberExpr>(ME->getBase()); if (isa<FieldDecl>(MEAcc->getMemberDecl())) { FieldDecl *FD = dyn_cast<FieldDecl>(MEAcc->getMemberDecl()); // Image if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(), KS.compilerClasses.Image)) { KS.Diags.Report(E->getLocStart(), KS.DiagIDImageAccess) << FD->getNameAsString(); exit(EXIT_FAILURE); } // Accessor if (KS.compilerClasses.isTypeOfTemplateClass(FD->getType(), KS.compilerClasses.Accessor)) { // Accessor->getPixel() if (ME->getMemberNameInfo().getAsString()=="getPixel") { MemoryAccess memAcc = KS.imagesToAccess[FD]; MemoryAccessDetail memAccDetail = KS.imagesToAccessDetail[FD]; memAcc = (MemoryAccess) (memAcc|curMemAcc); KS.imagesToAccess[FD] = memAcc; memAccDetail = (MemoryAccessDetail) (memAccDetail|USER_XY); KS.imagesToAccessDetail[FD] = memAccDetail; KS.kernelType = UserOperator; if (curMemAcc & READ_ONLY) KS.num_img_loads++; if (curMemAcc & WRITE_ONLY) KS.num_img_stores++; return true; } } } } // output() if (ME->getMemberNameInfo().getAsString()=="output") { if (curMemAcc & READ_ONLY) KS.num_img_loads++; if (curMemAcc & WRITE_ONLY) KS.num_img_stores++; MemoryAccessDetail cur = KS.outputAccessDetail; KS.outputAccessDetail = (MemoryAccessDetail)(cur|NO_STRIDE); if (KS.kernelType < PointOperator) KS.kernelType = PointOperator; return true; } // outputAtPixel() if (ME->getMemberNameInfo().getAsString()=="outputAtPixel") { if (curMemAcc & READ_ONLY) KS.num_img_loads++; if (curMemAcc & WRITE_ONLY) KS.num_img_stores++; MemoryAccessDetail cur = KS.outputAccessDetail; KS.outputAccessDetail = (MemoryAccessDetail)(cur|USER_XY); KS.kernelType = UserOperator; return true; } } } return false; }