//! A default builder function handles all details: file use name, others use numbering // Algorithm: // Go through all parent scopes until reach SgSourceFile. store them into a list // iterate on the list to generate all abstract handles, with optional the parent handle information abstract_handle * buildAbstractHandle(SgNode* snode) { ROSE_ASSERT (snode != NULL); // simple nodes if (isSgSourceFile (snode) || isSgProject(snode) ||isSgGlobal(snode)) return buildSingleAbstractHandle (snode); // all other nodes, trace back to SgGlobal, store all intermediate scope nodes std::vector<SgNode*> scope_list; SgScopeStatement* p_scope = SageInterface::getEnclosingScope(snode); while (!isSgGlobal(p_scope)) { scope_list.push_back(p_scope); p_scope = SageInterface::getEnclosingScope(p_scope); } ROSE_ASSERT (isSgGlobal(p_scope)); abstract_handle * p_handle = buildSingleAbstractHandle (p_scope); // Now go through the list to generate numbering handles std::vector<SgNode*>::reverse_iterator riter; for (riter = scope_list.rbegin(); riter!= scope_list.rend(); riter++) { SgNode* c_node = *riter; p_handle = buildSingleAbstractHandle (c_node, p_handle); } ROSE_ASSERT (p_handle != NULL); return buildSingleAbstractHandle (snode, p_handle); }
void instr(SgScopeStatement* scope) { if(isSgBasicBlock(scope)) { #ifdef LOCK_KEY_INSERT instr(isSgBasicBlock(scope)); #endif } else if(isSgGlobal(scope)) { instr(isSgGlobal(scope)); } }
void visitorTraversal::visit(SgNode* n) { SgGlobal* globalScope = isSgGlobal(n); if (globalScope != NULL) { printf ("Looking for \"x\" in the global symbol table ... \n"); SgSymbol* symbol = globalScope->lookup_var_symbol("x"); ROSE_ASSERT(symbol != NULL); // Iterate through the symbol table SgSymbolTable::BaseHashType* hashTable = globalScope->get_symbol_table()->get_table(); SgSymbolTable::hash_iterator i = hashTable->begin(); while (i != hashTable->end()) { printf ("hash tabel entry: i->first = %s \n",i->first.str()); i++; } } #if 0 SgScopeStatement* scope = isSgScopeStatement(n); if (scope != NULL) { printf ("Looking for \"x\" in the global symbol table ... \n"); SgSymbol* symbol = globalScope->lookup_var_symbol("x"); ROSE_ASSERT(symbol != NULL); } #endif }
bool ClangToSageTranslator::VisitDecl(clang::Decl * decl, SgNode ** node) { #if DEBUG_VISIT_DECL std::cerr << "ClangToSageTranslator::VisitDecl" << std::endl; #endif if (*node == NULL) { std::cerr << "Runtime error: No Sage node associated with the declaration..." << std::endl; return false; } if (!isSgGlobal(*node)) applySourceRange(*node, decl->getSourceRange()); // TODO attributes /* std::cerr << "Attribute list for " << decl->getDeclKindName() << " (" << decl << "): "; clang::Decl::attr_iterator it; for (it = decl->attr_begin(); it != decl->attr_end(); it++) { std::cerr << (*it)->getKind() << ", "; } std::cerr << std::endl; if (clang::VarDecl::classof(decl)) { clang::VarDecl * var_decl = (clang::VarDecl *)decl; std::cerr << "Stoprage class for " << decl->getDeclKindName() << " (" << decl << "): " << var_decl->getStorageClass() << std::endl; } */ return true; }
void MyTraversal::visit ( SgNode* astNode ) { SgBasicBlock* bb = isSgBasicBlock(astNode); SgGlobal *sg=isSgGlobal(astNode); string symbol_id="foo"; string incstr="#include \"newadinc.h\""; if (bb!=NULL) { // insert declaration double foo; // on top of this block Sg_File_Info * finfo=new Sg_File_Info(bb->getFileName(), 1,1); SgName sgnm(symbol_id.c_str()); SgType * ptype = new SgTypeDouble(); SgVariableDeclaration *sgdecl=new SgVariableDeclaration(finfo,sgnm, ptype); bb->prepend_statement(sgdecl); // MiddleLevelRewrite::insert(bb, sgdecl->unparseToString(),MidLevelCollectionTypedefs::TopOfCurrentScope); } else { if(sg!=NULL) { MiddleLevelRewrite::insert(sg,incstr, MidLevelCollectionTypedefs::TopOfCurrentScope); } } }
SgFunctionDeclaration *CudaOutliner::createFuncSkeleton (const string& name, SgType* ret_type, SgFunctionParameterList* params, SgScopeStatement* scope) { ROSE_ASSERT(scope != NULL); ROSE_ASSERT(isSgGlobal(scope)!=NULL); SgFunctionDeclaration* func; SgProcedureHeaderStatement* fortranRoutine; if (SageInterface::is_Fortran_language()) { fortranRoutine = SageBuilder::buildProcedureHeaderStatement(name.c_str(),ret_type, params, SgProcedureHeaderStatement::e_subroutine_subprogram_kind,scope); func = isSgFunctionDeclaration(fortranRoutine); } else { func = SageBuilder::buildDefiningFunctionDeclaration(name,ret_type,params,scope); } ROSE_ASSERT (func != NULL); SgFunctionSymbol* func_symbol = scope->lookup_function_symbol(func->get_name()); ROSE_ASSERT(func_symbol != NULL); if (0)//Outliner::enable_debug) { printf("Found function symbol in %p for function:%s\n",scope,func->get_name().getString().c_str()); } return func; }
void StaticConstructorTraversal::visit(SgNode *n) { // Get declared variables SgInitializedName *vName = isSgInitializedName(n); if (vName && !isAcreIgnore(vName->get_declaration())) { Sg_File_Info *fInfo = vName->get_file_info(); SgScopeStatement *scope = vName->get_scope(); // Find global variables (variables in namespaces count, e.g. std) if (!fInfo->isCompilerGenerated() && (isSgGlobal(scope) || isSgNamespaceDefinitionStatement(scope))) { // Walk typedefs until reach pointer to base type SgTypedefType *tdType = isSgTypedefType(vName->get_type()); while (tdType && isSgTypedefType(tdType->get_base_type())) tdType = isSgTypedefType(tdType->get_base_type()); // Determine if type is a class (i.e. type with a constructor) SgClassType *cType = isSgClassType(vName->get_type()); if (tdType) cType = isSgClassType(tdType->get_base_type()); // Output location of globals with a static constructor if (cType) { *out << "Static Constructor Violation: " << fInfo->get_filename() << " @ " << fInfo->get_line() << "\n"; } } } }
//! A helper function to build a single abstract handle item static abstract_handle * buildSingleAbstractHandle(SgNode* snode, abstract_handle * p_handle = NULL) { abstract_handle * result = NULL; ROSE_ASSERT (snode != NULL); abstract_node * anode = buildroseNode(snode); ROSE_ASSERT (anode != NULL); // look up first result = handle_map[anode]; if (result != NULL) return result; //Create the single handle item if (isSgSourceFile (snode) || isSgProject(snode) ||isSgGlobal(snode)) result = new abstract_handle (anode); // default name or file location specifiers are used else { // any other types of AST node, use numbering or name within the parent handle ROSE_ASSERT (p_handle != NULL); if (isSgFunctionDefinition(snode)) result = new abstract_handle (anode, e_name, p_handle); else result = new abstract_handle (anode, e_numbering, p_handle); } ROSE_ASSERT (result != NULL); // cache the result handle_map[anode] = result; return result; }
void SgGlobal::fixupCopy_symbols(SgNode* copy, SgCopyHelp & help) const { #if DEBUG_FIXUP_COPY printf ("Inside of SgGlobal::fixupCopy_symbols() for %p copy = %p \n",this,copy); #endif SgGlobal* global_copy = isSgGlobal(copy); ROSE_ASSERT(global_copy != NULL); const SgDeclarationStatementPtrList & statementList_original = this->getDeclarationList(); const SgDeclarationStatementPtrList & statementList_copy = global_copy->getDeclarationList(); SgDeclarationStatementPtrList::const_iterator i_original = statementList_original.begin(); SgDeclarationStatementPtrList::const_iterator i_copy = statementList_copy.begin(); // Iterate over both lists to match up the correct pairs of SgStatement objects while ( (i_original != statementList_original.end()) && (i_copy != statementList_copy.end()) ) { (*i_original)->fixupCopy_symbols(*i_copy,help); i_original++; i_copy++; } // Call the base class fixupCopy member function SgScopeStatement::fixupCopy_symbols(copy,help); // printf ("\nLeaving SgGlobal::fixupCopy_symbols() this = %p = %s copy = %p \n",this,this->class_name().c_str(),copy); }
void SageUtils::addComment(const std::string & comment, SgScopeStatement * scope) { PreprocessingInfo::RelativePositionType pos; if(isSgGlobal(scope)) { pos = PreprocessingInfo::after; } else { pos = PreprocessingInfo::inside; } SageInterface::attachComment(scope, comment, pos); }
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.
void visit(SgNode *S) { switch (S->variantT()) { case V_SgFunctionDeclaration: visitSgFunctionDeclaration(dynamic_cast<SgFunctionDeclaration *>(S)); break; case V_SgGlobal: if (debugHooks) { SageInterface::insertHeader("assert.h", PreprocessingInfo::after, true, isSgGlobal(S)); } break; default: break; } }
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++; } } }
/** * Do not reuse variable names in subscopes */ bool DCL01_C( const SgNode *node ) { const SgInitializedName *varInitName = isSgInitializedName(node); if (!varInitName) return false; const SgName varName = varInitName->get_name(); const SgScopeStatement *varScope = varInitName->get_scope(); assert(varScope); while(!isSgGlobal(varScope)) { varScope = varScope->get_scope(); if(varScope->symbol_exists(varName)) { print_error(node, "DCL01-C", ("Do not reuse variable names in subscopes: " + varName.getString()).c_str(), true); return true; } } return false; }
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); } }
/* * The visit function is reimplemented from AstSimpleProcessing, and is called for every node * in the the AST. We are only really interested in looking at function calls to op_par_loop_3. */ void OPSource::visit(SgNode *n) { SgFile *file = isSgFile(n); if(file!=NULL) { file->set_unparse_includes(false); } // We need to put the global scope on the scope stack so that we can look // up the oplus datatypes later on (in generateSpecial). SgGlobal *globalScope = isSgGlobal(n); if(globalScope!=NULL) { pushScopeStack(globalScope); // Add the global kernel header insertHeader("kernels.h", PreprocessingInfo::after, false, globalScope); } fixParLoops(n); fixOpStructs(n); fixOpFunctions(n); }
SgFunctionDeclaration * CudaOutliner::generateFunction ( SgBasicBlock* s, const string& func_name_str, ASTtools::VarSymSet_t& syms, MintHostSymToDevInitMap_t hostToDevVars, const ASTtools::VarSymSet_t& pdSyms, const ASTtools::VarSymSet_t& psyms, SgScopeStatement* scope) { //Create a function named 'func_name_str', with a parameter list from 'syms' //pdSyms specifies symbols which must use pointer dereferencing if replaced during outlining, //only used when -rose:outline:temp_variable is used //psyms are the symbols for OpenMP private variables, or dead variables (not live-in, not live-out) ROSE_ASSERT ( s && scope); ROSE_ASSERT(isSgGlobal(scope)); // step 1: perform necessary liveness and side effect analysis, if requested. // --------------------------------------------------------- std::set< SgInitializedName *> liveIns, liveOuts; // Collect read-only variables of the outlining target std::set<SgInitializedName*> readOnlyVars; if (Outliner::temp_variable||Outliner::enable_classic) { SgStatement* firstStmt = (s->get_statements())[0]; if (isSgForStatement(firstStmt)&& Outliner::enable_liveness) { LivenessAnalysis * liv = SageInterface::call_liveness_analysis (SageInterface::getProject()); SageInterface::getLiveVariables(liv, isSgForStatement(firstStmt), liveIns, liveOuts); } SageInterface::collectReadOnlyVariables(s,readOnlyVars); if (0)//Outliner::enable_debug) { cout<<" INFO:Mint: CudaOutliner::generateFunction()---Found "<<readOnlyVars.size()<<" read only variables..:"; for (std::set<SgInitializedName*>::const_iterator iter = readOnlyVars.begin(); iter!=readOnlyVars.end(); iter++) cout<<" "<<(*iter)->get_name().getString()<<" "; cout<<endl; cout<<"CudaOutliner::generateFunction() -----Found "<<liveOuts.size()<<" live out variables..:"; for (std::set<SgInitializedName*>::const_iterator iter = liveOuts.begin(); iter!=liveOuts.end(); iter++) cout<<" "<<(*iter)->get_name().getString()<<" "; cout<<endl; } } //step 2. Create function skeleton, 'func'. // ----------------------------------------- SgName func_name (func_name_str); SgFunctionParameterList *parameterList = buildFunctionParameterList(); SgType* func_Type = SgTypeVoid::createType (); SgFunctionDeclaration* func = createFuncSkeleton (func_name, func_Type ,parameterList, scope); //adds __global__ keyword func->get_functionModifier().setCudaKernel(); ROSE_ASSERT (func); // Liao, 4/15/2009 , enforce C-bindings for C++ outlined code // enable C code to call this outlined function // Only apply to C++ , pure C has trouble in recognizing extern "C" // Another way is to attach the function with preprocessing info: // #if __cplusplus // extern "C" // #endif // We don't choose it since the language linkage information is not explicit in AST if ( SageInterface::is_Cxx_language() || is_mixed_C_and_Cxx_language() \ || is_mixed_Fortran_and_Cxx_language() || is_mixed_Fortran_and_C_and_Cxx_language() ) { // Make function 'extern "C"' func->get_declarationModifier().get_storageModifier().setExtern(); func->set_linkage ("C"); } //step 3. Create the function body // ----------------------------------------- // Generate the function body by deep-copying 's'. SgBasicBlock* func_body = func->get_definition()->get_body(); ROSE_ASSERT (func_body != NULL); // This does a copy of the statements in "s" to the function body of the outlined function. ROSE_ASSERT(func_body->get_statements().empty() == true); // This calls AST copy on each statement in the SgBasicBlock, but not on the block, so the // symbol table is setup by AST copy mechanism and it is setup properly SageInterface::moveStatementsBetweenBlocks (s, func_body); if (Outliner::useNewFile) ASTtools::setSourcePositionAtRootAndAllChildrenAsTransformation(func_body); //step 4: variable handling, including: // ----------------------------------------- // create parameters of the outlined functions // add statements to unwrap the parameters if wrapping is requested // add repacking statements if necessary // replace variables to access to parameters, directly or indirectly // do not wrap parameters Outliner::enable_classic = true; functionParameterHandling(syms, hostToDevVars, pdSyms, psyms, readOnlyVars, liveOuts, func); ROSE_ASSERT (func != NULL); // Retest this... // Copied the similar fix from the rose outliner // Liao 2/6/2013. It is essential to rebuild function type after the parameter list is finalized. // The original function type was build using empty parameter list. SgType* stale_func_type = func->get_type(); func->set_type(buildFunctionType(func->get_type()->get_return_type(), buildFunctionParameterTypeList(func->get_parameterList()))); SgFunctionDeclaration* non_def_func = isSgFunctionDeclaration(func->get_firstNondefiningDeclaration ()) ; ROSE_ASSERT (non_def_func != NULL); ROSE_ASSERT (stale_func_type == non_def_func->get_type()); non_def_func->set_type(func->get_type()); ROSE_ASSERT(func->get_definition()->get_body()->get_parent() == func->get_definition()); ROSE_ASSERT(scope->lookup_function_symbol(func->get_name())); return func; }
void FixupAstSymbolTables::visit ( SgNode* node ) { // DQ (6/27/2005): Output the local symbol table from each scope. // printf ("node = %s \n",node->sage_class_name()); SgScopeStatement* scope = isSgScopeStatement(node); if (scope != NULL) { #if 0 printf ("AST Fixup: Fixup Symbol Table for %p = %s at: \n",scope,scope->class_name().c_str()); #endif SgSymbolTable* symbolTable = scope->get_symbol_table(); if (symbolTable == NULL) { #if 0 printf ("AST Fixup: Fixup Symbol Table for %p = %s at: \n",scope,scope->class_name().c_str()); scope->get_file_info()->display("Symbol Table Location"); #endif SgSymbolTable* tempSymbolTable = new SgSymbolTable(); ROSE_ASSERT(tempSymbolTable != NULL); // name this table as compiler generated! The name is a static member used to store // state for the next_symbol() functions. It is meaningless to set these. // tempSymbolTable->set_name("compiler-generated symbol table"); scope->set_symbol_table(tempSymbolTable); // reset the symbolTable using the get_symbol_table() member function symbolTable = scope->get_symbol_table(); ROSE_ASSERT(symbolTable != NULL); // DQ (2/16/2006): Set this parent directly (now tested) symbolTable->set_parent(scope); ROSE_ASSERT(symbolTable->get_parent() != NULL); } ROSE_ASSERT(symbolTable != NULL); if (symbolTable->get_parent() == NULL) { printf ("Warning: Fixing up symbolTable, calling symbolTable->set_parent() (parent not previously set) \n"); symbolTable->set_parent(scope); } ROSE_ASSERT(symbolTable->get_parent() != NULL); // Make sure that the internal hash table used in the symbol table is also present! if (symbolTable->get_table() == NULL) { // DQ (6/27/2005): There are a lot of these built, perhaps more than we really need! #if 0 printf ("AST Fixup: Building internal Symbol Table hash table (rose_hash_multimap) for %p = %s at: \n", scope,scope->sage_class_name()); scope->get_file_info()->display("Symbol Table Location"); #endif rose_hash_multimap* internalHashTable = new rose_hash_multimap(); ROSE_ASSERT(internalHashTable != NULL); symbolTable->set_table(internalHashTable); } ROSE_ASSERT(symbolTable->get_table() != NULL); SgSymbolTable::BaseHashType* internalTable = symbolTable->get_table(); ROSE_ASSERT(internalTable != NULL); // DQ (6/23/2011): Note: Declarations that reference types that have not been seen yet may be placed into the // wronge scope, then later when we see the correct scope we have a symbol in two or more symbol tables. The // code below detects and fixes this problem. // DQ (6/16/2011): List of symbols we need to remove from symbol tables where they are multibily represented. std::vector<SgSymbol*> listOfSymbolsToRemove; // DQ (6/12/2011): Fixup symbol table by removing symbols that are not associated with a declaration in the current scope. int idx = 0; SgSymbolTable::hash_iterator i = internalTable->begin(); while (i != internalTable->end()) { // DQ: removed SgName casting operator to char* // cout << "[" << idx << "] " << (*i).first.str(); ROSE_ASSERT ( (*i).first.str() != NULL ); ROSE_ASSERT ( isSgSymbol( (*i).second ) != NULL ); // printf ("Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) sage_class_name() = %s \n", // idx,(*i).first.str(),(*i).second->sage_class_name()); SgSymbol* symbol = isSgSymbol((*i).second); ROSE_ASSERT ( symbol != NULL ); // We have to look at each type of symbol separately! This is because there is no virtual function, // the reason for this is that each get_declaration() function returns a different type! // ROSE_ASSERT ( symbol->get_declaration() != NULL ); switch(symbol->variantT()) { case V_SgClassSymbol: { SgClassSymbol* classSymbol = isSgClassSymbol(symbol); ROSE_ASSERT(classSymbol != NULL); ROSE_ASSERT(classSymbol->get_declaration() != NULL); SgDeclarationStatement* declarationToFindInScope = NULL; // Search for the declaration in the associated scope. declarationToFindInScope = classSymbol->get_declaration(); ROSE_ASSERT(declarationToFindInScope != NULL); SgClassDeclaration* classDeclaration = isSgClassDeclaration(declarationToFindInScope); ROSE_ASSERT(classDeclaration != NULL); SgName name = classDeclaration->get_name(); // SgType* declarationType = declarationToFindInScope->get_type(); SgType* declarationType = classDeclaration->get_type(); ROSE_ASSERT(declarationType != NULL); if (declarationToFindInScope->get_definingDeclaration() != NULL) { declarationToFindInScope = declarationToFindInScope->get_definingDeclaration(); SgClassDeclaration* definingClassDeclaration = isSgClassDeclaration(declarationToFindInScope); ROSE_ASSERT(definingClassDeclaration != NULL); // SgType* definingDeclarationType = declarationToFindInScope->get_type(); SgType* definingDeclarationType = definingClassDeclaration->get_type(); ROSE_ASSERT(definingDeclarationType != NULL); // DQ (6/22/2011): This assertion fails for CompileTests/copyAST_tests/copytest2007_24.C // A simple rule that all declarations should follow (now that we have proper global type tables). // ROSE_ASSERT(definingDeclarationType == declarationType); if (definingDeclarationType != declarationType) { printf ("In fixupSymbolTables.C: Note that definingDeclarationType != declarationType \n"); } } SgNamedType* namedType = isSgNamedType(declarationType); ROSE_ASSERT(namedType != NULL); SgDeclarationStatement* declarationAssociatedToType = namedType->get_declaration(); ROSE_ASSERT(declarationAssociatedToType != NULL); #if 0 printf ("Found a symbol without a matching declaration in the current scope (declList): declarationToFindInScope = %p = %s \n",declarationToFindInScope,declarationToFindInScope->class_name().c_str()); printf ("Symbol number: %d (pair.first (SgName) = %s) pair.second (SgSymbol) class_name() = %s \n",idx,(*i).first.str(),(*i).second->class_name().c_str()); #endif SgScopeStatement* scopeOfDeclarationToFindInScope = declarationToFindInScope->get_scope(); SgScopeStatement* scopeOfDeclarationAssociatedWithType = declarationAssociatedToType->get_scope(); #if 0 printf ("declarationToFindInScope = %p declarationToFindInScope->get_scope() = %p = %s \n",declarationToFindInScope,declarationToFindInScope->get_scope(),declarationToFindInScope->get_scope()->class_name().c_str()); printf ("declarationAssociatedToType = %p declarationAssociatedToType->get_scope() = %p = %s \n",declarationAssociatedToType,declarationAssociatedToType->get_scope(),declarationAssociatedToType->get_scope()->class_name().c_str()); #endif if (scopeOfDeclarationToFindInScope != scopeOfDeclarationAssociatedWithType) { // DQ (6/12/2011): Houston, we have a problem! The trick is to fix it... // A symbol has been placed into a scope when we could not be certain which scope it should be placed. // We have a default of placing such symbols into the global scope, but it might be better to just have // a special scope where such symbols could be placed so that we could have them separate from the global // scope and then fix them up more clearly. // Note that test2011_80.C still fails but the AST is at least correct (I think). SgGlobal* scopeOfDeclarationToFindInScope_GlobalScope = isSgGlobal(scopeOfDeclarationToFindInScope); // SgGlobal* scopeOfDeclarationAssociatedWithType_GlobalScope = isSgGlobal(scopeOfDeclarationAssociatedWithType); if (scopeOfDeclarationToFindInScope_GlobalScope != NULL) { // In general which ever scope is the global scope is where the error is...??? // This is because when we don't know where to put a symbol (e.g. from a declaration of a pointer) we put it into global scope. // There is even an agrument that this is correct as a default for C/C++, but only if it must exist (see test2011_80.C). // Remove the symbol from the symbol table of the global scope. printf ("Remove the associated symbol in the current symbol table \n"); // DQ (6/22/2011): This assertion fails for CompileTests/copyAST_tests/copytest2007_24.C // ROSE_ASSERT (declarationToFindInScope->get_scope() == declarationAssociatedToType->get_scope()); if (declarationToFindInScope->get_scope() != declarationAssociatedToType->get_scope()) printf ("In fixupSymbolTables.C: Note that declarationToFindInScope->get_scope() != declarationAssociatedToType->get_scope() \n"); } else { listOfSymbolsToRemove.push_back(classSymbol); } } // ROSE_ASSERT (declarationToFindInScope->get_scope() == declarationAssociatedToType->get_scope()); break; } default: { // It night be there are are no other types of symbols to consider... // printf ("Ignoring non SgClassSymbols (fixupSymbolTables.C) symbol = %s \n",symbol->class_name().c_str()); // ROSE_ASSERT(false); } } // Increment iterator! i++; // Increment counter! idx++; } // DQ (6/18/2011): Now that we are through with the symbol table we can support removal of any // identified problematic symbol without worrying about STL iterator invalidation. for (size_t j = 0; j < listOfSymbolsToRemove.size(); j++) { // Remove these symbols. SgSymbol* removeSymbol = listOfSymbolsToRemove[j]; ROSE_ASSERT(removeSymbol != NULL); SgSymbolTable* associatedSymbolTable = isSgSymbolTable(removeSymbol->get_parent()); ROSE_ASSERT(associatedSymbolTable != NULL); ROSE_ASSERT(associatedSymbolTable == symbolTable); associatedSymbolTable->remove(removeSymbol); printf ("Redundant symbol removed...from symbol table \n"); // ROSE_ASSERT(false); } #if 0 // debugging symbolTable->print("In FixupAstSymbolTables::visit(): printing out the symbol tables"); #endif } }
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); } }
// GB (05/30/2007): This was completely rewritten from the old version to // use much more efficient comparisons now available to us; it also never // causes visits to included files, something that happened from time to // time with the old version. bool SgTreeTraversal_inFileToTraverse(SgNode* node, bool traversalConstraint, SgFile* fileToVisit) { // If traversing without constraint, just continue. // if (!traversalConstraint) if (traversalConstraint == false) { return true; } #if 0 // DQ (8/20/2018): Added debugging for support unparsing of header files. printf ("In SgTreeTraversal_inFileToTraverse(): fileToVisit = %p filename = %s \n",fileToVisit,fileToVisit->getFileName().c_str()); #endif // DQ (1/21/2008): Recently added SgAsmNodes for binaries also do not // have a SgFileInfo object. // Of all the nodes to be traversed, only SgProject is allowed to have // a NULL file info; go ahead and try to traverse it (even though this // does not make sense since it is not within any file). if (node->get_file_info() == NULL) { // DQ (1/20/2008): This fails for binary files, why is this! // if (isSgProject(node) == NULL) // printf ("What node is this: node = %p = %s \n",node,node->class_name().c_str()); // SageInterface::get_name(node).c_str()); // ROSE_ASSERT(isSgProject(node) != NULL); // DQ (11/20/2013): Added SgJavaImportStatementList and SgJavaClassDeclarationList to the exception list since they don't have a source position field. // if (isSgProject(node) == NULL && isSgAsmNode(node) == NULL) if (isSgProject(node) == NULL && isSgAsmNode(node) == NULL && isSgJavaImportStatementList(node) == NULL && isSgJavaClassDeclarationList(node) == NULL) { printf ("Error: SgTreeTraversal_inFileToTraverse() --- node->get_file_info() == NULL: node = %p = %s \n",node,node->class_name().c_str()); SageInterface::dumpInfo(node); } #if 0 // DQ (11/19/2013): Allow this to pass while we are evaluating the AST traversal for Java. // ROSE_ASSERT(isSgProject(node) != NULL || isSgAsmNode(node) != NULL); // if (isSgProject(node) == NULL && isSgAsmNode(node) == NULL) if (isSgProject(node) == NULL && isSgAsmNode(node) == NULL && isSgJavaImportStatementList(node) == NULL && isSgJavaClassDeclarationList(node) == NULL) { printf ("WARNING: isSgProject(node) == NULL && isSgAsmNode(node) == NULL: this could be Java code using an incomplete AST: node = %p = %s \n",node,node->class_name().c_str()); } #endif return true; } // Traverse compiler generated code and code generated from // transformations, unless it is "frontend specific" like the stuff in // rose_edg_required_macros_and_functions.h. bool isFrontendSpecific = node->get_file_info()->isFrontendSpecific(); bool isCompilerGeneratedOrPartOfTransformation; if (isFrontendSpecific) { isCompilerGeneratedOrPartOfTransformation = false; } else { // DQ (11/14/2008): Implicitly defined functions in Fortran are not marked as compiler generated // (the function body is at least explicit in the source file), but the function declaration IR // nodes is marked as coming from file == NULL_FILE and it is also marked as "outputInCodeGeneration" // So it should be traversed so that we can see the function body and so that it can be a proper // part of the definition of the AST. // isCompilerGeneratedOrPartOfTransformation = node->get_file_info()->isCompilerGenerated() || node->get_file_info()->isTransformation(); bool isOutputInCodeGeneration = node->get_file_info()->isOutputInCodeGeneration(); isCompilerGeneratedOrPartOfTransformation = node->get_file_info()->isCompilerGenerated() || node->get_file_info()->isTransformation() || isOutputInCodeGeneration; } // Traverse this node if it is in the file we want to visit. bool isRightFile = node->get_file_info()->isSameFile(fileToVisit); #if 0 printf ("In SgTreeTraversal_inFileToTraverse(): node = %p = %s isRightFile = %s \n",node,node->class_name().c_str(),isRightFile ? "true" : "false"); #endif // This function is meant to traverse input files in the sense of not // visiting "header" files (a fuzzy concept). But not every #included file // is a header, "code" (another fuzzy concept) can also be #included; see // test2005_157.C for an example. We want to traverse such code, so we // cannot rely on just comparing files. // The following heuristic is therefore used: If a node is included from // global scope or from within a namespace definition, we guess that it is // a header and don't traverse it. Otherwise, we guess that it is "code" // and do traverse it. bool isCode = node->get_parent() != NULL && !isSgGlobal(node->get_parent()) && !isSgNamespaceDefinitionStatement(node->get_parent()); bool traverseNode; if (isCompilerGeneratedOrPartOfTransformation || isRightFile || isCode) traverseNode = true; else traverseNode = false; #if 0 // DQ (8/17/2018): Need to stop here and debug this function tomorrow. printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif return traverseNode; }
/** * Const-qualify immutable objects * * \todo count assignments, if only one, report violation */ bool DCL00_C( const SgNode *node ) { const SgInitializedName *varName = isSgInitializedName(node); if (!varName) return false; /** * Ignore variables generated by macros */ if ((varName->get_name().getString().substr(0,2) == "__") || isCompilerGeneratedNode(node)) return false; /** * Ignore global variables */ if (isGlobalVar(varName)) return false; /** * Ignore variables that are already const, are function pointers, or are * declared inside of a struct, enum, or as an argument to a function */ SgType *varType = varName->get_type(); if (isConstType(varType) || isConstType(varType->dereference()) || isConstType(varType->dereference()->dereference()) || isSgFunctionType(varType) || isSgClassType(varType) || findParentOfType(varName, SgCtorInitializerList) || findParentOfType(varName, SgEnumDeclaration) || findParentOfType(varName, SgClassDeclaration)) return false; /** * DCL13-C is a subset of this rule, figure out which rule we are dealing * with here */ std::string ruleStr; std::string errStr; if (findParentOfType(varName, SgFunctionParameterList)) { /** ignore function prototypes, just worry about the definitions */ const SgFunctionDeclaration *fnDecl = findParentOfType(varName, SgFunctionDeclaration); /** * Disabling assertion due to C++ code */ if (!fnDecl) return false; // assert(fnDecl); if (!fnDecl->get_definition()) return false; if (isSgPointerType(varName->get_type()) || isSgArrayType(varName->get_type())) { ruleStr = "DCL13-C"; errStr = "Declare function parameters that are pointers to values not changed by the function as const: "; } else { return false; } } else { ruleStr = "DCL00-C"; errStr = "Const-qualify immutable objects: "; } /** * Ignore global variables or variables declared as extern */ const SgScopeStatement *varScope = varName->get_scope(); if (isSgGlobal(varScope) || isExternVar(varName)) return false; FOREACH_SUBNODE(varScope, nodes, i, V_SgVarRefExp) { const SgVarRefExp *iVar = isSgVarRefExp(*i); assert(iVar); if (getRefDecl(iVar) != varName) continue; const SgNode *parent = iVar->get_parent(); while(isSgCastExp(parent)) { parent = parent->get_parent(); } assert(parent); /** * If the variable is written to or it's address is taken, we can no * longer be sure it should be const, if it's a struct and gets * dereferenced, who knows what's getting written there :/ */ if (varWrittenTo(iVar) || isSgArrowExp(parent) || findParentOfType(iVar, SgAddressOfOp)) return false; /** * If the variable is a pointer or array, and we pass it to a function * or as an argument to pointer arithmetic, or assign it's value * somewhere, we can longer be sure it should be const */ if ((isSgPointerType(varType) || isSgArrayType(varType)) && (findParentOfType(iVar, SgFunctionCallExp) || isSgAddOp(parent) || isSgSubtractOp(parent) || isSgAssignOp(parent) || isSgPntrArrRefExp(parent) || isSgPointerDerefExp(parent) || isSgAssignInitializer(parent))) return false; } const std::string msg = errStr + varName->get_name().getString(); print_error(node, ruleStr.c_str(), msg.c_str(), true); return true; }