void VisitMemberExpr(MemberExpr *Node) { // this is copied from somewhere PrintExpr(Node->getBase()); MemberExpr *ParentMember = dyn_cast<MemberExpr>(Node->getBase()); FieldDecl *ParentDecl = ParentMember ? dyn_cast<FieldDecl>(ParentMember->getMemberDecl()) : nullptr; if (!ParentDecl || !ParentDecl->isAnonymousStructOrUnion()) OS << (Node->isArrow() ? "->" : "."); if (FieldDecl *FD = dyn_cast<FieldDecl>(Node->getMemberDecl())) if (FD->isAnonymousStructOrUnion()) return; if (NestedNameSpecifier *Qualifier = Node->getQualifier()) Qualifier->print(OS, Policy); if (Node->hasTemplateKeyword()) OS << "template "; OS << Node->getMemberNameInfo(); if (Node->hasExplicitTemplateArgs()) TemplateSpecializationType::PrintTemplateArgumentList(OS, Node->getTemplateArgs(), Node->getNumTemplateArgs(), Policy); }
/// \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); }
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; }