[ping][PATCH] cp: warn uninitialized const/ref in base class [PR80681]
On this example: ``` struct Fine { private: const int f; }; struct BuggyA { const int a; int &b; }; struct BuggyB : private BuggyA { }; ``` g++ currently emits: ``` test.cc:3:19: warning: non-static const member ‘const int Fine::f’ in class without a constructor [-Wuninitialized] 3 | const int f; | ``` (relevant godbolt: https://godbolt.org/z/KGMK6e1zc) The issue here is that g++ misses the uninitialized const and ref members in BuggyA that are inherited as private in BuggyB. It should warn about those members when checking BuggyB. With this patch, g++ emits the following: ``` test.cc:3:19: warning: non-static const member ‘const int Fine::f’ in class without a constructor [-Wuninitialized] 3 | const int f; | ^ test.cc:7:19: warning: while processing ‘BuggyB’: non-static const member ‘const int BuggyA::a’ in class without a constructor [-Wuninitialized] 7 | const int a; | ^ test.cc:7:19: note: ‘BuggyB’ inherits ‘BuggyA’ as private, so all fields contained within ‘BuggyA’ are private to ‘BuggyB’ test.cc:8:14: warning: while processing ‘BuggyB’: non-static reference ‘int& BuggyA::b’ in class without a constructor [-Wuninitialized] 8 | int &b; | ^ test.cc:8:14: note: ‘BuggyB’ inherits ‘BuggyA’ as private, so all fields contained within ‘BuggyA’ are private to ‘BuggyB’ ``` Now, the compiler warns about the uninitialized members. In terms of testing, I added three tests: - a status quo test that makes sure that the existing warning behavior works - A simple test based off of the PR - Another example with multiple inheritance - A final example with mutliple levels of inheritance. These tests all pass. I also bootstrapped the project without any regressions. PR c++/80681 gcc/cp/ChangeLog: * class.cc (warn_uninitialized_const_and_ref): Extract warn logic into new func, add inform for inheritance warning (check_bases_and_members): Move warn logic to warn_unintialized_const_and_ref, check subclasses for warnings as well gcc/testsuite/ChangeLog: * g++.dg/pr80681-1.C: New test. Signed-off-by: Charlie Sale --- gcc/cp/class.cc | 110 +-- gcc/testsuite/g++.dg/pr80681-1.C | 51 ++ 2 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr80681-1.C diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index aebcb53739e..72172bea6ad 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -6018,6 +6018,76 @@ explain_non_literal_class (tree t) } } + +/* Warn for private const or reference class members that cannot be initialized + due to the class not having a default constructor. If a child type is + provided, then we are checking class_type's members in case they cannot be + initialized by child_type. If child_type is null, then we simply check + class_type. */ +static void +warn_uninitialized_const_and_ref (tree class_type, tree child_type) +{ + /* Check the fields on this class type. */ + tree field; + for (field = TYPE_FIELDS (class_type); field; field = DECL_CHAIN (field)) +{ + /* We only want to check variable declarations. + Exclude fields that are not field decls or are not initialized. */ + if (TREE_CODE (field) != FIELD_DECL + || DECL_INITIAL (field) != NULL_TREE) + continue; + + tree type = TREE_TYPE (field); + + if (TYPE_REF_P (type)) + { + if (child_type != nullptr) + { + /* Show parent class while processing. */ + auto_diagnostic_group d; + warning_at (DECL_SOURCE_LOCATION (field), + OPT_Wuninitialized, "while processing %qE: " + "non-static reference %q#D in class without a constructor", + child_type, field); + inform (DECL_SOURCE_LOCATION (field), + "%qE inherits %qE as private, so all fields " + "contained within %qE are private to %qE", + child_type, class_type, class_type, child_type); + } + else + { + warning_at (DECL_SOURCE_LOCATION (field), + OPT_Wuninitialized, "non-static reference %q#D " + "in class without a constructor", field); + } + } + else if (CP_TYPE_CONST_P (type) + && (!CLASS_TYPE_P (type) + || !TYPE_HAS_DEFAULT_CONSTRUCTOR (type))) + { + if (child_type) + { + /* ditto. */ + auto_diagnostic_group d; + warning_at (DECL_SOURCE_LOCATION (field), + OPT_Wuninitialized, "while processing %qE: " + "non-static const member %q#D in class " + "without a constructor", child_type, field); + inform (DECL_SOURCE_LOCATION (field), + "%qE inherits %qE as private, so all fields "
[PATCH] cp: warn uninitialized const/ref in base class [PR80681]
On this example: ``` struct Fine { private: const int f; }; struct BuggyA { const int a; int &b; }; struct BuggyB : private BuggyA { }; ``` g++ currently emits: ``` test.cc:3:19: warning: non-static const member ‘const int Fine::f’ in class without a constructor [-Wuninitialized] 3 | const int f; | ``` (relevant godbolt: https://godbolt.org/z/KGMK6e1zc) The issue here is that g++ misses the uninitialized const and ref members in BuggyA that are inherited as private in BuggyB. It should warn about those members when checking BuggyB. With this patch, g++ emits the following: ``` test.cc:3:19: warning: non-static const member ‘const int Fine::f’ in class without a constructor [-Wuninitialized] 3 | const int f; | ^ test.cc:7:19: warning: while processing ‘BuggyB’: non-static const member ‘const int BuggyA::a’ in class without a constructor [-Wuninitialized] 7 | const int a; | ^ test.cc:7:19: note: ‘BuggyB’ inherits ‘BuggyA’ as private, so all fields contained within ‘BuggyA’ are private to ‘BuggyB’ test.cc:8:14: warning: while processing ‘BuggyB’: non-static reference ‘int& BuggyA::b’ in class without a constructor [-Wuninitialized] 8 | int &b; | ^ test.cc:8:14: note: ‘BuggyB’ inherits ‘BuggyA’ as private, so all fields contained within ‘BuggyA’ are private to ‘BuggyB’ ``` Now, the compiler warns about the uninitialized members. In terms of testing, I added three tests: - a status quo test that makes sure that the existing warning behavior works - A simple test based off of the PR - Another example with multiple inheritance - A final example with mutliple levels of inheritance. These tests all pass. I also bootstrapped the project without any regressions. PR c++/80681 gcc/cp/ChangeLog: * class.cc (warn_uninitialized_const_and_ref): Extract warn logic into new func, add inform for inheritance warning (check_bases_and_members): Move warn logic to warn_unintialized_const_and_ref, check subclasses for warnings as well gcc/testsuite/ChangeLog: * g++.dg/pr80681-1.C: New test. Signed-off-by: Charlie Sale --- gcc/cp/class.cc | 110 +-- gcc/testsuite/g++.dg/pr80681-1.C | 51 ++ 2 files changed, 142 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr80681-1.C diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index aebcb53739e..72172bea6ad 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -6018,6 +6018,76 @@ explain_non_literal_class (tree t) } } + +/* Warn for private const or reference class members that cannot be initialized + due to the class not having a default constructor. If a child type is + provided, then we are checking class_type's members in case they cannot be + initialized by child_type. If child_type is null, then we simply check + class_type. */ +static void +warn_uninitialized_const_and_ref (tree class_type, tree child_type) +{ + /* Check the fields on this class type. */ + tree field; + for (field = TYPE_FIELDS (class_type); field; field = DECL_CHAIN (field)) +{ + /* We only want to check variable declarations. + Exclude fields that are not field decls or are not initialized. */ + if (TREE_CODE (field) != FIELD_DECL + || DECL_INITIAL (field) != NULL_TREE) + continue; + + tree type = TREE_TYPE (field); + + if (TYPE_REF_P (type)) + { + if (child_type != nullptr) + { + /* Show parent class while processing. */ + auto_diagnostic_group d; + warning_at (DECL_SOURCE_LOCATION (field), + OPT_Wuninitialized, "while processing %qE: " + "non-static reference %q#D in class without a constructor", + child_type, field); + inform (DECL_SOURCE_LOCATION (field), + "%qE inherits %qE as private, so all fields " + "contained within %qE are private to %qE", + child_type, class_type, class_type, child_type); + } + else + { + warning_at (DECL_SOURCE_LOCATION (field), + OPT_Wuninitialized, "non-static reference %q#D " + "in class without a constructor", field); + } + } + else if (CP_TYPE_CONST_P (type) + && (!CLASS_TYPE_P (type) + || !TYPE_HAS_DEFAULT_CONSTRUCTOR (type))) + { + if (child_type) + { + /* ditto. */ + auto_diagnostic_group d; + warning_at (DECL_SOURCE_LOCATION (field), + OPT_Wuninitialized, "while processing %qE: " + "non-static const member %q#D in class " + "without a constructor", child_type, field); + inform (DECL_SOURCE_LOCATION (field), + "%qE inherits %qE as private, so all fields "
[PATCH] rtl: add predicates for addition, subtraction & multiplication
This is my first contribution to GCC :) one of the beginner projects suggested on the website was to add and use RTL type predicates. I added predicates for addition, subtraction and multiplication. I also went through and used them in the code. I did not add tests because I'm not addding/modifying any behavior. All existings tests did pass. Like I said, this is my first patch. Please let me know if I did anything wrong or if there's anything I can improve for next time. Signed-off-by: Charlie Sale --- gcc/ChangeLog| 43 +++ gcc/alias.cc | 30 +++-- gcc/auto-inc-dec.cc | 11 +- gcc/calls.cc | 8 +- gcc/cfgexpand.cc | 16 +-- gcc/combine-stack-adj.cc | 39 +++ gcc/combine.cc | 241 +-- gcc/compare-elim.cc | 3 +- gcc/cse.cc | 66 +-- gcc/cselib.cc| 37 +++--- gcc/dce.cc | 4 +- gcc/dwarf2cfi.cc | 2 +- gcc/dwarf2out.cc | 11 +- gcc/emit-rtl.cc | 6 +- gcc/explow.cc| 31 ++--- gcc/expr.cc | 23 ++-- gcc/final.cc | 20 ++-- gcc/function.cc | 7 +- gcc/fwprop.cc| 2 +- gcc/haifa-sched.cc | 10 +- gcc/ifcvt.cc | 11 +- gcc/ira.cc | 6 +- gcc/loop-doloop.cc | 70 ++-- gcc/loop-iv.cc | 21 +--- gcc/lra-constraints.cc | 34 +++--- gcc/lra-eliminations.cc | 25 ++-- gcc/lra.cc | 6 +- gcc/modulo-sched.cc | 2 +- gcc/postreload.cc| 25 ++-- gcc/reginfo.cc | 12 +- gcc/reload.cc| 180 + gcc/reload1.cc | 85 ++ gcc/reorg.cc | 12 +- gcc/rtl.cc | 3 +- gcc/rtl.h| 11 ++ gcc/rtlanal.cc | 25 ++-- gcc/sched-deps.cc| 8 +- gcc/simplify-rtx.cc | 143 +-- gcc/var-tracking.cc | 37 +++--- 39 files changed, 595 insertions(+), 731 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f999e2cba43..1fd2c94c873 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,46 @@ +2022-11-26 Charlie Sale + + * rtl.h (PLUS_P): RTL addition predicate + (MINUS_P): RTL subtraction predicate + (MULT_P): RTL multiplication predicate + * alias.cc: use RTL predicates + * auto-inc-dec.cc: use RTL predicates + * calls.cc: use RTL predicates + * cfgexpand.cc: use RTL predicates + * combine-stack-adj.cc: use RTL predicates + * combine.cc: use RTL predicates + * compare-elim.cc: use RTL predicates + * cse.cc: use RTL predicates + * cselib.cc: use RTL predicates + * dce.cc: use RTL predicates + * dwarf2cfi.cc: use RTL predicates + * dwarf2out.cc: use RTL predicates + * emit-rtl.cc: use RTL predicates + * explow.cc: use RTL predicates + * expr.cc: use RTL predicates + * final.cc: use RTL predicates + * function.cc: use RTL predicates + * fwprop.cc: use RTL predicates + * haifa-sched.cc: use RTL predicates + * ifcvt.cc: use RTL predicates + * ira.cc: use RTL predicates + * loop-doloop.cc: use RTL predicates + * loop-iv.cc: use RTL predicates + * lra-constraints.cc: use RTL predicates + * lra-eliminations.cc: use RTL predicates + * lra.cc: use RTL predicates + * modulo-sched.cc: use RTL predicates + * postreload.cc: use RTL predicates + * reginfo.cc: use RTL predicates + * reload.cc: use RTL predicates + * reload1.cc: use RTL predicates + * reorg.cc: use RTL predicates + * rtl.cc: use RTL predicates + * rtlanal.cc: use RTL predicates + * sched-deps.cc: use RTL predicates + * simplify-rtx.cc: use RTL predicates + * var-tracking.cc: use RTL predicates + 2022-11-25 Sandra Loosemore * common.opt (fopenmp-target-simd-clone): New option. diff --git a/gcc/alias.cc b/gcc/alias.cc index c62837dd854..2d9bd79fe21 100644 --- a/gcc/alias.cc +++ b/gcc/alias.cc @@ -1473,7 +1473,7 @@ find_base_value (rtx src) otherwise. */ if (copying_arguments && (XEXP (src, 0) == arg_pointer_rtx - || (GET_CODE (XEXP (src, 0)) == PLUS + || (PLUS_P (XEXP (src, 0)) && XEXP (XEXP (src, 0), 0) == arg_pointer_rtx))) return arg_base_value; return 0; @@ -1790,7 +1790,7 @@ canon_rtx (rtx x) return canon_rtx (t); } - if (GET_CODE (x) == PLUS) + if (PLUS_P (x)) { rtx x0 = canon_rtx (XEXP (x, 0)); rtx x1 = canon_rtx (XEXP (x, 1)); @@ -2357,19 +2357,17 @@ get_addr (rtx x) if (GET_CODE (x) != VALUE) { - if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS) - && GET_CODE (XEXP (x, 0)) == VALUE + if ((PLUS_P (x) || MINUS_P (x)) && GET_CODE (XEXP (x, 0)) == VALUE