string IndexOperandDataBase::generateIdentifierString() const { string returnString; #if 0 switch (origin) { case unknown: returnString = "unknown"; break; case notStaticlyKnown: returnString = "notStaticlyKnown"; break; case scalarValue: returnString = "scalar0"; break; case baseBoundValues: returnString = "scalar1"; break; case baseBoundStrideValues: returnString = "scalar2"; break; default: printf ("Error: default reached in IndexOperandDataBase::generateIdentifierString() \n"); ROSE_ABORT(); break; } #else returnString = indexVariableName; #endif return returnString; }
ProgramTransformationSynthesizedAttributeType ArrayStatementTraversal::arrayAssignmentTransformation ( const ProgramTransformationInheritedAttributeType & inheritedAttribute, SgNode* astNode ) { // The purpose of this transformation is to insert the array transformation in place of each array // statement. This is a function defined in the class derived from the TransformationSpecificationType. // This function is a pure virtual function within the TransformationSpecificationType base class. // This function requires that the inherited attribute be passed so that we can pass it along to // the nested transformation. ROSE_ASSERT (astNode != NULL); ROSE_ASSERT (isSgExprStatement(astNode) != NULL); // This function is at the top level using the SgProject as input (to make the source position mechanism work) // ROSE_ASSERT (isSgProject(astNode) != NULL); ProgramTransformationSynthesizedAttributeType gatheredInfo(astNode); if (ArrayAssignmentStatementTransformation::targetForTransformation(astNode) == true) { // printf ("Calling ArrayAssignmentStatementTransformation::transformation() \n"); gatheredInfo = ArrayAssignmentStatementTransformation::transformation ( inheritedAttribute, astNode ); // printf ("At base of case 'ArrayAssignmentStatementTransformation::targetForTransformation(astNode) == true' \n"); // gatheredInfo.display("Called from ArrayStatementTraversal::arrayAssignmentTransformation() after ArrayAssignmentStatementTransformation::transformation()"); // Since the transformation shouldhave generated global variable we can make sure that some strings are present ROSE_ASSERT (gatheredInfo.isEmpty() == false); #if 0 printf ("Exiting as part of testing ... (at base of ArrayStatementTraversal::arrayAssignmentTransformation) \n"); ROSE_ABORT(); #endif } // gatheredInfo.display("Called from ArrayStatementTraversal::arrayAssignmentTransformation()"); #if 0 printf ("Exiting as part of testing ... (at base of ArrayStatementTraversal::arrayTransformation) \n"); ROSE_ABORT(); #endif // This copies and returns the SynthesizedAttributeBaseClassType information return gatheredInfo; }
ArrayStatementQueryInheritedAttributeType:: ArrayStatementQueryInheritedAttributeType () { // This constructor should never be called printf ("In ArrayStatementQueryInheritedAttributeType: Base class initialized with NULL pointer \n"); ROSE_ABORT(); arrayStatementDimensionDefined = false; arrayStatementDimension = -1; }
void OperandDataBaseType:: setVariableNameList ( const list<string> & X ) { // This interface is to support the addition of a list of variables into the data base // this occurs when we add all the variables represented in a synthesized attribute // to a new attribute (as part of the the assemble process). #if 0 printf ("In OperandDataBaseType::setVariableNameList(): Now add the information in X to the current database \n"); printf ("... X names ------------- (list size = %d): %s \n",X.size(),StringUtility::listToString(X).c_str()); // printf ("... variableNameList names (list size = %d): %s \n",variableNameList.size(),StringUtility::listToString(variableNameList).c_str()); #endif bool appendedNewArrayOperand = FALSE; list<string>::const_iterator i; for (i = X.begin(); i != X.end(); i++) { // printf ("Looping through variable names \n"); #if 1 // newer implementation (shorter) setVariableName(*i); #else appendedNewArrayOperand = ArrayOperandDataBase::contains(arrayOperandList,*i); if ( appendedNewArrayOperand == FALSE ) { printf ("append database info to array operand already present (name = %s) \n",(*i).c_str()); arrayOperandList.push_back( ArrayOperandDataBase(*i) ); } else { printf ("Variable already exists (name = %s) \n",(*i).c_str()); } ROSE_ASSERT (arrayOperandList.size() > 0); #endif } #if 0 // variableNameList = X; // This steals the data out of the X list (X.size() == 0 afterwards) variableNameList.merge(X); variableNameList.sort(); variableNameList.unique(); #endif #if 0 printf ("Exiting in OperandDataBaseType::setVariableNameList() \n"); ROSE_ABORT(); #endif }
bool isMethodCall(SgFunctionCallExp *functionCall, bool &isDotExp) { ROSE_ASSERT(functionCall != NULL); SgExpression *expression = functionCall->get_function(); ROSE_ASSERT(expression != NULL); bool isMethod = false; isDotExp = false; switch(expression->variantT()) { case V_SgDotExp: { isMethod = true; SgDotExp *dotExp = isSgDotExp(expression); ROSE_ASSERT(dotExp != NULL); SgExpression *lhs = dotExp->get_lhs_operand(); ROSE_ASSERT(lhs != NULL); SgPointerDerefExp *pointerDerefExp = isSgPointerDerefExp(lhs); if ( pointerDerefExp != NULL ) { ; } else { isDotExp = true; } break; } case V_SgMemberFunctionRefExp: case V_SgArrowExp: { isMethod = true; break; } case V_SgFunctionRefExp: case V_SgPointerDerefExp: { isMethod = false; break; } default: { std::cerr << "Was not expecting an " << expression->sage_class_name() << std::endl; std::cerr << "in a function call." << std::endl; ROSE_ABORT(); } } return isMethod; }
// Functions required by the global tree traversal mechanism ProgramTransformationSynthesizedAttributeType ArrayStatementTraversal::evaluateRewriteSynthesizedAttribute ( SgNode* astNode, ProgramTransformationInheritedAttributeType inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList) { // Build the synthesizied attribute that this function will return ProgramTransformationSynthesizedAttributeType returnSynthesizedAttribute(astNode); #if 0 printf ("$$$$$ TOP of ArrayStatementTraversal::evaluateRewriteSynthesizedAttribute (astNode = %s) (synthesizedAttributeList.size() = %d) \n", astNode->sage_class_name(),synthesizedAttributeList.size()); // inheritedAttribute.display("In ArrayStatementTraversal::evaluateRewriteInheritedAttribute"); #endif if (astNode->variantT() == V_SgExprStatement) { // The program logic can't reset the returnSynthesizedAttribute for each transformation #if 0 printf ("ERROR: In ArrayStatementTraversal::evaluateRewriteSynthesizedAttribute(): The program logic can't reset the returnSynthesizedAttribute for each transformation... \n"); ROSE_ABORT(); #endif // printf ("Found an expression statement (programTransformation.C) \n"); // We use the operator+=() because more than one transformation function could be called in general. // Below we will call the scalar indexing transformation as a second transformation. Both, and more, // will be called for Expression statements in the future (e.g. indirect addressing). // returnSynthesizedAttribute += arrayAssignmentTransformation(inheritedAttribute,astNode); #if 0 // printf ("Calling arrayAssignmentTransformation() \n"); returnSynthesizedAttribute = arrayAssignmentTransformation(inheritedAttribute,astNode); // arrayAssignmentTransformation(inheritedAttribute,astNode); // printf ("DONE: arrayAssignmentTransformation() \n"); #endif #if 1 // Turn off the scalar indexing transformation for now // returnSynthesizedAttribute += ScalarIndexingArrayStatementTransformation::transformation(project,astNode); // returnSynthesizedAttribute += ScalarIndexingArrayStatementTransformation::transformation(inheritedAttribute,astNode); returnSynthesizedAttribute = arrayScalarIndexingTransformation(inheritedAttribute,astNode); #endif } #if 0 printf ("$$$$$ BOTTOM of attributeAssemblyFunction (astNode = %s) (declaration list size = %d) (returnSynthesizedAttribute.getTransformationSourceCode() = \n%s) \n", astNode->sage_class_name(), returnSynthesizedAttribute.variableDeclarationList.size(), returnSynthesizedAttribute.getSourceCodeString().c_str()); #endif return returnSynthesizedAttribute; }
ProgramTransformationSynthesizedAttributeType ArrayStatementTraversal::arrayScalarIndexingTransformation ( const ProgramTransformationInheritedAttributeType & inheritedAttribute, SgNode* astNode ) { ROSE_ASSERT (astNode != NULL); ROSE_ASSERT (isSgExprStatement(astNode) != NULL); ProgramTransformationSynthesizedAttributeType gatheredInfo(astNode); if (ScalarIndexingStatementTransformation::targetForTransformation(astNode) == true) { // printf ("Calling ScalarIndexingArrayStatementTransformation::transformation() \n"); gatheredInfo = ScalarIndexingStatementTransformation::transformation(inheritedAttribute,astNode); // printf ("At base of case 'ScalarIndexingArrayStatementTransformation::targetForTransformation(astNode) == true' \n"); // gatheredInfo.display("Called from ArrayStatementTraversal::arrayAssignmentTransformation() after ArrayAssignmentStatementTransformation::transformation()"); // Since the transformation shouldhave generated global variable we can make sure that some strings are present ROSE_ASSERT (gatheredInfo.isEmpty() == false); #if 0 printf ("Exiting as part of testing ... (at base of ArrayStatementTraversal::arrayScalarIndexingTransformation) \n"); ROSE_ABORT(); #endif } // gatheredInfo.display("Called from ArrayStatementTraversal::arrayScalarIndexingTransformation()"); #if 0 printf ("Exiting as part of testing ... (at base of ArrayStatementTraversal::arrayScalarIndexingTransformation) \n"); ROSE_ABORT(); #endif // This copies and returns the SynthesizedAttributeBaseClassType information return gatheredInfo; }
void IndexOperandDataBase::merge( vector<IndexOperandDataBase> & X, const vector<IndexOperandDataBase> & Y ) { // traverse Y and add elements to X if they represent new operands // printf ("In IndexOperandDataBase::merge(X,Y): merging list Y into list X \n"); // printf ("In IndexOperandDataBase::merge(X,Y): X.size() = %d Y.size() = %d \n",X.size(),Y.size()); vector<IndexOperandDataBase> listOfIndexOperandsToAdd; vector<IndexOperandDataBase>::const_iterator i; for (i = Y.begin(); i != Y.end(); i++) { // printf ("Iterating through array operands in Y (*i).displayString() = %s \n",(*i).displayString().c_str()); vector<IndexOperandDataBase>::iterator j; for (j = X.begin(); j != X.end(); j++) { // printf ("Iterating through array operands in X (*j).displayString() = %s \n",(*j).displayString().c_str()); if (*j == *i) { // printf ("Processing index operand: calling (*j).merge(*i) \n"); (*j).merge(*i); } else { // printf ("Processing index operand: calling X.push_back(*i) \n"); X.push_back(*i); } } } // Now add the identified index operands to the X list vector<IndexOperandDataBase>::iterator k; for (k = listOfIndexOperandsToAdd.begin(); k != listOfIndexOperandsToAdd.end(); k++) { // printf ("Adding identified index operand to X list: (*k).displayString() = %s \n",(*k).displayString().c_str()); X.push_back(*k); } // IndexOperandDataBase::merge( X, Y ); #if 0 printf ("Exiting in IndexOperandDataBase::merge() \n"); ROSE_ABORT(); #endif }
string typeStringFromType(SgType* sageType){ ROSE_ASSERT( sageType != NULL ); vector<SgType*> typeVector = typeVectorFromType(sageType); string typeParsed = ""; for(int i = typeVector.size()-1; i>=0; i=i-1){ sageType = typeVector[i]; switch(sageType->variantT()) { case V_SgReferenceType: break; case V_SgPointerType: typeParsed = typeParsed + "*"; break; case V_SgTypedefType: ROSE_ABORT(); default: typeParsed = typeParsed + TransformationSupport::getTypeName(sageType); break; }; } return typeParsed; };
// ScalarIndexingStatementQuerySynthesizedAttributeType SynthesizedAttributeBaseClassType ScalarIndexingStatementTransformation::transformation ( const ArrayStatementQueryInheritedAttributeType & X, SgNode* astNode ) { // This function returns the string representing the array statement transformation ROSE_ASSERT (isSgExprStatement(astNode) != NULL); ScalarIndexingStatementQueryInheritedAttributeType scalarIndexingStatementQueryInheritedData(X,astNode); // Declare the list to place transformation options into from each scope as we traverse backward // (up) the AST to the Global scope. // list<int> transformationOptions; // inherited attribute list<int> & transformationOptions = scalarIndexingStatementQueryInheritedData.getTransformationOptions(); printf ("ScalarIndexingStatementQueryInheritedData.arrayStatementDimension = %d \n", scalarIndexingStatementQueryInheritedData.arrayStatementDimension); // We have to use a special function here instead of the Query mechanism since the Query mechanism // searches down through he AST (parents traverse their children) and we want to traverse up // through the AST (and not the whole AST) from the child to the parent stopping at the root of // the AST (the global scope: SgGlobal) printf ("############### CALLING TRANSFORMATION OPTION QUERY FROM ASSIGNMENT TRANSFORMATION ############ \n"); // Find all the hints specified as enum values constructor parameters for declarations of // variables of type "TransformationAssertion". The current scope and all parent scopes are // searched back to the global scope. (Maybe this should return a value rather than modify a // reference parameter???) TransformationSupport::getTransformationOptions ( astNode, transformationOptions, "TransformationAssertion"); #if 1 // List the different transformation options that are specified in the user's code // list<TransformationAssertion::TransformationOption>::iterator transformationOptionListIterator; list<int>::iterator transformationOptionListIterator; for (transformationOptionListIterator = transformationOptions.begin(); transformationOptionListIterator != transformationOptions.end(); transformationOptionListIterator++) { // display each value // TransformationAssertion::TransformationOption i = *transformationOptionListIterator; int i = *transformationOptionListIterator; printf (" Value in transformation option = %d name = %s \n",i,TransformationAssertion::getOptionString(i)); } #endif // If there are any index object in use then we can't do the transformation (so make sure there are none) ROSE_ASSERT (NameQuery::getVariableNamesWithTypeNameQuery (astNode,"Internal_Index").size() == 0); printf ("######################### END OF INTERNALINDEX NAME QUERY ######################## \n"); printf ("################# START OF ARRAY STATEMENT DIMENSION QUERY ################ \n"); // The dimension of the array statement must be computed on the way down (in the traversal of the AST). // This query gets the list of integer associated with the dimension of each array operand (array // operands using the doubleArray::operator() member function). list<int> operandDimensionList = NumberQuery::getNumberOfArgumentsToParenthesisOperatorQuery (astNode, "doubleArray" ); ROSE_ASSERT (operandDimensionList.size() >= 0); #if 1 printf ("operandDimensionList.size() = %d \n",operandDimensionList.size()); printf ("operandDimensionList = \n%s\n",StringUtility::listToString(operandDimensionList).c_str()); #endif // Now use STL to build a list of unique names operandDimensionList.unique(); #if 0 printf ("Unique Names: operandDimensionList = \n%s\n",StringUtility::listToString(operandDimensionList).c_str()); #endif // If there is no dimension computed for the query then it means that there were no operator() // used in which case we have to assume 6D array operations int dimensionOfArrayStatement = (operandDimensionList.size() == 0) ? 6 : *(operandDimensionList.begin()); printf ("Array statement is %d dimensional \n",dimensionOfArrayStatement); // Make sure that it has the default value before we change it (error checking) printf ("ScalarIndexingStatementQueryInheritedData.arrayStatementDimension = %d \n", scalarIndexingStatementQueryInheritedData.arrayStatementDimension); ROSE_ASSERT (scalarIndexingStatementQueryInheritedData.arrayStatementDimension == -1); // Modify the inherited attribute using the array statement dimension data scalarIndexingStatementQueryInheritedData.arrayStatementDimensionDefined = TRUE; scalarIndexingStatementQueryInheritedData.arrayStatementDimension = dimensionOfArrayStatement; #if 0 printf ("ScalarIndexingStatementQueryInheritedData.arrayStatementDimension = %d \n", scalarIndexingStatementQueryInheritedData.arrayStatementDimension); printf ("Exiting as part of testing (after search for array statement dimension) ... \n"); ROSE_ABORT(); #endif ScalarIndexingStatementTransformation transformation; // Build a return value for this function ScalarIndexingStatementQuerySynthesizedAttributeType returnScalarIndexingStatementTransformation(astNode); // We need these until we have a new interface which will allow us to skip them (they are not used) // ScalarIndexingStatementQueryAccumulatorType accumulatorValue; // WARNING: It is a design problem that we have the dimension set in two locations // To to implement this transformation withouth a database mechanism // Set the dimension of the array statement in the array operand database transformation.accumulatorValue.operandDataBase.setDimension(dimensionOfArrayStatement); ROSE_ASSERT (transformation.accumulatorValue.operandDataBase.getDimension() > 0); // Setup the data base with the options specified by the use and extracted from the current scope // of the application code. transformation.accumulatorValue.operandDataBase.setUserOptimizationAssertions (scalarIndexingStatementQueryInheritedData.transformationOptions); ROSE_ASSERT ( transformation.accumulatorValue.operandDataBase.transformationOption > ArrayTransformationSupport::UnknownIndexingAccess ); // Make sure the data base has been setup properly ROSE_ASSERT ( transformation.accumulatorValue.operandDataBase.transformationOption > ArrayTransformationSupport::UnknownIndexingAccess ); ROSE_ASSERT ( transformation.accumulatorValue.operandDataBase.dimension > -1 ); // We must call this preorder because we modify the inherited attribute on the way down into the // AST so that the assembly will have the correct array statment dimension on the way back up (the // assembly of attributes always happens postorder). returnScalarIndexingStatementTransformation = transformation.traverse ( astNode, scalarIndexingStatementQueryInheritedData ); // printf ("accumulatorValue.operandDataBase.displayString() = %s \n",accumulatorValue.operandDataBase.displayString().c_str()); // ROSE_ASSERT (accumulatorValue.operandDataBase.size() > 0); // Copy the operand data base out of the accumulator attribute and into the ScalarIndexingStatementTransformation object // operandDataBase = transformation.accumulatorValue.operandDataBase; // printf ("transformation.accumulatorValue.operandDataBase.displayString() = %s \n", // transformation.accumulatorValue.operandDataBase.displayString().c_str()); #if 0 // Verify that we have saved the global and variable declarations and variable initializations ROSE_ASSERT (returnScalarIndexingStatementTransformation.globalDeclarationStrings.isEmpty() == false); ROSE_ASSERT (returnScalarIndexingStatementTransformation.variableDeclarationStrings.isEmpty() == false); ROSE_ASSERT (returnScalarIndexingStatementTransformation.variableInitializationStrings.isEmpty() == false); #endif // Verify that we have a valid string ROSE_ASSERT (returnScalarIndexingStatementTransformation.isEmpty() == false); printf ("######################### END OF SCALAR INDEXING TRANSFORMATION QUERY ######################## \n"); printf ("returnScalarIndexingStatementTransformation.getTransformationSourceCode().c_str() = \n%s \n", returnScalarIndexingStatementTransformation.getWorkSpace().c_str()); #if 0 // NOTE: I think we need to get the variable declarations out of returnArrayStatementTransformation list<string> stringList = returnArrayStatementTransformation.getVariableDeclarationStrings(); ROSE_ASSERT (stringList.size() > 0); for (list<string>::iterator i = stringList.begin(); i != stringList.end(); i++) printf ("Base of ScalarIndexingStatementTransformation::transformation(): getVariableDeclarationStrings() = %s \n",(*i).c_str()); #endif #if 0 printf ("Exiting as part of testing (after SCALAR INDEXING TRANSFORMATION QUERY) ... \n"); ROSE_ABORT(); #endif return returnScalarIndexingStatementTransformation; }
int main ( int argc, char* argv[] ) { // Main Function for default example ROSE Preprocessor // This is an example of a preprocessor that can be built with ROSE // This example can be used to test the ROSE infrastructure #if 1 list<string> l = CommandlineProcessing::generateArgListFromArgcArgv (argc,argv); printf ("Preprocessor (before): argv = \n%s \n",StringUtility::listToString(l).c_str()); // testing removeArgs CommandlineProcessing::removeArgs (argc,argv,"-edg:"); CommandlineProcessing::removeArgs (argc,argv,"--edg:"); CommandlineProcessing::removeArgsWithParameters (argc,argv,"-edg_parameter:"); CommandlineProcessing::removeArgsWithParameters (argc,argv,"--edg_parameter:"); printf ("argc = %d \n",argc); l = CommandlineProcessing::generateArgListFromArgcArgv (argc,argv); printf ("l.size() = %d \n",l.size()); printf ("Preprocessor (after): argv = \n%s \n",StringUtility::listToString(l).c_str()); // printf ("Exiting in main! \n"); // ROSE_ASSERT(1 == 2); #endif #if 0 int modifiedArgc = 0; char** modifiedArgv = NULL; // resets modifiedArgc and allocates memory to modifiedArgv // list<string> edgOptionWithNameParameterList = // CommandlineProcessing::generateOptionWithNameParameterList (argc, argv,"-edg_parameter:",modifiedArgc,modifiedArgv); // resets modifiedArgc and allocates memory to modifiedArgv list<string> edgOptionWithNumberParameterList = CommandlineProcessing::generateOptionWithNameParameterList (argc, argv,"-edg_parameter:",modifiedArgc,modifiedArgv); l = CommandlineProcessing::generateArgListFromArgcArgv (modifiedArgc,modifiedArgv); printf ("Preprocessor (after): argv = \n%s \n",StringUtility::listToString(l).c_str()); // resets modifiedArgc to zero and releases memory from modifiedArgv (resets modifiedArgv to NULL) CommandlineProcessing::releaseArgListMemory(modifiedArgc,modifiedArgv); #endif #if 0 if ( CommandlineProcessing::isOption(argc,argv,"-rose:","(h|help)",true) || CommandlineProcessing::isOption(argc,argv,"-", "(h|help)",true) || CommandlineProcessing::isOption(argc,argv,"--","(h|help)",true) ) { printf ("\nROSE (pre-release alpha version: %s) \n",VERSION); ROSE::usage(0); exit(0); } l = CommandlineProcessing::generateArgListFromArgcArgv (argc,argv); printf ("Preprocessor (after): argv = \n%s \n",StringUtility::listToString(l).c_str()); printf ("Exiting after initial command line processing \n"); ROSE_ABORT(); #endif #if 0 string stringParameter; if ( CommandlineProcessing::isOptionWithParameter(argc,argv,"-rose:","(o|output)",stringParameter,true) ) { printf ("-rose:output %s \n",stringParameter.c_str()); // Make our own copy of the filename string int length = stringParameter.length(); char* p_unparse_output_filename = (char*) new char[length+1]; ROSE_ASSERT (p_unparse_output_filename != NULL); stringParameter.copy(p_unparse_output_filename,length,0); p_unparse_output_filename[length] = '\0'; printf ("p_unparse_output_filename = %s \n",p_unparse_output_filename); } else { printf ("-rose:output not set! \n"); } #endif #if 0 int modifiedArgc = 0; char** modifiedArgv = NULL; // resets modifiedArgc and allocates memory to modifiedArgv list<string> edgOptionList = CommandlineProcessing::generateOptionList (argc, argv,"-edg:",modifiedArgc,modifiedArgv); // resets modifiedArgc to zero and releases memory from modifiedArgv (resets modifiedArgv to NULL) CommandlineProcessing::releaseArgListMemory(modifiedArgc,modifiedArgv); if ( CommandlineProcessing::isOption(argc,argv,"-","help",true) ) { printf ("Option -help found! \n"); } if ( CommandlineProcessing::isOption(argc,argv,"--","help",true) ) { printf ("Option --help found! \n"); } int integerParameter; if ( CommandlineProcessing::isOptionWithParameter(argc,argv,"-edg:","test",integerParameter,true) ) { printf ("Option (integer parameter) -test %d found! \n",integerParameter); } string stringParameter; if ( CommandlineProcessing::isOptionWithParameter(argc,argv,"-edg:","test",stringParameter,true) ) { printf ("Option (string parameter) -test %s found! \n",stringParameter.c_str()); } #endif SgProject* project = frontend(argc,argv); ROSE_ASSERT (project != NULL); #if 0 // See if we can access the EDG AST directly ROSE_ASSERT (il_header.primary_source_file != NULL); ROSE_ASSERT (il_header.primary_source_file->file_name != NULL); printf ("##### il_header.primary_source_file->file_name = %s \n",il_header.primary_source_file->file_name); #endif // DQ (2/6/2004): These tests fail in Coco for test2004_14.C // AstTests::runAllTests(const_cast<SgProject*>(project)); // printf ("Generate the pdf output of the SAGE III AST \n"); // generatePDF ( project ); printf ("Generate the DOT output of the SAGE III AST \n"); generateDOT ( *project ); return backend(project); // alternative form // return backend(frontend(argc,argv)); }
void SgNode::insertSourceCode ( SgProject & project, const char* sourceCodeString, const char* localDeclaration, const char* globalDeclaration, bool locateNewCodeAtTop, bool isADeclaration ) { // If this function is useful only for SgBasicBlock then it should be put into that class directly. // This function is used to insert code into AST object for which insertion make sense: // (specifically any BASIC_BLOCK_STMT) if (variant() != BASIC_BLOCK_STMT) { printf ("ERROR: insert only make since for BASIC_BLOCK_STMT statements (variant() == variant()) \n"); ROSE_ABORT(); } SgBasicBlock* currentBlock = isSgBasicBlock(this); ROSE_ASSERT (currentBlock != NULL); // printf ("##### Calling SgNode::generateAST() \n"); #if 0 printf ("In insertSourceCode(): globalDeclaration = \n%s\n",globalDeclaration); printf ("In insertSourceCode(): localDeclaration = \n%s\n",localDeclaration); printf ("In insertSourceCode(): sourceCodeString = \n%s\n",sourceCodeString); #endif // SgNode* newTransformationAST = generateAST (project,sourceCodeString,globalDeclaration); // ROSE_ASSERT (newTransformationAST != NULL); SgStatementPtrList* newTransformationStatementListPtr = generateAST (project,sourceCodeString,localDeclaration,globalDeclaration,isADeclaration); ROSE_ASSERT (newTransformationStatementListPtr != NULL); ROSE_ASSERT (newTransformationStatementListPtr->size() > 0); // printf ("##### DONE: Calling SgNode::generateAST() \n"); // get a reference to the statement list out of the basic block SgStatementPtrList & currentStatementList = currentBlock->get_statements(); if (locateNewCodeAtTop == true) { // Insert at top of list (pull the elements off the bottom of the new statement list to get the order correct // printf ("Insert new statements (new statement list size = %d) at the top of the block (in reverse order to preset the order in the final block) \n",newTransformationStatementListPtr->size()); SgStatementPtrList::reverse_iterator transformationStatementIterator; for (transformationStatementIterator = newTransformationStatementListPtr->rbegin(); transformationStatementIterator != newTransformationStatementListPtr->rend(); transformationStatementIterator++) { // Modify where a statement is inserted to avoid dependent variables from being inserted // before they are declared. // Get a list of the variables // Generate the list of types used within the target subtree of the AST list<string> typeNameStringList = NameQuery::getTypeNamesQuery ( *transformationStatementIterator ); int statementCounter = 0; int previousStatementCounter = 0; // Declaration furthest in source sequence of all variables referenced in code to be inserted (last in source sequence order) // SgStatementPtrList::iterator furthestDeclarationInSourceSequence = NULL; SgStatementPtrList::iterator furthestDeclarationInSourceSequence; #if 0 string unparsedDeclarationCodeString = (*transformationStatementIterator)->unparseToString(); ROSE_ASSERT (unparsedDeclarationCodeString.c_str() != NULL); printf ("unparsedDeclarationCodeString = %s \n",unparsedDeclarationCodeString.c_str()); #endif if ( typeNameStringList.size() > 0 ) { // There should be at least one type in the statement ROSE_ASSERT (typeNameStringList.size() > 0); // printf ("typeNameStringList.size() = %d \n",typeNameStringList.size()); // printf ("This statement has a dependence upon a variable of some type \n"); // Loop over all the types and get list of variables of each type // (so they can be declared properly when the transformation is compiled) list<string>::iterator typeListStringElementIterator; for (typeListStringElementIterator = typeNameStringList.begin(); typeListStringElementIterator != typeNameStringList.end(); typeListStringElementIterator++) { // printf ("Type = %s \n",(*typeListStringElementIterator).c_str()); // Find a list of names of variable of type (*listStringElementIterator) list<string> operandNameStringList = NameQuery::getVariableNamesWithTypeNameQuery ( *transformationStatementIterator, *typeListStringElementIterator ); // There should be at least one variable of that type in the statement ROSE_ASSERT (operandNameStringList.size() > 0); // printf ("operandNameStringList.size() = %d \n",operandNameStringList.size()); // Loop over all the types and get list of variable of each type list<string>::iterator variableListStringElementIterator; for (variableListStringElementIterator = operandNameStringList.begin(); variableListStringElementIterator != operandNameStringList.end(); variableListStringElementIterator++) { #if 0 printf ("Type = %s Variable = %s \n", (*typeListStringElementIterator).c_str(), (*variableListStringElementIterator).c_str()); #endif string variableName = *variableListStringElementIterator; string typeName = *typeListStringElementIterator; SgName name = variableName.c_str(); SgVariableSymbol* symbol = currentBlock->lookup_var_symbol(name); if ( symbol != NULL ) { // found a variable with name -- make sure that the declarations // represented by *transformationStatementIterator are inserted // after their declaration. #if 0 printf ("Found a valid symbol corresponding to Type = %s Variable = %s (must be defined in the local scope) \n", (*typeListStringElementIterator).c_str(), (*variableListStringElementIterator).c_str()); #endif ROSE_ASSERT (symbol != NULL); SgInitializedName* declarationInitializedName = symbol->get_declaration(); ROSE_ASSERT (declarationInitializedName != NULL); SgDeclarationStatement* declarationStatement = declarationInitializedName->get_declaration(); ROSE_ASSERT (declarationStatement != NULL); #if 0 printf ("declarationStatementString located at line = %d of file = %s \n", rose::getLineNumber(declarationStatement), rose::getFileName(declarationStatement)); string declarationStatementString = declarationStatement->unparseToString(); printf ("declarationStatementString = %s \n",declarationStatementString.c_str()); #endif statementCounter = 1; SgStatementPtrList::iterator i = currentStatementList.begin(); bool declarationFound = false; while ( ( i != currentStatementList.end() ) && ( declarationFound == false ) ) { // searching for the declarationStatement #if 0 printf ("statementCounter = %d previousStatementCounter = %d \n", statementCounter,previousStatementCounter); string currentStatementString = (*i)->unparseToString(); printf ("currentStatementString = %s \n",currentStatementString.c_str()); #endif if ( (*i == declarationStatement) && (statementCounter > previousStatementCounter) ) { // printf ("Found the declarationStatement at position (statementCounter = %d previousStatementCounter = %d) \n",statementCounter,previousStatementCounter); declarationFound = true; } else { // printf ("Not the declaration we are looking for! \n"); i++; statementCounter++; } } // Save a reference to the variable declaration that is furthest in // the source sequence so that we can append the new statement just // after it (so that variables referenced in the new statement will // be defined). if ( (statementCounter > previousStatementCounter) && ( declarationFound == true ) ) { previousStatementCounter = statementCounter; furthestDeclarationInSourceSequence = i; } #if 0 printf ("AFTER LOOP OVER STATEMENTS: previousStatementCounter = %d \n",previousStatementCounter); string lastStatementString = (*furthestDeclarationInSourceSequence)->unparseToString(); printf ("lastStatementString = %s \n",lastStatementString.c_str()); #endif } else { // If the variable is not found then insert the new statement at the front of the list #if 0 printf ("Can NOT find a valid symbol corresponding to Type = %s Variable = %s (so it is not declared in the local scope) \n", (*typeListStringElementIterator).c_str(), (*variableListStringElementIterator).c_str()); #endif // currentStatementList.push_front(*transformationStatementIterator); } #if 0 printf ("BOTTOM OF LOOP OVER VARIABLES: previousStatementCounter = %d \n",previousStatementCounter); #endif } if (statementCounter > previousStatementCounter) previousStatementCounter = statementCounter; #if 0 printf ("BOTTOM OF LOOP OVER TYPES: previousStatementCounter = %d \n",previousStatementCounter); #endif #if 0 printf ("Exiting in insertSourceCode(): transformationStatementIterator loop (type = %s) ... \n",(*typeListStringElementIterator).c_str()); ROSE_ABORT(); #endif } #if 0 printf ("Exiting in loop insertSourceCode (type = %s) ... \n",(*typeListStringElementIterator).c_str()); ROSE_ABORT(); #endif // Now append the new statement AFTER the declaration that we have found // currentStatementList.insert(*targetDeclarationStatementIterator,*transformationStatementIterator); // currentStatementList.insert(lastStatementIterator,*transformationStatementIterator); #if 1 // printf ("BEFORE ADDING NEW STATEMENT: previousStatementCounter = %d \n",previousStatementCounter); if (previousStatementCounter == 0) { printf ("##### Prepend new statement to the top of the local scope \n"); // currentStatementList.push_front(*transformationStatementIterator); currentBlock->prepend_statement (*transformationStatementIterator); } else { // printf ("##### Append the new statement after the last position where a dependent variable is declared in the local scope \n"); // Use new function added to append/prepend at a specified location in the list of statements currentBlock->append_statement (furthestDeclarationInSourceSequence,*transformationStatementIterator); } #else SgStatementPtrList::iterator tempIterator = furthestDeclarationInSourceSequence; tempIterator++; // Handle the case of appending at the end of the list if ( tempIterator == currentStatementList.end() ) { currentBlock->append_statement (*transformationStatementIterator); } else { currentBlock->insert_statement (tempIterator,*transformationStatementIterator); } #endif } else { // This statement has no type information (so it has no dependence upon any non-primative type) // "int x;" would be an example of a statement that would not generate a type (though perhaps it should?) // printf ("This statement has no type information (so it has no dependence upon any non-primative type) \n"); // So this statment can be places at the front of the list of statements in this block // *** Note that we can't use the STL function directly since it does not set the parent information *** // currentStatementList.push_front(*transformationStatementIterator); currentBlock->insert_statement (currentStatementList.begin(),*transformationStatementIterator); } #if 0 string bottomUnparsedDeclarationCodeString = (*transformationStatementIterator)->unparseToString(); ROSE_ASSERT (bottomUnparsedDeclarationCodeString.c_str() != NULL); printf ("bottomUnparsedDeclarationCodeString = %s \n",bottomUnparsedDeclarationCodeString.c_str()); #endif } #if 0 printf ("Exiting in insertSourceCode(): case of locateNewCodeAtTop == true ... \n"); ROSE_ABORT(); #endif } else { // Put the new statements at the end of the list (traverse the new statements from first to last) // But put it before any return statement! So find the last statement! SgStatementPtrList::iterator lastStatement = currentStatementList.begin(); bool foundEndOfList = false; while ( (foundEndOfList == false) && (lastStatement != currentStatementList.end()) ) { SgStatementPtrList::iterator tempStatement = lastStatement; tempStatement++; if (tempStatement == currentStatementList.end()) foundEndOfList = true; else lastStatement++; } ROSE_ASSERT ( *lastStatement != NULL ); // printf ("(*lastStatement)->sage_class_name() = %s \n",(*lastStatement)->sage_class_name()); // printf ("Insert new statements at the bottom of the block \n"); SgStatementPtrList::iterator transformationStatementIterator; for (transformationStatementIterator = newTransformationStatementListPtr->begin(); transformationStatementIterator != newTransformationStatementListPtr->end(); transformationStatementIterator++) { // If there is a RETURN_STMT in the block then insert the new statement just before the // existing RETURN_STMT if ( (*lastStatement)->variant() == RETURN_STMT) { // printf ("Backing away from the end of the list to find the last non-return statement \n"); // lastStatement--; currentBlock->insert_statement(lastStatement,*transformationStatementIterator); } else { currentStatementList.push_back(*transformationStatementIterator); } } } // printf ("$CLASSNAME::insertSourceCode taking (SgProject,char*,char*) not implemented yet! \n"); // ROSE_ABORT(); }
string AST_Rewrite::AccumulatedDeclarationsAttribute:: generateDeclarationString ( SgDeclarationStatement* declaration ) const { // This function generates a string for a declaration. The string is required for // the intermediate file to make sure that all transformation code will compile // (since it could depend on declarations defined within the code). // Details: // 1) Only record declarations found within the source file (exclude all header files // since they will be seen when the same header files are included). // 2) Resort the variable declarations to remove redundent entries. // WRONG: variable declarations could have dependences upon class declarations! // 3) Don't sort all declarations since some could have dependences. // a) class declarations // b) typedefs // c) function declarations // d) template declarations // e) variable definition??? ROSE_ASSERT (this != NULL); ROSE_ASSERT ( declaration != NULL ); string declarationString; // Build a SgUnparse_Info object to represent formatting options for // this statement (use the default values). SgUnparse_Info info; // exclude comments info.set_SkipComments(); // exclude all CPP directives (since they have already been evaluated by the front-end) info.set_SkipCPPDirectives(); switch ( declaration->variantT() ) { // Enum declarations should not skip their definition since // this is where the constants are declared. case V_SgEnumDeclaration: case V_SgVariableDeclaration: case V_SgTemplateDeclaration: case V_SgTypedefDeclaration: // Need to figure out if a forward declaration would work or be // more conservative and always output the complete class definition. // turn off output of initializer values info.set_SkipInitializer(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; case V_SgClassDeclaration: // Need to figure out if a forward declaration would work or be // more conservative and always output the complete class definition. // turn off the generation of the function definitions only // (we still want the restof the class definition since these // define all member data and member functions). // info.set_SkipClassDefinition(); info.set_SkipFunctionDefinition(); info.set_AddSemiColonAfterDeclaration(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; // For functions just output the declaration and skip the definition // (This also avoids the generation of redundent definitions since the // function we are in when we generate all declarations would be included). case V_SgMemberFunctionDeclaration: case V_SgFunctionDeclaration: { // turn off the generation of the definition info.set_SkipFunctionDefinition(); info.set_AddSemiColonAfterDeclaration(); // output the declaration as a string declarationString = globalUnparseToString(declaration,&info); break; } case V_SgFunctionParameterList: { // Handle generation of declaration strings this case differnetly from unparser // since want to generate declaration strings and not function parameter lists // (function parameter lists would be delimited by "," while declarations would // be delimited by ";"). SgFunctionParameterList* parameterListDeclaration = dynamic_cast<SgFunctionParameterList*>(declaration); ROSE_ASSERT (parameterListDeclaration != NULL); SgInitializedNameList & argList = parameterListDeclaration->get_args(); SgInitializedNameList::iterator i; for (i = argList.begin(); i != argList.end(); i++) { string typeNameString = (*i).get_type()->unparseToString(); // (9/8/2003) Bug Fix suggested by Nils // string variableName = (*i).get_name().str(); string variableName; SgName nodeName = (*i).get_name(); if(nodeName.str() != NULL) variableName = nodeName.str(); else variableName = ""; declarationString += typeNameString + " " + variableName + "; "; } break; } // ignore this case ... not really a declaration case V_SgCtorInitializerList: // printf ("Ignore the SgCtorInitializerList (constructor initializer list) \n"); break; case V_SgVariableDefinition: printf ("ERROR: SgVariableDefinition nodes not used in AST \n"); ROSE_ABORT(); break; // default case should always be an error default: printf ("Default reached in AST_Rewrite::AccumulatedDeclarationsAttribute::generateDeclarationString() \n"); printf (" declaration->sage_class_name() = %s \n",declaration->sage_class_name()); ROSE_ABORT(); break; } // Add a space to make it easier to read (not required) declarationString += " "; // printf ("For this scope: declarationString = %s \n",declarationString.c_str()); return declarationString; }
string globalUnparseToString ( SgNode* astNode, SgUnparse_Info* inputUnparseInfoPointer ) { // This global function permits any SgNode (including it's subtree) to be turned into a string // DQ (3/2/2006): Let's make sure we have a valid IR node! ROSE_ASSERT(astNode != NULL); string returnString; // all options are now defined to be false. When these options can be passed in // from the prompt, these options will be set accordingly. bool _auto = false; bool linefile = false; bool useOverloadedOperators = false; bool num = false; // It is an error to have this always turned off (e.g. pointer = this; will not unparse correctly) bool _this = true; bool caststring = false; bool _debug = false; bool _class = false; bool _forced_transformation_format = false; bool _unparse_includes = false; // printf ("In globalUnparseToString(): astNode->sage_class_name() = %s \n",astNode->sage_class_name()); Unparser_Opt roseOptions( _auto, linefile, useOverloadedOperators, num, _this, caststring, _debug, _class, _forced_transformation_format, _unparse_includes ); int lineNumber = 0; // Zero indicates that ALL lines should be unparsed // Initialize the Unparser using a special string stream inplace of the usual file stream ostringstream outputString; SgLocatedNode* locatedNode = isSgLocatedNode(astNode); string fileNameOfStatementsToUnparse; if (locatedNode == NULL) { // printf ("WARNING: applying AST -> string for non expression/statement AST objects \n"); fileNameOfStatementsToUnparse = "defaultFileNameInGlobalUnparseToString"; } else { ROSE_ASSERT (locatedNode != NULL); // DQ (5/31/2005): Get the filename from a traversal back through the parents to the SgFile // fileNameOfStatementsToUnparse = locatedNode->getFileName(); // fileNameOfStatementsToUnparse = rose::getFileNameByTraversalBackToFileNode(locatedNode); if (locatedNode->get_parent() == NULL) { // DQ (7/29/2005): // Allow this function to be called with disconnected AST fragments not connected to // a previously generated AST. This happens in Qing's interface where AST fragements // are built and meant to be unparsed. Only the parent of the root of the AST // fragement is expected to be NULL. fileNameOfStatementsToUnparse = locatedNode->getFileName(); } else { fileNameOfStatementsToUnparse = rose::getFileNameByTraversalBackToFileNode(locatedNode); } } ROSE_ASSERT (fileNameOfStatementsToUnparse.size() > 0); Unparser roseUnparser ( &outputString, fileNameOfStatementsToUnparse, roseOptions, lineNumber ); // Information that is passed down through the tree (inherited attribute) // Use the input SgUnparse_Info object if it is available. SgUnparse_Info* inheritedAttributeInfoPointer = NULL; if (inputUnparseInfoPointer != NULL) { // printf ("Using the input inputUnparseInfoPointer object \n"); // Use the user provided SgUnparse_Info object inheritedAttributeInfoPointer = inputUnparseInfoPointer; } else { // DEFINE DEFAULT BEHAVIOUR FOR THE CASE WHEN NO inputUnparseInfoPointer (== NULL) IS // PASSED AS ARGUMENT TO THE FUNCTION // printf ("Building a new Unparse_Info object \n"); // If no input parameter has been specified then allocate one // inheritedAttributeInfoPointer = new SgUnparse_Info (NO_UNPARSE_INFO); inheritedAttributeInfoPointer = new SgUnparse_Info(); ROSE_ASSERT (inheritedAttributeInfoPointer != NULL); // MS: 09/30/2003: comments de-activated in unparsing ROSE_ASSERT (inheritedAttributeInfoPointer->SkipComments() == false); // Skip all comments in unparsing inheritedAttributeInfoPointer->set_SkipComments(); ROSE_ASSERT (inheritedAttributeInfoPointer->SkipComments() == true); // Skip all whitespace in unparsing (removed in generated string) inheritedAttributeInfoPointer->set_SkipWhitespaces(); ROSE_ASSERT (inheritedAttributeInfoPointer->SkipWhitespaces() == true); // Skip all directives (macros are already substituted by the front-end, so this has no effect on those) inheritedAttributeInfoPointer->set_SkipCPPDirectives(); ROSE_ASSERT (inheritedAttributeInfoPointer->SkipCPPDirectives() == true); } ROSE_ASSERT (inheritedAttributeInfoPointer != NULL); SgUnparse_Info & inheritedAttributeInfo = *inheritedAttributeInfoPointer; // Turn ON the error checking which triggers an error if the default SgUnparse_Info constructor is called // SgUnparse_Info::forceDefaultConstructorToTriggerError = true; #if 1 // DQ (10/19/2004): Cleaned up this code, remove this dead code after we are sure that this worked properly // Actually, this code is required to be this way, since after this branch the current function returns and // some data must be cleaned up differently! So put this back and leave it this way, and remove the // "Implementation Note". // Both SgProject and SgFile are handled via recursive calls if ( (isSgProject(astNode) != NULL) || (isSgFile(astNode) != NULL) ) { // printf ("Implementation Note: Put these cases (unparsing the SgProject and SgFile into the cases for nodes derived from SgSupport below! \n"); // Handle recursive call for SgProject if (isSgProject(astNode) != NULL) { SgProject* project = isSgProject(astNode); ROSE_ASSERT(project != NULL); for (int i = 0; i < project->numberOfFiles(); i++) { SgFile* file = &(project->get_file(i)); ROSE_ASSERT(file != NULL); string unparsedFileString = globalUnparseToString(file,inputUnparseInfoPointer); string prefixString = string("/* TOP:") + string(rose::getFileName(file)) + string(" */ \n"); string suffixString = string("\n/* BOTTOM:") + string(rose::getFileName(file)) + string(" */ \n\n"); returnString += prefixString + unparsedFileString + suffixString; } } // Handle recursive call for SgFile if (isSgFile(astNode) != NULL) { SgFile* file = isSgFile(astNode); ROSE_ASSERT(file != NULL); SgGlobal* globalScope = file->get_root(); ROSE_ASSERT(globalScope != NULL); returnString = globalUnparseToString(globalScope,inputUnparseInfoPointer); } } else #endif { // DQ (1/12/2003): Only now try to trap use of SgUnparse_Info default constructor // Turn ON the error checking which triggers an error if the default SgUnparse_Info constructor is called SgUnparse_Info::set_forceDefaultConstructorToTriggerError(true); if (isSgStatement(astNode) != NULL) { SgStatement* stmt = isSgStatement(astNode); roseUnparser.unparseStatement ( stmt, inheritedAttributeInfo ); } if (isSgExpression(astNode) != NULL) { SgExpression* expr = isSgExpression(astNode); roseUnparser.unparseExpression ( expr, inheritedAttributeInfo ); } if (isSgType(astNode) != NULL) { SgType* type = isSgType(astNode); roseUnparser.unparseType ( type, inheritedAttributeInfo ); } if (isSgSymbol(astNode) != NULL) { SgSymbol* symbol = isSgSymbol(astNode); roseUnparser.unparseSymbol ( symbol, inheritedAttributeInfo ); } if (isSgSupport(astNode) != NULL) { // Handle different specific cases derived from SgSupport // (e.g. template parameters and template arguments). switch (astNode->variantT()) { #if 0 case V_SgProject: { SgProject* project = isSgProject(astNode); ROSE_ASSERT(project != NULL); for (int i = 0; i < project->numberOfFiles(); i++) { SgFile* file = &(project->get_file(i)); ROSE_ASSERT(file != NULL); string unparsedFileString = globalUnparseToString(file,inputUnparseInfoPointer); string prefixString = string("/* TOP:") + string(rose::getFileName(file)) + string(" */ \n"); string suffixString = string("\n/* BOTTOM:") + string(rose::getFileName(file)) + string(" */ \n\n"); returnString += prefixString + unparsedFileString + suffixString; } break; } case V_SgFile: { SgFile* file = isSgFile(astNode); ROSE_ASSERT(file != NULL); SgGlobal* globalScope = file->get_root(); ROSE_ASSERT(globalScope != NULL); returnString = globalUnparseToString(globalScope,inputUnparseInfoPointer); break; } #endif case V_SgTemplateParameter: { SgTemplateParameter* templateParameter = isSgTemplateParameter(astNode); roseUnparser.unparseTemplateParameter(templateParameter,inheritedAttributeInfo); break; } case V_SgTemplateArgument: { SgTemplateArgument* templateArgument = isSgTemplateArgument(astNode); roseUnparser.unparseTemplateArgument(templateArgument,inheritedAttributeInfo); break; } case V_SgInitializedName: { // QY: not sure how to implement this // DQ (7/23/2004): This should unparse as a declaration // (type and name with initializer). break; } case V_Sg_File_Info: { // DQ (5/11/2006): Not sure how or if we shoul implement this break; } // Perhaps the support for SgFile and SgProject shoud be moved to this location? default: printf ("Error: default reached in node derived from SgSupport astNode = %s \n",astNode->sage_class_name()); ROSE_ABORT(); } } // Turn OFF the error checking which triggers an if the default SgUnparse_Info constructor is called SgUnparse_Info::set_forceDefaultConstructorToTriggerError(false); // MS: following is the rewritten code of the above outcommented // code to support ostringstream instead of ostrstream. returnString = outputString.str(); // Call function to tighten up the code to make it more dense if (inheritedAttributeInfo.SkipWhitespaces() == true) { returnString = roseUnparser.removeUnwantedWhiteSpace ( returnString ); } // delete the allocated SgUnparse_Info object if (inputUnparseInfoPointer == NULL) delete inheritedAttributeInfoPointer; } return returnString; }
SgFunctionDeclaration * getFunctionDeclaration(SgFunctionCallExp *functionCall) { SgFunctionDeclaration *funcDec = NULL; SgExpression *expression = functionCall->get_function(); ROSE_ASSERT(expression != NULL); switch(expression->variantT()) { case V_SgMemberFunctionRefExp: { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(expression); ROSE_ASSERT(memberFunctionRefExp != NULL); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); ROSE_ASSERT(funcDec != NULL); break; } case V_SgDotExp: { SgDotExp *dotExp = isSgDotExp(expression); ROSE_ASSERT(dotExp != NULL); if(dotExp->get_traversalSuccessorContainer().size()>=2) { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(dotExp->get_traversalSuccessorContainer()[1]); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); } ROSE_ASSERT(funcDec != NULL); break; } case V_SgArrowExp: { SgArrowExp *arrowExp = isSgArrowExp(expression); ROSE_ASSERT(arrowExp != NULL); if(arrowExp->get_traversalSuccessorContainer().size()>=2) { SgMemberFunctionRefExp *memberFunctionRefExp = isSgMemberFunctionRefExp(arrowExp->get_traversalSuccessorContainer()[1]); funcDec = memberFunctionRefExp->get_symbol_i()->get_declaration(); } ROSE_ASSERT(funcDec != NULL); break; } case V_SgFunctionRefExp: { SgFunctionRefExp *functionRefExp = isSgFunctionRefExp(expression); ROSE_ASSERT(functionRefExp != NULL); // found a standard function reference funcDec = functionRefExp->get_symbol_i()->get_declaration(); ROSE_ASSERT(funcDec != NULL); break; } case V_SgPointerDerefExp: { ROSE_ABORT(); break; } default: { ROSE_ABORT(); } } return funcDec; }