From bb3a5ef25df2f63fcd57a07c0d02d1873e1625ab Mon Sep 17 00:00:00 2001 From: Dan Quinlan Date: Thu, 10 Jul 2014 18:49:04 -0700 Subject: [PATCH] Fixed function prototype handling of original function type syntax in code generation (modified IR to support added type_syntax, but only for function declarations at this point). --- README.git | 24 ++++++++ src/ROSETTA/src/statement.C | 14 +++++ .../CxxCodeGeneration/unparseCxx_statements.C | 59 ++++++++++++++++++- src/frontend/CxxFrontend/EDG | 2 +- tests/CompileTests/Cxx_tests/Makefile.am | 6 ++ tests/CompileTests/Cxx_tests/test2014_85.C | 3 +- tests/CompileTests/Cxx_tests/test2014_86.C | 39 ++++++++++++ 7 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 tests/CompileTests/Cxx_tests/test2014_86.C diff --git a/README.git b/README.git index cbaf5e058ef..12988cb2ef7 100644 --- a/README.git +++ b/README.git @@ -936,3 +936,27 @@ Working with the new_app branch on tux231: Working with the new_app branch on zeus: 145 9:45 smgit fetch origin 146 9:46 smgit merge origin/dquinlan/dq-new_app-rc + + +Technique for debugging exceptions: + 1) Look for the name of the exception + terminate called after throwing an instance of 'std::logic_error' + what(): basic_string::_S_construct NULL not valid + + 2) search for the name of the exception to find the associated function in the + include-staging/g++_HEADERS directory. + grep -r "basic_string::_S_construct NULL not valid" * + + 3) Set a break point in gdb to detect when that function is called. + (gdb) b std::__throw_logic_error(char const*) + + 4) Use the where command in gdb to get the trace back to the location of the exception. + (gdb) w + +Example ouput of gdb trace: +#0 0x000000348f4617d0 in std::__throw_logic_error(char const*) () from /usr/lib64/libstdc++.so.6 +#1 0x000000348f49ce59 in ?? () from /usr/lib64/libstdc++.so.6 +#2 0x000000348f49cf33 in std::basic_string, std::allocator >::basic_string(char const*, std::allocator const&) () from /usr/lib64/libstdc++.so.6 +#3 0x00007ffff6680036 in EDG_ROSE_Translation::getDeclarationScope (scp=...) at /home/dquinlan/ROSE/git-dq-new_app-rc/src/frontend/CxxFrontend/EDG/edgRose/edgRose.C:31917 +#4 0x00007ffff668d7f8 in EDG_ROSE_Translation::convert_variable_use (p=0x947d90) at /home/dquinlan/ROSE/git-dq-new_app-rc/src/frontend/CxxFrontend/EDG/edgRose/edgRose.C:30057 +#5 0x00007ffff667358b in EDG_ROSE_Translation::convert_expression (e=0x9486a8) at /home/dquinlan/ROSE/git-dq-new_app-rc/src/frontend/CxxFrontend/EDG/edgRose/edgRose.C:8025 diff --git a/src/ROSETTA/src/statement.C b/src/ROSETTA/src/statement.C index 4d4d836659e..052260d55ce 100644 --- a/src/ROSETTA/src/statement.C +++ b/src/ROSETTA/src/statement.C @@ -1042,6 +1042,20 @@ Grammar::setUpStatements () FunctionDeclaration.setDataPrototype ( "int","gnu_regparm_attribute", "= 0", NO_CONSTRUCTOR_PARAMETER, BUILD_ACCESS_FUNCTIONS, NO_TRAVERSAL, NO_DELETE); + // DQ (7/9/2014): Example test2014_85.C demonstrates that the declared type of a function can be + // equivalent to other same functions (associated defining and non-defining declarations), but + // syntatically different in a way that makes a difference to the code generated from the unparser + // (but not to the formal type system). I am not clear if this type should be traversed, I think + // not, since it is a function type used only for the representation of syntax. + FunctionDeclaration.setDataPrototype ( "SgFunctionType*", "type_syntax", "= NULL", + NO_CONSTRUCTOR_PARAMETER, BUILD_ACCESS_FUNCTIONS, NO_TRAVERSAL /* || DEF2TYPE_TRAVERSAL */, NO_DELETE); + + // DQ (7/9/2014): Added boolean flag to communicate when the function's type syntax is different from + // the function's type. However, when the type_syntax is non-null, it is always an equivalent type. + // Future work will enforce this concept fo type equivalence, not yet supported. + FunctionDeclaration.setDataPrototype ( "bool","type_syntax_is_available", "= false", + NO_CONSTRUCTOR_PARAMETER, BUILD_ACCESS_FUNCTIONS, NO_TRAVERSAL, NO_DELETE); + FunctionDefinition.setFunctionPrototype ( "HEADER_FUNCTION_DEFINITION_STATEMENT", "../Grammar/Statement.code" ); FunctionDefinition.editSubstitute ( "HEADER_LIST_DECLARATIONS", "HEADER_LIST_DECLARATIONS", "../Grammar/Statement.code" ); diff --git a/src/backend/unparser/CxxCodeGeneration/unparseCxx_statements.C b/src/backend/unparser/CxxCodeGeneration/unparseCxx_statements.C index a0c830b4eca..7a6c9e467d1 100644 --- a/src/backend/unparser/CxxCodeGeneration/unparseCxx_statements.C +++ b/src/backend/unparser/CxxCodeGeneration/unparseCxx_statements.C @@ -273,10 +273,65 @@ Unparse_ExprStmt::unparseFunctionParameterDeclaration ( { ROSE_ASSERT (funcdecl_stmt != NULL); + ROSE_ASSERT (initializedName != NULL); SgName tmp_name = initializedName->get_name(); SgInitializer *tmp_init = initializedName->get_initializer(); SgType *tmp_type = initializedName->get_type(); - ROSE_ASSERT (initializedName!= NULL); + + // DQ (7/10/2014): Added support for using the original type syntax (saved as the declared function type). + if (funcdecl_stmt->get_type_syntax_is_available() == true) + { + // Here we want to use the type syntx that originally appears with this function declaration in the original code. + SgFunctionType* function_type = funcdecl_stmt->get_type_syntax(); + ROSE_ASSERT(function_type != NULL); +#if 0 + // printf ("Found the original function type syntax: function_type = %p = %s \n",function_type,function_type->unparseToString().c_str()); + printf ("In unparseFunctionParameterDeclaration(): Found the original function type syntax: function_type = %p = %s \n",function_type,function_type->class_name().c_str()); +#endif + SgFunctionParameterTypeList* type_argument_list = function_type->get_argument_list(); + ROSE_ASSERT(type_argument_list != NULL); + + // find the associated index from the initializedName. + SgFunctionParameterList* name_argument_list = funcdecl_stmt->get_parameterList(); + ROSE_ASSERT(name_argument_list != NULL); + + SgInitializedNamePtrList & name_list = name_argument_list->get_args(); + + SgInitializedNamePtrList::iterator i = name_list.begin(); + size_t counter = 0; + while (i != name_list.end() && (*i) != initializedName) + { +#if 0 + printf ("In unparseFunctionParameterDeclaration(): loop: counter = %zu \n",counter); +#endif + counter++; + i++; + } + + ROSE_ASSERT(i != name_list.end()); +#if 0 + printf ("In unparseFunctionParameterDeclaration(): counter = %zu \n",counter); +#endif + // SgTypePtrList & get_arguments() + tmp_type = type_argument_list->get_arguments()[counter]; +#if 0 + printf ("tmp_type = %p = %s \n",tmp_type,tmp_type->class_name().c_str()); +#endif +#if 0 + printf ("In unparseFunctionParameterDeclaration(): (funcdecl_stmt->get_type_syntax_is_available() == true): exiting as a test! \n"); + ROSE_ASSERT(false); +#endif + } + else + { + // DQ (7/10/2014): Enforce this rule. + ROSE_ASSERT(funcdecl_stmt->get_type_syntax() == NULL); + } + +#if 0 + printf ("In unparseFunctionParameterDeclaration(): exiting as a test! \n"); + ROSE_ASSERT(false); +#endif // DQ (8/9/2013): refactored to support additional refactoring to seperate out code to unparse SgInitializedName. bool oldStyleDefinition = funcdecl_stmt->get_oldStyleDefinition(); @@ -3039,6 +3094,7 @@ Unparse_ExprStmt::unparseFuncDeclStmt(SgStatement* stmt, SgUnparse_Info& info) #endif #if OUTPUT_FUNCTION_DECLARATION_DATA || 0 + printf ("calling unparse_helper \n"); curprint ("/* calling unparse_helper */"); #endif unparse_helper(funcdecl_stmt, ninfo); @@ -3047,6 +3103,7 @@ Unparse_ExprStmt::unparseFuncDeclStmt(SgStatement* stmt, SgUnparse_Info& info) ninfo.set_declstatement_ptr(NULL); #if 0 + printf ("DONE: calling unparse_helper \n"); curprint ("/* DONE: calling unparse_helper */"); #endif diff --git a/src/frontend/CxxFrontend/EDG b/src/frontend/CxxFrontend/EDG index 52cf9c05774..2fa35349569 160000 --- a/src/frontend/CxxFrontend/EDG +++ b/src/frontend/CxxFrontend/EDG @@ -1 +1 @@ -Subproject commit 52cf9c057749504a34558b11883c012e09a38d90 +Subproject commit 2fa353495696e7442f78a6b1e069701f5c9bbb1d diff --git a/tests/CompileTests/Cxx_tests/Makefile.am b/tests/CompileTests/Cxx_tests/Makefile.am index 1c850c386d2..b9608773f04 100644 --- a/tests/CompileTests/Cxx_tests/Makefile.am +++ b/tests/CompileTests/Cxx_tests/Makefile.am @@ -121,9 +121,15 @@ EXAMPLE_TESTCODES_REQUIRED_TO_PASS += \ test2014_80.C \ test2014_81.C \ test2014_82.C \ + test2014_85.C \ + test2014_86.C \ lulesh.C \ luleshTALC.C +# DQ (7/10/2014): Remaining bugs in new application. +# test2014_83.C +# test2014_84.C + # DQ (7/3/2014): This C++ language feature is only properly supported in EDG version 4.9 if ROSE_USE_EDG_VERSION_4_9 EXAMPLE_TESTCODES_REQUIRED_TO_PASS += \ diff --git a/tests/CompileTests/Cxx_tests/test2014_85.C b/tests/CompileTests/Cxx_tests/test2014_85.C index 32a6e30477f..6dfc39e7894 100644 --- a/tests/CompileTests/Cxx_tests/test2014_85.C +++ b/tests/CompileTests/Cxx_tests/test2014_85.C @@ -5,7 +5,8 @@ namespace const unsigned array_size = 3; } +#if 1 void foo( int reverse_boundary[array_size] ) { } - +#endif diff --git a/tests/CompileTests/Cxx_tests/test2014_86.C b/tests/CompileTests/Cxx_tests/test2014_86.C new file mode 100644 index 00000000000..28ff604f8c5 --- /dev/null +++ b/tests/CompileTests/Cxx_tests/test2014_86.C @@ -0,0 +1,39 @@ +void foo(int a[1]); // size is irrelevant +void bar(int(&a)[1]); // size is irrelevant +void baz(int(*a)[1]); // size is irrelevant + +namespace +{ + const unsigned array_size = 3; + const unsigned array_size2 = 2; +} + +/* +C++ '03 8.3.5/3: ...The type of a function is determined using the + following rules. The type of each parameter is determined from its + own decl-specifier-seq and declarator. After determining the type + of each parameter, any parameter of type "array of T" or "function + returning T" is adjusted to be "pointer to T" or "pointer to + function returning T," respectively.... +*/ + +void foo(int a[array_size]) { // decays to a pointer and becomes int* (C inheritage) + a[0]=a[1]+1; +} + +void bar(int(&a)[array_size2]) { // size is enforced + a[0]=a[1]+1; +} + +void baz(int(*a)[array_size2]) { // size is enforced + (*a)[0]=(*a)[1]+1; +} + +int main() { + int a[2]; + a[1]=1; + foo(a); + bar(a); + baz(&a); + return 0; +}