From: John P. <jwp...@gm...> - 2021-03-22 18:27:17
|
On Mon, Mar 22, 2021 at 1:10 PM <ed...@in...> wrote: > > Hi Edgar, > > > > I don't think this mailing list --8<-- accept{s} attachments. > > I live in a bubble :P . > > > Second best would be to paste a diff into > > the body of an email (assuming it's not too long, in which case the > > first > > option should be used). > > Third best: create a fork on notabug.org or GNU Savannah and send you > the link to the corresponding branch, right? ;D > > In any case, below is the original suggestion. Let me know if you like > the idea, and I will create the branch on notabug.org :D . > > Hello, > > I would kindly and respectfully like to suggest turning some macros in > =libmesh_common.h= into functions. As I was exploring libMesh, I naïvely > tried this: > > #+CAPTION: Using the =libmesh_error_msg= macro > #+begin_src cpp :libs $(libmesh-config --cxxflags --include --ldflags > --libs) > #include <stdio.h> > #include <iostream> > #include "libmesh/libmesh.h" > #include "libmesh/mesh.h" > > int main (int argc, char * argv[]){ > libMesh::LibMeshInit init(argc, argv); > > if (argc < 4){ > libMesh::libmesh_error_msg("Usage: "); > } > > } > #+end_src > > #+caption: Result from using =libmesh_error_msg= (does not compile). > #+begin_example > In file included from /usr/include/libmesh/libmesh.h:25, > from /tmp/babel-hlBzed/C-src-YQnbkN.cpp:3: > /tmp/babel-hlBzed/C-src-YQnbkN.cpp: In function 'int main(int, > char**)': > /tmp/babel-hlBzed/C-src-YQnbkN.cpp:15:14: error: expected > unqualified-id before 'do' > 15 | libMesh::libmesh_error_msg("Usage: " // << argv[0] << > | ^~~~~~~~~~~~~~~~~ > #+end_example > > This does not work, because =libmesh_error_msg= is actually a macro > defined in =libmesh_common.h=, and does not need =libMesh::=. > > If, however, the macro is replaced with the code, it should produce: > #+caption: Using the raw text from =libmesh_error_msg= > #+begin_src cpp :libs $(libmesh-config --cxxflags --include --ldflags > --libs) > #include <stdio.h> > #include <iostream> > #include "libmesh/libmesh.h" > #include "libmesh/mesh.h" > > int main (int argc, char * argv[]){ > libMesh::LibMeshInit init(argc, argv); > > if (argc < 4){ > char msg[] = "Usage: "; > do { > libMesh::err << msg << std::endl; > std::stringstream msg_stream; > msg_stream << msg; > libMesh::MacroFunctions::report_error(__FILE__, __LINE__, > LIBMESH_DATE, LIBMESH_TIME); > LIBMESH_THROW(libMesh::LogicError(msg_stream.str())); > } while (0); > } > > } > #+end_src > > #+caption: Expected output (error message from libMesh) with raw text > from =libmesh_error_msg= > #+begin_example > Usage: > Stack frames: 5 > 0: libMesh::print_trace(std::ostream&) > 1: libMesh::MacroFunctions::report_error(char const*, int, char > const*, char const*) > 2: /tmp/babel-hlBzed/C-bin-tb49Ls(+0xcdee) [0x563818bc5dee] > 3: __libc_start_main > 4: /tmp/babel-hlBzed/C-bin-tb49Ls(+0xceae) [0x563818bc5eae] > [0] /tmp/babel-hlBzed/C-src-APc5Dz.cpp, line 22, compiled Mar 18 > 2021 at 17:20:53 > > -------------------------------------------------------------------------- > MPI_ABORT was invoked on rank 0 in communicator MPI_COMM_WORLD > with errorcode 1. > > NOTE: invoking MPI_ABORT causes Open MPI to kill all MPI processes. > You may or may not see output from other processes, depending on > exactly when Open MPI kills them. > > -------------------------------------------------------------------------- > #+end_example > > This makes me think that we can have a function (or a template) like > this: > #+caption: Fuction to replace =libmesh_error_msg= macro > #+begin_src cpp :libs $(libmesh-config --cxxflags --include --ldflags > --libs) > #include <stdio.h> > #include <iostream> > #include "libmesh/libmesh.h" > #include "libmesh/mesh.h" > > void libmesh_error_msg_fun(std::string &msg) { > do { > libMesh::err << msg << std::endl; > std::stringstream msg_stream; > msg_stream << msg; > libMesh::MacroFunctions::report_error(__FILE__, __LINE__, > LIBMESH_DATE, LIBMESH_TIME); > LIBMESH_THROW(libMesh::LogicError(msg_stream.str())); > } while (0); > } > > template<typename X, typename Y> > int libmesh_example_requires(X condition, Y option){ > do { > if (!(condition)) { > libMesh::out << > "Configuring libMesh with " << > option << > " is required to run this example." << std::endl; > return 77; > } > } while (0); > } > > int main (int argc, char * argv[]){ > libMesh::LibMeshInit init(argc, argv); > > if (argc < 4){ > std::string msg = {"Usage: "}; > libmesh_error_msg_fun(msg); > } > } > #+end_src > > #+RESULTS: > > #+begin_example > Usage: > Stack frames: 6 > 0: libMesh::print_trace(std::ostream&) > 1: libMesh::MacroFunctions::report_error(char const*, int, char > const*, char const*) > 2: /tmp/babel-CpgWD6/C-bin-mEeZoe(+0xcf4f) [0x55567f87ef4f] > 3: /tmp/babel-CpgWD6/C-bin-mEeZoe(+0xcd76) [0x55567f87ed76] > 4: __libc_start_main > 5: /tmp/babel-CpgWD6/C-bin-mEeZoe(+0xcdbe) [0x55567f87edbe] > [0] /tmp/babel-CpgWD6/C-src-HfTgSq.cpp, line 18, compiled Mar 18 > 2021 at 20:48:30 > > -------------------------------------------------------------------------- > MPI_ABORT was invoked on rank 0 in communicator MPI_COMM_WORLD > with errorcode 1. > > NOTE: invoking MPI_ABORT causes Open MPI to kill all MPI processes. > You may or may not see output from other processes, depending on > exactly when Open MPI kills them. > > -------------------------------------------------------------------------- > #+end_example > > I was expecting =libMesh::= to work as well, because =libmesh_*_msg= > look very much like functions, and they are inside a =namespace=. I am > sure that there is a solid reason for which they were kept as macros, > and that is why this is a humble suggestion. Thank you. > The main reason that libmesh_error_msg() and friends are macros is that they use the __FILE__ and __LINE__ preprocessor defines to help direct the user to the exact place in the code where the error was triggered. I'm not sure if it is possible to do this same trick with inline functions, IIRC it will always report the line where the inline function is defined in the source rather than the line where it is called. -- John |