virtual void HandleTranslationUnit(TranslationUnit& tu) { // called when everything is done UsageMap uses; for (int i = 0; i < globals.size(); ++i) { uses[globals[i]] = vector<DeclRefExpr*>(); } FindUsages fu(uses); for (int i = 0; i < functions.size(); ++i) { fu.process(functions[i]); } for (int i = 0; i < globals.size(); ++i) { VarDecl* VD = globals[i]; FullSourceLoc loc(VD->getLocation(), *sm); bool isStatic = VD->getStorageClass() == VarDecl::Static; cout << "<span class=\"global\">" << loc.getSourceName() << ": " << (isStatic?"static ":"") << VD->getName() << " (" << uses[VD].size() << " local uses)" << "\n</span>"; cout << "<span class=\"uses\">"; for (int j = 0; j < uses[VD].size(); ++j) { DeclRefExpr* dre = uses[VD][j]; FunctionDecl* fd = enclosing[dre]; FullSourceLoc loc(dre->getLocStart(), *sm); cout << " " << fd->getName() << ":" << loc.getLogicalLineNumber() << "\n"; } cout << "</span>"; } }
bool VisitBinAssign(const BinaryOperator *assign) { DeclRefExpr *lhs = llvm::dyn_cast<DeclRefExpr>(assign->getLHS()); if (lhs && lhs->getDecl() == _Decl) { _Set.insert(assign->getRHS()->IgnoreParenImpCasts()); } return true; }
static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M, const ParmVarDecl *Callback, ArrayRef<Expr *> CallArgs) { QualType Ty = Callback->getType(); DeclRefExpr *Call = M.makeDeclRefExpr(Callback); Expr *SubExpr; if (Ty->isRValueReferenceType()) { SubExpr = M.makeImplicitCast( Call, Ty.getNonReferenceType(), CK_LValueToRValue); } else if (Ty->isLValueReferenceType() && Call->getType()->isFunctionType()) { Ty = C.getPointerType(Ty.getNonReferenceType()); SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay); } else if (Ty->isLValueReferenceType() && Call->getType()->isPointerType() && Call->getType()->getPointeeType()->isFunctionType()){ SubExpr = Call; } else { llvm_unreachable("Unexpected state"); } return CallExpr::Create(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, SourceLocation()); }
bool VarCollector::VisitBinaryOperator(BinaryOperator *e) { CompilerInstance &CI = FullDirectives->GetCI(e->getLocStart()); // If it's not an assignment, no contamination can occur if (!e->isAssignmentOp()) { return true; } // If we're not changing a pointer, no contamination can occur if (!e->getLHS()->getType()->isPointerType()) { return true; } assert(!e->getLHS()->getType()->isArrayType()); // Get Dominant LHS DeclRef and its expr DeclRefExpr * LDominantRef = NULL; Expr * LDominantExpr = NULL; VarTraverser lvt(e->getLHS(), LDominantRef, LDominantExpr, CI); lvt.TraverseStmt(e->getLHS()); // Shouldn't get this!! // But if there isn't a dominant variable being written to just return // Where on earth is it writing to!? // TODO: Convert to actual error! if (!LDominantRef) { llvm::errs() << "Warning: Found a pointer being modified that we have no " << "idea where came from. Can't determine if private or not!\n"; return true; } // Get Dominant RHS DeclRef and its expr DeclRefExpr * RDominantRef = NULL; Expr * RDominantExpr = NULL; VarTraverser rvt(e->getRHS(), RDominantRef, RDominantExpr, CI); rvt.TraverseStmt(e->getRHS()); // If there isn't a dominant variable now being pointed to, just return if (!RDominantRef) { llvm::errs() << "No dominant right ref\n"; return true; } VarDecl * VDLHS = dyn_cast<VarDecl>(LDominantRef->getDecl()); VarDecl * VDRHS = dyn_cast<VarDecl>(RDominantRef->getDecl()); const Type * T = LDominantExpr->getType().getTypePtr(); string LT = GetType(LDominantExpr); string RT = GetType(RDominantExpr); maybeContaminated(VDLHS, LT, VDRHS, RT, T, e->getLocStart()); return true; }
void NetworkDriverRewriteVisitor::InstrumentEntryPoints(FunctionDecl* funcDecl, string fdFile) { if (funcDecl->getStorageClass() == SC_Static) RW.RemoveText(funcDecl->getInnerLocStart(), 7); if (DI->getInstance().GetInitFunction() == funcDecl->getNameInfo().getName().getAsString()) return; if (funcDecl->getParamDecl(0)->getOriginalType().getAsString() != "struct device *" && funcDecl->getParamDecl(0)->getOriginalType().getAsString() != "struct pci_dev *") return; SourceRange sr = funcDecl->getParamDecl(0)->getSourceRange(); RW.InsertTextBefore(sr.getBegin(), "struct net_device *dev, "); Stmt *body = funcDecl->getBody(); list<DeclStmt*> stmtsToRewrite; for (auto i = body->child_begin(), e = body->child_end(); i != e; ++i) { if (!isa<DeclStmt>(*i)) continue; DeclStmt *declStmt = cast<DeclStmt>(*i); if (!declStmt->isSingleDecl() && !isa<VarDecl>(declStmt->getSingleDecl())) continue; VarDecl *var = cast<VarDecl>(declStmt->getSingleDecl()); if (!var->hasInit()) continue; Expr *expr = var->getInit(); if (!isa<ImplicitCastExpr>(expr)) continue; ImplicitCastExpr *implicit = cast<ImplicitCastExpr>(expr); if (!isa<CallExpr>(implicit->getSubExpr())) continue; CallExpr *call = cast<CallExpr>(implicit->getSubExpr()); DeclRefExpr *callee = cast<DeclRefExpr>(cast<ImplicitCastExpr>(call->getCallee())->getSubExpr()); if (callee->getNameInfo().getName().getAsString() == "to_pci_dev" || callee->getNameInfo().getName().getAsString() == "pci_get_drvdata") { stmtsToRewrite.push_back(declStmt); } } while (!stmtsToRewrite.empty()) { DeclStmt *stmt = stmtsToRewrite.back(); RW.RemoveText(stmt->getSourceRange()); stmtsToRewrite.pop_back(); } }
Stmt *TransformWCR::VisitWhileStmt(WhileStmt *S) { StmtVector OuterBody; StmtVector BodyStmts; StmtVector WCRBody; // Declaration of condition variable VarDecl *CondVD = NewCondVarDecl(S->getCond()->getType()); CondDecls.push_back(NewDeclStmt(CondVD)); // Computation of condition DeclRefExpr *LHS = new (ASTCtx) DeclRefExpr(CondVD, CondVD->getType(), VK_RValue, SourceLocation()); BinaryOperator *CondBinOp = new (ASTCtx) BinaryOperator( LHS, S->getCond(), BO_Assign, LHS->getType(), VK_RValue, OK_Ordinary, SourceLocation()); // Cond WCR MergeBodyAndCond(BodyStmts, CondBinOp); // Exit condition DeclRefExpr *CondRef = new (ASTCtx) DeclRefExpr(CondVD, CondVD->getType(), VK_RValue, SourceLocation()); UnaryOperator *NotCond = new (ASTCtx) UnaryOperator( CondRef, UO_LNot, CondVD->getType(), VK_RValue, OK_Ordinary, SourceLocation()); BreakStmt *ThenStmt = new (ASTCtx) BreakStmt(SourceLocation()); IfStmt *ExitStmt = new (ASTCtx) IfStmt(ASTCtx, SourceLocation(), NULL, NotCond, ThenStmt); BodyStmts.push_back(ExitStmt); // Body Stmt *Body = S->getBody(); CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); assert(CS && "Not a CompoundStmt"); // Identify each WCR VisitRawCompoundStmt(CS, BodyStmts, WCRBody); MergeBodyAndWCR(BodyStmts, WCRBody); ASTCtx.Deallocate(S); ASTCtx.Deallocate(CS); // Outer WhileStmt Expr *Cond = CLExprs.getExpr(CLExpressions::ONE); Body = MergeWCRsAndMakeCompoundStmt(BodyStmts); WhileStmt *WS = new (ASTCtx) WhileStmt(ASTCtx, NULL, Cond, Body, SourceLocation()); OuterBody.push_back(WS); // Landing pad - empty WCR OuterBody.push_back(NewLandingPad(WS)); return NewStmtList(OuterBody); }
void VarCollector::HandleArrayInitList(VarDecl *VDLHS, string TLHS, InitListExpr * Inits, SourceLocation StmtLoc) { CompilerInstance &CI = FullDirectives->GetCI(Inits->getLocStart()); for (unsigned i = 0; i < Inits->getNumInits(); i++) { Expr * Current = Inits->getInit(i); InitListExpr * InitList = dyn_cast<InitListExpr>(Current); if (InitList) { HandleArrayInitList(VDLHS, TLHS, InitList, StmtLoc); } else { // Get Dominant RHS DeclRef and its expr DeclRefExpr * RDominantRef = NULL; Expr * RDominantExpr = NULL; VarTraverser rvt(Current, RDominantRef, RDominantExpr, CI); rvt.TraverseStmt(Current); // If there isn't a dominant variable now being pointed to, just return if (!RDominantRef) { continue; } // DEBUG: // Print out the dominant LHS and RHS /* llvm::errs() << "Found init of a pointer:\n"; llvm::errs() << "RHS Ref " << RDominantRef->getDecl()->getName() << " -> " << GetStmtString(RDominantExpr) << " (" << RDominantExpr->getType().getAsString() << ")\n";*/ VarDecl * VDRHS = dyn_cast<VarDecl>(RDominantRef->getDecl()); string TRHS = GetType(RDominantExpr); const Type * T = RDominantExpr->getType()->getUnqualifiedDesugaredType(); maybeContaminated(VDLHS, TLHS, VDRHS, TRHS, T, StmtLoc); } } }
OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( SourceLocation Loc, ArrayRef<Expr *> VarList) { SmallVector<Expr *, 8> Vars; for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); I != E; ++I) { DeclRefExpr *DE = cast<DeclRefExpr>(*I); VarDecl *VD = cast<VarDecl>(DE->getDecl()); SourceLocation ILoc = DE->getExprLoc(); // OpenMP [2.9.2, Restrictions, C/C++, p.10] // A threadprivate variable must not have an incomplete type. if (RequireCompleteType(ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) { continue; } // OpenMP [2.9.2, Restrictions, C/C++, p.10] // A threadprivate variable must not have a reference type. if (VD->getType()->isReferenceType()) { Diag(ILoc, diag::err_omp_ref_type_arg) << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType(); bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; continue; } // Check if this is a TLS variable. if (VD->getTLSKind()) { Diag(ILoc, diag::err_omp_var_thread_local) << VD; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; continue; } Vars.push_back(*I); } OMPThreadPrivateDecl *D = 0; if (!Vars.empty()) { D = OMPThreadPrivateDecl::Create(Context, getCurLexicalContext(), Loc, Vars); D->setAccess(AS_public); } return D; }
ValueDecl *valueDeclFromIncExpr(Expr *incExpr) { UnaryOperator *unaryOperator = dyn_cast_or_null<UnaryOperator>(incExpr); if (unaryOperator) { Expr *unaryOpSubExpr = unaryOperator->getSubExpr(); if (unaryOpSubExpr && isa<DeclRefExpr>(unaryOpSubExpr)) { DeclRefExpr *declRefExpr = dyn_cast<DeclRefExpr>(unaryOpSubExpr); return declRefExpr->getDecl(); } } return nullptr; }
NamedDecl* RedundantLocalVariableRule::extractFromReturnStmt(Stmt *stmt) { ReturnStmt *returnStmt = dyn_cast<ReturnStmt>(stmt); if (returnStmt) { Expr *returnValue = returnStmt->getRetValue(); if (returnValue) { ImplicitCastExpr *implicitCastExpr = dyn_cast<ImplicitCastExpr>(returnValue); if (implicitCastExpr) { DeclRefExpr *returnExpr = dyn_cast<DeclRefExpr>(implicitCastExpr->getSubExpr()); if (returnExpr) { return returnExpr->getFoundDecl(); } } } } return NULL; }
//--------------------------------------------------------- FunctionDecl* findFunctionDecl(CallExpr* expr) { if (CXXMemberCallExpr* CMC = dyn_cast<CXXMemberCallExpr>(expr)) { return CMC->getMethodDecl(); } CastExpr* castExpr; Expr* calleeExpr = expr->getCallee(); while ((castExpr = dyn_cast<CastExpr>(calleeExpr)) != NULL) { calleeExpr = castExpr->getSubExpr(); } DeclRefExpr* fnRef = dyn_cast<DeclRefExpr>(calleeExpr); return fnRef ? dyn_cast<FunctionDecl>(fnRef->getDecl()) : NULL; }
bool VisitBinaryOperator(BinaryOperator *binaryOperator) { Expr *leftExpr = binaryOperator->getLHS(); if (binaryOperator->getOpcode() == BO_Assign && leftExpr && isa<DeclRefExpr>(leftExpr)) { DeclRefExpr *declRefExpr = dyn_cast<DeclRefExpr>(leftExpr); for (const auto& name : _names) { if (declRefExpr->getFoundDecl()->getNameAsString() == name) { _binaryOperators.push_back(binaryOperator); break; } } } return true; }
static bool isArgOfFunc(T expr, FunctionDecl *fDecl, const VarDecl *varDecl, bool byRefOrPtrOnly) { unsigned int param = -1; for (auto arg : expr->arguments()) { ++param; DeclRefExpr *refExpr = dyn_cast<DeclRefExpr>(arg); if (!refExpr) { if (clazy_std::hasChildren(arg)) { Stmt* firstChild = *(arg->child_begin()); // Can be null (bug #362236) refExpr = firstChild ? dyn_cast<DeclRefExpr>(firstChild) : nullptr; if (!refExpr) continue; } else { continue; } } if (refExpr->getDecl() != varDecl) // It's our variable ? continue; if (!byRefOrPtrOnly) { // We found it return true; } // It is, lets see if the callee takes our variable by const-ref if (param >= fDecl->param_size()) continue; ParmVarDecl *paramDecl = fDecl->getParamDecl(param); if (!paramDecl) continue; QualType qt = paramDecl->getType(); const Type *t = qt.getTypePtrOrNull(); if (!t) continue; if ((t->isReferenceType() || t->isPointerType()) && !t->getPointeeType().isConstQualified()) return true; // function receives non-const ref, so our foreach variable cant be const-ref } return false; }
void TransferFunctions::VisitObjCForCollectionStmt(ObjCForCollectionStmt *OS) { // Kill the iteration variable. DeclRefExpr *DR = nullptr; const VarDecl *VD = nullptr; Stmt *element = OS->getElement(); if (DeclStmt *DS = dyn_cast<DeclStmt>(element)) { VD = cast<VarDecl>(DS->getSingleDecl()); } else if ((DR = dyn_cast<DeclRefExpr>(cast<Expr>(element)->IgnoreParens()))) { VD = cast<VarDecl>(DR->getDecl()); } if (VD) { val.liveDecls = LV.DSetFact.remove(val.liveDecls, VD); if (observer && DR) observer->observerKill(DR); } }
string NetworkDriverRewriteVisitor::GetSharedStructStr(CallExpr *callExpr) { string shared_struct_str = ""; Expr *callee = callExpr->getCallee(); if (!isa<ImplicitCastExpr>(callee)) return shared_struct_str; ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); if (!isa<DeclRefExpr>(calleeImplExpr->getSubExpr())) return shared_struct_str; DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); Stmt *body = callExpr->getCalleeDecl()->getBody(); if (calleeDeclExpr->getNameInfo().getAsString() != "alloc_etherdev") shared_struct_str = GetSharedStructStrInFunctionBody(body, false); if (calleeDeclExpr->getNameInfo().getAsString() != "alloc_etherdev") return shared_struct_str; for (auto i = callExpr->arg_begin(), e = callExpr->arg_end(); i != e; ++i) { if (!isa<ImplicitCastExpr>(*i)) continue; ImplicitCastExpr *argImplExpr = cast<ImplicitCastExpr>(*i); if (!isa<UnaryExprOrTypeTraitExpr>(argImplExpr->getSubExpr())) continue; UnaryExprOrTypeTraitExpr *argExpr = cast<UnaryExprOrTypeTraitExpr>(argImplExpr->getSubExpr()); ParenExpr *parenExpr = cast<ParenExpr>(argExpr->getArgumentExpr()); UnaryOperator *uop = cast<UnaryOperator>(parenExpr->getSubExpr()); ImplicitCastExpr *implExpr = cast<ImplicitCastExpr>(uop->getSubExpr()); DeclRefExpr *declExpr = cast<DeclRefExpr>(implExpr->getSubExpr()); ValueDecl *valueDecl = cast<ValueDecl>(declExpr->getDecl()); shared_struct_str = valueDecl->getType().getAsString(Context->getPrintingPolicy()); break; } return shared_struct_str; }
void UnnecessaryValueParamCheck::handleMoveFix(const ParmVarDecl &Var, const DeclRefExpr &CopyArgument, const ASTContext &Context) { auto Diag = diag(CopyArgument.getLocStart(), "parameter %0 is passed by value and only copied once; " "consider moving it to avoid unnecessary copies") << &Var; // Do not propose fixes in macros since we cannot place them correctly. if (CopyArgument.getLocStart().isMacroID()) return; const auto &SM = Context.getSourceManager(); auto EndLoc = Lexer::getLocForEndOfToken(CopyArgument.getLocation(), 0, SM, Context.getLangOpts()); Diag << FixItHint::CreateInsertion(CopyArgument.getLocStart(), "std::move(") << FixItHint::CreateInsertion(EndLoc, ")"); if (auto IncludeFixit = Inserter->CreateIncludeInsertion( SM.getFileID(CopyArgument.getLocStart()), "utility", /*IsAngled=*/true)) Diag << *IncludeFixit; }
void Fix(CompoundStmt* CS) { if (!CS->size()) return; typedef llvm::SmallVector<Stmt*, 32> Statements; Statements Stmts; Stmts.append(CS->body_begin(), CS->body_end()); for (Statements::iterator I = Stmts.begin(); I != Stmts.end(); ++I) { if (!TraverseStmt(*I) && !m_HandledDecls.count(m_FoundDRE->getDecl())) { Sema::DeclGroupPtrTy VDPtrTy = m_Sema->ConvertDeclToDeclGroup(m_FoundDRE->getDecl()); StmtResult DS = m_Sema->ActOnDeclStmt(VDPtrTy, m_FoundDRE->getLocStart(), m_FoundDRE->getLocEnd()); assert(!DS.isInvalid() && "Invalid DeclStmt."); I = Stmts.insert(I, DS.take()); m_HandledDecls.insert(m_FoundDRE->getDecl()); } } CS->setStmts(m_Sema->getASTContext(), Stmts.data(), Stmts.size()); }
//--------------------------------------------------------- VarDecl* isFortranLoop(ForStmt* Node, const char*& errMsg) { // cond must be of form "x >/</!=/ expr": BinaryOperator* condCmp = dyn_cast_or_null<BinaryOperator>(Node->getCond()); if (condCmp == 0 || ((!condCmp->isRelationalOp()) && condCmp->getOpcode() != BO_NE)) { errMsg = "for-cond not fortran-like (must be x rel expr)"; return 0; } DeclRefExpr* condVar = dyn_cast<DeclRefExpr>(stripParenCasts(condCmp->getLHS())); if (condVar == 0 || !condVar->getType()->isIntegerType()) { errMsg = "no integer for-init variable"; return 0; } VarDecl* VD = dyn_cast<VarDecl>(condVar->getDecl()); if (VD == 0) { errMsg = "strange unrecognized lhs in for-condition"; return 0; } // inc must be of form "++x/x++": UnaryOperator* incStmt = dyn_cast_or_null<UnaryOperator>(Node->getInc()); if (incStmt == 0 || (!incStmt->isIncrementOp())) { errMsg = "for-inc not fortran-like (must be ++x/x++)"; return 0; } DeclRefExpr* incVar = dyn_cast<DeclRefExpr>(incStmt->getSubExpr()); if (incVar == 0 || incVar->getDecl() != VD) { errMsg = "for-inc doesn't refer to for-cond variable"; return 0; } return VD; }
Stmt *TransformWCR::VisitIfStmt(IfStmt *S) { StmtVector OuterBody; // Declaration of the condition variable VarDecl *CondVD = NewCondVarDecl(S->getCond()->getType()); CondDecls.push_back(NewDeclStmt(CondVD)); // Computation of the condition DeclRefExpr *LHS = new (ASTCtx) DeclRefExpr(CondVD, CondVD->getType(), VK_RValue, SourceLocation()); BinaryOperator *CondBinOp = new (ASTCtx) BinaryOperator( LHS, S->getCond(), BO_Assign, LHS->getType(), VK_RValue, OK_Ordinary, SourceLocation()); MergeBodyAndCond(OuterBody, CondBinOp); // Cond DeclRefExpr *CondRef = new (ASTCtx) DeclRefExpr(CondVD, CondVD->getType(), VK_RValue, SourceLocation()); S->setCond(CondRef); // Then Stmt *Then = S->getThen(); CompoundStmt *ThenCS = dyn_cast<CompoundStmt>(Then); assert(ThenCS && "Not a CompoundStmt"); S->setThen(VisitCompoundStmt(ThenCS)); // Else if (Stmt *Else = S->getElse()) { CompoundStmt *ElseCS = dyn_cast<CompoundStmt>(Else); assert(ElseCS && "Not a CompoundStmt"); S->setElse(VisitCompoundStmt(ElseCS)); } OuterBody.push_back(S); return NewStmtList(OuterBody); }
void VarCollector::HandlePointerInit(VarDecl *VDLHS, string TLHS, SourceLocation StmtLoc) { CompilerInstance &CI = FullDirectives->GetCI(StmtLoc); // Get Dominant RHS DeclRef and its expr DeclRefExpr * RDominantRef = NULL; Expr * RDominantExpr = NULL; VarTraverser rvt(VDLHS->getInit(), RDominantRef, RDominantExpr, CI); rvt.TraverseStmt(VDLHS->getInit()); // If there isn't a dominant variable now being pointed to, just return if (!RDominantRef) { return; } // DEBUG: // Print out the dominant LHS and RHS /*llvm::errs() << "Found init of a pointer:\n"; llvm::errs() << "RHS Ref " << RDominantRef->getDecl()->getName() << " -> " << GetStmtString(RDominantExpr) << " (" << RDominantExpr->getType().getAsString() << ")\n";*/ VarDecl * VDRHS = dyn_cast<VarDecl>(RDominantRef->getDecl()); string TRHS = GetType(RDominantExpr); const Type * T = RDominantExpr->getType()->getUnqualifiedDesugaredType(); maybeContaminated(VDLHS, TLHS, VDRHS, TRHS, T, StmtLoc); }
void TransferFunctions::VisitBinaryOperator(BinaryOperator *E) { DeclRefExpr *DRE = nullptr; switch (E->getOpcode()) { case BO_PtrMemD: case BO_PtrMemI: default: KS.num_ops++; if (checkImageAccess(E->getLHS(), READ_WRITE) || checkImageAccess(E->getRHS(), READ_WRITE)) { // not supported on image objects KS.Diags.Report(E->getOperatorLoc(), KS.DiagIDUnsupportedBO) << E->getOpcodeStr(); exit(EXIT_FAILURE); } case BO_Mul: case BO_Div: case BO_Rem: case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_LT: case BO_GT: case BO_LE: case BO_GE: case BO_EQ: case BO_NE: case BO_And: case BO_Xor: case BO_Or: case BO_LAnd: case BO_LOr: KS.num_ops++; if (checkImageAccess(E->getLHS(), READ_ONLY)) { KS.curStmtVectorize = (VectorInfo) (KS.curStmtVectorize|VECTORIZE); } if (checkImageAccess(E->getRHS(), READ_ONLY)) { KS.curStmtVectorize = (VectorInfo) (KS.curStmtVectorize|VECTORIZE); } break; case BO_Assign: KS.num_ops++; if (checkImageAccess(E->getRHS(), READ_ONLY)) { KS.curStmtVectorize = (VectorInfo) (KS.curStmtVectorize|VECTORIZE); } else { if (isa<DeclRefExpr>(E->getRHS()->IgnoreParenImpCasts())) { DRE = dyn_cast<DeclRefExpr>(E->getRHS()->IgnoreParenImpCasts()); if (isa<VarDecl>(DRE->getDecl())) { VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); KS.declsToVector[VD] = (VectorInfo) (KS.curStmtVectorize|KS.declsToVector[VD]); } } } if (!checkImageAccess(E->getLHS(), WRITE_ONLY)) { if (isa<DeclRefExpr>(E->getLHS())) { DRE = dyn_cast<DeclRefExpr>(E->getLHS()); if (isa<VarDecl>(DRE->getDecl())) { VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); KS.declsToVector[VD] = (VectorInfo) (KS.curStmtVectorize|KS.declsToVector[VD]); } } else { #ifdef DEBUG_ANALYSIS llvm::errs() << "==DEBUG==: is not a DRE (LHS):\n"; E->getLHS()->dump(); llvm::errs() << "\n"; #endif } } // reset vectorization status for next statement KS.curStmtVectorize = SCALAR; break; case BO_MulAssign: case BO_DivAssign: case BO_RemAssign: case BO_AddAssign: case BO_SubAssign: case BO_ShlAssign: case BO_ShrAssign: case BO_AndAssign: case BO_XorAssign: case BO_OrAssign: KS.num_ops+=2; if (checkImageAccess(E->getRHS(), READ_ONLY)) { KS.curStmtVectorize = (VectorInfo) (KS.curStmtVectorize|VECTORIZE); } else { if (isa<DeclRefExpr>(E->getRHS()->IgnoreParenImpCasts())) { DRE = dyn_cast<DeclRefExpr>(E->getRHS()->IgnoreParenImpCasts()); if (isa<VarDecl>(DRE->getDecl())) { VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); KS.declsToVector[VD] = (VectorInfo) (KS.curStmtVectorize|KS.declsToVector[VD]); } } } if (!checkImageAccess(E->getLHS(), READ_WRITE)) { if (isa<DeclRefExpr>(E->getLHS())) { DRE = dyn_cast<DeclRefExpr>(E->getLHS()); if (isa<VarDecl>(DRE->getDecl())) { VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); KS.declsToVector[VD] = (VectorInfo) (KS.curStmtVectorize|KS.declsToVector[VD]); } } else { #ifdef DEBUG_ANALYSIS llvm::errs() << "==DEBUG==: is not a DRE (LHS):\n"; E->getLHS()->dump(); llvm::errs() << "\n"; #endif } } // reset vectorization status for next statement KS.curStmtVectorize = SCALAR; break; case BO_Comma: break; } }
OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); I != E; ++I) { assert(*I && "NULL expr in OpenMP firstprivate clause."); if (isa<DependentScopeDeclRefExpr>(*I)) { // It will be analyzed later. Vars.push_back(*I); continue; } SourceLocation ELoc = (*I)->getExprLoc(); // OpenMP [2.1, C/C++] // A list item is a variable name. // OpenMP [2.9.3.3, Restrictions, p.1] // A variable that is part of another variable (as an array or // structure element) cannot appear in a private clause. DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I); if (!DE || !isa<VarDecl>(DE->getDecl())) { Diag(ELoc, diag::err_omp_expected_var_name) << (*I)->getSourceRange(); continue; } Decl *D = DE->getDecl(); VarDecl *VD = cast<VarDecl>(D); QualType Type = VD->getType(); if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); continue; } // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] // A variable that appears in a private clause must not have an incomplete // type or a reference type. if (RequireCompleteType(ELoc, Type, diag::err_omp_firstprivate_incomplete_type)) { continue; } if (Type->isReferenceType()) { Diag(ELoc, diag::err_omp_clause_ref_type_arg) << getOpenMPClauseName(OMPC_firstprivate) << Type; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; continue; } // OpenMP [2.9.3.4, Restrictions, C/C++, p.1] // A variable of class type (or array thereof) that appears in a private // clause requires an accesible, unambiguous copy constructor for the // class type. Type = Context.getBaseElementType(Type); CXXRecordDecl *RD = getLangOpts().CPlusPlus ? Type.getNonReferenceType()->getAsCXXRecordDecl() : 0; if (RD) { CXXConstructorDecl *CD = LookupCopyingConstructor(RD, 0); PartialDiagnostic PD = PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); if (!CD || CheckConstructorAccess(ELoc, CD, InitializedEntity::InitializeTemporary(Type), CD->getAccess(), PD) == AR_inaccessible || CD->isDeleted()) { Diag(ELoc, diag::err_omp_required_method) << getOpenMPClauseName(OMPC_firstprivate) << 1; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; Diag(RD->getLocation(), diag::note_previous_decl) << RD; continue; } MarkFunctionReferenced(ELoc, CD); DiagnoseUseOfDecl(CD, ELoc); CXXDestructorDecl *DD = RD->getDestructor(); if (DD) { if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || DD->isDeleted()) { Diag(ELoc, diag::err_omp_required_method) << getOpenMPClauseName(OMPC_firstprivate) << 4; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; Diag(RD->getLocation(), diag::note_previous_decl) << RD; continue; } MarkFunctionReferenced(ELoc, DD); DiagnoseUseOfDecl(DD, ELoc); } } // If StartLoc and EndLoc are invalid - this is an implicit firstprivate // variable and it was checked already. if (StartLoc.isValid() && EndLoc.isValid()) { DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); Type = Type.getNonReferenceType().getCanonicalType(); bool IsConstant = Type.isConstant(Context); Type = Context.getBaseElementType(Type); // OpenMP [2.4.13, Data-sharing Attribute Clauses] // A list item that specifies a given variable may not appear in more // than one clause on the same directive, except that a variable may be // specified in both firstprivate and lastprivate clauses. // TODO: add processing for lastprivate. if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate && DVar.RefExpr) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_firstprivate); Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(DVar.CKind); continue; } // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] // Variables with the predetermined data-sharing attributes may not be // listed in data-sharing attributes clauses, except for the cases // listed below. For these exceptions only, listing a predetermined // variable in a data-sharing attribute clause is allowed and overrides // the variable's predetermined data-sharing attributes. // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, C/C++, p.2] // Variables with const-qualified type having no mutable member may be // listed in a firstprivate clause, even if they are static data members. if (!(IsConstant || VD->isStaticDataMember()) && !DVar.RefExpr && DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_firstprivate); Diag(VD->getLocation(), diag::note_omp_predetermined_dsa) << getOpenMPClauseName(DVar.CKind); continue; } // OpenMP [2.9.3.4, Restrictions, p.2] // A list item that is private within a parallel region must not appear // in a firstprivate clause on a worksharing construct if any of the // worksharing regions arising from the worksharing construct ever bind // to any of the parallel regions arising from the parallel construct. // OpenMP [2.9.3.4, Restrictions, p.3] // A list item that appears in a reduction clause of a parallel construct // must not appear in a firstprivate clause on a worksharing or task // construct if any of the worksharing or task regions arising from the // worksharing or task construct ever bind to any of the parallel regions // arising from the parallel construct. // OpenMP [2.9.3.4, Restrictions, p.4] // A list item that appears in a reduction clause in worksharing // construct must not appear in a firstprivate clause in a task construct // encountered during execution of any of the worksharing regions arising // from the worksharing construct. // TODO: } DSAStack->addDSA(VD, DE, OMPC_firstprivate); Vars.push_back(DE); } if (Vars.empty()) return 0; return OMPFirstprivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); }
OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); I != E; ++I) { assert(*I && "NULL expr in OpenMP private clause."); if (isa<DependentScopeDeclRefExpr>(*I)) { // It will be analyzed later. Vars.push_back(*I); continue; } SourceLocation ELoc = (*I)->getExprLoc(); // OpenMP [2.1, C/C++] // A list item is a variable name. // OpenMP [2.9.3.3, Restrictions, p.1] // A variable that is part of another variable (as an array or // structure element) cannot appear in a private clause. DeclRefExpr *DE = dyn_cast_or_null<DeclRefExpr>(*I); if (!DE || !isa<VarDecl>(DE->getDecl())) { Diag(ELoc, diag::err_omp_expected_var_name) << (*I)->getSourceRange(); continue; } Decl *D = DE->getDecl(); VarDecl *VD = cast<VarDecl>(D); QualType Type = VD->getType(); if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); continue; } // OpenMP [2.9.3.3, Restrictions, C/C++, p.3] // A variable that appears in a private clause must not have an incomplete // type or a reference type. if (RequireCompleteType(ELoc, Type, diag::err_omp_private_incomplete_type)) { continue; } if (Type->isReferenceType()) { Diag(ELoc, diag::err_omp_clause_ref_type_arg) << getOpenMPClauseName(OMPC_private) << Type; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; continue; } // OpenMP [2.9.3.3, Restrictions, C/C++, p.1] // A variable of class type (or array thereof) that appears in a private // clause requires an accesible, unambiguous default constructor for the // class type. while (Type.getNonReferenceType()->isArrayType()) { Type = cast<ArrayType>( Type.getNonReferenceType().getTypePtr())->getElementType(); } CXXRecordDecl *RD = getLangOpts().CPlusPlus ? Type.getNonReferenceType()->getAsCXXRecordDecl() : 0; if (RD) { CXXConstructorDecl *CD = LookupDefaultConstructor(RD); PartialDiagnostic PD = PartialDiagnostic(PartialDiagnostic::NullDiagnostic()); if (!CD || CheckConstructorAccess(ELoc, CD, InitializedEntity::InitializeTemporary(Type), CD->getAccess(), PD) == AR_inaccessible || CD->isDeleted()) { Diag(ELoc, diag::err_omp_required_method) << getOpenMPClauseName(OMPC_private) << 0; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; Diag(RD->getLocation(), diag::note_previous_decl) << RD; continue; } MarkFunctionReferenced(ELoc, CD); DiagnoseUseOfDecl(CD, ELoc); CXXDestructorDecl *DD = RD->getDestructor(); if (DD) { if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || DD->isDeleted()) { Diag(ELoc, diag::err_omp_required_method) << getOpenMPClauseName(OMPC_private) << 4; bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), IsDecl ? diag::note_previous_decl : diag::note_defined_here) << VD; Diag(RD->getLocation(), diag::note_previous_decl) << RD; continue; } MarkFunctionReferenced(ELoc, DD); DiagnoseUseOfDecl(DD, ELoc); } } // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] // Variables with the predetermined data-sharing attributes may not be // listed in data-sharing attributes clauses, except for the cases // listed below. For these exceptions only, listing a predetermined // variable in a data-sharing attribute clause is allowed and overrides // the variable's predetermined data-sharing attributes. DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_private); if (DVar.RefExpr) { Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(DVar.CKind); } else { Diag(VD->getLocation(), diag::note_omp_predetermined_dsa) << getOpenMPClauseName(DVar.CKind); } continue; } DSAStack->addDSA(VD, DE, OMPC_private); Vars.push_back(DE); } if (Vars.empty()) return 0; return OMPPrivateClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); }
/* this helper function is called when the traversal reaches a node of type Stmt */ void StmtHelper(Stmt *x){ //variable used for <cond> </cond> //bool condition = false; bool isElse = false; if(x != NULL){ string output = ""; //find current level and next level int intLevel = getLevelStmt(x); int intNextLevel = intLevel+1; //convert them both to strings to use for output string level; string nextLevel; stringstream ss; ss << intLevel; level = ss.str(); stringstream ss2; ss2 << intNextLevel; nextLevel = ss2.str(); const Stmt* parent = getStmtParent(x, Context); //PROBLEM if(x->getStmtClassName() != std::string("ForStmt") && isFlowControl(x, Context)){ //return; } //if the parent is calling any type of funciton then this node should be enclosed in <args> </args> string filename; if(callStackDebug && !callStack.empty()){ cerr << "stmt: call stack top: " << callStack.top()->getStmtClassName() << endl; } while(!callStack.empty() && numClosingArgsNeeded > 0 && !isParentStmt(parent, callStack.top()->getStmtClassName())){ if(debugPrint){ cerr << "adding args" << endl; } numClosingArgsNeeded--; output += "</args,1>\n"; callStack.pop(); if(callStackDebug){ cerr << "popping" << endl; printCallStack(); } } if(isParentStmtInCurFile(x,"CXXConstructExpr") && isParentStmt(x, "CXXConstructExpr")){ if(debugPrint){ cerr << "setting previousConstructorCall to true" << endl; } }else if(isParentStmtInCurFile(x,"CXXTemporaryObjectExpr") && isParentStmt(x, "CXXTemporaryObjectExpr")){ if(debugPrint){ cerr << "setting previousTempConstructorCallArg" << endl; } }else if(isParentStmt(x, "CallExpr")){ if(debugPrint){ cerr << "setting previousCallArgs to true" << endl; } }else if(isParentStmt(x, "CXXMemberCallExpr")){ if(debugPrint){ cerr << "setting previousMemberCallArgs to true" << endl; } } //if the parent is a variable declaration then this node should be encolsed in <decl> </decl> if(isParentStmt(x, "Var")){ previousRhsDecl = true; if(debugPrint){ cout << "setting prev var to true" << endl; } }else if(previousRhsDecl && numClosingVarsNeeded > 0){ //if the current node is not a child of a variable declaration //but the previous node was a child of a variable declation //then we know to print a </decl> output +="</variableDecl,1>\n"; numClosingVarsNeeded--; previousRhsDecl = false; } if(parent != NULL && strcmp(parent->getStmtClassName(), "IfStmt") == 0){ if(debugPrint){ cerr << "possibly an if statement" << endl; } //find the first child of the if statemt const Stmt* firstChild = NULL; auto children = parent->children(); for(const Stmt* child : children){ if(child != NULL){ firstChild = child; break; } } //if the first child is the current node, then we know it is part of the condition if(firstChild != NULL && x->getLocStart() == firstChild->getLocStart()){ if(debugPrint){ cerr << "part of the condition" << endl; } prevCondition = true; }else if(prevCondition){ output +="</cond,1>\n"; prevCondition = false; } //find if else const IfStmt* ifstmt = (IfStmt*) parent; const Stmt* elseStmt = ifstmt->getElse(); if(elseStmt != NULL){ if(debugPrint){ cout << "checking if " << x->getLocStart().printToString(Context->getSourceManager()); cout << " == " << elseStmt->getLocStart().printToString(Context->getSourceManager()); cout << " : " << (x->getLocStart() == elseStmt->getLocStart()) << endl; } if(x->getLocStart() == elseStmt->getLocStart()){ isElse = true; } } } string node = x->getStmtClassName(); if(node == "ReturnStmt"){ output += "<return"; }else if(node == "ForStmt"){ output += "<forLoop"; }else if(node == "WhileStmt"){ output += "<whileLoop"; }else if(node == "DoStmt"){ output += "<do"; }else if(node == "IfStmt"){ if(parent->getStmtClassName() != std::string("IfStmt")){ stringstream ssminus; ssminus << (intLevel-1); output += "<ifBlock," + ssminus.str() + ">\n"; intLevel += 1; stringstream ssif; ssif << intLevel; level = ssif.str(); } output += "<ifStatement"; }else if(node == "SwitchStmt"){ output += "<switch"; }else if(node == "CaseStmt"){ output += "<case"; }else if(node == "CXXMemberCallExpr"){ CXXMemberCallExpr* ce = (CXXMemberCallExpr*) x; Expr* obj = ce->getImplicitObjectArgument(); CallExpr* expr = (CallExpr*) x; output += "<object: "; QualType qt = obj->getType(); output += qt.getBaseTypeIdentifier()->getName().str(); output += "; calling func: "; output += expr->getDirectCallee()->getNameInfo().getAsString(); output += ", " + level + ">\n"; output += "<args"; numClosingArgsNeeded++; callStack.push(x); if(callStackDebug){ cerr << "pushing" << endl; printCallStack(); } }else if(node == "CallExpr"){ CallExpr* expr = (CallExpr*) x; output += "<calling func: "; output += expr->getDirectCallee()->getNameInfo().getAsString(); output += ", " + level + ">\n"; output += "<args"; numClosingArgsNeeded++; callStack.push(x); if(callStackDebug){ cerr << "pushing" << endl; printCallStack(); } }else if(node == "CXXConstructExpr"){ CXXConstructExpr* ce = (CXXConstructExpr*) x; //Decl* CD = ce->getConstructor(); string filename; //if(isInCurFile(Context, CD, filename)){ CXXMethodDecl* MD = ce->getConstructor(); output += "<calling func: "; output += MD->getNameInfo().getAsString(); output += "," + level + ">\n"; output += "<args"; numClosingArgsNeeded++; callStack.push(x); if(callStackDebug){ cerr << "pushing" << endl; printCallStack(); } //} }else if(node == "BinaryOperator"){ BinaryOperator* binaryOp = (BinaryOperator*) x; if(binaryOp->isAssignmentOp()){ output += "<assignment"; }else if(binaryOp->isComparisonOp()){ output += "<comparison"; }else{ output += "<binaryOp"; } }else if(node == "UnaryOperator"){ UnaryOperator* uo = (UnaryOperator*) x; string op = uo->getOpcodeStr(uo->getOpcode()).str(); if(op != "-"){ output += "<unaryOp"; } }else if(node == "CompoundAssignOperator"){ output += "<augAssign"; }else if(node == "CompoundStmt"){ if(isElse){ output += "<elseStatement"; }else{ output += "<compoundStmt"; } }else if(node == "CXXThrowExpr"){ output += "<raisingException"; }else if(node == "CXXTryStmt"){ output += "<try"; }else if(node == "CXXCatchStmt"){ output += "<except"; }else if(node == "CXXOperatorCallExpr"){ CXXOperatorCallExpr* ce = (CXXOperatorCallExpr*) x; if(ce->isAssignmentOp()){ output += "<assignment"; } }else if(node == "CXXTemporaryObjectExpr"){ CXXTemporaryObjectExpr* ce = (CXXTemporaryObjectExpr*) x; Decl* CD = ce->getConstructor(); string filename; if(isInCurFile(Context, CD, filename)){ CXXMethodDecl* MD = ce->getConstructor(); output += "<calling func: "; output += MD->getNameInfo().getAsString(); output += "," + level + ">\n"; output += "<args"; numClosingArgsNeeded++; callStack.push(x); if(callStackDebug){ cerr << "pushing" << endl; printCallStack(); } } }else if(node == "DeclRefExpr"){ if(parent != NULL && parent->getStmtClassName() == std::string("ImplicitCastExpr")){ DeclRefExpr* dr = (DeclRefExpr*) x; ValueDecl* d = (ValueDecl*) dr->getDecl(); //cout << d->getQualType().getAsString() << endl; if(d != NULL){ QualType qt = d->getType(); //cout << qt.getAsString() << endl; if(qt.getAsString() == "std::vector<int, class std::allocator<int> >::const_reference (std::vector::size_type) const noexcept"){ //string type = io->getName().str(); //cout << type << endl; //if(type == "vector"){ output += "<expr"; //} } } } }else{ if(allNodes){ output += "<"; output += node; output += ">"; } } if(output.size() != 0 && !endsIn(output, "</cond,1>\n") && !endsIn(output,"</variableDecl,1>\n") && !endsIn(output,"</args,1>\n") && !endsIn(output,">") && !endsIn(output, ">\n")){ output += ", " + level + ">"; cout << output << endl; output = ""; }else if(output.size() != 0){ cout << output << endl; output = ""; if(debugPrint){ cerr << "printing output" << endl; } } } }
OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; for (ArrayRef<Expr *>::iterator I = VarList.begin(), E = VarList.end(); I != E; ++I) { assert(*I && "NULL expr in OpenMP shared clause."); if (isa<DependentScopeDeclRefExpr>(*I)) { // It will be analyzed later. Vars.push_back(*I); continue; } SourceLocation ELoc = (*I)->getExprLoc(); // OpenMP [2.1, C/C++] // A list item is a variable name. // OpenMP [2.9.3.4, Restrictions, p.1] // A variable that is part of another variable (as an array or // structure element) cannot appear in a private clause. DeclRefExpr *DE = dyn_cast<DeclRefExpr>(*I); if (!DE || !isa<VarDecl>(DE->getDecl())) { Diag(ELoc, diag::err_omp_expected_var_name) << (*I)->getSourceRange(); continue; } Decl *D = DE->getDecl(); VarDecl *VD = cast<VarDecl>(D); QualType Type = VD->getType(); if (Type->isDependentType() || Type->isInstantiationDependentType()) { // It will be analyzed later. Vars.push_back(DE); continue; } // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct] // Variables with the predetermined data-sharing attributes may not be // listed in data-sharing attributes clauses, except for the cases // listed below. For these exceptions only, listing a predetermined // variable in a data-sharing attribute clause is allowed and overrides // the variable's predetermined data-sharing attributes. DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && DVar.RefExpr) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_shared); Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(DVar.CKind); continue; } DSAStack->addDSA(VD, DE, OMPC_shared); Vars.push_back(DE); } if (Vars.empty()) return 0; return OMPSharedClause::Create(Context, StartLoc, LParenLoc, EndLoc, Vars); }
Stmt *TransformWCR::VisitForStmt(ForStmt *S) { StmtVector OuterBody; StmtVector BodyStmts; StmtVector WCRBody; // If Init of ForStmt has a DeclStmt, we make a CompoundStmt that encloses // an Init stmt and WhileStmt made from orginal ForStmt. bool HasDecl = false; // Init if (Stmt *Init = S->getInit()) { if (DeclStmt *DS = dyn_cast<DeclStmt>(Init)) { HasDecl = true; StmtVector tmpWCR; VisitRawDeclStmt(DS, OuterBody, tmpWCR); MergeBodyAndWCR(OuterBody, tmpWCR); } else { MergeBodyAndCond(OuterBody, Init); } } // Declaration of condition variable VarDecl *CondVD = NewCondVarDecl(ASTCtx.IntTy); CondDecls.push_back(NewDeclStmt(CondVD)); // Computation of condition DeclRefExpr *LHS = new (ASTCtx) DeclRefExpr(CondVD, CondVD->getType(), VK_RValue, SourceLocation()); Expr *Cond = S->getCond(); if (!Cond) Cond = CLExprs.getExpr(CLExpressions::ONE); BinaryOperator *CondBinOp = new (ASTCtx) BinaryOperator( LHS, Cond, BO_Assign, LHS->getType(), VK_RValue, OK_Ordinary, SourceLocation()); // Cond WCR MergeBodyAndCond(BodyStmts, CondBinOp); // Exit condition DeclRefExpr *CondRef = new (ASTCtx) DeclRefExpr(CondVD, CondVD->getType(), VK_RValue, SourceLocation()); UnaryOperator *NotCond = new (ASTCtx) UnaryOperator( CondRef, UO_LNot, CondVD->getType(), VK_RValue, OK_Ordinary, SourceLocation()); BreakStmt *ThenStmt = new (ASTCtx) BreakStmt(SourceLocation()); IfStmt *ExitStmt = new (ASTCtx) IfStmt(ASTCtx, SourceLocation(), NULL, NotCond, ThenStmt); BodyStmts.push_back(ExitStmt); // Body Stmt *Body = S->getBody(); CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); assert(CS && "Not a CompoundStmt"); // Identify each WCR VisitRawCompoundStmt(CS, BodyStmts, WCRBody); MergeBodyAndWCR(BodyStmts, WCRBody); // Inc if (Expr *Inc = S->getInc()) MergeBodyAndCond(BodyStmts, Inc); ASTCtx.Deallocate(S); ASTCtx.Deallocate(CS); // Outer WhileStmt Cond = CLExprs.getExpr(CLExpressions::ONE); Body = MergeWCRsAndMakeCompoundStmt(BodyStmts); WhileStmt *WS = new (ASTCtx) WhileStmt(ASTCtx, NULL, Cond, Body, SourceLocation()); OuterBody.push_back(WS); // Landing pad - empty WCR OuterBody.push_back(NewLandingPad(WS)); CompoundStmt *Out = NewCompoundStmt(OuterBody); if (!HasDecl) Out->setIsStmtList(true); return Out; }
string NetworkDriverRewriteVisitor::GetSharedStructStrInFunctionBody(Stmt *body, bool doLog) { string shared_struct_str = ""; for (auto i = body->child_begin(), e = body->child_end(); i != e; ++i) { if (isa<DeclStmt>(*i)) { DeclStmt *declStmt = cast<DeclStmt>(*i); if (!declStmt->isSingleDecl() && !isa<VarDecl>(declStmt->getSingleDecl())) continue; VarDecl *varDecl = cast<VarDecl>(declStmt->getSingleDecl()); if (!isa<ValueDecl>(varDecl)) continue; ValueDecl *value = cast<ValueDecl>(varDecl); if (value->getType().getAsString(Context->getPrintingPolicy()) != "struct net_device *") continue; if (!isa<NamedDecl>(varDecl)) continue; if (varDecl->getInit() == 0 || !isa<CallExpr>(varDecl->getInit())) continue; CallExpr *callExpr = cast<CallExpr>(varDecl->getInit()); shared_struct_str = GetSharedStructStr(callExpr); if (shared_struct_str != "") { if (doLog) { Expr *callee = callExpr->getCallee(); ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); DI->getInstance().AddSharedStructInformation("whoop_network_shared_struct", calleeDeclExpr->getNameInfo().getAsString()); } break; } } else if (isa<BinaryOperator>(*i)) { BinaryOperator *binOp = cast<BinaryOperator>(*i); if (!isa<CallExpr>(binOp->getRHS())) continue; CallExpr *callExpr = cast<CallExpr>(binOp->getRHS()); shared_struct_str = GetSharedStructStr(callExpr); if (shared_struct_str != "") { if (doLog) { Expr *callee = callExpr->getCallee(); ImplicitCastExpr *calleeImplExpr = cast<ImplicitCastExpr>(callee); DeclRefExpr *calleeDeclExpr = cast<DeclRefExpr>(calleeImplExpr->getSubExpr()); DI->getInstance().AddSharedStructInformation("whoop_network_shared_struct", calleeDeclExpr->getNameInfo().getAsString()); } break; } } } return shared_struct_str; }