1.. ## Copyright (c) 2017-2021, Lawrence Livermore National Security, LLC and
2.. ## other Axom Project Developers. See the top-level LICENSE file for details.
3.. ##
4.. ## SPDX-License-Identifier: (BSD-3-Clause)
5
6.. _codemacros-label:
7
8=======================================================
910 Common Code Development Macros, Types, etc.
10=======================================================
11
12This section provides guidelines for consistent use of macros and types
13defined in Axom components, such as "axom_utils" and "slic", and in our build
14system that we use in day-to-day code development.
15
16.. important:: Code that is guarded with macros described in this section
17               **must not** change the *externally-observable* execution
18               behavior of the code.
19
20               The macros are intended to help users and developers avoid
21               unintended or potentially erroneous usage, etc. not confuse them.
22
23------------------------------------
24Unused variables
25------------------------------------
26
2710.2 To silence compiler warnings and express variable usage intent more
28clearly, macros in the `AxomMacros.hpp` header file in the source include
29directory **must** be used when appropriate. For example,::
30
31    void my_function(int x, int AXOM_DEBUG_PARAM(y))
32    {
33      // use variable y only for debug compilation
34    }
35
36Here, the `AXOM_DEBUG_PARAM` macro indicates that the variable 'y' is only
37used when the code is compiled in debug mode. It also removes the variable
38name in the argument list in non-debug compilation to prevent unwanted
39compiler warnings.
40
41Please see the `AxomMacros.hpp` header file for other available macros and
42usage examples.
43
44
45------------------------------------
46Disabling compiler-generated methods
47------------------------------------
48
4910.3 To disable compiler-generated class/struct methods when this is desired
50and to clearly express this intent, the `AXOMMacros.hpp` header file in
51source include directory contains macros that **should** be used for this
52purpose. See :ref:`compilergenmethods-label` for more information about
53compiler-generated methods.
54
55Please see the `AXOMMacros.hpp` header file for other available macros and
56usage examples.
57
58
59------------------------------------
60Conditionally compiled code
61------------------------------------
62
6310.4 Macros defined by Axom build system **must** be used to
64control conditional code compilation.
65
66For example, complex or multi-line code that is intended to be exposed only
67for a debug build **must** be guarded using the `AXOM_DEBUG` macro::
68
69   void MyMethod(...)
70   {
71   #if defined(AXOM_DEBUG)
72     // Code that performs debugging checks on object state, method args,
73     // reports diagnostic messages, etc. goes here
74   #endif
75
76      // rest of method implementation
77   }
78
79The Axom build system provides various other macros for controlling
80conditionally-compiled code. The macro constants will be defined based
81on CMake options given when the code is configured. Please see the
82`config.hpp` header file in the source include directory for a complete list.
83
84
85------------------------------------
86Error handling
87------------------------------------
88
8910.5 Macros provided in the "slic" component **should** be used to provide
90runtime checks for incorrect or questionable usage and informative messages
91for developers and users.
92
93Runtime checks for incorrect or questionable usage and generation of
94informative warning, error, notice messages can be a tremendous help to
95users and developers. This is an excellent way to provide run-time debugging
96capabilities in code. Using the "slic" macros ensures that syntax and meaning
97are consistent and that output information is handled similarly throughout
98the code.
99
100When certain conditions are encountered, the macros can emit failed boolean
101expressions and descriptive messages that help to understand potentially
102problematic usage. Here's an example of common *SLIC* macro usage in AXOM::
103
104   Bar* myCoolFunction(int in_val, Foo* in_foo)
105   {
106     if ( in_val < 0 || in_foo == nullptr )
107     {
108       SLIC_CHECK_MSG( in_val >= 0, "in_val must be non-negative" );
109       SLIC_CHECK( in_foo != nullptr );
110       return nullptr;
111     } else if ( !in_foo->isSet() ) {
112       SLIC_CHECK_MSG( in_foo->isSet(),
113                       "in_foo is not set, will use default settings");
114       const int val = in_val >= 0 ? in_val : DEFAULT_VAL;
115       in_foo->setDefaults( val );
116     }
117
118     Bar* bar = new Bar(in_foo);
119
120     return bar;
121   }
122
123This example uses slic macros that are only active when the code is compiled
124in debug mode. When compiled in release mode, for example, the macros are
125empty and so do nothing. Also, when a condition is encountered that is
126problematic, such as 'in_val < 0' or 'in_foo == nullptr', the code will
127emit the condition and an optional message and not halt. This allows calling
128code to catch the issue (in this case a null return value) and react. There
129are other macros (e.g., SLIC_ASSERT) that will halt the code if that is
130desired.
131
132Slic macros operate in one of two compilation-defined modes. Some macros are
133active only in for a debug compile. Others are active for any build type.
134Macros provided for each of these modes can be used to halt the code or not
135after describing the condition that triggered them. The following table
136summarizes the SLIC macros.
137
138============== ================ ====================
139  Macro type     When active?     Halts code?
140============== ================ ====================
141  ERROR          Always           Yes
142  WARNING        Always           No
143  ASSERT         Debug only       Yes
144  CHECK          Debug only       No
145============== ================ ====================
146
147Typically, we use macros ERROR/WARNING macros rarely. They are used primarily
148to catch cases that are obvious programming errors or would put an application
149in a state where continuing is seriously in doubt. CHECK macros are used most
150often, since they provide useful debugging information and do not halt the
151code -- they allow users to catch cases from which they can recover. ASSERT
152macros are used in cases where halting the code is desired, but only in
153debug mode.
154
155Please see the `slic.hpp` header file to see which macros are available and
156how to use them.
157
158.. important:: It is important to apply these macros judiciously so that they
159               benefit users and other developers. We want to help folks use
160               our software correctly and not "spam" them with too much
161               information.
162
163