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; }
void ModelBuilder::add(Model::model_t & model, SgType * sg_type) { SgModifierType * modifier_type = isSgModifierType(sg_type); if (modifier_type != NULL) { add(model, modifier_type->get_base_type()); return; } Model::type_t element = Model::build<Model::e_model_type>(); element->node->type = sg_type; SgNamedType * named_type = isSgNamedType(sg_type); SgArrayType * array_type = isSgArrayType(sg_type); SgPointerType * pointer_type = isSgPointerType(sg_type); SgReferenceType * reference_type = isSgReferenceType(sg_type); if (named_type != NULL) { SgClassType * class_type = isSgClassType(named_type); SgEnumType * enum_type = isSgEnumType(named_type); SgTypedefType * typedef_type = isSgTypedefType(named_type); SgDeclarationStatement * decl_stmt = named_type->get_declaration()->get_firstNondefiningDeclaration(); assert(decl_stmt != NULL); SgSymbol * decl_sym = decl_stmt->get_symbol_from_symbol_table(); assert(decl_sym != NULL); if (class_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_class_type; SgClassSymbol * class_sym = isSgClassSymbol(decl_sym); assert(class_sym != NULL); element->node->base_class = model.lookup_class(class_sym); if (element->node->base_class == NULL) { add(model, class_sym); element->node->base_class = model.lookup_class(class_sym); } assert(element->node->base_class != NULL); } else if (enum_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_enum_type; SgEnumSymbol * enum_sym = isSgEnumSymbol(decl_sym); assert(enum_sym != NULL); element->node->enum_symbol = enum_sym; } else if (typedef_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_typedef_type; SgTypedefSymbol * typedef_sym = isSgTypedefSymbol(decl_sym); assert(typedef_sym != NULL); element->node->typedef_symbol = typedef_sym; element->node->base_type = model.lookup_type(typedef_type->get_base_type()); if (element->node->base_type == NULL) { add(model, typedef_type->get_base_type()); element->node->base_type = model.lookup_type(typedef_type->get_base_type()); } assert(element->node->base_type != NULL); } else assert(false); } else if (array_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_array_type; element->node->base_type = model.lookup_type(array_type->get_base_type()); if (element->node->base_type == NULL) { add(model, array_type->get_base_type()); element->node->base_type = model.lookup_type(array_type->get_base_type()); } assert(element->node->base_type != NULL); } else if (pointer_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_pointer_type; element->node->base_type = model.lookup_type(pointer_type->get_base_type()); if (element->node->base_type == NULL) { add(model, pointer_type->get_base_type()); element->node->base_type = model.lookup_type(pointer_type->get_base_type()); } assert(element->node->base_type != NULL); } else if (reference_type != NULL) { element->node->kind = Model::node_t<Model::e_model_type>::e_reference_type; element->node->base_type = model.lookup_type(reference_type->get_base_type()); if (element->node->base_type == NULL) { add(model, reference_type->get_base_type()); element->node->base_type = model.lookup_type(reference_type->get_base_type()); } assert(element->node->base_type != NULL); } else { element->node->kind = Model::node_t<Model::e_model_type>::e_native_type; } element->scope->parent.a_namespace = NULL; /// \todo model.types.push_back(element); }
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); } }