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"; } } } }
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 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<SgNamespaceSymbol>(SgNamespaceSymbol * symbol) { SgNamespaceSymbol * parent = NULL; if (p_valid_symbols.find(symbol) != p_valid_symbols.end()) return true; SgNamespaceDefinitionStatement * namespace_scope = isSgNamespaceDefinitionStatement(symbol->get_scope()); if (namespace_scope != NULL) { SgNamespaceDeclarationStatement * parent_decl = namespace_scope->get_namespaceDeclaration(); assert(parent_decl != NULL); parent = SageInterface::lookupNamespaceSymbolInParentScopes(parent_decl->get_name(), parent_decl->get_scope()); assert(parent != NULL); if (!resolveValidParent<SgNamespaceSymbol>(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_namespace_symbols.insert(symbol); return true; }
void SgNamespaceDefinitionStatement::fixupCopy_symbols(SgNode* copy, SgCopyHelp & help) const { #if DEBUG_FIXUP_COPY printf ("Inside of SgNamespaceDefinitionStatement::fixupCopy_symbols() for %p = %s copy = %p \n",this,this->class_name().c_str(),copy); #endif #if 0 printf ("Inside of SgNamespaceDefinitionStatement::fixupCopy_symbols() for %p = %s copy = %p \n",this,this->class_name().c_str(),copy); #endif SgNamespaceDefinitionStatement* namespaceDefinition_copy = isSgNamespaceDefinitionStatement(copy); ROSE_ASSERT(namespaceDefinition_copy != NULL); const SgDeclarationStatementPtrList & statementList_original = this->getDeclarationList(); const SgDeclarationStatementPtrList & statementList_copy = namespaceDefinition_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()) ) { #if 0 printf ("Inside of SgNamespaceDefinitionStatement::fixupCopy_symbols() for %p = %s copy = %p (in loop over statements) \n",this,this->class_name().c_str(),copy); #endif (*i_original)->fixupCopy_symbols(*i_copy,help); i_original++; i_copy++; } #if 0 printf ("Leaving SgNamespaceDefinitionStatement::fixupCopy_symbols() for %p = %s copy = %p (call SgScopeStatement::fixupCopy_symbols()) \n",this,this->class_name().c_str(),copy); #endif // Call the base class fixupCopy member function SgScopeStatement::fixupCopy_symbols(copy,help); #if 0 printf ("Leaving SgNamespaceDefinitionStatement::fixupCopy_symbols() for %p = %s copy = %p \n",this,this->class_name().c_str(),copy); #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; }