/* * The function * findScope() * takes as a parameter a SgNode* which is a SgStatement*. It returns a SgNodePtrVector of all * preceding scopes the SgStatement is in. * */ SgNodePtrVector findScopes (SgNode * astNode) { ROSE_ASSERT (isSgStatement (astNode)); SgNodePtrVector returnVector; SgScopeStatement *currentScope; if (isSgScopeStatement (astNode)) { currentScope = isSgScopeStatement (astNode); ROSE_ASSERT (currentScope != NULL); returnVector.push_back (astNode); } else { SgStatement *sageStatement = isSgStatement (astNode); ROSE_ASSERT (sageStatement != NULL); currentScope = sageStatement->get_scope (); ROSE_ASSERT (currentScope != NULL); returnVector.push_back (currentScope); } while (currentScope->variantT () != V_SgGlobal) { currentScope = currentScope->get_scope (); ROSE_ASSERT (currentScope != NULL); returnVector.push_back (currentScope); } //Must also include the Global Scopes of the other files in the project if (currentScope->variantT () == V_SgGlobal) { SgFile *sageFile = isSgFile ((currentScope)->get_parent ()); ROSE_ASSERT (sageFile != NULL); SgProject *sageProject = isSgProject (sageFile->get_parent ()); ROSE_ASSERT (sageProject != NULL); //Get a list of all files in the current project const SgFilePtrList& sageFilePtrList = sageProject->get_fileList (); //Iterate over the list of files to find all Global Scopes SgNodePtrVector globalScopes; for (unsigned int i = 0; i < sageFilePtrList.size (); i += 1) { const SgSourceFile *sageFile = isSgSourceFile (sageFilePtrList[i]); ROSE_ASSERT (sageFile != NULL); SgGlobal *sageGlobal = sageFile->get_globalScope(); ROSE_ASSERT (sageGlobal != NULL); returnVector.push_back (sageGlobal); } } return returnVector; };
SgSymbol * ClangToSageTranslator::GetSymbolFromSymbolTable(clang::NamedDecl * decl) { if (decl == NULL) return NULL; SgScopeStatement * scope = SageBuilder::topScopeStack(); SgName name(decl->getNameAsString()); #if DEBUG_SYMBOL_TABLE_LOOKUP std::cerr << "Lookup symbol for: " << name << std::endl; #endif if (name == "") { return NULL; } std::list<SgScopeStatement *>::reverse_iterator it; SgSymbol * sym = NULL; switch (decl->getKind()) { case clang::Decl::Typedef: { it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_typedef_symbol(name); it++; } break; } case clang::Decl::Var: case clang::Decl::ParmVar: { it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_variable_symbol(name); it++; } break; } case clang::Decl::Function: { SgType * tmp_type = buildTypeFromQualifiedType(((clang::FunctionDecl *)decl)->getType()); SgFunctionType * type = isSgFunctionType(tmp_type); ROSE_ASSERT(type); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_function_symbol(name, type); it++; } break; } case clang::Decl::Field: { SgClassDeclaration * sg_class_decl = isSgClassDeclaration(Traverse(((clang::FieldDecl *)decl)->getParent())); ROSE_ASSERT(sg_class_decl != NULL); if (sg_class_decl->get_definingDeclaration() == NULL) std::cerr << "Runtime Error: cannot find the definition of the class/struct associate to the field: " << name << std::endl; else { scope = isSgClassDeclaration(sg_class_decl->get_definingDeclaration())->get_definition(); // TODO: for C++, if 'scope' is in 'SageBuilder::ScopeStack': problem!!! // It means that we are currently building the class while (scope != NULL && sym == NULL) { sym = scope->lookup_variable_symbol(name); scope = scope->get_scope(); } } break; } case clang::Decl::CXXRecord: case clang::Decl::Record: { it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_class_symbol(name); it++; } break; } case clang::Decl::Label: { // Should not be reach as we use Traverse to retrieve Label (they are "terminal" statements) (it avoids the problem of forward use of label: goto before declaration) name = SgName(((clang::LabelDecl *)decl)->getStmt()->getName()); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_label_symbol(name); it++; } break; } case clang::Decl::EnumConstant: { name = SgName(((clang::EnumConstantDecl *)decl)->getName()); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_enum_field_symbol(name); it++; } break; } case clang::Decl::Enum: { name = SgName(((clang::EnumDecl *)decl)->getName()); it = SageBuilder::ScopeStack.rbegin(); while (it != SageBuilder::ScopeStack.rend() && sym == NULL) { sym = (*it)->lookup_enum_symbol(name); it++; } break; } default: std::cerr << "Runtime Error: Unknown type of Decl. (" << decl->getDeclKindName() << ")" << std::endl; } return sym; }
void FunctionCallNormalization::visit( SgNode *astNode ) { SgStatement *stm = isSgStatement( astNode ); // visiting all statements which may contain function calls; // Note 1: we do not look at the body of loops, or sequences of statements, but only // at statements which may contain directly function calls; all other statements will have their component parts visited in turn if ( isSgEnumDeclaration( astNode ) || isSgVariableDeclaration( astNode ) || isSgVariableDefinition( astNode ) || isSgExprStatement( astNode ) || isSgForStatement( astNode ) || isSgReturnStmt( astNode ) || isSgSwitchStatement( astNode ) ) { // maintain the mappings from function calls to expressions (variables or dereferenced variables) map<SgFunctionCallExp *, SgExpression *> fct2Var; // list of Declaration structures, one structure per function call DeclarationPtrList declarations; bool variablesDefined = false; // list of function calls, in correnspondence with the inForTest list below list<SgNode*> functionCallExpList; list<bool> inForTest; SgForStatement *forStm = isSgForStatement( stm ); SgSwitchStatement *swStm = isSgSwitchStatement( stm ); list<SgNode*> temp1, temp2; // for-loops and Switch statements have conditions ( and increment ) expressed as expressions // and not as standalone statements; this will change in future Sage versions // TODO: when for-loops and switch statements have conditions expressed via SgStatements // these cases won't be treated separately; however, do-while will have condition expressed via expression // so that will be the only exceptional case to be treated separately if (forStm != NULL) { // create a list of function calls in the condition and increment expression // the order is important, the condition is evaluated after the increment expression // temp1 = FEOQueryForNodes( forStm->get_increment_expr_root(), V_SgFunctionCallExp ); // temp2 = FEOQueryForNodes( forStm->get_test_expr_root(), V_SgFunctionCallExp ); temp1 = FEOQueryForNodes( forStm->get_increment(), V_SgFunctionCallExp ); temp2 = FEOQueryForNodes( forStm->get_test_expr(), V_SgFunctionCallExp ); functionCallExpList = temp1; functionCallExpList.splice( functionCallExpList.end(), temp2 ); } else { if (swStm != NULL) { // create a list of function calls in the condition in the order of function evaluation // DQ (11/23/2005): Fixed SgSwitchStmt to have SgStatement for conditional. // list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector_root(), V_SgFunctionCallExp ); list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector(), V_SgFunctionCallExp ); functionCallExpList = temp1; } else { // create a list of function calls in the statement in the order of function evaluation functionCallExpList = FEOQueryForNodes( stm, V_SgFunctionCallExp ); } } // all function calls get replaced: this is because they can occur in expressions (e.g. for-loops) // which makes it difficult to build control flow graphs if ( functionCallExpList.size() > 0 ) { cout << "--------------------------------------\nStatement "; cout << stm->unparseToString() << "\n";; // traverse the list of function calls in the current statement, generate a structure Declaration for each call // put these structures in a list to be inserted in the code later for ( list<SgNode *>::iterator i = functionCallExpList.begin(); i != functionCallExpList.end(); i++ ) { variablesDefined = true; // get function call exp SgFunctionCallExp *exp = isSgFunctionCallExp( *i ); ROSE_ASSERT ( exp ); // get type of expression, generate unique variable name SgType *expType = exp->get_type(); ROSE_ASSERT ( expType ); Sg_File_Info *location = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); ROSE_ASSERT ( location ); ostringstream os; os << "__tempVar__" << location; SgName name = os.str().c_str(); // replace previous variable bindings in the AST SgExprListExp *paramsList = exp->get_args(); SgExpression *function = exp->get_function(); ROSE_ASSERT ( paramsList && function ); replaceFunctionCallsInExpression( paramsList, fct2Var ); replaceFunctionCallsInExpression( function, fct2Var ); // duplicate function call expression, for the initialization declaration and the assignment SgTreeCopy treeCopy; SgFunctionCallExp *newExpInit = isSgFunctionCallExp( exp->copy( treeCopy ) ); ROSE_ASSERT ( newExpInit ); SgFunctionCallExp *newExpAssign = isSgFunctionCallExp( exp->copy( treeCopy ) ); ROSE_ASSERT ( newExpAssign ); // variables Sg_File_Info *initLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(), *nonInitLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(), *assignLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); Declaration *newDecl = new Declaration(); SgStatement *nonInitVarDeclaration, *initVarDeclaration, *assignStmt; SgExpression *varRefExp; SgVariableSymbol *varSymbol; SgAssignOp *assignOp; SgInitializedName *initName; bool pointerTypeNeeded = false; // mark whether to replace inside or outside of ForStatement due to the // function call being inside the test or the increment for a for-loop statement // the 'inForTest' list is in 1:1 ordered correpondence with the 'declarations' list if ( forStm ) { // SgExpressionRoot // *testExp = isSgForStatement( astNode )->get_test_expr_root(), // *incrExp = isSgForStatement( astNode )->get_increment_expr_root(); SgExpression *testExp = isSgForStatement( astNode )->get_test_expr(), *incrExp = isSgForStatement( astNode )->get_increment(); SgNode *up = exp; while ( up && up != testExp && up != incrExp ) up = up->get_parent(); ROSE_ASSERT ( up ); // function call is in the condition of the for-loop if ( up == testExp ) inForTest.push_back( true ); // function call is in the increment expression else { inForTest.push_back( false ); // for increment expressions we need to be able to reassign the return value // of the function; if the ret value is a reference, we need to generate a // pointer of that type (to be able to reassign it later) if ( isSgReferenceType( expType ) ) pointerTypeNeeded = true; } } // for do-while statements: we need to generate declaration of type pointer to be able to have // non-assigned references when looping and assign them at the end of the body of the loop if ( isSgDoWhileStmt( stm->get_parent() ) && isSgReferenceType( expType ) ) pointerTypeNeeded = true; // we have a function call returning a reference and we can't initialize the variable // at the point of declaration; we need to define the variable as a pointer if ( pointerTypeNeeded ) { // create 'address of' term for function expression, so we can assign it to the pointer SgAddressOfOp *addressOp = new SgAddressOfOp( assignLoc, newExpAssign, expType ); // create noninitialized declaration SgType *base = isSgReferenceType( expType )->get_base_type(); ROSE_ASSERT( base ); SgPointerType *ptrType = SgPointerType::createType( isSgReferenceType( expType )->get_base_type() ); ROSE_ASSERT ( ptrType ); nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, ptrType ); // create assignment (symbol, varRefExp, assignment) initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name ); ROSE_ASSERT ( initName ); varSymbol = new SgVariableSymbol( initName ); ROSE_ASSERT ( varSymbol ); varRefExp = new SgVarRefExp( assignLoc, varSymbol ); SgPointerDerefExp *ptrDeref= new SgPointerDerefExp( assignLoc, varRefExp, expType ); ROSE_ASSERT ( isSgExpression( varRefExp ) && ptrDeref ); assignOp = new SgAssignOp( assignLoc, varRefExp, addressOp, ptrType ); assignStmt = new SgExprStatement( assignLoc, assignOp ); ROSE_ASSERT ( assignStmt && nonInitVarDeclaration ); // we don't need initialized declarations in this case initVarDeclaration = NULL; // save new mapping fct2Var.insert( Fct2Var( exp, ptrDeref ) ); } else { // create (non- &)initialized declarations, initialized name & symbol SgAssignInitializer *declInit = new SgAssignInitializer( initLoc, newExpInit, expType ); ROSE_ASSERT ( declInit ); initVarDeclaration = new SgVariableDeclaration ( initLoc, name, expType, declInit ); nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, expType ); ROSE_ASSERT ( initVarDeclaration && nonInitVarDeclaration ); initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name ); ROSE_ASSERT ( initName ); newExpInit->set_parent( initName ); varSymbol = new SgVariableSymbol( initName ); ROSE_ASSERT ( varSymbol ); // create variable ref exp varRefExp = new SgVarRefExp( assignLoc, varSymbol ); ROSE_ASSERT ( isSgVarRefExp( varRefExp ) ); // create the assignment assignOp = new SgAssignOp( assignLoc, varRefExp, newExpAssign, expType ); assignStmt = new SgExprStatement( assignLoc, assignOp ); ROSE_ASSERT ( assignStmt ); initVarDeclaration->set_parent( stm->get_parent() ); isSgVariableDeclaration( initVarDeclaration )->set_definingDeclaration( isSgDeclarationStatement( initVarDeclaration ) ); // save new mapping fct2Var.insert( Fct2Var( exp, varRefExp ) ); } // save the 'declaration' structure, with all 3 statements and the variable name newDecl->nonInitVarDeclaration = nonInitVarDeclaration; newDecl->initVarDeclaration = initVarDeclaration; newDecl->assignment = assignStmt; newDecl->name = name; nonInitVarDeclaration->set_parent( stm->get_parent() ); isSgVariableDeclaration( nonInitVarDeclaration )->set_definingDeclaration( isSgVariableDeclaration( nonInitVarDeclaration ) ); assignStmt->set_parent( stm->get_parent() ); declarations.push_back( newDecl ); } // end for } // end if fct calls in crt stmt > 1 SgScopeStatement *scope = stm->get_scope(); ROSE_ASSERT ( scope ); // insert function bindings to variables; each 'declaration' structure in the list // corresponds to one function call for ( DeclarationPtrList::iterator i = declarations.begin(); i != declarations.end(); i++ ) { Declaration *d = *i; ROSE_ASSERT ( d && d->assignment && d->nonInitVarDeclaration ); // if the current statement is a for-loop, we insert Declarations before & in the loop body, depending on the case if ( forStm ) { SgStatement *parentScope = isSgStatement( stm->get_scope() ); SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfFor(forStm); ROSE_ASSERT ( !inForTest.empty() && body && parentScope ); // SgStatementPtrList &list = body->get_statements(); // if function call is in loop condition, we add initialized variable before the loop and at its end // hoist initialized variable declarations outside the loop if ( inForTest.front() ) { ROSE_ASSERT ( d->initVarDeclaration ); parentScope->insert_statement( stm, d->initVarDeclaration ); // set the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( isSgScopeStatement( parentScope ) ); ROSE_ASSERT ( initName->get_scope() ); } // function call is in loop post increment so add noninitialized variable decls above the loop else { parentScope->insert_statement( stm, d->nonInitVarDeclaration ); // set the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( isSgScopeStatement( parentScope ) ); ROSE_ASSERT ( initName->get_scope() ); } // in a for-loop, always insert assignments at the end of the loop body->get_statements().push_back( d->assignment ); d->assignment->set_parent( body ); // remove marker inForTest.pop_front(); } else { // look at the type of the enclosing scope switch ( scope->variantT() ) { // while stmts have to repeat the function calls at the end of the loop; // note there is no "break" statement, since we want to also add initialized // declarations before the while-loop case V_SgWhileStmt: { // assignments need to be inserted at the end of each while loop SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfWhile(isSgWhileStmt( scope ) ); ROSE_ASSERT ( body ); d->assignment->set_parent( body ); body->get_statements().push_back( d->assignment ); } // SgForInitStatement has scope SgForStatement, move declarations before the for loop; // same thing if the enclosing scope is an If, or Switch statement case V_SgForStatement: case V_SgIfStmt: case V_SgSwitchStatement: { // adding bindings (initialized variable declarations only, not assignments) // outside the statement, in the parent scope SgStatement *parentScope = isSgStatement( scope->get_parent() ); ROSE_ASSERT ( parentScope ); parentScope->insert_statement( scope, d->initVarDeclaration, true );\ // setting the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); } break; // do-while needs noninitialized declarations before the loop, with assignments inside the loop case V_SgDoWhileStmt: { // adding noninitialized variable declarations before the body of the loop SgStatement *parentScope = isSgStatement( scope->get_parent() ); ROSE_ASSERT ( parentScope ); parentScope->insert_statement( scope, d->nonInitVarDeclaration, true ); // initialized name scope setting SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); // adding assignemts at the end of the do-while loop SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfDoWhile( isSgDoWhileStmt(scope) ); ROSE_ASSERT ( body ); body->get_statements().push_back( d->assignment ); d->assignment->set_parent(body); } break; // for all other scopes, add bindings ( initialized declarations ) before the statement, in the same scope default: scope->insert_statement( stm, d->initVarDeclaration, true ); // initialized name scope setting SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); } } } // once we have inserted all variable declarations, we need to replace top-level calls in the original statement if ( variablesDefined ) { cout << "\tReplacing in the expression " << stm->unparseToString() << "\n"; // for ForStatements, replace expressions in condition and increment expressions, // not in the body, since those get replace later if ( forStm ) { // SgExpressionRoot *testExp = forStm->get_test_expr_root(), *incrExp = forStm->get_increment_expr_root(); SgExpression *testExp = forStm->get_test_expr(), *incrExp = forStm->get_increment(); replaceFunctionCallsInExpression( incrExp, fct2Var ); replaceFunctionCallsInExpression( testExp, fct2Var ); } else if ( swStm ) { // DQ (11/23/2005): Fixed SgSwitch to permit use of declaration for conditional // replaceFunctionCallsInExpression( swStm->get_item_selector_root(), fct2Var ); replaceFunctionCallsInExpression( swStm->get_item_selector(), fct2Var ); } else replaceFunctionCallsInExpression( stm, fct2Var ); } } // end if isSgStatement block }
// Count the load and store bytes for the // I think we can only return expressions to calculate the value, not the actual values, // since sizeof(type) is machine dependent // Consider both scalar and array accesses by default. Consider both floating point and integer types by default. // return a pair of expressions: // load_byte_exp, and // store_byte_exp // Algorithm: // 1. Call side effect analysis to find read/write variables, some reference may trigger both read and write accesses // Accesses to the same array/scalar variable are grouped into one read (or write) access // e.g. array[i][j], array[i][j+1], array[i][j-1], etc are counted a single access // 2. Group accesses based on the types (same type? increment the same counter to shorten expression length) // 4. Iterate on the results to generate expression like 2*sizeof(float) + 5* sizeof(double) // As an approximate, we use simple analysis here assuming no function calls. std::pair <SgExpression*, SgExpression*> CountLoadStoreBytes (SgLocatedNode* input, bool includeScalars /* = true */, bool includeIntType /* = true */) { std::pair <SgExpression*, SgExpression*> result; assert (input != NULL); // the input is essentially the loop body, a scope statement SgScopeStatement* scope = isSgScopeStatement(input); // We need to record the associated loop info. //SgStatement* loop= NULL; SgForStatement* forloop = isSgForStatement(scope->get_scope()); SgFortranDo* doloop = isSgFortranDo(scope->get_scope()); if (forloop) { //loop = forloop; } else if (doloop) { //loop = doloop; } else { cerr<<"Error in CountLoadStoreBytes (): input is not loop body type:"<< input->class_name()<<endl; assert(false); } //Plan A: use and extend Qing's side effect analysis std::set<SgInitializedName*> readVars; std::set<SgInitializedName*> writeVars; bool success = SageInterface::collectReadWriteVariables (isSgStatement(input), readVars, writeVars); if (success!= true) { cout<<"Warning: CountLoadStoreBytes(): failed to collect load/store, mostly due to existence of function calls inside of loop body @ "<<input->get_file_info()->get_line()<<endl; } std::set<SgInitializedName*>::iterator it; if (debug) cout<<"debug: found read variables (SgInitializedName) count = "<<readVars.size()<<endl; for (it=readVars.begin(); it!=readVars.end(); it++) { SgInitializedName* iname = (*it); if (debug) cout<<scalar_or_array (iname->get_type()) <<" "<<iname->get_name()<<"@"<<iname->get_file_info()->get_line()<<endl; } if (!includeScalars ) readVars = filterVariables (readVars); if (debug) cout<<"debug: found write variables (SgInitializedName) count = "<<writeVars.size()<<endl; for (it=writeVars.begin(); it!=writeVars.end(); it++) { SgInitializedName* iname = (*it); if (debug) cout<<scalar_or_array(iname->get_type()) <<" "<<iname->get_name()<<"@"<<iname->get_file_info()->get_line()<<endl; } if (!includeScalars ) writeVars = filterVariables (writeVars); result.first = calculateBytes (readVars, scope, true); result.second = calculateBytes (writeVars, scope, false); return result; }
void fixupInstantiatedTemplates ( SgProject* project ) { // DQ (7/12/2005): Introduce tracking of performance of ROSE. TimingPerformance timer ("AST Object Code Generation (fixupInstantiatedTemplates): time (sec) = "); // DQ (9/6/2005): I think these operations have been superseded // by the AST post processing mechanism which is more complete. printf ("In fixupInstantiatedTemplates(): I think this may be dead code! \n"); ROSE_ASSERT(false); // This must be done prior to the unparsing of the SAGE III AST, so that any transformations // (new function prototypes for the specialized template function) can be inserted before we // unparse the final code! Could be done in AST fixup! Not clear if it should be done in // the EDG/SAGE III connection! It is currently called from the backend() function just // before the unparser! // Add forward references for instantiated template functions and member functions // (which are by default defined at the bottom of the file (but should be declared // at the top once we know what instantiations should be built)). They must be // defined at the bottom since they could call other functions not yet declared in // the file. Note that this fixup is required since we have skipped the class template // definitions which would contain the declarations that we are generating. We might // need that as a solution at some point if this fails to be sufficently robust. // Build a lists of intatiatied templates Rose_STL_Container<SgNode*> classList = NodeQuery::querySubTree (project,V_SgTemplateInstantiationDecl); Rose_STL_Container<SgNode*> functionList = NodeQuery::querySubTree (project,V_SgTemplateInstantiationFunctionDecl); Rose_STL_Container<SgNode*> memberFunctionList = NodeQuery::querySubTree (project,V_SgTemplateInstantiationMemberFunctionDecl); #if 1 printf ("In fixupInstantiatedTemplates SgTemplateInstantiationDecl: classList.size() = %ld \n",classList.size()); printf ("In fixupInstantiatedTemplates SgTemplateInstantiationFunctionDecl: functionList.size() = %ld \n",functionList.size()); printf ("In fixupInstantiatedTemplates SgTemplateInstantiationMemberFunctionDecl: memberFunctionList.size() = %ld \n",memberFunctionList.size()); #endif // These are not handled yet! // ROSE_ASSERT(classList.size() == 0); // ROSE_ASSERT(functionList.size() == 0); Rose_STL_Container<SgNode*>::iterator functionIndex = functionList.begin(); while ( functionIndex != functionList.end() ) { // SgDeclarationStatement* declaration = isSgDeclarationStatement(*i); SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDeclaration = isSgTemplateInstantiationFunctionDecl(*functionIndex); ROSE_ASSERT (templateInstantiationFunctionDeclaration != NULL); // printf ("SgTemplateInstantiationFunctionDecl: *i = %p = %s \n",*functionIndex,(*functionIndex)->unparseToString().c_str()); // Mark this function as a specialization, since we have transformed it into one when we converted the // name format (e.g.from __A45_ to A<int>). The handling of templates in ROSE is one of converting // the templae instantiations (generated by EDG) into explicit template specializations so that they // can be operated upon within ROSE (for translation/optimization). printf ("Error in fixupInstantiatedTemplates (function templates): It is now an error to mark something that was not explicitly a specialization in the original source code as a specialization ... \n"); templateInstantiationFunctionDeclaration->set_specialization(SgTemplateInstantiationFunctionDecl::e_specialization); bool generateForwardDeclarationForFunction = (templateInstantiationFunctionDeclaration->isForward() == false); if ( generateForwardDeclarationForFunction == true ) { // This is just a regular member function inside of a templated class (or a class nested in a templated class) // it's associated template declaration will not have the template text (appears to be lost in EDG), but it // is not essential if we unparse the instantated template for the member function. // This is the instantiate template member function definition, the steps are: // 1) Build a forward declaration for the instantiated template (member function). // 2) Place the new forward declaration after the class containing the templated member function. } functionIndex++; } Rose_STL_Container<SgNode*>::iterator classIndex = classList.begin(); while ( classIndex != classList.end() ) { SgTemplateInstantiationDecl* templateInstantiationClassDeclaration = isSgTemplateInstantiationDecl(*classIndex); ROSE_ASSERT (templateInstantiationClassDeclaration != NULL); // printf ("SgTemplateInstantiationDecl: *i = %p = %s \n",*classIndex,(*classIndex)->unparseToString().c_str()); #if 0 printf ("In fixupInstantiatedTemplates: templateInstantiationClassDeclaration = %p compilerGenerated = %s \n", templateInstantiationClassDeclaration, templateInstantiationClassDeclaration->get_file_info()->isCompilerGenerated() ? "true" : "false"); templateInstantiationClassDeclaration->get_file_info()->display("In fixupInstantiatedTemplates: templateInstantiationClassDeclaration"); #endif // Mark this class as a specialization, since we have transformed it into one when we converted the // name format (e.g.from __A45_ to A<int>). The handling of templates in ROSE is one of converting // the templae instantiations (generated by EDG) into explicit template specializations so that they // can be operated upon within ROSE (for translation/optimization). printf ("Error in fixupInstantiatedTemplates (class templates): It is now an error to mark something that was not explicitly a specialization in the original source code as a specialization ... \n"); templateInstantiationClassDeclaration->set_specialization(SgTemplateInstantiationDecl::e_specialization); bool generateForwardDeclarationForClass = (templateInstantiationClassDeclaration->isForward() == false); if ( generateForwardDeclarationForClass == true ) { // Nothing to do in this case since EDG should have already instered the forward class declaration! } classIndex++; } // Loop over the SgTemplateInstantiationMemberFunction objects and insert a function prototype. // We need the function prototypes because the template instatiation function definitions appear // at the end of the file! Rose_STL_Container<SgNode*>::iterator i = memberFunctionList.begin(); while ( i != memberFunctionList.end() ) { // SgDeclarationStatement* declaration = isSgDeclarationStatement(*i); SgTemplateInstantiationMemberFunctionDecl* templateInstantiationMemberFunctionDeclaration = isSgTemplateInstantiationMemberFunctionDecl(*i); ROSE_ASSERT (templateInstantiationMemberFunctionDeclaration != NULL); #if 0 printf ("templateInstantiationMemberFunctionDeclaration->isTemplateFunction() == %s \n", templateInstantiationMemberFunctionDeclaration->isTemplateFunction() ? "true" : "false"); #endif // Mark this function as a specialization, since we have transformed it into one when we converted the // name formate (e.g.from __A45_ to A<int>). The handling of templates in ROSE is one of converting // the templae instantiations (generated by EDG) into explicit template specializations so that they // can be operated upon within ROSE (for translation/optimization). // If this is not a truely templated function then it can't be a specialization! // if it is not a templated function then is is likely just a member function of a templated class. if (templateInstantiationMemberFunctionDeclaration->isTemplateFunction() == true) { printf ("Error in fixupInstantiatedTemplates (member function templates): It is now an error to mark something that was not explicitly a specialization in the original source code as a specialization ... \n"); templateInstantiationMemberFunctionDeclaration->set_specialization(SgTemplateInstantiationMemberFunctionDecl::e_specialization); } #if 0 // DQ (9/5/2005): Updated comment. // DQ (5/31/2005): Commented out since the class declaration itself is the forward declaration // for the member function. I don't think we need another one! Actually we do but this is now // handled within ROSE/src/frontend/SageIII/astPostProcessing/ files. bool generateForwardDeclarationForInlinedMemberFunction = (templateInstantiationMemberFunctionDeclaration->isForward() == false) && (templateInstantiationMemberFunctionDeclaration->isTemplateFunction() == false); if ( generateForwardDeclarationForInlinedMemberFunction == true ) { // This is just a regular member function inside of a templated class (or a class nested in a templated class) // it's associated template declaration will not have the templae text (appears to be lost in EDG), but it // is not essential if we unparse the instantated template for the member function. printf ("For inlined template member functions get the templateDeclaration from the class declaration \n"); // This is the instantiate template member function definition, the steps are: // 1) Build a forward declaration for the instantiated template (member function). // 2) Place the new forward declaration after the class containing the templated member function. printf ("SgTemplateInstantiationMemberFunctionDecl: *i = %p = %s \n",*i,(*i)->unparseToString().c_str()); // Call the AST's copy mechanism SgShallowCopy shallow; SgNode * forwardDeclarationNode = templateInstantiationMemberFunctionDeclaration->copy(shallow); SgTemplateInstantiationMemberFunctionDecl* forwardDeclaration = isSgTemplateInstantiationMemberFunctionDecl(forwardDeclarationNode); ROSE_ASSERT(forwardDeclaration != NULL); // find the template declaration of the class contining the member function SgClassDeclaration* classDeclaration = templateInstantiationMemberFunctionDeclaration->get_class_scope()->get_declaration(); ROSE_ASSERT(classDeclaration != NULL); SgTemplateInstantiationDecl* templateInstantiationDeclaration = isSgTemplateInstantiationDecl(classDeclaration); ROSE_ASSERT(templateInstantiationDeclaration != NULL); SgTemplateDeclaration* templateDeclaration = templateInstantiationDeclaration->get_templateDeclaration(); ROSE_ASSERT (templateDeclaration != NULL); // Reset the file info object so that we can mark this as compiler generated (copy builds a new Sg_File_Info object) // ROSE_ASSERT (forwardDeclaration->get_file_info() != NULL); // forwardDeclaration->set_file_info(new Sg_File_Info(*(forwardDeclaration->get_file_info()))); ROSE_ASSERT(forwardDeclaration->get_file_info() != templateInstantiationMemberFunctionDeclaration->get_file_info()); // Both of these may be set (implemented as bit flags internally) forwardDeclaration->get_file_info()->setCompilerGenerated(); forwardDeclaration->get_file_info()->setTransformation(); // Remove the shallow copy of the function definition forwardDeclaration->set_definition(NULL); // Mark the declaration as a forward declarations forwardDeclaration->setForward(); // Mark this function as a specialization (should be done within copy function) // forwardDeclaration->set_specialization(SgTemplateInstantiationMemberFunctionDecl::e_specialization); ROSE_ASSERT(forwardDeclaration->isSpecialization() == true); ROSE_ASSERT(forwardDeclaration->isPartialSpecialization() == false); // Now insert the forwardDeclaration after the templateDeclaration! // templateDeclaration.insert_statement(forwardDeclaration,true); SgScopeStatement* templateDeclarationScope = templateDeclaration->get_scope(); ROSE_ASSERT (templateDeclarationScope != NULL); printf ("BEFORE loop: Insert before: templateDeclarationScope = %p = %s \n",templateDeclarationScope,templateDeclarationScope->sage_class_name()); // Trace back through the scopes to find a non class declaration scope into which to put the forward declaration // Does this then work with nested template classes????? while (isSgTemplateInstantiationDefn(templateDeclarationScope) != NULL) { templateDeclarationScope = templateDeclarationScope->get_scope(); printf ("In loop templateDeclarationScope = %p = %s \n",templateDeclarationScope,templateDeclarationScope->sage_class_name()); } ROSE_ASSERT (templateDeclarationScope != NULL); printf ("AFTER loop: Insert before: templateDeclarationScope = %p = %s \n",templateDeclarationScope,templateDeclarationScope->sage_class_name()); templateDeclaration->get_file_info()->display("templateDeclaration"); templateDeclarationScope->get_file_info()->display("templateDeclarationScope"); int insertBeforeStatement = false; // printf ("Calling templateDeclarationScope->insert_statement() \n"); // templateDeclaration->insert_statement ( templateDeclaration, forwardDeclaration, insertBeforeStatement ); SgTemplateInstantiationDefn *templateClassDefinition = isSgTemplateInstantiationDefn(templateDeclarationScope); if (templateClassDefinition != NULL) { SgDeclarationStatementPtrList::iterator start = templateClassDefinition->get_members().begin(); SgDeclarationStatementPtrList::iterator end = templateClassDefinition->get_members().end(); printf ("templateDeclaration unparsed = %s \n",templateDeclaration->unparseToString().c_str()); printf ("templateDeclaration name = %s string = %s \n", templateDeclaration->get_name().str(),templateDeclaration->get_string().str()); for (SgDeclarationStatementPtrList::iterator i = start; i != end; i++) { string s = (*i)->unparseToString(); printf ("(*i)->unparseToString() = %s \n",s.c_str()); } ROSE_ASSERT(find(start,end,templateInstantiationMemberFunctionDeclaration) != end); templateDeclarationScope->insert_statement ( templateInstantiationMemberFunctionDeclaration, forwardDeclaration, insertBeforeStatement ); } else { // ROSE_ASSERT(find(templateDeclarationScope->get_members().begin(),templateDeclarationScope->get_members().end(),templateDeclaration) != templateDeclarationScope->get_members().end() ); templateDeclarationScope->insert_statement ( templateDeclaration, forwardDeclaration, insertBeforeStatement ); } printf ("forwardDeclaration = %s \n",forwardDeclaration->unparseToString().c_str()); // printf ("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD \n"); // printf ("Exiting after construction of forward declaration for template instantiation! \n"); // ROSE_ASSERT (false); } else { // This is a forward declaration (does it have the template arguments!) printf ("SgTemplateInstantiationMemberFunctionDecl: (forward) *i = %p = %s \n",*i,(*i)->unparseToString().c_str()); } #endif i++; } }