NamedDecl* RedundantLocalVariableRule::extractFromDeclStmt(Stmt *stmt) { CompoundStmt *compoundStmt = dyn_cast<CompoundStmt>(stmt); if (compoundStmt && compoundStmt->size() >= 2) { Stmt *lastSecondStmt = (Stmt *)*(compoundStmt->body_end() - 2); DeclStmt *declStmt = dyn_cast<DeclStmt>(lastSecondStmt); if (declStmt && declStmt->isSingleDecl()) { return dyn_cast<NamedDecl>(declStmt->getSingleDecl()); } } return NULL; }
bool VisitForStmt(ForStmt *parentStmt) { Stmt *bodyStmt = parentStmt->getBody(); ForStmt *forStmt = dyn_cast_or_null<ForStmt>(bodyStmt); CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(bodyStmt); if (!forStmt && compoundStmt && compoundStmt->size() == 1) { forStmt = dyn_cast_or_null<ForStmt>(compoundStmt->body_back()); } if (forStmt) { Stmt *initStmt = parentStmt->getInit(); Expr *incExpr = forStmt->getInc(); if (isInnerIncMatchingOuterInit(incExpr, initStmt)) { addViolation(incExpr, this); } } return true; }
//--------------------------------------------------------- void removeGotosToNextLabel(StmtEditor& editor, Stmt* Node) { RemoveGotosToNextLabel visitor(editor); visit_df(Node, visitor); for (RemoveGotosToNextLabel::tTouchedLabels::iterator i = visitor.m_TouchedLabels.begin(), e = visitor.m_TouchedLabels.end(); i != e; ++i) { if (!i->second.m_Used) { LabelStmt* LS = i->second.LS; assert(LS); CompoundStmt* CS = dyn_cast<CompoundStmt>(editor.getParent(LS)); if (CS && CS->size() > 1 && isa<NullStmt>(LS->getSubStmt())) { editor.removeStmt(CS, LS); } else { editor.replaceStatement(LS, LS->getSubStmt()); } } } }
//--------------------------------------------------------- void expandOneUsedInitDeclsToUse(StmtEditor& editor, Stmt* Node) { CountVarUses visitor(editor); CompileTimeComputedExprTester tester; visit_df(Node, visitor); for (CountVarUses::tVarRefCountMap::iterator i = visitor.m_VarUseCount.begin(), e = visitor.m_VarUseCount.end(); i != e; ++i) { if (i->second.second < 2 || (i->first->getInit() && tester.Visit(i->first->getInit()))) { CompoundStmt* CS = dyn_cast<CompoundStmt>(editor.getParent(i->second.first)); if (CS && CS->size() > 1) { if (i->second.second > 0) { visit_df(Node, ExpandVariableRefs(editor, i->first)); i->first->setInit(0); // ownership was transferred, so don't confuse anyone after us } editor.removeStmt(CS, i->second.first); } } } }
bool ValuePrinterSynthesizer::tryAttachVP(FunctionDecl* FD) { // We have to be able to mark the expression for printout. There are // three scenarios: // 0: Expression printing disabled - don't do anything just exit. // 1: Expression printing enabled - print no matter what. // 2: Expression printing auto - analyze - rely on the omitted ';' to // not produce the suppress marker. int indexOfLastExpr = -1; Expr* To = utils::Analyze::GetOrCreateLastExpr(FD, &indexOfLastExpr, /*omitDS*/false, m_Sema); if (To) { // Update the CompoundStmt body, avoiding alloc/dealloc of all the el. CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); assert(CS && "Missing body?"); switch (getCompilationOpts().ValuePrinting) { case CompilationOptions::VPDisabled: assert(0 && "Don't wait that long. Exit early!"); break; case CompilationOptions::VPEnabled: break; case CompilationOptions::VPAuto: { // FIXME: Propagate the flag to the nested transactions also, they // must have the same CO as their parents. getCompilationOpts().ValuePrinting = CompilationOptions::VPEnabled; if ((int)CS->size() > indexOfLastExpr+1 && (*(CS->body_begin() + indexOfLastExpr + 1)) && isa<NullStmt>(*(CS->body_begin() + indexOfLastExpr + 1))) { // If next is NullStmt disable VP is disabled - exit. Signal this in // the CO of the transaction. getCompilationOpts().ValuePrinting = CompilationOptions::VPDisabled; } if (getCompilationOpts().ValuePrinting == CompilationOptions::VPDisabled) return true; } break; } // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, FD); if (To) { // Strip the parenthesis if any if (ParenExpr* PE = dyn_cast<ParenExpr>(To)) To = PE->getSubExpr(); Expr* Result = 0; // if (!m_Sema->getLangOpts().CPlusPlus) // Result = SynthesizeVP(To); if (Result) *(CS->body_begin()+indexOfLastExpr) = Result; } // Clear the artificial NullStmt-s if (!ClearNullStmts(CS)) { // FIXME: Why it is here? Shouldn't it be in DeclExtractor? // if no body remove the wrapper DeclContext* DC = FD->getDeclContext(); Scope* S = m_Sema->getScopeForContext(DC); if (S) S->RemoveDecl(FD); DC->removeDecl(FD); } } else // if nothing to attach to set the CO's ValuePrinting to disabled. getCompilationOpts().ValuePrinting = CompilationOptions::VPDisabled; return true; }
ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope, llvm::Optional<unsigned> ManglingNumber, Decl *ContextDecl, bool IsInstantiation) { // Collect information from the lambda scope. llvm::SmallVector<LambdaExpr::Capture, 4> Captures; llvm::SmallVector<Expr *, 4> CaptureInits; LambdaCaptureDefault CaptureDefault; CXXRecordDecl *Class; CXXMethodDecl *CallOperator; SourceRange IntroducerRange; bool ExplicitParams; bool ExplicitResultType; bool LambdaExprNeedsCleanups; llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; llvm::SmallVector<unsigned, 4> ArrayIndexStarts; { LambdaScopeInfo *LSI = getCurLambda(); CallOperator = LSI->CallOperator; Class = LSI->Lambda; IntroducerRange = LSI->IntroducerRange; ExplicitParams = LSI->ExplicitParams; ExplicitResultType = !LSI->HasImplicitReturnType; LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; ArrayIndexVars.swap(LSI->ArrayIndexVars); ArrayIndexStarts.swap(LSI->ArrayIndexStarts); // Translate captures. for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) { LambdaScopeInfo::Capture From = LSI->Captures[I]; assert(!From.isBlockCapture() && "Cannot capture __block variables"); bool IsImplicit = I >= LSI->NumExplicitCaptures; // Handle 'this' capture. if (From.isThisCapture()) { Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, LCK_This)); CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(), getCurrentThisType(), /*isImplicit=*/true)); continue; } VarDecl *Var = From.getVariable(); LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef; Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, Kind, Var, From.getEllipsisLoc())); CaptureInits.push_back(From.getCopyExpr()); } switch (LSI->ImpCaptureStyle) { case CapturingScopeInfo::ImpCap_None: CaptureDefault = LCD_None; break; case CapturingScopeInfo::ImpCap_LambdaByval: CaptureDefault = LCD_ByCopy; break; case CapturingScopeInfo::ImpCap_LambdaByref: CaptureDefault = LCD_ByRef; break; case CapturingScopeInfo::ImpCap_Block: llvm_unreachable("block capture in lambda"); break; } // C++11 [expr.prim.lambda]p4: // If a lambda-expression does not include a // trailing-return-type, it is as if the trailing-return-type // denotes the following type: // FIXME: Assumes current resolution to core issue 975. if (LSI->HasImplicitReturnType) { // - if there are no return statements in the // compound-statement, or all return statements return // either an expression of type void or no expression or // braced-init-list, the type void; if (LSI->ReturnType.isNull()) { LSI->ReturnType = Context.VoidTy; } else { // C++11 [expr.prim.lambda]p4: // - if the compound-statement is of the form // // { attribute-specifier-seq[opt] return expression ; } // // the type of the returned expression after // lvalue-to-rvalue conversion (4.1), array-to-pointer // conver- sion (4.2), and function-to-pointer conversion // (4.3); // // Since we're accepting the resolution to a post-C++11 core // issue with a non-trivial extension, provide a warning (by // default). CompoundStmt *CompoundBody = cast<CompoundStmt>(Body); if (!(CompoundBody->size() == 1 && isa<ReturnStmt>(*CompoundBody->body_begin())) && !Context.hasSameType(LSI->ReturnType, Context.VoidTy)) Diag(IntroducerRange.getBegin(), diag::ext_lambda_implies_void_return); } // Create a function type with the inferred return type. const FunctionProtoType *Proto = CallOperator->getType()->getAs<FunctionProtoType>(); QualType FunctionTy = Context.getFunctionType(LSI->ReturnType, Proto->arg_type_begin(), Proto->getNumArgs(), Proto->getExtProtoInfo()); CallOperator->setType(FunctionTy); } // C++ [expr.prim.lambda]p7: // The lambda-expression's compound-statement yields the // function-body (8.4) of the function call operator [...]. ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation); CallOperator->setLexicalDeclContext(Class); Class->addDecl(CallOperator); PopExpressionEvaluationContext(); // C++11 [expr.prim.lambda]p6: // The closure type for a lambda-expression with no lambda-capture // has a public non-virtual non-explicit const conversion function // to pointer to function having the same parameter and return // types as the closure type's function call operator. if (Captures.empty() && CaptureDefault == LCD_None) addFunctionPointerConversion(*this, IntroducerRange, Class, CallOperator); // Objective-C++: // The closure type for a lambda-expression has a public non-virtual // non-explicit const conversion function to a block pointer having the // same parameter and return types as the closure type's function call // operator. if (getLangOpts().Blocks && getLangOpts().ObjC1) addBlockPointerConversion(*this, IntroducerRange, Class, CallOperator); // Finalize the lambda class. SmallVector<Decl*, 4> Fields(Class->field_begin(), Class->field_end()); ActOnFields(0, Class->getLocation(), Class, Fields, SourceLocation(), SourceLocation(), 0); CheckCompletedCXXClass(Class); } if (LambdaExprNeedsCleanups) ExprNeedsCleanups = true; // If we don't already have a mangling number for this lambda expression, // allocate one now. if (!ManglingNumber) { ContextDecl = ExprEvalContexts.back().LambdaContextDecl; enum ContextKind { Normal, DefaultArgument, DataMember, StaticDataMember } Kind = Normal; // Default arguments of member function parameters that appear in a class // definition, as well as the initializers of data members, receive special // treatment. Identify them. if (ContextDecl) { if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) { if (const DeclContext *LexicalDC = Param->getDeclContext()->getLexicalParent()) if (LexicalDC->isRecord()) Kind = DefaultArgument; } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) { if (Var->getDeclContext()->isRecord()) Kind = StaticDataMember; } else if (isa<FieldDecl>(ContextDecl)) { Kind = DataMember; } } switch (Kind) { case Normal: if (CurContext->isDependentContext() || isInInlineFunction(CurContext)) ManglingNumber = Context.getLambdaManglingNumber(CallOperator); else ManglingNumber = 0; // There is no special context for this lambda. ContextDecl = 0; break; case StaticDataMember: if (!CurContext->isDependentContext()) { ManglingNumber = 0; ContextDecl = 0; break; } // Fall through to assign a mangling number. case DataMember: case DefaultArgument: ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() .getManglingNumber(CallOperator); break; } } LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, Body->getLocEnd(), *ManglingNumber, ContextDecl); // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand // (Clause 5). if (!CurContext->isDependentContext()) { switch (ExprEvalContexts.back().Context) { case Unevaluated: // We don't actually diagnose this case immediately, because we // could be within a context where we might find out later that // the expression is potentially evaluated (e.g., for typeid). ExprEvalContexts.back().Lambdas.push_back(Lambda); break; case ConstantEvaluated: case PotentiallyEvaluated: case PotentiallyEvaluatedIfUsed: break; } } return MaybeBindToTemporary(Lambda); }