void ReturnSynthesizer::Transform() { if (!getTransaction()->getCompilationOpts().ResultEvaluation) return; FunctionDecl* FD = getTransaction()->getWrapperFD(); int foundAtPos = -1; Expr* lastExpr = utils::Analyze::GetOrCreateLastExpr(FD, &foundAtPos, /*omitDS*/false, m_Sema); if (lastExpr) { QualType RetTy = lastExpr->getType(); if (!RetTy->isVoidType() && RetTy.isTriviallyCopyableType(*m_Context)) { // Change the void function's return type // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, FD); FunctionProtoType::ExtProtoInfo EPI; QualType FnTy = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(), EPI); FD->setType(FnTy); CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); assert(CS && "Missing body?"); // Change it to a return stmt (Avoid dealloc/alloc of all el.) *(CS->body_begin() + foundAtPos) = m_Sema->ActOnReturnStmt(lastExpr->getExprLoc(), lastExpr).take(); } } else if (foundAtPos >= 0) { // check for non-void return statement CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); Stmt* CSS = *(CS->body_begin() + foundAtPos); if (ReturnStmt* RS = dyn_cast<ReturnStmt>(CSS)) { if (Expr* RetV = RS->getRetValue()) { QualType RetTy = RetV->getType(); // Any return statement will have been "healed" by Sema // to correspond to the original void return type of the // wrapper, using a ImplicitCastExpr 'void' <ToVoid>. // Remove that. if (RetTy->isVoidType()) { ImplicitCastExpr* VoidCast = dyn_cast<ImplicitCastExpr>(RetV); if (VoidCast) { RS->setRetValue(VoidCast->getSubExpr()); RetTy = VoidCast->getSubExpr()->getType(); } } if (!RetTy->isVoidType() && RetTy.isTriviallyCopyableType(*m_Context)) { Sema::ContextRAII pushedDC(*m_Sema, FD); FunctionProtoType::ExtProtoInfo EPI; QualType FnTy = m_Context->getFunctionType(RetTy, llvm::ArrayRef<QualType>(), EPI); FD->setType(FnTy); } // not returning void } // have return value } // is a return statement } // have a statement }
Stmt *TransformVector::VisitDoStmt(DoStmt *Node) { // Body Stmt *Body = Node->getBody(); CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); if (!CS) { // Convert a single stmt Body into a compound stmt. SourceLocation loc; CS = new (ASTCtx) CompoundStmt(ASTCtx, &Body, 1, loc, loc); } Node->setBody(TransformStmt(CS)); // Cond Expr *Cond = Node->getCond(); if (Cond->getType()->isVectorType()) { DeclVector DeclVec; Node->setCond(ConvertVecLiteralInExpr(DeclVec, Cond)); if (DeclVec.size() > 0) { CS = dyn_cast<CompoundStmt>(Node->getBody()); StmtVector StmtVec; CompoundStmt::body_iterator I, E; for (I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { StmtVec.push_back(*I); } PushBackDeclStmts(StmtVec, DeclVec); CS->setStmts(ASTCtx, StmtVec.data(), StmtVec.size()); } } else { Node->setCond(TransformExpr(Cond)); } return Node; }
bool VisitSwitchStmt(SwitchStmt *switchStmt) { CompoundStmt *compoundStmt = dyn_cast_or_null<CompoundStmt>(switchStmt->getBody()); if (compoundStmt) { bool breakFound = true; for (CompoundStmt::body_iterator body = compoundStmt->body_begin(), bodyEnd = compoundStmt->body_end(); body != bodyEnd; body++) { Stmt *bodyStmt = dyn_cast<Stmt>(*body); if (isBreakingPoint(bodyStmt)) { breakFound = true; continue; } if (isSwitchCase(bodyStmt)) { if (!breakFound) { addViolation(switchStmt, this); break; } FindingBreak findingBreak; breakFound = findingBreak.findBreak(dyn_cast<SwitchCase>(bodyStmt)); } } if (!breakFound) { addViolation(switchStmt, this); } } return true; }
void UnreachableCodeRule::apply( CXCursor& node, CXCursor& parentNode, ViolationSet& violationSet) { Stmt *stmt = CursorHelper::getStmt(node); if (stmt) { CompoundStmt *compoundStmt = dyn_cast<CompoundStmt>(stmt); if (compoundStmt) { bool hasBreakPoint = false; for (CompoundStmt::body_iterator body = compoundStmt->body_begin(), bodyEnd = compoundStmt->body_end(); body != bodyEnd; body++) { if (hasBreakPoint) { Violation violation(node, this); violationSet.addViolation(violation); return; } else { Stmt *bodyStmt = (Stmt *)*body; hasBreakPoint = isBreakPoint(bodyStmt, parentNode); } } } } }
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true, /// this captures the expression result of the last sub-statement and returns it /// (for use by the statement expression extension). RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, llvm::Value *AggLoc, bool isAggVol) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(), "LLVM IR generation of compound statement ('{}')"); CGDebugInfo *DI = getDebugInfo(); if (DI) { EnsureInsertPoint(); DI->setLocation(S.getLBracLoc()); // FIXME: The llvm backend is currently not ready to deal with region_end // for block scoping. In the presence of always_inline functions it gets so // confused that it doesn't emit any debug info. Just disable this for now. //DI->EmitRegionStart(CurFn, Builder); } // Keep track of the current cleanup stack depth. size_t CleanupStackDepth = CleanupEntries.size(); bool OldDidCallStackSave = DidCallStackSave; DidCallStackSave = false; for (CompoundStmt::const_body_iterator I = S.body_begin(), E = S.body_end()-GetLast; I != E; ++I) EmitStmt(*I); if (DI) { EnsureInsertPoint(); DI->setLocation(S.getRBracLoc()); // FIXME: The llvm backend is currently not ready to deal with region_end // for block scoping. In the presence of always_inline functions it gets so // confused that it doesn't emit any debug info. Just disable this for now. //DI->EmitRegionEnd(CurFn, Builder); } RValue RV; if (!GetLast) RV = RValue::get(0); else { // We have to special case labels here. They are statements, but when put // at the end of a statement expression, they yield the value of their // subexpression. Handle this by walking through all labels we encounter, // emitting them before we evaluate the subexpr. const Stmt *LastStmt = S.body_back(); while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) { EmitLabel(*LS); LastStmt = LS->getSubStmt(); } EnsureInsertPoint(); RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); } DidCallStackSave = OldDidCallStackSave; EmitCleanupBlocks(CleanupStackDepth); return RV; }
bool RNFStatementVisitor::VisitStmtExpr(StmtExpr *SE) { CompoundStmt *CS = SE->getSubStmt(); if (ConsumerInstance->CallExprQueue.empty()) { TraverseStmt(CS); return false; } CallExpr *CallE = ConsumerInstance->CallExprQueue.back(); CurrentStmt = CallE; for (clang::CompoundStmt::body_iterator I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { TraverseStmt(*I); } return false; }
int NPathComplexityMetric::nPath(SwitchStmt *stmt) { int internalNPath = 0, nPathSwitchStmt = nPath(stmt->getCond()); CompoundStmt *body = (CompoundStmt *)stmt->getBody(); for (CompoundStmt::body_iterator bodyStmt = body->body_begin(), bodyStmtEnd = body->body_end(); bodyStmt != bodyStmtEnd; bodyStmt++) { if (isa<SwitchCase>(*bodyStmt)) { SwitchCase *switchCase = dyn_cast<SwitchCase>(*bodyStmt); nPathSwitchStmt += internalNPath; internalNPath = nPath(switchCase->getSubStmt()); } else { internalNPath *= nPath(*bodyStmt); } } return nPathSwitchStmt + internalNPath; }
void ValueExtractionSynthesizer::Transform() { const CompilationOptions& CO = getTransaction()->getCompilationOpts(); // If we do not evaluate the result, or printing out the result return. if (!(CO.ResultEvaluation || CO.ValuePrinting)) return; FunctionDecl* FD = getTransaction()->getWrapperFD(); int foundAtPos = -1; Expr* lastExpr = utils::Analyze::GetOrCreateLastExpr(FD, &foundAtPos, /*omitDS*/false, m_Sema); if (foundAtPos < 0) return; typedef llvm::SmallVector<Stmt**, 4> StmtIters; StmtIters returnStmts; ReturnStmtCollector collector(returnStmts); CompoundStmt* CS = cast<CompoundStmt>(FD->getBody()); collector.VisitStmt(CS); if (isa<Expr>(*(CS->body_begin() + foundAtPos))) returnStmts.push_back(CS->body_begin() + foundAtPos); // We want to support cases such as: // gCling->evaluate("if() return 'A' else return 12", V), that puts in V, // either A or 12. // In this case the void wrapper is compiled with the stmts returning // values. Sema would cast them to void, but the code will still be // executed. For example: // int g(); void f () { return g(); } will still call g(). // for (StmtIters::iterator I = returnStmts.begin(), E = returnStmts.end(); I != E; ++I) { ReturnStmt* RS = dyn_cast<ReturnStmt>(**I); if (RS) { // When we are handling a return stmt, the last expression must be the // return stmt value. Ignore the calculation of the lastStmt because it // might be wrong, in cases where the return is not in the end of the // function. lastExpr = RS->getRetValue(); if (lastExpr) { assert (lastExpr->getType()->isVoidType() && "Must be void type."); // Any return statement will have been "healed" by Sema // to correspond to the original void return type of the // wrapper, using a ImplicitCastExpr 'void' <ToVoid>. // Remove that. if (ImplicitCastExpr* VoidCast = dyn_cast<ImplicitCastExpr>(lastExpr)) { lastExpr = VoidCast->getSubExpr(); } } // if no value assume void else { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, FD); RS->setRetValue(SynthesizeSVRInit(0)); } } else lastExpr = cast<Expr>(**I); if (lastExpr) { QualType lastExprTy = lastExpr->getType(); // May happen on auto types which resolve to dependent. if (lastExprTy->isDependentType()) continue; // Set up lastExpr properly. // Change the void function's return type // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, FD); if (lastExprTy->isFunctionType()) { // A return type of function needs to be converted to // pointer to function. lastExprTy = m_Context->getPointerType(lastExprTy); lastExpr = m_Sema->ImpCastExprToType(lastExpr, lastExprTy, CK_FunctionToPointerDecay, VK_RValue).take(); } // // Here we don't want to depend on the JIT runFunction, because of its // limitations, when it comes to return value handling. There it is // not clear who provides the storage and who cleans it up in a // platform independent way. // // Depending on the type we need to synthesize a call to cling: // 0) void : set the value's type to void; // 1) enum, integral, float, double, referece, pointer types : // call to cling::internal::setValueNoAlloc(...); // 2) object type (alloc on the stack) : // cling::internal::setValueWithAlloc // 2.1) constant arrays: // call to cling::runtime::internal::copyArray(...) // // We need to synthesize later: // Wrapper has signature: void w(cling::Value SVR) // case 1): // setValueNoAlloc(gCling, &SVR, lastExprTy, lastExpr()) // case 2): // new (setValueWithAlloc(gCling, &SVR, lastExprTy)) (lastExpr) // case 2.1): // copyArray(src, placement, size) Expr* SVRInit = SynthesizeSVRInit(lastExpr); // if we had return stmt update to execute the SVR init, even if the // wrapper returns void. if (RS) { if (ImplicitCastExpr* VoidCast = dyn_cast<ImplicitCastExpr>(RS->getRetValue())) VoidCast->setSubExpr(SVRInit); } else **I = SVRInit; } } }
bool DeclExtractor::ExtractDecl(FunctionDecl* FD) { llvm::SmallVector<NamedDecl*, 4> TouchedDecls; CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody()); assert(CS && "Function body not a CompoundStmt?"); DeclContext* DC = FD->getTranslationUnitDecl(); Scope* TUScope = m_Sema->TUScope; assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?"); llvm::SmallVector<Stmt*, 4> Stmts; for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end(); I != EI; ++I) { DeclStmt* DS = dyn_cast<DeclStmt>(*I); if (!DS) { Stmts.push_back(*I); continue; } for (DeclStmt::decl_iterator J = DS->decl_begin(); J != DS->decl_end(); ++J) { NamedDecl* ND = dyn_cast<NamedDecl>(*J); if (isa<UsingDirectiveDecl>(*J)) continue; // FIXME: Here we should be more elegant. if (ND) { if (Stmts.size()) { // We need to emit a new custom wrapper wrapping the stmts EnforceInitOrder(Stmts); assert(!Stmts.size() && "Stmt list must be flushed."); } // We know the transaction is closed, but it is safe. getTransaction()->forceAppend(ND); DeclContext* OldDC = ND->getDeclContext(); // Make sure the decl is not found at its old possition ND->getLexicalDeclContext()->removeDecl(ND); if (Scope* S = m_Sema->getScopeForContext(OldDC)) { S->RemoveDecl(ND); if (utils::Analyze::isOnScopeChains(ND, *m_Sema)) m_Sema->IdResolver.RemoveDecl(ND); } // For variable definitions causing var/function ambiguity such as: // MyClass my();, C++ standard says it shall be resolved as a function // // In the particular context this definition is inside a function // already, but clang thinks it as a lambda, so we need to ignore the // check decl context vs lexical decl context. if (ND->getDeclContext() == ND->getLexicalDeclContext() || isa<FunctionDecl>(ND)) ND->setLexicalDeclContext(DC); else assert(0 && "Not implemented: Decl with different lexical context"); ND->setDeclContext(DC); if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { VD->setStorageClass(SC_None); } clearLinkage(ND); TouchedDecls.push_back(ND); } } } bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope); if (hasNoErrors) { for (size_t i = 0; i < TouchedDecls.size(); ++i) { // We should skip the checks for annonymous decls and we should not // register them in the lookup. if (!TouchedDecls[i]->getDeclName()) continue; m_Sema->PushOnScopeChains(TouchedDecls[i], m_Sema->getScopeForContext(DC), /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i])); // The transparent DeclContexts (eg. scopeless enum) doesn't have // scopes. While extracting their contents we need to update the // lookup tables and telling them to pick up the new possitions // in the AST. if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) { if (InnerDC->isTransparentContext()) { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, InnerDC); for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), DE = InnerDC->decls_end(); DI != DE ; ++DI) { if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI)) InnerDC->makeDeclVisibleInContext(ND); } } } } } CS->setStmts(*m_Context, Stmts.data(), Stmts.size()); // The order matters, because when we extract decls from the wrapper we // append them to the transaction. If the transaction gets unloaded it will // introduce a fake dependency, so put the move last. Transaction* T = getTransaction(); for (Transaction::iterator I = T->decls_begin(), E = T->decls_end(); I != E; ++I) if (!I->m_DGR.isNull() && I->m_DGR.isSingleDecl() && I->m_DGR.getSingleDecl() == T->getWrapperFD()) { T->erase(I); break; } T->forceAppend(FD); // Put the wrapper after its declarations. (Nice when AST dumping) DC->removeDecl(FD); DC->addDecl(FD); return hasNoErrors; }
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; }
Stmt *TransformVector::VisitSwitchStmt(SwitchStmt *Node) { DeclVector DeclVec; // Cond Expr *Cond = Node->getCond(); if (Cond->getType()->isVectorType()) { Node->setCond(ConvertVecLiteralInExpr(DeclVec, Cond)); } else { Node->setCond(TransformExpr(Cond)); } // Body Stmt *Body = Node->getBody(); CompoundStmt *CS = dyn_cast<CompoundStmt>(Body); if (!CS) { // Convert a single stmt body into a CompoundStmt. SourceLocation loc; CS = new (ASTCtx) CompoundStmt(ASTCtx, &Body, 1, loc, loc); } // Check all SwitchCase stmts themselves. SwitchCase *CurCase = Node->getSwitchCaseList(); while (CurCase) { if (CaseStmt *CaseS = dyn_cast<CaseStmt>(CurCase)) { Expr *CaseLHS = CaseS->getLHS(); if (CaseLHS->getType()->isVectorType()) { CaseS->setLHS(ConvertVecLiteralInExpr(DeclVec, CaseLHS)); } else { CaseS->setLHS(TransformExpr(CaseLHS)); } Expr *CaseRHS = CaseS->getRHS(); if (CaseRHS && CaseRHS->getType()->isVectorType()) { CaseS->setRHS(ConvertVecLiteralInExpr(DeclVec, CaseRHS)); } else { CaseS->setRHS(TransformExpr(CaseRHS)); } } CurCase = CurCase->getNextSwitchCase(); } // Check if there was a vector literal code motion. if (DeclVec.size() > 0) { PushBackDeclStmts(*CurStmtVec, DeclVec); } // If case stmts are not CompoundStmts, convert them into CompoundStmts StmtVector BodyStmts; CompoundStmt::body_iterator I, E; for (I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { // Save the current stmt BodyStmts.push_back(*I); if (SwitchCase *SC = dyn_cast<SwitchCase>(*I)) { CompoundStmt::body_iterator NextI = I + 1; if (NextI == E) break; if (isa<SwitchCase>(*NextI)) { // No stmt between current case stmt and next case stmt. if (Stmt *SubStmt = SC->getSubStmt()) { if (!isa<CompoundStmt>(SubStmt)) { SourceLocation loc; CompoundStmt *SubCS = new (ASTCtx) CompoundStmt(ASTCtx, &SubStmt, 1, loc, loc); if (CaseStmt *CaseS = dyn_cast<CaseStmt>(SC)) { CaseS->setSubStmt(SubCS); } else if (DefaultStmt *DefaultS = dyn_cast<DefaultStmt>(SC)) { DefaultS->setSubStmt(SubCS); } else { assert(0 && "What statement?"); } } } } else { StmtVector StmtVec; // SubStmt if (Stmt *SubStmt = SC->getSubStmt()) { StmtVec.push_back(SubStmt); } // Following stmts do { I = NextI; StmtVec.push_back(*I); } while ((++NextI != E) && !isa<SwitchCase>(*NextI)); // Convert all stmts into a CompoundStmt. SourceLocation loc; CompoundStmt *SubCS = new (ASTCtx) CompoundStmt(ASTCtx, StmtVec.data(), StmtVec.size(), loc, loc); if (CaseStmt *CaseS = dyn_cast<CaseStmt>(SC)) { CaseS->setSubStmt(SubCS); } else if (DefaultStmt *DefaultS = dyn_cast<DefaultStmt>(SC)) { DefaultS->setSubStmt(SubCS); } else { assert(0 && "What statement?"); } } } //end if } //end for CS = new (ASTCtx) CompoundStmt(ASTCtx, BodyStmts.data(), BodyStmts.size(), SourceLocation(), SourceLocation()); ASTCtx.Deallocate(Node->getBody()); Node->setBody(TransformStmt(CS)); return Node; }
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); }
bool DeclExtractor::ExtractDecl(Decl* D) { FunctionDecl* FD = dyn_cast<FunctionDecl>(D); if (FD) { if (FD->getNameAsString().find("__cling_Un1Qu3")) return true; llvm::SmallVector<NamedDecl*, 4> TouchedDecls; CompoundStmt* CS = dyn_cast<CompoundStmt>(FD->getBody()); assert(CS && "Function body not a CompoundStmt?"); DeclContext* DC = FD->getTranslationUnitDecl(); Scope* TUScope = m_Sema->TUScope; assert(TUScope == m_Sema->getScopeForContext(DC) && "TU scope from DC?"); llvm::SmallVector<Stmt*, 4> Stmts; for (CompoundStmt::body_iterator I = CS->body_begin(), EI = CS->body_end(); I != EI; ++I) { DeclStmt* DS = dyn_cast<DeclStmt>(*I); if (!DS) { Stmts.push_back(*I); continue; } for (DeclStmt::decl_iterator J = DS->decl_begin(); J != DS->decl_end(); ++J) { NamedDecl* ND = dyn_cast<NamedDecl>(*J); if (ND) { DeclContext* OldDC = ND->getDeclContext(); // Make sure the decl is not found at its old possition OldDC->removeDecl(ND); if (Scope* S = m_Sema->getScopeForContext(OldDC)) { S->RemoveDecl(ND); m_Sema->IdResolver.RemoveDecl(ND); } if (ND->getDeclContext() == ND->getLexicalDeclContext()) ND->setLexicalDeclContext(DC); else assert("Not implemented: Decl with different lexical context"); ND->setDeclContext(DC); if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { VD->setStorageClass(SC_None); VD->setStorageClassAsWritten(SC_None); // if we want to print the result of the initializer of int i = 5 // or the default initializer int i if (I+1 == EI || !isa<NullStmt>(*(I+1))) { QualType VDTy = VD->getType().getNonReferenceType(); Expr* DRE = m_Sema->BuildDeclRefExpr(VD, VDTy,VK_LValue, SourceLocation() ).take(); Stmts.push_back(DRE); } } // force recalc of the linkage (to external) ND->ClearLinkageCache(); TouchedDecls.push_back(ND); } } } bool hasNoErrors = !CheckForClashingNames(TouchedDecls, DC, TUScope); if (hasNoErrors) { for (size_t i = 0; i < TouchedDecls.size(); ++i) { m_Sema->PushOnScopeChains(TouchedDecls[i], m_Sema->getScopeForContext(DC), /*AddCurContext*/!isa<UsingDirectiveDecl>(TouchedDecls[i])); // The transparent DeclContexts (eg. scopeless enum) doesn't have // scopes. While extracting their contents we need to update the // lookup tables and telling them to pick up the new possitions // in the AST. if (DeclContext* InnerDC = dyn_cast<DeclContext>(TouchedDecls[i])) { if (InnerDC->isTransparentContext()) { // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushedDC(*m_Sema, InnerDC); for(DeclContext::decl_iterator DI = InnerDC->decls_begin(), DE = InnerDC->decls_end(); DI != DE ; ++DI) { if (NamedDecl* ND = dyn_cast<NamedDecl>(*DI)) InnerDC->makeDeclVisibleInContext(ND); } } } // Append the new top level decl to the current transaction. getTransaction()->appendUnique(DeclGroupRef(TouchedDecls[i])); } } CS->setStmts(*m_Context, Stmts.data(), Stmts.size()); // Put the wrapper after its declarations. (Nice when AST dumping) DC->removeDecl(FD); DC->addDecl(FD); return hasNoErrors; } return true; }