diff --git a/src/attr.cpp b/src/attr.cpp index 35e8f99..93b581c 100644 --- a/src/attr.cpp +++ b/src/attr.cpp @@ -52,6 +52,13 @@ vector Project::projnames(attr_end); string Attributes::attribute_names[] = { "__attribute(__unused__)", "Identifier token from a macro", + "Function-like macro", + "Used in preprocessor constant", + "Value used as preprocessor string operand", + "Value defined as a C compile-time constant", + "Value defined as not a C compile-time constant", + "Value expanded as a C compile-time constant", + "Value expanded as not a C compile-time constant", // User-visible attributes start here "Read-only", @@ -64,8 +71,6 @@ string Attributes::attribute_names[] = { "Macro", "Undefined macro", "Macro argument", - "Used in preprocessor constant", - "Value used as preprocessor string operand", "File scope", "Project scope", @@ -80,6 +85,13 @@ string Attributes::attribute_names[] = { string Attributes::attribute_short_names[] = { "__attribute(__unused__)", "idmtoken", + "funmacro", + "cppconst", + "cppstrval", + "defcconst", + "defnotcconst", + "expcconst", + "expnotcconst", // User-visible attributes start here "ro", @@ -92,8 +104,6 @@ string Attributes::attribute_short_names[] = { "macro", "umacro", "macroarg", - "cppconst", - "cppstrval", "fscope", "pscope", diff --git a/src/attr.h b/src/attr.h index 7255262..b27a603 100644 --- a/src/attr.h +++ b/src/attr.h @@ -37,6 +37,20 @@ enum e_attribute { is_declared_unused, // Declared with __unused__ attribute is_macro_token, // Identifier stored in a macro // Used to determine macro nesting + // The following are used to determine object-like macros that + // can be converted into C constants + is_fun_macro, // Defined as a function-like macro + is_cpp_const, // Used to derive a preprocessor constant + // used in #if, #include, defined() + is_cpp_str_val, // Macro's value is used as a string (pasting + // or stringization) in the preprocessor + // Below are probable values; findings can include both cases. + // Findings based on defined object-like macros. + is_def_c_const, // Value seen as a C compile-time constant. + is_def_not_c_const, // Value seen as not a C compile-time constant. + // Findings based on expanded object-like macros. + is_exp_c_const, // Value seen as a C compile-time constant. + is_exp_not_c_const, // Value seen as not a C compile-time constant. // User-visible attributes start here is_readonly, // Read-only; true if any member @@ -50,10 +64,7 @@ enum e_attribute { is_macro, // Name of an object or function-like macro is_undefined_macro, // Macro (heuristic: ifdef, defined) is_macro_arg, // Macro argument - is_cpp_const, // Used to derive a preprocessor constant - // used in #if, #include, defined() - is_cpp_str_val, // Macro's value is used as a string (pasting - // or stringization) in the preprocessor + // The following are valid if is_ordinary is true: is_cscope, // Compilation-unit (file) scoped // identifier (static) diff --git a/src/cscout.cpp b/src/cscout.cpp index 463cd34..1aed87d 100644 --- a/src/cscout.cpp +++ b/src/cscout.cpp @@ -1392,7 +1392,26 @@ static void show_id_prop(FILE *fo, const string &name, bool val) { if (!Option::show_true->get() || val) - fprintf(fo, ("
  • " + name + ": %s\n").c_str(), val ? "Yes" : "No"); + fprintf(fo, ("
  • " + name + ": %s
  • \n").c_str(), val ? "Yes" : "No"); +} + +// Display whether a macro can be replaced by a C constant +static void +show_c_const(FILE *fo, Eclass *e) +{ + bool val = !e->get_attribute(is_fun_macro) + && !e->get_attribute(is_cpp_const) + && !e->get_attribute(is_cpp_str_val) + && ((e->get_attribute(is_def_c_const) + && !e->get_attribute(is_def_not_c_const)) + || (e->get_attribute(is_exp_c_const) + && !e->get_attribute(is_exp_not_c_const)) + ); + fprintf(fo, "
  • Can be replaced by C constant: %s\n", val ? "Yes" : "No"); + fprintf(fo, "
  • \n"); } // Details for each identifier @@ -1426,6 +1445,8 @@ identifier_page(FILE *fo, void *p) show_id_prop(fo, Attributes::name(i), e->get_attribute(i)); show_id_prop(fo, "Crosses file boundary", id.get_xfile()); show_id_prop(fo, "Unused", e->is_unused()); + if (e->get_attribute(is_macro)) + show_c_const(fo, e); fprintf(fo, "
  • Matches %d occurence(s)\n", e->get_size()); if (Option::show_projects->get()) { fprintf(fo, "
  • Appears in project(s): \n