MemberExpr *MemberExpr::Create(ASTContext &C, Expr *base, NestedNameSpecifier *qual, SourceRange qualrange, ValueDefn *member, DefnAccessPair founddefn, DefinitionNameInfo nameinfo, Type ty, ExprValueKind vk) { std::size_t Size = sizeof(MemberExpr); bool hasQualOrFound = (qual != 0 || founddefn.getDefn() != member || founddefn.getAccess() != member->getAccess()); if (hasQualOrFound) Size += sizeof(MemberNameQualifier); void *Mem = C.Allocate(Size, llvm::alignOf<MemberExpr>()); MemberExpr *E = new (Mem) MemberExpr(base, member, nameinfo, ty, vk); if (hasQualOrFound) { E->HasQualifierOrFoundDefn = true; MemberNameQualifier *NQ = E->getMemberQualifier(); NQ->NNS = qual; NQ->Range = qualrange; NQ->FoundDefn = founddefn; } return E; }
void FakeDirectiveHandler::HandleMemberExpr(DeclRefExpr * Original, Expr * Var, Expr * Next, vector<LocalStmtPair> WritePairs, bool ActualVar, string Struct) { MemberExpr * Member = dyn_cast<MemberExpr>(Next); if (Member->isArrow()) { InsertAccess(Var, Original, false, WritePairs, ActualVar, Struct); } Struct = GetType(Member); WalkUpExpr(Original, Member, WritePairs, ActualVar, Struct); }
std::vector<FixItHint> StringRefCandidates::fixit(CXXMemberCallExpr *call) { MemberExpr *memberExpr = Utils::getFirstChildOfType<MemberExpr>(call); if (!memberExpr) { queueManualFixitWarning(call->getLocStart(), FixitUseQStringRef, "Internal error 1"); return {}; } auto insertionLoc = Lexer::getLocForEndOfToken(memberExpr->getLocEnd(), 0, m_ci.getSourceManager(), m_ci.getLangOpts()); // llvm::errs() << insertionLoc.printToString(m_ci.getSourceManager()) << "\n"; if (!insertionLoc.isValid()) { queueManualFixitWarning(call->getLocStart(), FixitUseQStringRef, "Internal error 2"); return {}; } std::vector<FixItHint> fixits; fixits.push_back(createInsertion(insertionLoc, "Ref")); return fixits; }
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); }
/// Create a fake body for std::call_once. /// Emulates the following function body: /// /// \code /// typedef struct once_flag_s { /// unsigned long __state = 0; /// } once_flag; /// template<class Callable> /// void call_once(once_flag& o, Callable func) { /// if (!o.__state) { /// func(); /// } /// o.__state = 1; /// } /// \endcode static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { DEBUG(llvm::dbgs() << "Generating body for call_once\n"); // We need at least two parameters. if (D->param_size() < 2) return nullptr; ASTMaker M(C); const ParmVarDecl *Flag = D->getParamDecl(0); const ParmVarDecl *Callback = D->getParamDecl(1); if (!Callback->getType()->isReferenceType()) { llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n"; return nullptr; } if (!Flag->getType()->isReferenceType()) { llvm::dbgs() << "unknown std::call_once implementation, skipping.\n"; return nullptr; } QualType CallbackType = Callback->getType().getNonReferenceType(); // Nullable pointer, non-null iff function is a CXXRecordDecl. CXXRecordDecl *CallbackRecordDecl = CallbackType->getAsCXXRecordDecl(); QualType FlagType = Flag->getType().getNonReferenceType(); auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->getAsTagDecl()); if (!FlagRecordDecl) { DEBUG(llvm::dbgs() << "Flag field is not a record: " << "unknown std::call_once implementation, " << "ignoring the call.\n"); return nullptr; } // We initially assume libc++ implementation of call_once, // where the once_flag struct has a field `__state_`. ValueDecl *FlagFieldDecl = M.findMemberField(FlagRecordDecl, "__state_"); // Otherwise, try libstdc++ implementation, with a field // `_M_once` if (!FlagFieldDecl) { FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once"); } if (!FlagFieldDecl) { DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on " << "std::once_flag struct: unknown std::call_once " << "implementation, ignoring the call."); return nullptr; } bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda(); if (CallbackRecordDecl && !isLambdaCall) { DEBUG(llvm::dbgs() << "Not supported: synthesizing body for functors when " << "body farming std::call_once, ignoring the call."); return nullptr; } SmallVector<Expr *, 5> CallArgs; const FunctionProtoType *CallbackFunctionType; if (isLambdaCall) { // Lambda requires callback itself inserted as a first parameter. CallArgs.push_back( M.makeDeclRefExpr(Callback, /* RefersToEnclosingVariableOrCapture=*/ true)); CallbackFunctionType = CallbackRecordDecl->getLambdaCallOperator() ->getType() ->getAs<FunctionProtoType>(); } else if (!CallbackType->getPointeeType().isNull()) { CallbackFunctionType = CallbackType->getPointeeType()->getAs<FunctionProtoType>(); } else { CallbackFunctionType = CallbackType->getAs<FunctionProtoType>(); } if (!CallbackFunctionType) return nullptr; // First two arguments are used for the flag and for the callback. if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) { DEBUG(llvm::dbgs() << "Types of params of the callback do not match " << "params passed to std::call_once, " << "ignoring the call\n"); return nullptr; } // All arguments past first two ones are passed to the callback, // and we turn lvalues into rvalues if the argument is not passed by // reference. for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) { const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx); Expr *ParamExpr = M.makeDeclRefExpr(PDecl); if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) { QualType PTy = PDecl->getType().getNonReferenceType(); ParamExpr = M.makeLvalueToRvalue(ParamExpr, PTy); } CallArgs.push_back(ParamExpr); } CallExpr *CallbackCall; if (isLambdaCall) { CallbackCall = create_call_once_lambda_call(C, M, Callback, CallbackRecordDecl, CallArgs); } else { // Function pointer case. CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs); } DeclRefExpr *FlagDecl = M.makeDeclRefExpr(Flag, /* RefersToEnclosingVariableOrCapture=*/true); MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FlagFieldDecl); assert(Deref->isLValue()); QualType DerefType = Deref->getType(); // Negation predicate. UnaryOperator *FlagCheck = new (C) UnaryOperator( /* input=*/ M.makeImplicitCast(M.makeLvalueToRvalue(Deref, DerefType), DerefType, CK_IntegralToBoolean), /* opc=*/ UO_LNot, /* QualType=*/ C.IntTy, /* ExprValueKind=*/ VK_RValue, /* ExprObjectKind=*/ OK_Ordinary, SourceLocation()); // Create assignment. BinaryOperator *FlagAssignment = M.makeAssignment( Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType), DerefType); IfStmt *Out = new (C) IfStmt(C, SourceLocation(), /* IsConstexpr=*/ false, /* init=*/ nullptr, /* var=*/ nullptr, /* cond=*/ FlagCheck, /* then=*/ M.makeCompound({CallbackCall, FlagAssignment})); return Out; }
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; }