StmtResult Parser::HandlePragmaCaptured() { assert(Tok.is(tok::annot_pragma_captured)); ConsumeToken(); if (Tok.isNot(tok::l_brace)) { PP.Diag(Tok, diag::err_expected_lbrace); return StmtError(); } SourceLocation Loc = Tok.getLocation(); ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope); Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default); StmtResult R = ParseCompoundStatement(); CapturedRegionScope.Exit(); if (R.isInvalid()) { Actions.ActOnCapturedRegionError(); return StmtError(); } return Actions.ActOnCapturedRegionEnd(R.get()); }
int main(int argc, char **argv) { static const char *src = "a = 3\n" "b = 4\n" "c = a + b\n"; MemoryManager manager; Lexer lexer(src); Parser parser(manager, lexer); StmtResult result = parser.parseStatement(); if (result.hasError()) { std::cout << result.error() << std::endl; return 1; } //FunctionTranslator xlator(static_cast<const Ast::FnDeclStmt &>(*result.value())); // Program program(manager); // VirtualMachine virtualMachine(program); // virtualMachine.run(View<const char *>(argv, argv + argc)); #ifdef SNW_OS_WIN32 std::system("pause"); #endif return 0; }
bool VisitCompoundStmt(CompoundStmt* CS) { for(CompoundStmt::body_iterator I = CS->body_begin(), E = CS->body_end(); I != E; ++I) { if (!isa<BinaryOperator>(*I)) continue; const BinaryOperator* BinOp = cast<BinaryOperator>(*I); if (isAutoCandidate(BinOp)) { ASTContext& C = m_Sema->getASTContext(); VarDecl* VD = cast<VarDecl>(cast<DeclRefExpr>(BinOp->getLHS())->getDecl()); TypeSourceInfo* ResTSI = 0; TypeSourceInfo* TrivialTSI = C.getTrivialTypeSourceInfo(VD->getType()); Expr* RHS = BinOp->getRHS(); m_Sema->DeduceAutoType(TrivialTSI, RHS, ResTSI); VD->setTypeSourceInfo(ResTSI); VD->setType(ResTSI->getType()); VD->setInit(RHS); Sema::DeclGroupPtrTy VDPtrTy = m_Sema->ConvertDeclToDeclGroup(VD); // Transform the AST into a "sane" state. Replace the binary operator // with decl stmt, because the binop semantically is a decl with init. StmtResult DS = m_Sema->ActOnDeclStmt(VDPtrTy, BinOp->getLocStart(), BinOp->getLocEnd()); assert(!DS.isInvalid() && "Invalid DeclStmt."); *I = DS.take(); } } return true; // returning false will abort the in-depth traversal. }
StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) { auto *Context = checkCoroutineContext(*this, Loc, "co_return"); StmtResult Res = StmtError(); if (Context && !Res.isInvalid()) Context->CoroutineStmts.push_back(Res.get()); return Res; }
C2::StmtResult C2Sema::ActOnIfStmt(SourceLocation ifLoc, Stmt* condition, StmtResult thenStmt, SourceLocation elseLoc, StmtResult elseStmt) { #ifdef SEMA_DEBUG std::cerr << COL_SEMA"SEMA: if statement at "; ifLoc.dump(SourceMgr); std::cerr << ANSI_NORMAL"\n"; #endif return StmtResult(new IfStmt(ifLoc, condition, thenStmt.get(), elseLoc, elseStmt.get())); }
bool CoroutineStmtBuilder::makePromiseStmt() { // Form a declaration statement for the promise declaration, so that AST // visitors can more easily find it. StmtResult PromiseStmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(Fn.CoroutinePromise), Loc, Loc); if (PromiseStmt.isInvalid()) return false; this->Promise = PromiseStmt.get(); return true; }
/// ParseMainProgram - Parse the main program. /// /// [R1101]: /// main-program := /// [program-stmt] /// [specification-part] /// [execution-part] /// [internal-subprogram-part] /// end-program-stmt bool Parser::ParseMainProgram(std::vector<StmtResult> &Body) { // If the PROGRAM statement didn't have an identifier, pretend like it did for // the time being. StmtResult ProgStmt; if (Tok.is(tok::kw_PROGRAM)) { ProgStmt = ParsePROGRAMStmt(); Body.push_back(ProgStmt); } // If the PROGRAM statement has an identifier, pass it on to the main program // action. const IdentifierInfo *IDInfo = 0; SMLoc NameLoc; if (ProgStmt.isUsable()) { ProgramStmt *PS = ProgStmt.takeAs<ProgramStmt>(); IDInfo = PS->getProgramName(); NameLoc = PS->getNameLocation(); // FIXME: Debugging dump(PS); } Actions.ActOnMainProgram(IDInfo, NameLoc); // FIXME: Check for the specific keywords and not just absence of END or // ENDPROGRAM. ParseStatementLabel(); if (Tok.isNot(tok::kw_END) && Tok.isNot(tok::kw_ENDPROGRAM)) ParseSpecificationPart(Body); // FIXME: Check for the specific keywords and not just absence of END or // ENDPROGRAM. ParseStatementLabel(); if (Tok.isNot(tok::kw_END) && Tok.isNot(tok::kw_ENDPROGRAM)) ParseExecutionPart(Body); // FIXME: Debugging support. dump(Body); ParseStatementLabel(); StmtResult EndProgStmt = ParseEND_PROGRAMStmt(); Body.push_back(EndProgStmt); IDInfo = 0; NameLoc = SMLoc(); if (EndProgStmt.isUsable()) { EndProgramStmt *EPS = EndProgStmt.takeAs<EndProgramStmt>(); IDInfo = EPS->getProgramName(); NameLoc = EPS->getNameLocation(); } Actions.ActOnEndMainProgram(IDInfo, NameLoc); return EndProgStmt.isInvalid(); }
/// ParseExecutableConstruct - Parse the executable construct. /// /// [R213]: /// executable-construct := /// action-stmt /// or associate-construct /// or block-construct /// or case-construct /// or critical-construct /// or do-construct /// or forall-construct /// or if-construct /// or select-type-construct /// or where-construct StmtResult Parser::ParseExecutableConstruct() { ParseStatementLabel(); ParseConstructNameLabel(); LookForExecutableStmtKeyword(StmtLabel || StmtConstructName.isUsable()? false : true); auto Loc = Tok.getLocation(); StmtResult SR = ParseActionStmt(); CheckStmtOrder(Loc, SR); if (SR.isInvalid()) return StmtError(); if (!SR.isUsable()) return StmtResult(); return SR; }
bool CoroutineStmtBuilder::makeOnFallthrough() { assert(!IsPromiseDependentType && "cannot make statement while the promise type is dependent"); // [dcl.fct.def.coroutine]/4 // The unqualified-ids 'return_void' and 'return_value' are looked up in // the scope of class P. If both are found, the program is ill-formed. bool HasRVoid, HasRValue; LookupResult LRVoid = lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid); LookupResult LRValue = lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue); StmtResult Fallthrough; if (HasRVoid && HasRValue) { // FIXME Improve this diagnostic S.Diag(FD.getLocation(), diag::err_coroutine_promise_incompatible_return_functions) << PromiseRecordDecl; S.Diag(LRVoid.getRepresentativeDecl()->getLocation(), diag::note_member_first_declared_here) << LRVoid.getLookupName(); S.Diag(LRValue.getRepresentativeDecl()->getLocation(), diag::note_member_first_declared_here) << LRValue.getLookupName(); return false; } else if (!HasRVoid && !HasRValue) { // FIXME: The PDTS currently specifies this case as UB, not ill-formed. // However we still diagnose this as an error since until the PDTS is fixed. S.Diag(FD.getLocation(), diag::err_coroutine_promise_requires_return_function) << PromiseRecordDecl; S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here) << PromiseRecordDecl; return false; } else if (HasRVoid) { // If the unqualified-id return_void is found, flowing off the end of a // coroutine is equivalent to a co_return with no operand. Otherwise, // flowing off the end of a coroutine results in undefined behavior. Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr, /*IsImplicit*/false); Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get()); if (Fallthrough.isInvalid()) return false; } this->OnFallthrough = Fallthrough.get(); return true; }
/// ParseExecutionPart - Parse the execution part. /// /// [R208]: /// execution-part := /// executable-construct /// [ execution-part-construct ] ... bool Parser::ParseExecutionPart(std::vector<StmtResult> &Body) { bool HadError = false; while (true) { StmtResult SR = ParseExecutableConstruct(); if (SR.isInvalid()) { LexToEndOfStatement(); HadError = true; } else if (!SR.isUsable()) { break; } Body.push_back(SR); } return HadError; }
/// ParseImplicitPartList - Parse a (possibly empty) list of implicit part /// statements. bool Parser::ParseImplicitPartList(std::vector<StmtResult> &Body) { bool HasErrors = false; while (true) { StmtResult S = ParseImplicitPart(); if (S.isUsable()) { Body.push_back(S); } else if (S.isInvalid()) { LexToEndOfStatement(); HasErrors = true; } else { break; } } return HasErrors; }
C2::StmtResult C2Sema::ActOnDoStmt(SourceLocation loc, ExprResult Cond, StmtResult Then) { #ifdef SEMA_DEBUG std::cerr << COL_SEMA"SEMA: do statement at "; loc.dump(SourceMgr); std::cerr << ANSI_NORMAL"\n"; #endif return StmtResult(new DoStmt(loc, Cond.get(), Then.get())); }
bool CoroutineStmtBuilder::makeReturnOnAllocFailure() { assert(!IsPromiseDependentType && "cannot make statement while the promise type is dependent"); // [dcl.fct.def.coroutine]/8 // The unqualified-id get_return_object_on_allocation_failure is looked up in // the scope of class P by class member access lookup (3.4.5). ... // If an allocation function returns nullptr, ... the coroutine return value // is obtained by a call to ... get_return_object_on_allocation_failure(). DeclarationName DN = S.PP.getIdentifierInfo("get_return_object_on_allocation_failure"); LookupResult Found(S, DN, Loc, Sema::LookupMemberName); if (!S.LookupQualifiedName(Found, PromiseRecordDecl)) return true; CXXScopeSpec SS; ExprResult DeclNameExpr = S.BuildDeclarationNameExpr(SS, Found, /*NeedsADL=*/false); if (DeclNameExpr.isInvalid()) return false; if (!diagReturnOnAllocFailure(S, DeclNameExpr.get(), PromiseRecordDecl, Fn)) return false; ExprResult ReturnObjectOnAllocationFailure = S.ActOnCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc); if (ReturnObjectOnAllocationFailure.isInvalid()) return false; StmtResult ReturnStmt = S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get()); if (ReturnStmt.isInvalid()) { S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here) << DN; S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here) << Fn.getFirstCoroutineStmtKeyword(); return false; } this->ReturnStmtOnAllocFailure = ReturnStmt.get(); return true; }
void Parser::CheckStmtOrder(SourceLocation Loc, StmtResult SR) { auto S = SR.get(); if(SR.isUsable()) { if(Actions.InsideWhereConstruct(S)) Actions.CheckValidWhereStmtPart(S); } if(PrevStmtWasSelectCase) { PrevStmtWasSelectCase = false; if(SR.isUsable() && (isa<SelectionCase>(S) || (isa<ConstructPartStmt>(S) && cast<ConstructPartStmt>(S)->getConstructStmtClass() == ConstructPartStmt::EndSelectStmtClass))) return; Diag.Report(SR.isUsable()? S->getLocation() : Loc, diag::err_expected_case_or_end_select); } if(SR.isUsable() && isa<SelectCaseStmt>(S)) PrevStmtWasSelectCase = true; }
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()); }
bool CoroutineStmtBuilder::makeParamMoves() { for (auto *paramDecl : FD.parameters()) { auto Ty = paramDecl->getType(); if (Ty->isDependentType()) continue; // No need to copy scalars, llvm will take care of them. if (Ty->getAsCXXRecordDecl()) { if (!paramDecl->getIdentifier()) continue; ExprResult ParamRef = S.BuildDeclRefExpr(paramDecl, paramDecl->getType(), ExprValueKind::VK_LValue, Loc); // FIXME: scope? if (ParamRef.isInvalid()) return false; Expr *RCast = castForMoving(S, ParamRef.get()); auto D = buildVarDecl(S, Loc, Ty, paramDecl->getIdentifier()->getName()); S.AddInitializerToDecl(D, RCast, /*DirectInit=*/true); // Convert decl to a statement. StmtResult Stmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(D), Loc, Loc); if (Stmt.isInvalid()) return false; ParamMovesVector.push_back(Stmt.get()); } } // Convert to ArrayRef in CtorArgs structure that builder inherits from. ParamMoves = ParamMovesVector; return true; }
static bool actOnCoroutineBodyStart(Sema &S, Scope *SC, SourceLocation KWLoc, StringRef Keyword) { if (!checkCoroutineContext(S, KWLoc, Keyword)) return false; auto *ScopeInfo = S.getCurFunction(); assert(ScopeInfo->CoroutinePromise); // If we have existing coroutine statements then we have already built // the initial and final suspend points. if (!ScopeInfo->NeedsCoroutineSuspends) return true; ScopeInfo->setNeedsCoroutineSuspends(false); auto *Fn = cast<FunctionDecl>(S.CurContext); SourceLocation Loc = Fn->getLocation(); // Build the initial suspend point auto buildSuspends = [&](StringRef Name) mutable -> StmtResult { ExprResult Suspend = buildPromiseCall(S, ScopeInfo->CoroutinePromise, Loc, Name, None); if (Suspend.isInvalid()) return StmtError(); Suspend = buildOperatorCoawaitCall(S, SC, Loc, Suspend.get()); if (Suspend.isInvalid()) return StmtError(); Suspend = S.BuildResolvedCoawaitExpr(Loc, Suspend.get(), /*IsImplicit*/ true); Suspend = S.ActOnFinishFullExpr(Suspend.get()); if (Suspend.isInvalid()) { S.Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); S.Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword; return StmtError(); } return cast<Stmt>(Suspend.get()); }; StmtResult InitSuspend = buildSuspends("initial_suspend"); if (InitSuspend.isInvalid()) return true; StmtResult FinalSuspend = buildSuspends("final_suspend"); if (FinalSuspend.isInvalid()) return true; ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get()); return true; }
/// ParseSpecificationPart - Parse the specification part. /// /// [R204]: /// specification-part := /// [use-stmt] ... /// [import-stmt] ... /// [implicit-part] ... /// [declaration-construct] ... bool Parser::ParseSpecificationPart(std::vector<StmtResult> &Body) { bool HasErrors = false; while (Tok.is(tok::kw_USE)) { StmtResult S = ParseUSEStmt(); if (S.isUsable()) { Body.push_back(S); } else if (S.isInvalid()) { LexToEndOfStatement(); HasErrors = true; } else { break; } ParseStatementLabel(); } while (Tok.is(tok::kw_IMPORT)) { StmtResult S = ParseIMPORTStmt(); if (S.isUsable()) { Body.push_back(S); } else if (S.isInvalid()) { LexToEndOfStatement(); HasErrors = true; } else { break; } ParseStatementLabel(); } if (ParseImplicitPartList(Body)) HasErrors = true; if (ParseDeclarationConstructList()) { LexToEndOfStatement(); HasErrors = true; } return HasErrors; }
/// ParseSAVEStmt - Parse the SAVE statement. /// /// [R543]: /// save-stmt := /// SAVE [ [::] saved-entity-list ] Parser::StmtResult Parser::ParseSAVEStmt() { // Check if this is an assignment. if (IsNextToken(tok::equal)) return StmtResult(); auto Loc = ConsumeToken(); if(Tok.isAtStartOfStatement()) return Actions.ActOnSAVE(Context, Loc, StmtLabel); bool IsSaveStmt = ConsumeIfPresent(tok::coloncolon); SmallVector<Stmt *,8> StmtList; bool ListParsedOk = true; auto IDLoc = Tok.getLocation(); auto II = Tok.getIdentifierInfo(); StmtResult Stmt; if(ConsumeIfPresent(tok::slash)) { IDLoc = Tok.getLocation(); II = Tok.getIdentifierInfo(); if(ExpectAndConsume(tok::identifier)) { if(!ExpectAndConsume(tok::slash)) ListParsedOk = false; Stmt = Actions.ActOnSAVECommonBlock(Context, Loc, IDLoc, II); } else ListParsedOk = false; } else if(ExpectAndConsume(tok::identifier)) { if(!IsSaveStmt && Features.FixedForm && (IsPresent(tok::equal) || IsPresent(tok::l_paren))) return ReparseAmbiguousAssignmentStatement(); Stmt = Actions.ActOnSAVE(Context, Loc, IDLoc, II, nullptr); } else ListParsedOk = false; if(Stmt.isUsable()) StmtList.push_back(Stmt.get()); if(ListParsedOk) { while(ConsumeIfPresent(tok::comma)) { IDLoc = Tok.getLocation(); II = Tok.getIdentifierInfo(); if(ConsumeIfPresent(tok::slash)) { IDLoc = Tok.getLocation(); II = Tok.getIdentifierInfo(); if(!ExpectAndConsume(tok::identifier)) { ListParsedOk = false; break; } if(!ExpectAndConsume(tok::slash)) { ListParsedOk = false; break; } Stmt = Actions.ActOnSAVECommonBlock(Context, Loc, IDLoc, II); } else if(ExpectAndConsume(tok::identifier)) Stmt = Actions.ActOnSAVE(Context, Loc, IDLoc, II, nullptr); else { ListParsedOk = false; break; } if(Stmt.isUsable()) StmtList.push_back(Stmt.get()); } } if(ListParsedOk) ExpectStatementEnd(); else SkipUntilNextStatement(); return Actions.ActOnCompoundStmt(Context, Loc, StmtList, StmtLabel); }
/// \brief Parsing of declarative or executable OpenMP directives. /// /// threadprivate-directive: /// annot_pragma_openmp 'threadprivate' simple-variable-list /// annot_pragma_openmp_end /// /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | /// 'barrier' | 'taskwait' | 'flush' {clause} annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector<Expr *, 5> Identifiers; SmallVector<OMPClause *, 5> Clauses; SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> FirstClauses(OMPC_unknown + 1); unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; SourceLocation Loc = ConsumeToken(), EndLoc; auto DKind = ParseOpenMPDirectiveKind(*this); // Name of critical directive. DeclarationNameInfo DirName; StmtResult Directive = StmtError(); bool HasAssociatedStatement = true; bool FlushHasClause = false; switch (DKind) { case OMPD_threadprivate: ConsumeToken(); if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { // The last seen token is annot_pragma_openmp_end - need to check for // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) << getOpenMPDirectiveName(OMPD_threadprivate); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); } SkipUntil(tok::annot_pragma_openmp_end); break; case OMPD_flush: if (PP.LookAhead(0).is(tok::l_paren)) { FlushHasClause = true; // Push copy of the current token back to stream to properly parse // pseudo-clause OMPFlushClause. PP.EnterToken(Tok); } case OMPD_taskyield: case OMPD_barrier: case OMPD_taskwait: if (!StandAloneAllowed) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind); } HasAssociatedStatement = false; // Fall through for further analysis. case OMPD_parallel: case OMPD_simd: case OMPD_for: case OMPD_sections: case OMPD_single: case OMPD_section: case OMPD_master: case OMPD_critical: case OMPD_parallel_for: case OMPD_parallel_sections: case OMPD_task: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (!T.consumeOpen()) { if (Tok.isAnyIdentifier()) { DirName = DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeAnyToken(); } else { Diag(Tok, diag::err_omp_expected_identifier_for_critical); } T.consumeClose(); } } if (isOpenMPLoopDirective(DKind)) ScopeFlags |= Scope::OpenMPLoopDirectiveScope; if (isOpenMPSimdDirective(DKind)) ScopeFlags |= Scope::OpenMPSimdDirectiveScope; ParseScope OMPDirectiveScope(this, ScopeFlags); Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); while (Tok.isNot(tok::annot_pragma_openmp_end)) { OpenMPClauseKind CKind = Tok.isAnnotation() ? OMPC_unknown : FlushHasClause ? OMPC_flush : getOpenMPClauseKind(PP.getSpelling(Tok)); FlushHasClause = false; OMPClause *Clause = ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); FirstClauses[CKind].setInt(true); if (Clause) { FirstClauses[CKind].setPointer(Clause); Clauses.push_back(Clause); } // Skip ',' if any. if (Tok.is(tok::comma)) ConsumeToken(); } // End location of the directive. EndLoc = Tok.getLocation(); // Consume final annot_pragma_openmp_end. ConsumeToken(); StmtResult AssociatedStmt; bool CreateDirective = true; if (HasAssociatedStatement) { // The body is a block scope like in Lambdas and Blocks. Sema::CompoundScopeRAII CompoundScope(Actions); Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); Actions.ActOnStartOfCompoundStmt(); // Parse statement AssociatedStmt = ParseStatement(); Actions.ActOnFinishOfCompoundStmt(); if (!AssociatedStmt.isUsable()) { Actions.ActOnCapturedRegionError(); CreateDirective = false; } else { AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get()); CreateDirective = AssociatedStmt.isUsable(); } } if (CreateDirective) Directive = Actions.ActOnOpenMPExecutableDirective( DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc); // Exit scope. Actions.EndOpenMPDSABlock(Directive.get()); OMPDirectiveScope.Exit(); break; } case OMPD_unknown: Diag(Tok, diag::err_omp_unknown_directive); SkipUntil(tok::annot_pragma_openmp_end); break; } return Directive; }
bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { assert(!IsPromiseDependentType && "cannot make statement while the promise type is dependent"); assert(this->ReturnValue && "ReturnValue must be already formed"); QualType const GroType = this->ReturnValue->getType(); assert(!GroType->isDependentType() && "get_return_object type must no longer be dependent"); QualType const FnRetType = FD.getReturnType(); assert(!FnRetType->isDependentType() && "get_return_object type must no longer be dependent"); if (FnRetType->isVoidType()) { ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc); if (Res.isInvalid()) return false; this->ResultDecl = Res.get(); return true; } if (GroType->isVoidType()) { // Trigger a nice error message. InitializedEntity Entity = InitializedEntity::InitializeResult(Loc, FnRetType, false); S.PerformMoveOrCopyInitialization(Entity, nullptr, FnRetType, ReturnValue); noteMemberDeclaredHere(S, ReturnValue, Fn); return false; } auto *GroDecl = VarDecl::Create( S.Context, &FD, FD.getLocation(), FD.getLocation(), &S.PP.getIdentifierTable().get("__coro_gro"), GroType, S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None); S.CheckVariableDeclarationType(GroDecl); if (GroDecl->isInvalidDecl()) return false; InitializedEntity Entity = InitializedEntity::InitializeVariable(GroDecl); ExprResult Res = S.PerformMoveOrCopyInitialization(Entity, nullptr, GroType, this->ReturnValue); if (Res.isInvalid()) return false; Res = S.ActOnFinishFullExpr(Res.get()); if (Res.isInvalid()) return false; if (GroType == FnRetType) { GroDecl->setNRVOVariable(true); } S.AddInitializerToDecl(GroDecl, Res.get(), /*DirectInit=*/false); S.FinalizeDeclaration(GroDecl); // Form a declaration statement for the return declaration, so that AST // visitors can more easily find it. StmtResult GroDeclStmt = S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc); if (GroDeclStmt.isInvalid()) return false; this->ResultDecl = GroDeclStmt.get(); ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc); if (declRef.isInvalid()) return false; StmtResult ReturnStmt = S.BuildReturnStmt(Loc, declRef.get()); if (ReturnStmt.isInvalid()) { noteMemberDeclaredHere(S, ReturnValue, Fn); return false; } this->ReturnStmt = ReturnStmt.get(); return true; }
/// \brief Parsing of declarative or executable OpenMP directives. /// /// threadprivate-directive: /// annot_pragma_openmp 'threadprivate' simple-variable-list /// annot_pragma_openmp_end /// /// parallel-directive: /// annot_pragma_openmp 'parallel' {clause} annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector<Expr *, 5> Identifiers; SmallVector<OMPClause *, 5> Clauses; SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, NUM_OPENMP_CLAUSES> FirstClauses(NUM_OPENMP_CLAUSES); const unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; SourceLocation Loc = ConsumeToken(), EndLoc; OpenMPDirectiveKind DKind = Tok.isAnnotation() ? OMPD_unknown : getOpenMPDirectiveKind(PP.getSpelling(Tok)); // Name of critical directive. DeclarationNameInfo DirName; StmtResult Directive = StmtError(); switch (DKind) { case OMPD_threadprivate: ConsumeToken(); if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { // The last seen token is annot_pragma_openmp_end - need to check for // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { Diag(Tok, diag::warn_omp_extra_tokens_at_eol) << getOpenMPDirectiveName(OMPD_threadprivate); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); } DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); } SkipUntil(tok::annot_pragma_openmp_end); break; case OMPD_parallel: { ConsumeToken(); Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope()); while (Tok.isNot(tok::annot_pragma_openmp_end)) { OpenMPClauseKind CKind = Tok.isAnnotation() ? OMPC_unknown : getOpenMPClauseKind(PP.getSpelling(Tok)); OMPClause *Clause = ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); FirstClauses[CKind].setInt(true); if (Clause) { FirstClauses[CKind].setPointer(Clause); Clauses.push_back(Clause); } // Skip ',' if any. if (Tok.is(tok::comma)) ConsumeToken(); } // End location of the directive. EndLoc = Tok.getLocation(); // Consume final annot_pragma_openmp_end. ConsumeToken(); StmtResult AssociatedStmt; bool CreateDirective = true; ParseScope OMPDirectiveScope(this, ScopeFlags); { // The body is a block scope like in Lambdas and Blocks. Sema::CompoundScopeRAII CompoundScope(Actions); Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_OpenMP, 1); Actions.ActOnStartOfCompoundStmt(); // Parse statement AssociatedStmt = ParseStatement(); Actions.ActOnFinishOfCompoundStmt(); if (!AssociatedStmt.isUsable()) { Actions.ActOnCapturedRegionError(); CreateDirective = false; } else { AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.take()); CreateDirective = AssociatedStmt.isUsable(); } } if (CreateDirective) Directive = Actions.ActOnOpenMPExecutableDirective(DKind, Clauses, AssociatedStmt.take(), Loc, EndLoc); // Exit scope. Actions.EndOpenMPDSABlock(Directive.get()); OMPDirectiveScope.Exit(); } break; case OMPD_unknown: Diag(Tok, diag::err_omp_unknown_directive); SkipUntil(tok::annot_pragma_openmp_end); break; case OMPD_task: case NUM_OPENMP_DIRECTIVES: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); SkipUntil(tok::annot_pragma_openmp_end); break; } return Directive; }
Stmt* SynthesizeCheck(SourceLocation Loc, Expr* Arg) { assert(Arg && "Cannot call with Arg=0"); ASTContext& Context = m_Sema.getASTContext(); //copied from DynamicLookup.cpp // Lookup Sema type CXXRecordDecl* SemaRD = dyn_cast<CXXRecordDecl>(utils::Lookup::Named(&m_Sema, "Sema", utils::Lookup::Namespace(&m_Sema, "clang"))); QualType SemaRDTy = Context.getTypeDeclType(SemaRD); Expr* VoidSemaArg = utils::Synthesize::CStyleCastPtrExpr(&m_Sema,SemaRDTy, (uint64_t)&m_Sema); // Lookup Expr type CXXRecordDecl* ExprRD = dyn_cast<CXXRecordDecl>(utils::Lookup::Named(&m_Sema, "Expr", utils::Lookup::Namespace(&m_Sema, "clang"))); QualType ExprRDTy = Context.getTypeDeclType(ExprRD); Expr* VoidExprArg = utils::Synthesize::CStyleCastPtrExpr(&m_Sema,ExprRDTy, (uint64_t)Arg); Expr *args[] = {VoidSemaArg, VoidExprArg}; Scope* S = m_Sema.getScopeForContext(m_Sema.CurContext); DeclarationName Name = &Context.Idents.get("cling__runtime__internal__throwNullDerefException"); SourceLocation noLoc; LookupResult R(m_Sema, Name, noLoc, Sema::LookupOrdinaryName, Sema::ForRedeclaration); m_Sema.LookupQualifiedName(R, Context.getTranslationUnitDecl()); assert(!R.empty() && "Cannot find valuePrinterInternal::Select(...)"); CXXScopeSpec CSS; Expr* UnresolvedLookup = m_Sema.BuildDeclarationNameExpr(CSS, R, /*ADL*/ false).take(); Expr* call = m_Sema.ActOnCallExpr(S, UnresolvedLookup, noLoc, args, noLoc).take(); // Check whether we can get the argument'value. If the argument is // null, throw an exception direclty. If the argument is not null // then ignore this argument and continue to deal with the next // argument with the nonnull attribute. bool Result = false; if (Arg->EvaluateAsBooleanCondition(Result, Context)) { if(!Result) { return call; } return Arg; } // The argument's value cannot be decided, so we add a UnaryOp // operation to check its value at runtime. ExprResult ER = m_Sema.ActOnUnaryOp(S, Loc, tok::exclaim, Arg); Decl* varDecl = 0; Stmt* varStmt = 0; Sema::FullExprArg FullCond(m_Sema.MakeFullExpr(ER.take())); StmtResult IfStmt = m_Sema.ActOnIfStmt(Loc, FullCond, varDecl, call, Loc, varStmt); return IfStmt.take(); }