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