void SgClassDefinition::fixupCopy_symbols(SgNode* copy, SgCopyHelp & help) const { #if DEBUG_FIXUP_COPY printf ("Inside of SgClassDefinition::fixupCopy_symbols() for class = %s class definition %p = %s copy = %p \n",this->get_declaration()->get_name().str(),this,this->class_name().c_str(),copy); #endif SgClassDefinition* classDefinition_copy = isSgClassDefinition(copy); ROSE_ASSERT(classDefinition_copy != NULL); SgBaseClassPtrList::const_iterator i_original = this->get_inheritances().begin(); SgBaseClassPtrList::iterator i_copy = classDefinition_copy->get_inheritances().begin(); ROSE_ASSERT(this->get_inheritances().size() == classDefinition_copy->get_inheritances().size()); while ( (i_original != this->get_inheritances().end()) && (i_copy != classDefinition_copy->get_inheritances().end()) ) { // Check the parent pointer to make sure it is properly set ROSE_ASSERT( (*i_original)->get_parent() != NULL); ROSE_ASSERT( (*i_original)->get_parent() == this); (*i_original)->fixupCopy_symbols(*i_copy,help); // DQ (11/7/2007): This was already setup on fixupCopy_scopes, but we can test it here. // (*i_copy)->set_parent(classDefinition_copy); ROSE_ASSERT( (*i_copy)->get_parent() != NULL); ROSE_ASSERT( (*i_copy)->get_parent() == classDefinition_copy); i_original++; i_copy++; } const SgDeclarationStatementPtrList & statementList_original = this->getDeclarationList(); const SgDeclarationStatementPtrList & statementList_copy = classDefinition_copy->getDeclarationList(); SgDeclarationStatementPtrList::const_iterator j_original = statementList_original.begin(); SgDeclarationStatementPtrList::const_iterator j_copy = statementList_copy.begin(); // Iterate over both lists to match up the correct pairs of SgStatement objects while ( (j_original != statementList_original.end()) && (j_copy != statementList_copy.end()) ) { (*j_original)->fixupCopy_symbols(*j_copy,help); j_original++; j_copy++; } // Call the base class fixupCopy member function SgScopeStatement::fixupCopy_symbols(copy,help); // printf ("\nLeaving SgClassDefinition::fixupCopy_symbols() this = %p = %s copy = %p \n",this,this->class_name().c_str(),copy); }
void CompassAnalyses::StaticConstructorInitialization::Traversal:: visit(SgNode* node) { // Test for static initialization of variables of type class, such initializations where they are // static or appear in global scope can be called in an order dependent upon the compiler and this // can lead to subtle bugs in large scale applications. SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node); if (variableDeclaration != NULL) { SgInitializedNamePtrList::iterator i = variableDeclaration->get_variables().begin(); while (i != variableDeclaration->get_variables().end()) { SgInitializedName* initializedName = *i; // Check the type and see if it is a class (check for typedefs too) SgType* variableType = initializedName->get_type(); SgClassType *classType = isSgClassType(variableType); if (classType != NULL) { // Now check if this is a global or namespace variable or an static class member // This might also have to be a test for other scopes as well. SgScopeStatement* scope = variableDeclaration->get_scope(); if (isSgGlobal(scope) != NULL || isSgNamespaceDefinitionStatement(scope) != NULL) { // printf ("Found a global variable defining a class = %p \n",initializedName); // variableDeclaration->get_file_info()->display("global variable defining a class"); output->addOutput(new CheckerOutput(initializedName)); } if (isSgClassDefinition(scope) != NULL) { // Now check if it is a static data member if (variableDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true) { // printf ("Found a static data member defining a class = %p \n",initializedName); // variableDeclaration->get_file_info()->display("static data member defining a class"); output->addOutput(new CheckerOutput(initializedName)); } } } // increment though the variables in the declaration (typically just one) i++; } } } //End of the visit function.
// Returns true if the function declaration is declared virtual in // some parent class, regardless of whether it is declared virtual // in its own class. bool isDeclaredVirtualWithinAncestor(SgFunctionDeclaration *functionDeclaration) { SgMemberFunctionDeclaration *memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration); if ( memberFunctionDeclaration == NULL ) return false; SgClassDefinition *classDefinition = isSgClassDefinition(memberFunctionDeclaration->get_scope()); ROSE_ASSERT(classDefinition != NULL); return isDeclaredVirtualWithinClassAncestry(functionDeclaration, classDefinition); }
void Traversal::visit(SgNode* node) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node); // Look for variable declarations appearing in global scope! // if (variableDeclaration != NULL && isSgGlobal(variableDeclaration->get_parent()) != NULL) if (variableDeclaration != NULL) { SgInitializedNamePtrList::iterator i = variableDeclaration->get_variables().begin(); while (i != variableDeclaration->get_variables().end()) { SgInitializedName* initializedName = *i; // Check the type and see if it is a class (check for typedefs too) SgType* variableType = initializedName->get_type(); SgClassType *classType = isSgClassType(variableType); if (classType != NULL) { // Now check if this is a global variable or an static class member SgScopeStatement* scope = variableDeclaration->get_scope(); if (isSgGlobal(scope) != NULL) { printf ("Found a global variable defining a class \n"); // variableDeclaration->get_file_info()->display("global variable defining a class"); outputPositionInformation(variableDeclaration); } if (isSgClassDefinition(scope) != NULL) { // Now check if it is a static data member if (variableDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true) { printf ("Found a static data member defining a class \n"); // variableDeclaration->get_file_info()->display("static data member defining a class"); outputPositionInformation(variableDeclaration); } } } // increment though the variables in the declaration (typically just one) i++; } } }
bool findPublicVarMembers (SgNode *node, string &str) { SgVariableDeclaration *decl; if (decl = isSgVariableDeclaration(node)) { SgDeclarationModifier &dfm = decl->get_declarationModifier(); if (dfm.get_accessModifier().isPublic()) { // check if it belongs to a class SgStatement *block = ((SgVariableDeclaration *) node)->get_scope(); SgClassDefinition *classDef; if (classDef = isSgClassDefinition(block)) { if (classDef->get_declaration()->get_class_type() == SgClassDeclaration::e_class) { str = classDef->get_qualified_name().getString(); return true; } } } } return false; }
/* The function: * getScopeString() * makes a string which represents the scopes of a SgNode*. If a * SgScopeStatement is inputted this will be included in the string. * The form is: * Scope N :: Scope N-1 :: .... :: Scope 1 :: Scope 0 :: * where scope N is the topmost scope. */ string getScopeString(SgNode* astNode) { ostringstream* scopes = new ostringstream(); (*scopes) << " "; SgNodePtrVector scopesVector = findScopes(astNode); SgClassDeclaration* sageClassDeclaration; for(int i = scopesVector.size()-1; i >= 0 ; i--) { if(scopesVector[i]->variantT() == V_SgClassDefinition) { sageClassDeclaration = isSgClassDefinition(scopesVector[i])->get_declaration(); (*scopes) << TransformationSupport::getTypeName(sageClassDeclaration->get_type()) << "::"; } } return scopes->str(); }
void ModelBuilder::add(Model::model_t & model, SgVariableSymbol * variable_symbol) { SgScopeStatement * scope = variable_symbol->get_scope(); assert(scope != NULL); SgNamespaceDefinitionStatement * nsp_defn = isSgNamespaceDefinitionStatement(scope); SgClassDefinition * class_defn = isSgClassDefinition(scope); SgGlobal * global_scope = isSgGlobal(scope); SgType * sg_type = variable_symbol->get_type(); assert(sg_type != NULL); Model::type_t type = model.lookup_type(sg_type); if (type == NULL) { add(model, sg_type); type = model.lookup_type(sg_type); } assert(type != NULL); if (nsp_defn != NULL || global_scope != NULL) { Model::variable_t element = Model::build<Model::e_model_variable>(); element->node->symbol = variable_symbol; element->node->type = type; setParentFromScope<Model::e_model_variable>(model, element, variable_symbol); model.variables.push_back(element); } else if (class_defn != NULL) { Model::field_t element = Model::build<Model::e_model_field>(); element->node->symbol = variable_symbol; element->node->type = type; setParentFromScope<Model::e_model_field>(model, element, variable_symbol); model.fields.push_back(element); } else { /// \todo error printing assert(false); } }
bool Driver<Sage>::resolveValidParent<SgMemberFunctionSymbol>(SgMemberFunctionSymbol * symbol) { SgClassSymbol * parent = NULL; if (p_valid_symbols.find(symbol) != p_valid_symbols.end()) return true; SgClassDefinition * class_scope = isSgClassDefinition(symbol->get_scope()); if (class_scope != NULL) { SgClassDeclaration * parent_decl = class_scope->get_declaration(); assert(parent_decl != NULL); parent = SageInterface::lookupClassSymbolInParentScopes(parent_decl->get_name(), parent_decl->get_scope()); assert(parent != NULL); if (!resolveValidParent<SgClassSymbol>((SgClassSymbol *)parent)) return false; assert(p_valid_symbols.find(parent) != p_valid_symbols.end()); } p_valid_symbols.insert(symbol); p_parent_map.insert(std::pair<SgSymbol *, SgSymbol *>(symbol, parent)); p_member_function_symbols.insert(symbol); return true; }
Sage<SgMemberFunctionDeclaration>::build_scopes_t Driver<Sage>::getBuildScopes<SgMemberFunctionDeclaration>(const Sage<SgMemberFunctionDeclaration>::object_desc_t & desc) { Sage<SgMemberFunctionDeclaration>::build_scopes_t result; assert(desc.parent != NULL); { SgClassDeclaration * class_decl = desc.parent->get_declaration(); assert(class_decl != NULL); class_decl = isSgClassDeclaration(class_decl->get_definingDeclaration()); assert(class_decl != NULL); SgClassDefinition * class_defn = isSgClassDefinition(class_decl->get_definition()); assert(class_defn != NULL); result.decl_scope = class_defn; } if (desc.create_definition) { size_t file_id = desc.file_id; if (file_id == 0) { std::map<SgSymbol *, size_t>::iterator it_symbol_to_file_id = p_symbol_to_file_id_map.find(desc.parent); assert(it_symbol_to_file_id != p_symbol_to_file_id_map.end()); file_id = it_symbol_to_file_id->second; } assert(file_id != 0); std::map<size_t, SgSourceFile *>::iterator it_file = id_to_file_map.find(file_id); assert(it_file != id_to_file_map.end()); SgSourceFile * defn_file = it_file->second; assert(defn_file != NULL); result.defn_scope = defn_file->get_globalScope(); } else result.defn_scope = NULL; return result; }
void CompassAnalyses::VariableNameEqualsDatabaseName::Traversal:: visit(SgNode* node) { if( isSgAssignInitializer(node) != NULL ) assignExp = node; if( isSgAssignOp(node) != NULL ) assignExp = node; SgFunctionCallExp* funcCall = isSgFunctionCallExp(node); // See if we have a dot expression or arrow expression which // accesses the desired member function in the class we are looking for. if ( funcCall != NULL ) { SgExpression* funcExp = funcCall->get_function(); if ( ( isSgDotExp(funcExp) != NULL ) | ( isSgArrowExp(funcExp) != NULL ) ) { SgBinaryOp* binOp = isSgBinaryOp(funcExp); SgExpression* rhsOp = binOp->get_rhs_operand(); // SgExpression* lhsOp = binOp->get_lhs_operand(); if ( SgMemberFunctionRefExp* funcRef = isSgMemberFunctionRefExp(rhsOp) ) { // std::cout << "c1\n" ; SgMemberFunctionSymbol* funcSymbol = funcRef->get_symbol(); ROSE_ASSERT(funcSymbol->get_declaration() != NULL); // DQ (1/16/2008): Note that the defining declaration need not exist (see test2001_11.C) // ROSE_ASSERT(funcSymbol->get_declaration()->get_definingDeclaration() != NULL); if (funcSymbol->get_declaration()->get_definingDeclaration() != NULL) { SgMemberFunctionDeclaration* funcDecl = isSgMemberFunctionDeclaration(funcSymbol->get_declaration()->get_definingDeclaration()); ROSE_ASSERT( funcDecl != NULL ); SgClassDefinition* clDef = isSgClassDefinition(funcDecl->get_scope()); SgClassDeclaration* clDecl = isSgClassDeclaration(clDef->get_declaration()); // SgClassDeclaration* clDecl = funcDecl->get_associatedClassDeclaration(); ROSE_ASSERT( clDecl != NULL ); std::string className = clDecl->get_name().getString(); ROSE_ASSERT(funcDecl != NULL); std::string functionName = funcDecl->get_name().getString(); // If the class is the class we are looking for see if the member function // access is to the member function we are interested in. // std::cout << "className = " << className << std::endl; // std::cout << "functionName = " << functionName << std::endl; if ( (className == classToLookFor) && ( functionName == memberFunctionToLookFor ) ) { SgExprListExp* actualArgs = funcCall->get_args(); SgExpressionPtrList& actualExpArgs = actualArgs->get_expressions (); ROSE_ASSERT(actualExpArgs.size() == 1); Rose_STL_Container<SgNode*> nodeLst = NodeQuery::querySubTree(*actualExpArgs.begin(), V_SgStringVal); ROSE_ASSERT( nodeLst.size() > 0); SgStringVal* actualArg = isSgStringVal(*nodeLst.begin()); ROSE_ASSERT(actualArg != NULL); std::string stringArg = actualArg->get_value(); std::cout << "arg:" << stringArg << std::endl; std::string varName; // SgInitializedName* initName = NULL; if ( SgAssignInitializer* assignInit = isSgAssignInitializer(assignExp) ) { SgInitializedName* initName = isSgInitializedName(assignInit->get_parent()); ROSE_ASSERT(initName != NULL); varName = initName->get_name().getString(); } else { if ( SgAssignOp* assignOp = isSgAssignOp(assignExp) ) { SgExpression* lhsOp = assignOp->get_lhs_operand(); SgVarRefExp* varRef = isSgVarRefExp(lhsOp); ROSE_ASSERT(varRef!=NULL); SgVariableSymbol* varSymbol = varRef->get_symbol(); ROSE_ASSERT(varSymbol != NULL); SgInitializedName* initName = varSymbol->get_declaration(); varName = initName->get_name().getString(); } } if (varName != "") { // we are only interested in the part of the argument after the last ":" // Database scopes in ALE3D are separated by ":" size_t posCol = stringArg.find_last_of(':'); if (posCol != std::string::npos) stringArg = stringArg.substr(posCol+1); //Find violations to the rule if ( stringArg != varName) { output->addOutput(new CheckerOutput(assignExp)); std::cout << "violation" << varName << std::endl; } else { std::cout << "non=violation" << varName << std::endl; } } } } } } } } // End of the visit function.
void ModelBuilder::setParentFromScope(Model::model_t & model, Model::element_t<kind> * element, SgSymbol * symbol) { SgScopeStatement * scope = symbol->get_scope(); assert(scope != NULL); SgNamespaceDefinitionStatement * nsp_defn = isSgNamespaceDefinitionStatement(scope); SgClassDefinition * class_defn = isSgClassDefinition(scope); SgGlobal * global_scope = isSgGlobal(scope); if (nsp_defn != NULL) { // field and method cannot have namespace for scope assert(kind != Model::e_model_field && kind != Model::e_model_method); SgNamespaceDeclarationStatement * nsp_decl = nsp_defn->get_namespaceDeclaration(); assert(nsp_decl != NULL); SgNamespaceSymbol * parent_symbol = isSgNamespaceSymbol(nsp_decl->get_symbol_from_symbol_table()); assert(parent_symbol != NULL); Model::namespace_t parent_element = model.lookup_namespace(parent_symbol); if (parent_element == NULL) { add(model, parent_symbol); parent_element = model.lookup_namespace(parent_symbol); } assert(parent_element != NULL); switch (kind) { case Model::e_model_variable: parent_element->scope->variable_children.push_back ( (Model::variable_t) element); break; case Model::e_model_function: parent_element->scope->function_children.push_back ( (Model::function_t) element); break; case Model::e_model_type: parent_element->scope->type_children.push_back ( (Model::type_t) element); break; case Model::e_model_class: parent_element->scope->class_children.push_back ( (Model::class_t) element); break; case Model::e_model_namespace: parent_element->scope->namespace_children.push_back ( (Model::namespace_t) element); break; case Model::e_model_field: case Model::e_model_method: assert(false); } switch (kind) { case Model::e_model_variable: ( (Model::variable_t) element)->scope->parent = parent_element; break; case Model::e_model_function: ( (Model::function_t) element)->scope->parent = parent_element; break; case Model::e_model_namespace: ( (Model::namespace_t) element)->scope->parent = parent_element; break; case Model::e_model_type: ( (Model::type_t) element)->scope->parent.a_namespace = parent_element; break; case Model::e_model_class: ( (Model::class_t) element)->scope->parent.a_namespace = parent_element; break; case Model::e_model_field: case Model::e_model_method: assert(false); } } else if (class_defn != NULL) { // namespace, function, and variable cannot have class for scope assert(kind != Model::e_model_namespace && kind != Model::e_model_function && kind != Model::e_model_variable); SgClassDeclaration * class_decl = class_defn->get_declaration(); assert(class_decl != NULL); SgClassSymbol * parent_symbol = isSgClassSymbol(class_decl->get_firstNondefiningDeclaration()->get_symbol_from_symbol_table()); assert(parent_symbol != NULL); Model::class_t parent_element = model.lookup_class(parent_symbol); if (parent_element == NULL) { add(model, parent_symbol); parent_element = model.lookup_class(parent_symbol); } assert(parent_element != NULL); switch (kind) { case Model::e_model_field: parent_element->scope->field_children.push_back ( (Model::field_t) element); break; case Model::e_model_method: parent_element->scope->method_children.push_back ( (Model::method_t) element); break; case Model::e_model_type: parent_element->scope->type_children.push_back ( (Model::type_t) element); break; case Model::e_model_class: parent_element->scope->class_children.push_back ( (Model::class_t) element); break; case Model::e_model_namespace: case Model::e_model_variable: case Model::e_model_function: assert(false); } switch (kind) { case Model::e_model_field: ( (Model::field_t) element)->scope->parent = parent_element; break; case Model::e_model_method: ( (Model::method_t) element)->scope->parent = parent_element; break; case Model::e_model_type: ( (Model::type_t) element)->scope->parent.a_class = parent_element; break; case Model::e_model_class: ( (Model::class_t) element)->scope->parent.a_class = parent_element; break; case Model::e_model_namespace: case Model::e_model_variable: case Model::e_model_function: assert(false); } } else if (global_scope != NULL) { /// \todo Should we have a root namespace to represent the global scope ??? } else { /// \todo error printing assert(false); } }
void fixupEdgBugDuplicateVariablesInAST() { // DQ (3/11/2006): Introduce tracking of performance of ROSE. TimingPerformance timer1 ("Fixup known EDG bug where some variable declarations are dropped from the source sequence lists:"); std::set<SgVariableDeclaration*> declarations_to_remove; // Loop over all variables added using the convert_field_use() function. std::set<SgVariableDeclaration*>::iterator i = nodesAddedWithinFieldUseSet.begin(); while (i != nodesAddedWithinFieldUseSet.end()) { SgVariableDeclaration* var_decl = *i; SgName name = var_decl->get_variables()[0]->get_name(); SgClassDefinition* classDefinition = isSgClassDefinition(var_decl->get_parent()); ROSE_ASSERT(classDefinition != NULL); std::vector<SgDeclarationStatement*> & members = classDefinition->get_members(); // Loop over all data members in the class. std::vector<SgDeclarationStatement*>::iterator j = members.begin(); while (j != members.end()) { SgVariableDeclaration* possible_matching_variable_declaration = isSgVariableDeclaration(*j); if (possible_matching_variable_declaration != NULL && possible_matching_variable_declaration != var_decl) { if (possible_matching_variable_declaration->get_variables()[0]->get_name() == name) { #if 0 printf ("matching variable declaration found for name = %s \n",name.str()); #endif declarations_to_remove.insert(var_decl); } } j++; } i++; } // Now remove all of the variable declarations that we detected to be duplicates. std::set<SgVariableDeclaration*>::iterator k = declarations_to_remove.begin(); while (k != declarations_to_remove.end()) { SgDeclarationStatement* var_decl = *k; SgClassDefinition* classDefinition = isSgClassDefinition(var_decl->get_parent()); ROSE_ASSERT(classDefinition != NULL); std::vector<SgDeclarationStatement*> myvector; myvector.push_back(*k); std::vector<SgDeclarationStatement*> & members = classDefinition->get_members(); // members.erase(*k); // members.erase(myvector.begin(),myvector.end()); // This is the remove/erase idiom. members.erase(remove(members.begin(), members.end(), *k), members.end()); k++; } }
void InsertFortranContainsStatement::visit ( SgNode* node ) { // DQ (10/3/2008): This bug in OFP is now fixed so no fixup is required. printf ("Error: fixup of contains statement no longer required. \n"); ROSE_ASSERT(false); // DQ (11/24/2007): Output the current IR node for debugging the traversal of the Fortran AST. ROSE_ASSERT(node != NULL); #if 0 Sg_File_Info* fileInfo = node->get_file_info(); printf ("node = %s fileInfo = %p \n",node->class_name().c_str(),fileInfo); if (fileInfo != NULL) { bool isCompilerGenerated = fileInfo->isCompilerGenerated(); std::string filename = fileInfo->get_filenameString(); int line_number = fileInfo->get_line(); int column_number = fileInfo->get_line(); printf ("--- isCompilerGenerated = %s position = %d:%d filename = %s \n",isCompilerGenerated ? "true" : "false",line_number,column_number,filename.c_str()); } #endif SgFunctionDefinition* functionDefinition = isSgFunctionDefinition(node); // This is for handling where CONTAINS is required in a function if (functionDefinition != NULL) { SgBasicBlock* block = functionDefinition->get_body(); SgStatementPtrList & statementList = block->get_statements(); SgStatementPtrList::iterator i = statementList.begin(); bool firstFunctionDeclaration = false; bool functionDeclarationSeen = false; while (i != statementList.end() && firstFunctionDeclaration == false) { SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); // DQ (1/20/2008): Note that entry statements should not cause introduction of a contains statement! if (isSgEntryStatement(functionDeclaration) != NULL) functionDeclaration = NULL; if (functionDeclaration != NULL) { firstFunctionDeclaration = functionDeclarationSeen == false; functionDeclarationSeen = true; if (firstFunctionDeclaration == true) { // Insert a CONTAINS statement. // printf ("Building a contains statement (in function) \n"); SgContainsStatement* containsStatement = new SgContainsStatement(); SageInterface::setSourcePosition(containsStatement); containsStatement->set_definingDeclaration(containsStatement); block->get_statements().insert(i,containsStatement); containsStatement->set_parent(block); ROSE_ASSERT(containsStatement->get_parent() != NULL); } } i++; } } #if 0 // OFP now has better support for the CONTAINS statement so this code is not longer required. // The use of CONTAINS in modules appears to be handled by OFP, so no fixup is required. SgClassDefinition* classDefinition = isSgClassDefinition(node); // This is for handling where CONTAINS is required in a module if (classDefinition != NULL) { SgDeclarationStatementPtrList & statementList = classDefinition->get_members(); SgDeclarationStatementPtrList::iterator i = statementList.begin(); bool firstFunctionDeclaration = false; bool functionDeclarationSeen = false; while (i != statementList.end() && firstFunctionDeclaration == false) { printf ("InsertFortranContainsStatement: *i in statementList in module = %p = %s \n",*i,(*i)->class_name().c_str()); SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); if (functionDeclaration != NULL) { firstFunctionDeclaration = functionDeclarationSeen == false; functionDeclarationSeen = true; if (firstFunctionDeclaration == true) { // Insert a CONTAINS statement. // printf ("Building a contains statement (in module) \n"); SgContainsStatement* containsStatement = new SgContainsStatement(); SageInterface::setSourcePosition(containsStatement); containsStatement->set_definingDeclaration(containsStatement); // This insert function does not set the parent (unlike for SgBasicBlock) classDefinition->get_members().insert(i,containsStatement); containsStatement->set_parent(classDefinition); ROSE_ASSERT(containsStatement->get_parent() != NULL); } } i++; } } #endif }
//----------------------------------------------------------------------------- // Functions required by the tree traversal mechanism ClasshierarchyInhAttr ClasshierarchyTraversal::evaluateInheritedAttribute ( SgNode* astNode, ClasshierarchyInhAttr inheritedAttribute ) { GlobalDatabaseConnection *gdb; // db connection //long funcId; // id of a function declaration Classhierarchy *classhier = getClasshierarchy(); gdb = getDB(); switch(astNode->variantT()) { case V_SgMemberFunctionDeclaration: { SgMemberFunctionDeclaration *funcDec = isSgMemberFunctionDeclaration( astNode ); //funcDec = funcDef->get_declaration(); //if(isSgMemberFunctionDeclaration(funcDec)) { // add to class hierarchy if member function definition //if(isSgMemberFunctionDeclaration()) { //cerr << " adding CHvinf for MembFunc " << endl; SgClassDefinition *classDef = isSgClassDefinition( funcDec->get_scope() ); //assert(classDef); if(classDef) { string classname = classDef->get_qualified_name().str(); // get the classhier. vertex Classhierarchy::dbgVertex chVert = 0; //?? init necessary bool foundClass = false; Classhierarchy::dbgVertexIterator chvi,chvend; boost::tie(chvi,chvend) = boost::vertices( *getClasshierarchy() ); for(; chvi!=chvend; chvi++) { if( boost::get( vertex_dbg_data, *getClasshierarchy() , *chvi).get_typeName() == classname ) { chVert = *chvi; foundClass = true; } } if(foundClass) { property_map< Classhierarchy::dbgType, boost::vertex_classhierarchy_t>::type chMap = boost::get( boost::vertex_classhierarchy, *getClasshierarchy() ); chMap[ chVert ].defined.insert( funcDec ); //get type? //cerr << " added! "; // debug } } //} cerr << " found V_SgMemberFunctionDeclaration done for " <<funcDec->get_mangled_name().str()<< " " << endl; // debug } break; case V_SgClassDefinition: { cerr << " found V_SgClassDef of "; // debug SgClassDefinition *classDef = isSgClassDefinition( astNode ); assert( classDef ); SgName classname = classDef->get_qualified_name(); // make db entry long typeId = UNKNOWNID; typesTableAccess types( gdb ); typesRowdata newtype( typeId, getProjectId(), classname.str() ); typeId = types.retrieveCreateByColumn( &newtype, "typeName", newtype.get_typeName(), newtype.get_projectId() ); cerr << classname.str()<< ", id:" << newtype.get_id() << endl; // debug //classhier->addNode( newtype, newtype.get_typeName() ); //classhier->insertWithName( newtype, newtype.get_typeName() ); classhier->insertVertex( newtype, newtype.get_typeName() ); SgBaseClassList inherits = classDef->get_inheritances(); for( SgBaseClassList::iterator i=inherits.begin(); i!=inherits.end(); i++) { SgClassDeclaration *parentDecl = (*i).get_base_class(); cerr << " found inheritance from " ; // debug assert( parentDecl ); // add new edge typesRowdata partype( UNKNOWNID, getProjectId(), parentDecl->get_name().str() ); // MANGLE long parentId = types.retrieveCreateByColumn( &partype, "typeName", partype.get_typeName(), partype.get_projectId() ); cerr << parentDecl->get_name().str() << ", id: " << parentId << endl; // add to class hierarchy graph, allow only one edge per inheritance //A classhier->addNode( partype, partype.get_typeName() ); //A classhier->addEdge( newtype, partype, false ); classhier->insertEdge( newtype, partype ); } } break; } // switch node type // Note that we have to use a particular constructor (to pass on context information about source code position). // This allows the Rewrite mechanism to position new source code relative to the current position using a simple interface. ClasshierarchyInhAttr returnAttribute(inheritedAttribute,astNode); // FIXME why not return inheritedAttribute??? return returnAttribute; }
int main(int argc, char **argv) { SgProject *project = frontend(argc, argv); // Instantiate a class hierarchy wrapper. ClassHierarchyWrapper classHierarchy( project ); std::list<SgNode *> nodes2 = NodeQuery::querySubTree(project, V_SgVariableDefinition); for (std::list<SgNode *>::iterator it = nodes2.begin(); it != nodes2.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDefinition *varDefn = isSgVariableDefinition(n); ROSE_ASSERT(varDefn != NULL); std::cout << "Var defn: " << varDefn->unparseToCompleteString() << std::endl; } std::list<SgNode *> nodes1 = NodeQuery::querySubTree(project, V_SgVariableDeclaration); for (std::list<SgNode *>::iterator it = nodes1.begin(); it != nodes1.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDeclaration *varDecl = isSgVariableDeclaration(n); ROSE_ASSERT(varDecl != NULL); SgInitializedNamePtrList &variables = varDecl->get_variables(); SgInitializedNamePtrList::iterator varIter; for (varIter = variables.begin(); varIter != variables.end(); ++varIter) { SgNode *var = *varIter; ROSE_ASSERT(var != NULL); SgInitializedName *initName = isSgInitializedName(var); ROSE_ASSERT(initName != NULL); if ( isSgClassType(initName->get_type()) ) { SgClassType *classType = isSgClassType(initName->get_type()); ROSE_ASSERT(classType != NULL); SgDeclarationStatement *declStmt = classType->get_declaration(); ROSE_ASSERT(declStmt != NULL); SgClassDeclaration *classDeclaration = isSgClassDeclaration(declStmt); ROSE_ASSERT(classDeclaration != NULL); // std::cout << "From var decl got: " << classDeclaration->unparseToCompleteString() << std::endl; SgClassDefinition *classDefinition = classDeclaration->get_definition(); if ( classDefinition != NULL ) { std::cout << "From var decl got: " << classDefinition->unparseToCompleteString() << std::endl; } } } } std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDeclaration); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDeclaration *classDeclaration1 = isSgClassDeclaration(n); ROSE_ASSERT(classDeclaration1 != NULL); SgDeclarationStatement *definingDecl = classDeclaration1->get_definingDeclaration(); if ( definingDecl == NULL ) continue; SgClassDeclaration *classDeclaration = isSgClassDeclaration(definingDecl); ROSE_ASSERT(classDeclaration != NULL); SgClassDefinition *classDefinition = classDeclaration->get_definition(); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #if 0 #if 0 std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDefinition); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDefinition *classDefinition = isSgClassDefinition(n); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #else // Collect all function/method invocations. std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgFunctionCallExp); unsigned int numCallSites = 0; unsigned int numMonomorphicCallSites = 0; unsigned int numPossibleResolutions = 0; // Visit each call site. for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(n); ROSE_ASSERT(functionCallExp != NULL); // We are only interested in examining method invocations. bool isDotExp = false; if ( !isMethodCall(functionCallExp, isDotExp) ) continue; numCallSites++; // Certainly can be resolved to the static method. numPossibleResolutions++; if ( isDotExp ) { // If this is a dot expression (i.e., a.foo()), we can // statically determine its type. numMonomorphicCallSites++; continue; } // Retrieve the static function declaration. SgFunctionDeclaration *functionDeclaration = getFunctionDeclaration(functionCallExp); // Ensure it is actually a method declaration. SgMemberFunctionDeclaration *memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration); ROSE_ASSERT(memberFunctionDeclaration != NULL); unsigned int numOverridesForMethod = 0; if ( ( isVirtual(functionDeclaration) ) || ( isDeclaredVirtualWithinAncestor(functionDeclaration) ) ) { SgClassDefinition *classDefinition = isSgClassDefinition(memberFunctionDeclaration->get_scope()); ROSE_ASSERT(classDefinition != NULL); SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; // Iterate over all of the methods defined in this subclass. SgDeclarationStatementPtrList &decls = subclass->get_members(); for (SgDeclarationStatementPtrList::iterator declIter = decls.begin(); declIter != decls.end(); ++declIter) { SgDeclarationStatement *declStmt = *declIter; ROSE_ASSERT(declStmt != NULL); SgMemberFunctionDeclaration *method = isSgMemberFunctionDeclaration(declStmt); if ( method == NULL ) { continue; } // Determine whether subclass of the class defining this // method overrides the method. if ( methodOverridesVirtualMethod(method, memberFunctionDeclaration) ) { numOverridesForMethod++; } } } if ( numOverridesForMethod == 0 ) numMonomorphicCallSites++; numPossibleResolutions += numOverridesForMethod; std::cout << "Method invocation has " << numOverridesForMethod + 1 << " possible resolutions " << std::endl; std::cout << functionCallExp->unparseToCompleteString() << std::endl; } } #endif #endif return 0; }
void ProcTraversal::visit(SgNode *node) { if (isSgFunctionDeclaration(node)) { SgFunctionDeclaration *decl = isSgFunctionDeclaration(node); if (decl->get_definition() != NULL) { /* collect statistics */ //AstNumberOfNodesStatistics anons; //anons.traverse(decl, postorder); //original_ast_nodes += anons.get_numberofnodes(); //original_ast_statements += anons.get_numberofstatements(); /* do the real work */ Procedure *proc = new Procedure(); proc->procnum = procnum++; proc->decl = decl; proc->funcsym = isSgFunctionSymbol(decl->get_symbol_from_symbol_table()); if (proc->funcsym == NULL) { #if 0 std::cout << std::endl << "*** NULL function symbol for declaration " << decl->unparseToString() << std::endl << "symbol: " << (void *) decl->get_symbol_from_symbol_table() << (decl->get_symbol_from_symbol_table() != NULL ? decl->get_symbol_from_symbol_table()->class_name() : "") << std::endl << "first nondef decl: " << (void *) decl->get_firstNondefiningDeclaration() << " sym: " << (decl->get_firstNondefiningDeclaration() != NULL ? (void *) decl->get_firstNondefiningDeclaration() ->get_symbol_from_symbol_table() : (void *) NULL) << std::endl; #endif if (decl->get_firstNondefiningDeclaration() != NULL) { proc->funcsym = isSgFunctionSymbol(decl ->get_firstNondefiningDeclaration() ->get_symbol_from_symbol_table()); } } assert(proc->funcsym != NULL); // GB (2008-05-14): We need two parameter lists: One for the names of the // variables inside the function definition, which is // decl->get_parameterList(), and one that contains any default arguments // the function might have. The default arguments are supposedly // associated with the first nondefining declaration. proc->params = decl->get_parameterList(); SgDeclarationStatement *fndstmt = decl->get_firstNondefiningDeclaration(); SgFunctionDeclaration *fnd = isSgFunctionDeclaration(fndstmt); if (fnd != NULL && fnd != decl) proc->default_params = fnd->get_parameterList(); else proc->default_params = proc->params; SgMemberFunctionDeclaration *mdecl = isSgMemberFunctionDeclaration(decl); if (mdecl) { proc->class_type = isSgClassDefinition(mdecl->get_scope()); std::string name = proc->class_type->get_mangled_name().str(); name += "::"; name += decl->get_name().str(); std::string mname = proc->class_type->get_mangled_name().str(); mname += "::"; mname += decl->get_mangled_name().str(); proc->memberf_name = name; proc->mangled_memberf_name = mname; proc->name = decl->get_name().str(); proc->mangled_name = decl->get_mangled_name().str(); // GB (2008-05-26): Computing a single this symbol for each // procedure. Thus, this symbol can also be compared by pointer // equality (as is the case for all other symbols). While we're at it, // we also build a VarRefExp for this which can be used everywhere the // this pointer occurs. proc->this_type = Ir::createPointerType( proc->class_type->get_declaration()->get_type()); proc->this_sym = Ir::createVariableSymbol("this", proc->this_type); proc->this_exp = Ir::createVarRefExp(proc->this_sym); } else { proc->name = decl->get_name().str(); proc->mangled_name = decl->get_mangled_name().str(); proc->class_type = NULL; proc->memberf_name = proc->mangled_memberf_name = ""; proc->this_type = NULL; proc->this_sym = NULL; proc->this_exp = NULL; // GB (2008-07-01): Better resolution of calls to static functions. // This only makes sense for non-member functions. SgStorageModifier &sm = (fnd != NULL ? fnd : decl)->get_declarationModifier().get_storageModifier(); proc->isStatic = sm.isStatic(); // Note that we query the first nondefining declaration for the // static modifier, but we save the file of the *defining* // declaration. This is because the first declaration might be in // some header file, but for call resolution, the actual source // file with the definition is relevant. // Trace back to the enclosing file node. The definition might be // included in foo.c from bar.c, in which case the Sg_File_Info // would refer to bar.c; but for function call resolution, foo.c is // the relevant file. SgNode *p = decl->get_parent(); while (p != NULL && !isSgFile(p)) p = p->get_parent(); proc->containingFile = isSgFile(p); } proc_map.insert(std::make_pair(proc->name, proc)); mangled_proc_map.insert(std::make_pair(proc->mangled_name, proc)); std::vector<SgVariableSymbol* >* arglist = new std::vector<SgVariableSymbol* >(); SgVariableSymbol *this_var = NULL, *this_temp_var = NULL; if (mdecl || decl->get_parameterList() != NULL && !decl->get_parameterList()->get_args().empty()) { proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum); if (mdecl) { // GB (2008-05-26): We now compute the this pointer right at the // beginning of building the procedure. // this_var = Ir::createVariableSymbol("this", this_type); this_var = proc->this_sym; // std::string varname // = std::string("$") + proc->name + "$this"; // this_temp_var = Ir::createVariableSymbol(varname, proc->this_type); this_temp_var = global_this_variable_symbol; ParamAssignment* paramAssignment = Ir::createParamAssignment(this_var, this_temp_var); proc->arg_block->statements.push_back(paramAssignment); arglist->push_back(this_var); if (proc->name.find('~') != std::string::npos) { arglist->push_back(this_temp_var); } } SgInitializedNamePtrList params = proc->params->get_args(); SgInitializedNamePtrList::const_iterator i; #if 0 int parnum = 0; for (i = params.begin(); i != params.end(); ++i) { SgVariableSymbol *i_var = Ir::createVariableSymbol(*i); std::stringstream varname; // varname << "$" << proc->name << "$arg_" << parnum++; SgVariableSymbol* var = Ir::createVariableSymbol(varname.str(),(*i)->get_type()); proc->arg_block->statements.push_back(Ir::createParamAssignment(i_var, var)); arglist->push_back(i_var); } #else // GB (2008-06-23): Trying to replace all procedure-specific argument // variables by a global list of argument variables. This means that at // this point, we do not necessarily need to build a complete list but // only add to the CFG's argument list if it is not long enough. size_t func_params = params.size(); size_t global_args = global_argument_variable_symbols.size(); std::stringstream varname; while (global_args < func_params) { varname.str(""); varname << "$tmpvar$arg_" << global_args++; SgVariableSymbol *var = Ir::createVariableSymbol(varname.str(), global_unknown_type); program->global_map[varname.str()] = std::make_pair(var, var->get_declaration()); global_argument_variable_symbols.push_back(var); } // now create the param assignments size_t j = 0; for (i = params.begin(); i != params.end(); ++i) { SgVariableSymbol *i_var = Ir::createVariableSymbol(params[j]); SgVariableSymbol *var = global_argument_variable_symbols[j]; j++; proc->arg_block->statements.push_back( Ir::createParamAssignment(i_var, var)); arglist->push_back(i_var); } #if 0 // replace the arglist allocated above by the new one; this must be // fixed for this pointers! delete arglist; arglist = &global_argument_variable_symbols; #endif #endif } else { proc->arg_block = NULL; } /* If this is a constructor, call default constructors * of all base classes. If base class constructors are * called manually, these calls will be removed later. */ if (mdecl && strcmp(mdecl->get_name().str(), proc->class_type->get_declaration()->get_name().str()) == 0 && proc->class_type != NULL) { SgBaseClassPtrList::iterator base; for (base = proc->class_type->get_inheritances().begin(); base != proc->class_type->get_inheritances().end(); ++base) { SgClassDeclaration* baseclass = (*base)->get_base_class(); SgVariableSymbol *lhs = Ir::createVariableSymbol("$tmpvar$" + baseclass->get_name(), baseclass->get_type()); program->global_map["$tmpvar$" + baseclass->get_name()] = std::make_pair(lhs, lhs->get_declaration()); SgMemberFunctionDeclaration* fd=get_default_constructor(baseclass); assert(fd); SgType* basetype=baseclass->get_type(); assert(basetype); SgConstructorInitializer *sci = Ir::createConstructorInitializer(fd,basetype); ArgumentAssignment* a = Ir::createArgumentAssignment(lhs, sci); proc->arg_block->statements.push_back(a); // std::string this_called_varname // = std::string("$") + baseclass->get_name() + "$this"; SgVariableSymbol *this_called_var // = Ir::createVariableSymbol(this_called_varname, // baseclass->get_type()); = global_this_variable_symbol; ReturnAssignment* this_ass = Ir::createReturnAssignment(this_var, this_called_var); proc->arg_block->statements.push_back(this_ass); } } if (mdecl && mdecl->get_CtorInitializerList() != NULL && !mdecl->get_CtorInitializerList()->get_ctors().empty()) { SgInitializedNamePtrList cis = mdecl->get_CtorInitializerList()->get_ctors(); SgInitializedNamePtrList::const_iterator i; if (proc->arg_block == NULL) { proc->arg_block = new BasicBlock(node_id, INNER, proc->procnum); } for (i = cis.begin(); i != cis.end(); ++i) { SgVariableSymbol* lhs = Ir::createVariableSymbol(*i); SgAssignInitializer *ai = isSgAssignInitializer((*i)->get_initializer()); SgConstructorInitializer *ci = isSgConstructorInitializer((*i)->get_initializer()); /* TODO: other types of initializers */ if (ai) { SgClassDeclaration *class_decl = proc->class_type->get_declaration(); // GB (2008-05-26): We now compute the this pointer right at the // beginning of building the procedure. // SgVarRefExp* this_ref // = Ir::createVarRefExp("this", // Ir::createPointerType(class_decl->get_type())); SgVarRefExp* this_ref = proc->this_exp; SgArrowExp* arrowExp = Ir::createArrowExp(this_ref,Ir::createVarRefExp(lhs)); // GB (2008-03-17): We need to handle function calls in // initializers. In order to be able to build an argument // assignment, we need to know the function's return variable, so // the expression labeler must be called on it. The expression // number is irrelevant, however, as it does not appear in the // return variable. if (isSgFunctionCallExp(ai->get_operand_i())) { #if 0 ExprLabeler el(0 /*expnum*/); el.traverse(ai->get_operand_i(), preorder); // expnum = el.get_expnum(); #endif // GB (2008-06-25): There is now a single global return // variable. This may or may not mean that we can simply ignore // the code above. I don't quite understand why this labeling // couldn't be done later on, and where its result was used. } ArgumentAssignment* argumentAssignment = Ir::createArgumentAssignment(arrowExp,ai->get_operand_i()); proc->arg_block->statements.push_back(argumentAssignment); } else if (ci) { /* if this is a call to a base class's * constructor, remove the call we generated * before */ SgStatement* this_a = NULL; SgClassDeclaration* cd = ci->get_class_decl(); std::deque<SgStatement *>::iterator i; for (i = proc->arg_block->statements.begin(); i != proc->arg_block->statements.end(); ++i) { ArgumentAssignment* a = dynamic_cast<ArgumentAssignment *>(*i); if (a && isSgConstructorInitializer(a->get_rhs())) { SgConstructorInitializer* c = isSgConstructorInitializer(a->get_rhs()); std::string c_decl_name = c->get_class_decl()->get_name().str(); std::string cd_name = cd->get_name().str(); // if (c->get_class_decl()->get_name() == cd->get_name()) { if (c_decl_name == cd_name) { #if 0 // erase the following assignment // of the this pointer as well this_a = *proc->arg_block->statements.erase(i+1); proc->arg_block->statements.erase(i); #endif // GB (2008-03-28): That's an interesting piece of code, but // it might be very mean to iterators. At least it is hard to // see whether it is correct. So let's try it like this: // erase i; we get an iterator back, which refers to the next // element. Save that element as this_a, and then erase. std::deque<SgStatement *>::iterator this_pos; this_pos = proc->arg_block->statements.erase(i); this_a = *this_pos; proc->arg_block->statements.erase(this_pos); // Good. Looks like this fixed a very obscure bug. break; } } } /* now add the initialization */ proc->arg_block->statements.push_back(Ir::createArgumentAssignment(lhs, ci)); if (this_a != NULL) proc->arg_block->statements.push_back(this_a); } } } proc->entry = new CallBlock(node_id++, START, proc->procnum, new std::vector<SgVariableSymbol *>(*arglist), (proc->memberf_name != "" ? proc->memberf_name : proc->name)); proc->exit = new CallBlock(node_id++, END, proc->procnum, new std::vector<SgVariableSymbol *>(*arglist), (proc->memberf_name != "" ? proc->memberf_name : proc->name)); proc->entry->partner = proc->exit; proc->exit->partner = proc->entry; proc->entry->call_target = Ir::createFunctionRefExp(proc->funcsym); proc->exit->call_target = Ir::createFunctionRefExp(proc->funcsym); /* In constructors, insert an assignment $A$this = this * at the end to make sure that the 'this' pointer can be * passed back to the calling function uncobbled. */ proc->this_assignment = NULL; if (mdecl) { SgMemberFunctionDeclaration* cmdecl = isSgMemberFunctionDeclaration(mdecl->get_firstNondefiningDeclaration()); // if (cmdecl && cmdecl->get_specialFunctionModifier().isConstructor()) { proc->this_assignment = new BasicBlock(node_id++, INNER, proc->procnum); ReturnAssignment* returnAssignment = Ir::createReturnAssignment(this_temp_var, this_var); proc->this_assignment->statements.push_back(returnAssignment); add_link(proc->this_assignment, proc->exit, NORMAL_EDGE); // } } std::stringstream varname; // varname << "$" << proc->name << "$return"; // proc->returnvar = Ir::createVariableSymbol(varname.str(), // decl->get_type()->get_return_type()); proc->returnvar = global_return_variable_symbol; procedures->push_back(proc); if(getPrintCollectedFunctionNames()) { std::cout << (proc->memberf_name != "" ? proc->memberf_name : proc->name) << " " /*<< proc->decl << std::endl*/; } if (proc->arg_block != NULL) { proc->arg_block->call_target = Ir::createFunctionRefExp(proc->funcsym); } // delete arglist; } } }
bool ClangToSageTranslator::VisitRecordDecl(clang::RecordDecl * record_decl, SgNode ** node) { #if DEBUG_VISIT_DECL std::cerr << "ClangToSageTranslator::VisitRecordDecl" << std::endl; #endif // FIXME May have to check the symbol table first, because of out-of-order traversal of C++ classes (Could be done in CxxRecord class...) bool res = true; SgClassDeclaration * sg_class_decl = NULL; // Find previous declaration clang::RecordDecl * prev_record_decl = record_decl->getPreviousDeclaration(); SgClassSymbol * sg_prev_class_sym = isSgClassSymbol(GetSymbolFromSymbolTable(prev_record_decl)); SgClassDeclaration * sg_prev_class_decl = sg_prev_class_sym == NULL ? NULL : isSgClassDeclaration(sg_prev_class_sym->get_declaration()); SgClassDeclaration * sg_first_class_decl = sg_prev_class_decl == NULL ? NULL : isSgClassDeclaration(sg_prev_class_decl->get_firstNondefiningDeclaration()); SgClassDeclaration * sg_def_class_decl = sg_prev_class_decl == NULL ? NULL : isSgClassDeclaration(sg_prev_class_decl->get_definingDeclaration()); ROSE_ASSERT(sg_first_class_decl != NULL || sg_def_class_decl == NULL); bool had_prev_decl = sg_first_class_decl != NULL; // Name SgName name(record_decl->getNameAsString()); // Type of class SgClassDeclaration::class_types type_of_class; switch (record_decl->getTagKind()) { case clang::TTK_Struct: type_of_class = SgClassDeclaration::e_struct; break; case clang::TTK_Class: type_of_class = SgClassDeclaration::e_class; break; case clang::TTK_Union: type_of_class = SgClassDeclaration::e_union; break; default: std::cerr << "Runtime error: RecordDecl can only be a struct/class/union." << std::endl; res = false; } // Build declaration(s) sg_class_decl = new SgClassDeclaration(name, type_of_class, NULL, NULL); sg_class_decl->set_scope(SageBuilder::topScopeStack()); sg_class_decl->set_parent(SageBuilder::topScopeStack()); SgClassType * type = NULL; if (sg_first_class_decl != NULL) { type = sg_first_class_decl->get_type(); } else { type = SgClassType::createType(sg_class_decl); } ROSE_ASSERT(type != NULL); sg_class_decl->set_type(type); if (record_decl->isAnonymousStructOrUnion()) sg_class_decl->set_isUnNamed(true); if (!had_prev_decl) { sg_first_class_decl = sg_class_decl; sg_first_class_decl->set_firstNondefiningDeclaration(sg_first_class_decl); sg_first_class_decl->set_definingDeclaration(NULL); sg_first_class_decl->set_definition(NULL); sg_first_class_decl->setForward(); if (!record_decl->field_empty()) { sg_def_class_decl = new SgClassDeclaration(name, type_of_class, type, NULL); sg_def_class_decl->set_scope(SageBuilder::topScopeStack()); if (record_decl->isAnonymousStructOrUnion()) sg_def_class_decl->set_isUnNamed(true); sg_def_class_decl->set_parent(SageBuilder::topScopeStack()); sg_class_decl = sg_def_class_decl; // we return thew defining decl sg_def_class_decl->set_firstNondefiningDeclaration(sg_first_class_decl); sg_def_class_decl->set_definingDeclaration(sg_def_class_decl); sg_first_class_decl->set_definingDeclaration(sg_def_class_decl); setCompilerGeneratedFileInfo(sg_first_class_decl); } } else if (!record_decl->field_empty()) { if (sg_def_class_decl != NULL) { delete sg_class_decl; *node = sg_def_class_decl; return true; } sg_def_class_decl = sg_class_decl; sg_def_class_decl->set_firstNondefiningDeclaration(sg_first_class_decl); sg_def_class_decl->set_definingDeclaration(sg_def_class_decl); sg_first_class_decl->set_definingDeclaration(sg_def_class_decl); } else // second (or more) non-defining declaration return false; // FIXME ROSE need only one non-defining declaration (SageBuilder don't let me build another one....) // Update symbol table if (!had_prev_decl) { SgScopeStatement * scope = SageBuilder::topScopeStack(); SgClassSymbol * class_symbol = new SgClassSymbol(sg_first_class_decl); scope->insert_symbol(name, class_symbol); } // Build ClassDefinition if (!record_decl->field_empty()) { SgClassDefinition * sg_class_def = isSgClassDefinition(sg_def_class_decl->get_definition()); if (sg_class_def == NULL) { sg_class_def = SageBuilder::buildClassDefinition_nfi(sg_def_class_decl); } sg_def_class_decl->set_definition(sg_class_def); ROSE_ASSERT(sg_class_def->get_symbol_table() != NULL); applySourceRange(sg_class_def, record_decl->getSourceRange()); SageBuilder::pushScopeStack(sg_class_def); clang::RecordDecl::field_iterator it; for (it = record_decl->field_begin(); it != record_decl->field_end(); it++) { SgNode * tmp_field = Traverse(*it); SgDeclarationStatement * field_decl = isSgDeclarationStatement(tmp_field); ROSE_ASSERT(field_decl != NULL); sg_class_def->append_member(field_decl); field_decl->set_parent(sg_class_def); } SageBuilder::popScopeStack(); } ROSE_ASSERT(sg_class_decl->get_definingDeclaration() == NULL || isSgClassDeclaration(sg_class_decl->get_definingDeclaration())->get_definition() != NULL); ROSE_ASSERT(sg_first_class_decl->get_definition() == NULL); ROSE_ASSERT(sg_def_class_decl == NULL || sg_def_class_decl->get_definition() != NULL); *node = sg_class_decl; return VisitTagDecl(record_decl, node) && res; }
Sage<SgMemberFunctionDeclaration>::build_result_t Driver<Sage>::build<SgMemberFunctionDeclaration>(const Sage<SgMemberFunctionDeclaration>::object_desc_t & desc) { Sage<SgMemberFunctionDeclaration>::build_result_t result; Sage<SgMemberFunctionDeclaration>::build_scopes_t scopes = getBuildScopes<SgMemberFunctionDeclaration>(desc); SgScopeStatement * decl_scope = scopes.decl_scope; SgScopeStatement * defn_scope = scopes.defn_scope; assert(isSgClassDefinition(decl_scope)); assert(decl_scope != defn_scope); // Build Declaration SgMemberFunctionDeclaration * mfunc_decl = NULL; { mfunc_decl = SageBuilder::buildNondefiningMemberFunctionDeclaration(desc.name, desc.return_type, desc.params, decl_scope, NULL, 0, false, NULL); SageInterface::appendStatement(mfunc_decl, decl_scope); if (desc.is_constructor) mfunc_decl->get_specialFunctionModifier().setConstructor(); assert(mfunc_decl->get_definition() == NULL); assert(mfunc_decl->get_associatedClassDeclaration() != NULL); } // Build Definition SgMemberFunctionDeclaration * mfunc_defn = NULL; { mfunc_defn = SageBuilder::buildDefiningMemberFunctionDeclaration(desc.name, desc.return_type, desc.params, decl_scope, NULL, 0, false, mfunc_decl, NULL); SageInterface::appendStatement(mfunc_defn, defn_scope); if (desc.is_constructor) mfunc_defn->get_specialFunctionModifier().setConstructor(); assert(mfunc_defn->get_associatedClassDeclaration() != NULL); result.definition = mfunc_defn->get_definition(); assert(result.definition != NULL); } { // Symbol handling result.symbol = isSgMemberFunctionSymbol(decl_scope->lookup_function_symbol(desc.name)); assert(result.symbol != NULL); std::map<SgSymbol *, size_t>::iterator it_symbol_to_file_id = p_symbol_to_file_id_map.find(desc.parent); assert(it_symbol_to_file_id != p_symbol_to_file_id_map.end()); p_symbol_to_file_id_map.insert(std::pair<SgSymbol *, size_t>(result.symbol, it_symbol_to_file_id->second)); p_valid_symbols.insert(result.symbol); p_parent_map.insert(std::pair<SgSymbol *, SgSymbol *>(result.symbol, desc.parent)); p_member_function_symbols.insert(result.symbol); } #if PATCHING_SAGE_BUILDER_ISSUES // Decl and Defn { mfunc_decl->set_definingDeclaration(mfunc_defn); mfunc_decl->set_firstNondefiningDeclaration(mfunc_decl); mfunc_defn->set_definingDeclaration(mfunc_defn); mfunc_defn->set_firstNondefiningDeclaration(mfunc_decl); } #endif return result; }