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; } } }
void FixupAstSymbolTablesToSupportAliasedSymbols::visit ( SgNode* node ) { // DQ (11/24/2007): Output the current IR node for debugging the traversal of the Fortran AST. #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols::visit() (preorder AST traversal) node = %p = %s \n",node,node->class_name().c_str()); #endif #if 0 // DQ (7/23/2011): New support for linking namespaces sharing the same name (mangled name). // std::map<SgName,std::vector<SgNamespaceDefinition*> > namespaceMap; SgNamespaceDefinitionStatement* namespaceDefinition = isSgNamespaceDefinitionStatement(node); if (namespaceDefinition != NULL) { // DQ (7/23/2011): Assemble namespaces with the same name into vectors defined in the map // accessed using the name of the namespace as a key. #error "DEAD CODE" SgName name = namespaceDefinition->get_namespaceDeclaration()->get_name(); #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: namespace definition found for name = %s #symbols = %d \n",name.str(),namespaceDefinition->get_symbol_table()->size()); #endif // It is important to use mangled names to define unique names when namespaces are nested. SgName mangledNamespaceName = namespaceDefinition->get_namespaceDeclaration()->get_mangled_name(); #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: namespace definition associated mangled name = %s \n",mangledNamespaceName.str()); #endif // DQ (7/23/2011): Fixup the name we use as a key in the map to relect that some namespaces don't have a name. if (name == "") { // Modify the mangled name to reflect the unnamed namespace... #if ALIAS_SYMBOL_DEBUGGING printf ("Warning in FixupAstSymbolTablesToSupportAliasedSymbols::visit(): Unnamed namespaces shuld be mangled to reflect the lack of a name \n"); #endif mangledNamespaceName += "_unnamed_namespace"; } #if ALIAS_SYMBOL_DEBUGGING printf ("namespace definition associated mangled name = %s \n",mangledNamespaceName.str()); #endif #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: associated mangled name = %s namespaceMap size = %" PRIuPTR " \n",mangledNamespaceName.str(),namespaceMap.size()); #endif std::map<SgName,std::vector<SgNamespaceDefinitionStatement*> >::iterator i = namespaceMap.find(mangledNamespaceName); if (i != namespaceMap.end()) { std::vector<SgNamespaceDefinitionStatement*> & namespaceVector = i->second; #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: (found an entry): Namespace vector size = %" PRIuPTR " \n",namespaceVector.size()); #endif // Testing each entry... for (size_t j = 0; j < namespaceVector.size(); j++) { ROSE_ASSERT(namespaceVector[j] != NULL); SgName existingNamespaceName = namespaceVector[j]->get_namespaceDeclaration()->get_name(); #if ALIAS_SYMBOL_DEBUGGING printf ("Existing namespace (SgNamespaceDefinitionStatement) %p = %s \n",namespaceVector[j],existingNamespaceName.str()); #endif if (j > 0) { ROSE_ASSERT(namespaceVector[j]->get_previousNamespaceDefinition() != NULL); } if (namespaceVector.size() > 1 && j < namespaceVector.size() - 2) { ROSE_ASSERT(namespaceVector[j]->get_nextNamespaceDefinition() != NULL); } } #error "DEAD CODE" size_t namespaceListSize = namespaceVector.size(); if (namespaceListSize > 0) { size_t lastNamespaceIndex = namespaceListSize - 1; // DQ (5/9/2013): Before setting these, I think they should be unset (to NULL values). // ROSE_ASSERT(namespaceVector[lastNamespaceIndex]->get_nextNamespaceDefinition() == NULL); // ROSE_ASSERT(namespaceDefinition->get_previousNamespaceDefinition() == NULL); // ROSE_ASSERT(namespaceVector[lastNamespaceIndex]->get_nextNamespaceDefinition() == NULL); ROSE_ASSERT(namespaceDefinition->get_previousNamespaceDefinition() != NULL); // namespaceVector[lastNamespaceIndex]->set_nextNamespaceDefinition(namespaceDefinition); #if 1 printf ("namespaceVector[lastNamespaceIndex]->get_nextNamespaceDefinition() = %p \n",namespaceVector[lastNamespaceIndex]->get_nextNamespaceDefinition()); #endif if (namespaceVector[lastNamespaceIndex]->get_nextNamespaceDefinition() == NULL) { namespaceVector[lastNamespaceIndex]->set_nextNamespaceDefinition(namespaceDefinition); } else { // DQ (5/9/2013): If this is already set then make sure it was set to the correct value. ROSE_ASSERT(namespaceVector[lastNamespaceIndex]->get_nextNamespaceDefinition() == namespaceDefinition); } #error "DEAD CODE" // DQ (5/9/2013): If this is already set then make sure it was set to the correct value. // namespaceDefinition->set_previousNamespaceDefinition(namespaceVector[lastNamespaceIndex]); ROSE_ASSERT(namespaceDefinition->get_previousNamespaceDefinition() != NULL); ROSE_ASSERT(namespaceDefinition->get_previousNamespaceDefinition() == namespaceVector[lastNamespaceIndex]); // DQ (5/9/2013): I think I can assert this. ROSE_ASSERT(namespaceVector[lastNamespaceIndex]->get_namespaceDeclaration()->get_name() == namespaceDefinition->get_namespaceDeclaration()->get_name()); ROSE_ASSERT(namespaceDefinition->get_previousNamespaceDefinition() != NULL); #if 1 printf ("namespaceDefinition = %p namespaceDefinition->get_nextNamespaceDefinition() = %p \n",namespaceDefinition,namespaceDefinition->get_nextNamespaceDefinition()); #endif // ROSE_ASSERT(namespaceDefinition->get_nextNamespaceDefinition() == NULL); // ROSE_ASSERT(namespaceVector[lastNamespaceIndex]->get_nextNamespaceDefinition() == NULL); } // Add the namespace matching a previous name to the list. namespaceVector.push_back(namespaceDefinition); #error "DEAD CODE" // Setup scopes as sources and distinations of alias symbols. SgNamespaceDefinitionStatement* referencedScope = namespaceDefinition->get_previousNamespaceDefinition(); ROSE_ASSERT(referencedScope != NULL); SgNamespaceDefinitionStatement* currentScope = namespaceDefinition; ROSE_ASSERT(currentScope != NULL); #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: Suppress injection of symbols from one namespace to the other for each reintrant namespace \n"); printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: referencedScope #symbols = %d currentScope #symbols = %d \n",referencedScope->get_symbol_table()->size(),currentScope->get_symbol_table()->size()); printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: referencedScope = %p currentScope = %p \n",referencedScope,currentScope); #endif #if 1 // Generate the alias symbols from the referencedScope and inject into the currentScope. injectSymbolsFromReferencedScopeIntoCurrentScope(referencedScope,currentScope,SgAccessModifier::e_default); #endif } else { #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols: (entry NOT found): Insert namespace %p for name = %s into the namespaceMap \n",namespaceDefinition,mangledNamespaceName.str()); #endif std::vector<SgNamespaceDefinitionStatement*> list(1); ROSE_ASSERT(list.size() == 1); #error "DEAD CODE" list[0] = namespaceDefinition; #if 0 // DQ (3/11/2012): New code, but maybe we should instead put the implicit "std" namespace into the global scope more directly. if (mangledNamespaceName == "std" && false) { // This case has to be handled special since the implicit "std" namespace primary declaration was // constructed but not added to the global scope. But maybe it should be. } else { // DQ (7/24/2011): get_nextNamespaceDefinition() == NULL is false in the case of the AST copy tests // (see tests/nonsmoke/functional/CompileTests/copyAST_tests/copytest2007_30.C). Only get_nextNamespaceDefinition() // appears to sometimes be non-null, so we reset them both to NULL just to make sure. namespaceDefinition->set_nextNamespaceDefinition(NULL); namespaceDefinition->set_previousNamespaceDefinition(NULL); ROSE_ASSERT(namespaceDefinition->get_nextNamespaceDefinition() == NULL); ROSE_ASSERT(namespaceDefinition->get_previousNamespaceDefinition() == NULL); } #else // DQ (7/24/2011): get_nextNamespaceDefinition() == NULL is false in the case of the AST copy tests // (see tests/nonsmoke/functional/CompileTests/copyAST_tests/copytest2007_30.C). Only get_nextNamespaceDefinition() // appears to sometimes be non-null, so we reset them both to NULL just to make sure. namespaceDefinition->set_nextNamespaceDefinition(NULL); namespaceDefinition->set_previousNamespaceDefinition(NULL); ROSE_ASSERT(namespaceDefinition->get_nextNamespaceDefinition() == NULL); ROSE_ASSERT(namespaceDefinition->get_previousNamespaceDefinition() == NULL); #endif namespaceMap.insert(std::pair<SgName,std::vector<SgNamespaceDefinitionStatement*> >(mangledNamespaceName,list)); #error "DEAD CODE" #if ALIAS_SYMBOL_DEBUGGING printf ("namespaceMap.size() = %" PRIuPTR " \n",namespaceMap.size()); #endif } } #error "DEAD CODE" #else // DQ (5/23/2013): Commented out since we now have a newer and better namespace support for symbol handling. // printf ("NOTE:: COMMENTED OUT old support for namespace declarations in FixupAstSymbolTablesToSupportAliasedSymbols traversal \n"); #endif SgUseStatement* useDeclaration = isSgUseStatement(node); if (useDeclaration != NULL) { // This must be done in the Fortran AST construction since aliased symbols must be inserted // before they are looked up as part of name resolution of variable, functions, and types. // For C++ we can be more flexible and support the construction of symbol aliases within // post-processing. } // DQ (4/14/2010): Added this C++ specific support. // In the future we may want to support the injection of alias symbols for C++ "using" directives and "using" declarations. SgUsingDeclarationStatement* usingDeclarationStatement = isSgUsingDeclarationStatement(node); if (usingDeclarationStatement != NULL) { #if ALIAS_SYMBOL_DEBUGGING printf ("Found the SgUsingDeclarationStatement \n"); #endif SgScopeStatement* currentScope = usingDeclarationStatement->get_scope(); ROSE_ASSERT(currentScope != NULL); SgDeclarationStatement* declaration = usingDeclarationStatement->get_declaration(); SgInitializedName* initializedName = usingDeclarationStatement->get_initializedName(); // Only one of these can be non-null. ROSE_ASSERT(initializedName != NULL || declaration != NULL); ROSE_ASSERT( (initializedName != NULL && declaration != NULL) == false); if (declaration != NULL) { #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols::visit(): declaration = %p = %s \n",declaration,declaration->class_name().c_str()); #endif } else { if (initializedName != NULL) { #if ALIAS_SYMBOL_DEBUGGING printf ("In FixupAstSymbolTablesToSupportAliasedSymbols::visit(): initializedName = %s \n",initializedName->get_name().str()); #endif } else { printf ("Error: both declaration and initializedName in SgUsingDeclarationStatement are NULL \n"); ROSE_ASSERT(false); } } #if 0 printf ("Exiting at the base of FixupAstSymbolTablesToSupportAliasedSymbols::visit() \n"); ROSE_ASSERT(false); #endif } SgUsingDirectiveStatement* usingDirectiveStatement = isSgUsingDirectiveStatement(node); if (usingDirectiveStatement != NULL) { #if ALIAS_SYMBOL_DEBUGGING printf ("Found the SgUsingDirectiveStatement \n"); #endif SgNamespaceDeclarationStatement* namespaceDeclaration = usingDirectiveStatement->get_namespaceDeclaration(); ROSE_ASSERT(namespaceDeclaration != NULL); SgScopeStatement* currentScope = usingDirectiveStatement->get_scope(); // To be more specific this is really a SgNamespaceDefinitionStatement SgScopeStatement* referencedScope = namespaceDeclaration->get_definition(); if (referencedScope == NULL) { // DQ (5/21/2010): Handle case of using "std" (predefined namespace in C++), but it not having been explicitly defined (see test2005_57.C). if (namespaceDeclaration->get_name() != "std") { printf ("ERROR: namespaceDeclaration has no valid definition \n"); namespaceDeclaration->get_startOfConstruct()->display("ERROR: namespaceDeclaration has no valid definition"); // DQ (5/20/2010): Added assertion to trap this case. printf ("Exiting because referencedScope could not be identified.\n"); ROSE_ASSERT(false); } } // Note that "std", as a predefined namespace, can have a null definition, so we can't // insist that we inject all symbols in namespaces that we can't see explicitly. if (referencedScope != NULL) { ROSE_ASSERT(referencedScope != NULL); ROSE_ASSERT(currentScope != NULL); #if 0 printf ("Calling injectSymbolsFromReferencedScopeIntoCurrentScope() for usingDirectiveStatement = %p = %s \n",node,node->class_name().c_str()); #endif injectSymbolsFromReferencedScopeIntoCurrentScope(referencedScope,currentScope,usingDirectiveStatement,SgAccessModifier::e_default); } #if 0 printf ("Exiting at the base of FixupAstSymbolTablesToSupportAliasedSymbols::visit() \n"); ROSE_ASSERT(false); #endif } // DQ (5/6/2011): Added support to build SgAliasSymbols in derived class scopes that reference the symbols of the base classes associated with protected and public declarations. SgClassDefinition* classDefinition = isSgClassDefinition(node); if (classDefinition != NULL) { // Handle any derived classes. SgBaseClassPtrList & baseClassList = classDefinition->get_inheritances(); SgBaseClassPtrList::iterator i = baseClassList.begin(); for ( ; i != baseClassList.end(); ++i) { // Check each base class. SgBaseClass* baseClass = *i; ROSE_ASSERT(baseClass != NULL); /* skip processing for SgExpBaseClasses (which don't have to define p_base_class) */ if (baseClass->variantT() == V_SgExpBaseClass) { continue; } // printf ("baseClass->get_baseClassModifier().displayString() = %s \n",baseClass->get_baseClassModifier().displayString().c_str()); // printf ("baseClass->get_baseClassModifier().get_accessModifier().displayString() = %s \n",baseClass->get_baseClassModifier().get_accessModifier().displayString().c_str()); // if (baseClass->get_modifier() == SgBaseClass::e_virtual) if (baseClass->get_baseClassModifier().get_modifier() == SgBaseClassModifier::e_virtual) { // Not clear if virtual as a modifier effects the handling of alias symbols. // printf ("Not clear if virtual as a modifier effects the handling of alias symbols. \n"); } // DQ (6/22/2011): Define the access level for alias symbol's declarations to be included. SgAccessModifier::access_modifier_enum accessLevel = baseClass->get_baseClassModifier().get_accessModifier().get_modifier(); SgClassDeclaration* tmpClassDeclaration = baseClass->get_base_class(); ROSE_ASSERT(tmpClassDeclaration != NULL); #if 0 // ROSE_ASSERT(tmpClassDeclaration->get_definingDeclaration() != NULL); SgClassDeclaration* targetClassDeclaration = isSgClassDeclaration(tmpClassDeclaration->get_definingDeclaration()); ROSE_ASSERT(targetClassDeclaration != NULL); SgScopeStatement* referencedScope = targetClassDeclaration->get_definition(); // We need this function to restrict it's injection of symbol to just those that are associated with public and protected declarations. injectSymbolsFromReferencedScopeIntoCurrentScope(referencedScope,classDefinition,accessLevel); #else // DQ (2/25/2012) We only want to inject the symbol where we have identified the defining scope. if (tmpClassDeclaration->get_definingDeclaration() != NULL) { SgClassDeclaration* targetClassDeclaration = isSgClassDeclaration(tmpClassDeclaration->get_definingDeclaration()); ROSE_ASSERT(targetClassDeclaration != NULL); SgScopeStatement* referencedScope = targetClassDeclaration->get_definition(); #if 0 printf ("Calling injectSymbolsFromReferencedScopeIntoCurrentScope() for classDefinition = %p = %s baseClass = %p accessLevel = %d \n", node,node->class_name().c_str(),baseClass,accessLevel); #endif // DQ (7/12/2014): Use the SgBaseClass as the causal node that has triggered the insertion of the SgAliasSymbols. // We need this function to restrict it's injection of symbol to just those that are associated with public and protected declarations. injectSymbolsFromReferencedScopeIntoCurrentScope(referencedScope,classDefinition,baseClass,accessLevel); } else { // DQ (2/25/2012): Print a warning message when this happens (so far only test2012_08.C). if (SgProject::get_verbose() > 0) { mprintf ("WARNING: In FixupAstSymbolTablesToSupportAliasedSymbols::visit(): Not really clear how to handle this case where tmpClassDeclaration->get_definingDeclaration() == NULL! \n"); } } #endif } } SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(node); if (functionDeclaration != NULL) { #if ALIAS_SYMBOL_DEBUGGING printf ("Found a the SgFunctionDeclaration \n"); #endif // SgScopeStatement* functionScope = functionDeclaration->get_scope(); SgScopeStatement* currentScope = isSgScopeStatement(functionDeclaration->get_parent()); SgClassDefinition* classDefinition = isSgClassDefinition(currentScope); if (classDefinition != NULL) { // This is a function declared in a class definition, test of friend (forget why it is important to test for isOperator(). if (functionDeclaration->get_declarationModifier().isFriend() == true || functionDeclaration->get_specialFunctionModifier().isOperator() == true) { // printf ("Process all friend function with a SgAliasSymbol to where they are declared in another scope (usually global scope) \n"); #if 0 SgName name = functionDeclaration->get_name(); SgSymbol* symbol = functionDeclaration->search_for_symbol_from_symbol_table(); ROSE_ASSERT ( symbol != NULL ); SgAliasSymbol* aliasSymbol = new SgAliasSymbol (symbol); // Use the current name and the alias to the symbol currentScope->insert_symbol(name,aliasSymbol); #endif #if 0 printf ("Error: friend functions not processed yet! \n"); ROSE_ASSERT(false); #endif } } } #if ALIAS_SYMBOL_DEBUGGING printf ("Leaving FixupAstSymbolTablesToSupportAliasedSymbols::visit() (preorder AST traversal) node = %p = %s \n",node,node->class_name().c_str()); #endif }