SNode SNode::multiplyStmtList() const { ENTERMETHOD(); CHECKNODETYPE(*this,NT_STMTLIST); const SNodeArray &a = getChildArray(); SNodeArray newChildArray(a.getTree(),a.size()); for(size_t i = 0; i < a.size(); i++) { newChildArray.add(a[i].multiplyParentheses()); } SNode result = stmtList(newChildArray); RETURNNODE( result ); }
void program () { std::cout << "\nIn program\n" ; match (scanner::BeginSym); stmtList (); match (scanner::EndSym); std::cout << "\nEnd program\n"; }
void stmtList () { std::cout << "\nIn stmtList\n" ; statement (); nextToken = getNextToken(); switch (nextToken) { case (scanner::Id) : case (scanner::ReadSym) : case (scanner::WriteSym) : stmtList(); break; } std::cout << "\nEnd stmtList\n"; }
clang::StmtResult InsiemeSema::ActOnCompoundStmt(clang::SourceLocation L, clang::SourceLocation R, llvm::ArrayRef<clang::Stmt*> Elts, bool isStmtExpr) { // we parse the original code segment, within the original locations StmtResult&& ret = Sema::ActOnCompoundStmt(L, R, std::move(Elts), isStmtExpr); clang::CompoundStmt* CS = cast<clang::CompoundStmt>(ret.get()); // This is still buggy as of Clang 3.6.2: // when pragmas are just after the beginning of a compound stmt, example: // { // #pragma xxx // ... // } // the location of the opening bracket is wrong because of a bug in the clang parser. // // We solve the problem by searching for the bracket in the input stream and overwrite // the value of L (which contains the wrong location) with the correct value. enum { MacroIDBit = 1U << 31 }; // from clang/Basic/SourceLocation.h for use with cpp classes { SourceLocation&& leftBracketLoc = SourceMgr.getImmediateSpellingLoc(L); std::pair<FileID, unsigned>&& locInfo = SourceMgr.getDecomposedLoc(leftBracketLoc); llvm::StringRef&& buffer = SourceMgr.getBufferData(locInfo.first); const char* strData = buffer.begin() + locInfo.second; char const* lBracePos = strbchr(strData, buffer.begin(), '{'); // We know the location of the left bracket, we overwrite the value of L with the correct location // but only if the location is valid as in getFileLocWithOffset() in SourceLocation if((((leftBracketLoc.getRawEncoding() & ~MacroIDBit) + (lBracePos - strData)) & MacroIDBit) == 0) { L = leftBracketLoc.getLocWithOffset(lBracePos - strData); } } // For the right bracket, we start at the final statement in the compound // (or its start if it is empty) and search forward until we find the first "}" // Otherwise, cases such as this: // // { // bla(); // } // #pragma test expect_ir(R"( {} )") // // will be broken { SourceLocation rightBracketLoc; if(CS->size() == 0) { rightBracketLoc = SourceMgr.getImmediateSpellingLoc(L); } else { rightBracketLoc = SourceMgr.getImmediateSpellingLoc(CS->body_back()->getLocEnd()); } std::pair<FileID, unsigned>&& locInfo = SourceMgr.getDecomposedLoc(rightBracketLoc); llvm::StringRef buffer = SourceMgr.getBufferData(locInfo.first); const char* strData = buffer.begin() + locInfo.second; char const* rBracePos = strchr(strData, '}'); // We know the location of the right bracket, we overwrite the value of R with the correct location if((((rightBracketLoc.getRawEncoding() & ~MacroIDBit) + (rBracePos - strData)) & MacroIDBit) == 0) { R = rightBracketLoc.getLocWithOffset(rBracePos - strData); } } // the source range we inspect is defined by the new source locations, // this fix the problem with boundaries jumping to the beginning of the file in // the macro expansions: // // #define F(x) { } // // ... // // F(r) // <-this statement will jum to the macro location // PragmaList matched; SourceRange SR(L, R); // for each of the pragmas in the range between brackets for(PragmaFilter&& filter = PragmaFilter(SR, SourceMgr, pimpl->pending_pragma); *filter; ++filter) { PragmaPtr P = *filter; unsigned int pragmaStart = utils::Line(P->getStartLocation(), SourceMgr); unsigned int pragmaEnd = utils::Line(P->getEndLocation(), SourceMgr); bool found = false; // problem with first pragma, compound start is delayed until fist usable line (first stmt) if(CS->size() > 0) { for(clang::CompoundStmt::body_iterator it = CS->body_begin(); it != CS->body_end(); ++it) { unsigned int stmtStart = (Line((*it)->getLocStart(), SourceMgr)); if((pragmaEnd <= stmtStart)) { // ACHTUNG: if the node is a nullStmt, and is not at the end of the compound (in // which case is most probably ours) we can not trust it. semantics wont change, // we move one more. (BUG: nullStmt followed by pragmas, the source begin is // postponed until next stmt) this makes pragmas to be attached to a previous // stmt if(!llvm::isa<clang::NullStmt>(*it)) { // this pragma is attached to the current stmt P->setStatement(*it); matched.push_back(P); found = true; break; } } } } if(!found && pragmaStart <= utils::Line(R, SourceMgr)) { // this is a de-attached pragma (barrier i.e.) at the end of the compound // we need to create a fake NullStmt ( ; ) to attach this Stmt** stmts = new Stmt*[CS->size() + 1]; ArrayRef<clang::Stmt*> stmtList(stmts, CS->size() + 1); clang::CompoundStmt* newCS = new(Context) clang::CompoundStmt(Context, stmtList, CS->getSourceRange().getBegin(), CS->getSourceRange().getEnd()); std::copy(CS->body_begin(), CS->body_end(), newCS->body_begin()); std::for_each(CS->body_begin(), CS->body_end(), [&](Stmt*& curr) { this->Context.Deallocate(curr); }); newCS->setLastStmt(new(Context) NullStmt(SourceLocation())); P->setStatement(*newCS->body_rbegin()); matched.push_back(P); // transfer the ownership of the statement clang::CompoundStmt* oldStmt = ret.getAs<clang::CompoundStmt>(); oldStmt->setStmts(Context, NULL, 0); ret = newCS; CS = newCS; // destroy the old compound stmt Context.Deallocate(oldStmt); delete[] stmts; } } // remove matched pragmas EraseMatchedPragmas(pimpl->pending_pragma, matched); return std::move(ret); }