Beispiel #1
0
	clang::Decl* InsiemeSema::ActOnFinishFunctionBody(clang::Decl* Decl, clang::Stmt* Body) {
		VLOG(2) << "{InsiemeSema}: ActOnFinishFunctionBody()";
		clang::Decl* ret = Sema::ActOnFinishFunctionBody(Decl, std::move(Body));
		// We are sure all the pragmas inside the function body have been matched

		FunctionDecl* FD = dyn_cast<FunctionDecl>(ret);
		
		if(!FD) { return ret; }

		PragmaList matched;
		std::list<PragmaPtr>::reverse_iterator I = pimpl->pending_pragma.rbegin(), E = pimpl->pending_pragma.rend();

		while(I != E && isAfterRange(FD->getSourceRange(), (*I)->getStartLocation(), SourceMgr)) {
			++I;
		}

		while(I != E) {
			unsigned int pragmaEnd = utils::Line((*I)->getEndLocation(), SourceMgr);
			unsigned int declBegin = utils::Line(ret->getSourceRange().getBegin(), SourceMgr);

			if(pragmaEnd <= declBegin) {
				(*I)->setDecl(FD);
				matched.push_back(*I);
			}
			++I;
		}
		EraseMatchedPragmas(pimpl->pending_pragma, matched);
		isInsideFunctionDef = false;

		return ret;
	}
Beispiel #2
0
	clang::StmtResult InsiemeSema::ActOnIfStmt(clang::SourceLocation IfLoc, clang::Sema::FullExprArg CondVal, clang::Decl* CondVar, clang::Stmt* ThenVal,
	                                           clang::SourceLocation ElseLoc, clang::Stmt* ElseVal) {
		VLOG(2) << "{InsiemeSema}: ActOnIfStmt()";
		clang::StmtResult ret = Sema::ActOnIfStmt(IfLoc, CondVal, CondVar, std::move(ThenVal), ElseLoc, std::move(ElseVal));

		clang::IfStmt* ifStmt = static_cast<clang::IfStmt*>(ret.get());
		PragmaList matched;

		matchStmt(ifStmt->getThen(), SourceRange(IfLoc, IfLoc), SourceMgr, matched);
		// is there any pragmas to be associated with the 'then' statement of this if?
		if(!isa<clang::CompoundStmt>(ifStmt->getThen())) {
			// if there is no compound stmt, check the then part
			matchStmt(ifStmt->getThen(), SourceRange(IfLoc, ThenVal->getLocEnd()), SourceMgr, matched);
		}
		EraseMatchedPragmas(pimpl->pending_pragma, matched);
		matched.clear();

		// is there any pragmas to be associated with the 'else' statement of this if?
		if(ifStmt->getElse() && !isa<clang::CompoundStmt>(ifStmt->getElse())) {
			matchStmt(ifStmt->getElse(), SourceRange(ElseLoc, ifStmt->getSourceRange().getEnd()), SourceMgr, matched);
		}

		EraseMatchedPragmas(pimpl->pending_pragma, matched);
		return std::move(ret);
	}
Beispiel #3
0
	clang::StmtResult InsiemeSema::ActOnForStmt(clang::SourceLocation ForLoc, clang::SourceLocation LParenLoc, clang::Stmt* First,
	                                            clang::Sema::FullExprArg Second, clang::Decl* SecondVar, clang::Sema::FullExprArg Third,
	                                            clang::SourceLocation RParenLoc, clang::Stmt* Body) {
		VLOG(2) << "{InsiemeSema}: ActOnForStmt()" << std::endl;
		clang::StmtResult ret = Sema::ActOnForStmt(ForLoc, LParenLoc, std::move(First), Second, SecondVar, Third, RParenLoc, std::move(Body));

		clang::ForStmt* forStmt = (clang::ForStmt*)ret.get();
		PragmaList matched;
		if(!isa<clang::CompoundStmt>(forStmt->getBody())) { matchStmt(forStmt->getBody(), forStmt->getSourceRange(), SourceMgr, matched); }
		EraseMatchedPragmas(pimpl->pending_pragma, matched);
		matched.clear();

		return std::move(ret);
	}
Beispiel #4
0
	void InsiemeSema::matchStmt(clang::Stmt* S, const clang::SourceRange& bounds, const clang::SourceManager& sm, PragmaList& matched) {
		for(PragmaFilter filter(bounds, sm, pimpl->pending_pragma); *filter; ++filter) {
			PragmaPtr&& P = *filter;

			P->setStatement(S);
			matched.push_back(P);
		}
	}
Beispiel #5
0
SgNodeHelper::PragmaList
SgNodeHelper::collectPragmaLines(string pragmaName,SgNode* root) {
  PragmaList l;
  RoseAst ast(root);
  for(RoseAst::iterator i=ast.begin();i!=ast.end();++i) {
    std::list<SgPragmaDeclaration*> pragmaNodes;
    ROSE_ASSERT(pragmaNodes.size()==0);
    // SgPragmaDeclaration(SgPragma),..., SgStatement
    // collects consecutive pragma declarations
    while(i!=ast.end()&&(isSgPragmaDeclaration(*i)||isSgPragma(*i))) {
      if(SgPragmaDeclaration* pragmaDecl=isSgPragmaDeclaration(*i)) {
        pragmaNodes.push_back(pragmaDecl);
      }
      ++i;
    }
    if(i!=ast.end()) {
      for(std::list<SgPragmaDeclaration*>::iterator p=pragmaNodes.begin();p!=pragmaNodes.end();++p) {
        string str=SgNodeHelper::getPragmaDeclarationString(*p);
        SgNodeHelper::replaceString(str,"#pragma ","");
        if(SgNodeHelper::isPrefix(pragmaName,str)) {
          SgPragmaDeclaration* lastPragmaDecl=pragmaNodes.back();
          // ensure we did not collect pragmas at the end of a block
          if(!(isLastChildOf(lastPragmaDecl,lastPragmaDecl->get_parent()))) {
            if(SgStatement* assocStmt=isSgStatement(*i)) {
              SgNodeHelper::replaceString(str,pragmaName+" ","");
              //cout<<"PRAGMA REVERSE: "<<str<<" : "<<(assocStmt)->unparseToString()<<endl;
              l.push_back(make_pair(str,assocStmt));
            } else {
              std::cerr<<"Error: "<<SgNodeHelper::sourceLineColumnToString(*p)<<": reverse pragma not associated with a method or statement."<<endl
                       <<"Pragma         : "<<str<<endl
                       <<"Associated code: "<<assocStmt->unparseToString()<<endl;
              exit(1);
            }
          } else {
            std::cerr<<"Error: "<<SgNodeHelper::sourceLineColumnToString(*p)<<": pragma at end of block. This is not allowed."<<endl;
            exit(1);
          }
        }
      }
    }
  }
  return l;
}
Beispiel #6
0
	void InsiemeSema::ActOnTagFinishDefinition(clang::Scope* S, clang::Decl* TagDecl, clang::SourceLocation RBraceLoc) {
		VLOG(2) << "{InsiemeSema}: ActOnTagFinishDefinition()";

		Sema::ActOnTagFinishDefinition(S, TagDecl, RBraceLoc);
		if(isInsideFunctionDef) { return; }

		PragmaList matched;
		std::list<PragmaPtr>::reverse_iterator I = pimpl->pending_pragma.rbegin(), E = pimpl->pending_pragma.rend();

		while(I != E && isAfterRange(TagDecl->getSourceRange(), (*I)->getStartLocation(), SourceMgr)) {
			++I;
		}

		while(I != E) {
			(*I)->setDecl(TagDecl);
			matched.push_back(*I);
			++I;
		}
		EraseMatchedPragmas(pimpl->pending_pragma, matched);
	}
Beispiel #7
0
	clang::Decl* InsiemeSema::ActOnDeclarator(clang::Scope* S, clang::Declarator& D) {
		VLOG(2) << "{InsiemeSema}: ActOnDeclarator()";

		clang::Decl* ret = Sema::ActOnDeclarator(S, D);
		if(isInsideFunctionDef) { return ret; }

		PragmaList matched;
		std::list<PragmaPtr>::reverse_iterator I = pimpl->pending_pragma.rbegin(), E = pimpl->pending_pragma.rend();

		while(I != E && isAfterRange(ret->getSourceRange(), (*I)->getStartLocation(), SourceMgr)) {
			++I;
		}

		while(I != E) {
			(*I)->setDecl(ret);
			matched.push_back(*I);
			++I;
		}

		EraseMatchedPragmas(pimpl->pending_pragma, matched);
		return ret;
	}
Beispiel #8
0
	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);
	}