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 }
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++; } }