Message ID | 20150427083417.GC46857@kam.mff.cuni.cz |
---|---|
State | New |
Headers | show |
On Mon, 27 Apr 2015, Jan Hubicka wrote: > Hi, > this patch strengten ODR checking for requiring match on declarations > (if both of them are defined in C++ tranlsation unit). Currently > ipa-symtab.c will warn only if declarations are incompatible in > useless_type_conversion sense. Now we warn more often, i.e. in the following > example: > > t.C: > char a; > > t2.C: > #include <stdtype.h> > extern int8_t a; > void *b=&a; > > Will lead to warning: > t2.C:2:15: warning: type of ???a??? does not match original declaration > extern int8_t a; > ^ > <built-in>: note: type name ???char??? should match type name ???signed char??? > /usr/include/stdint.h:37:22: note: the incompatible type is defined here > typedef signed char int8_t; > ^ > /aux/hubicka/t.C:1:6: note: previously declared here > char a; > ^ > > Funnilly enough we do not get warning when t2.C is just "signed char" > or "unsigned char" because that is builtin type and thus non-ODR. Something > I need to deal with incrementally. > > I also added call to warn_types_mismatch that outputs extra note about > what is wrong with the type: in C++ the mismatch is often carried over > several levels on declarations and it is hard to work out the reason > without extra info. > > Richard, According to comments, it seems that the code was tailored to not > output warning when we can avoid wrong code issues on mismatches based on fact > that linker would be also silent. I am particularly entertained by the > following hunk which I killed: > > - if (!types_compatible_p (TREE_TYPE (prevailing_decl), > - TREE_TYPE (decl))) > - /* If we don't have a merged type yet...sigh. The linker > - wouldn't complain if the types were mismatched, so we > - probably shouldn't either. Just use the type from > - whichever decl appears to be associated with the > - definition. If for some odd reason neither decl is, the > - older one wins. */ > - (void) 0; > > It is fun we go through the trouble of comparing types and then do nothing ;) > Type merging is also completed at this time, so at least the comment looks > out of date. > > I think as QOI issue, we do want to warn in cases the code is > inconsistent (it is pretty much surely a bug), but perhaps we may want > to have the warnings with -Wodr only and use slightly different warning > and different -W switch for warnings that unavoidably leads to wrong > code surprises? This should be easy to implement by adding two levels > into new warn_type_compatibility_p predicate. I am personaly also OK > however with warning always or making all the warnings -Wodr. > > What do you think? Only emitting the warnings with -Wodr looks good to me. I can't see how we can decide what cases lead to wrong code surprises and what not (other than using types_compatible_p ...). Wrong-code can only(?) happen if we happen to inline in a way that makes the incosistency visible in a single function. > Incrementally I am heading towards proper definition of decl > compatibility that I can plug into symtab merging and avoid merging > incompatible decls (so FORTIFY_SOURCE works). > > lto-symtab and ipa-icf both have some knowledge of the problem, I want to get > both right and factor out common logic. Sounds good. > Other improvement is to preserve the ODR type info when non-ODR variant > previals so one can diagnose clash in between C++ units even in mixed > language linktimes. Hmm, but then merging ODR with non-ODR variant is already pointing to a ODR violation? So why do you need to retain that info? Btw, there is that old PR41227 which has both wrong-code and diagnostic impact... Richard. > Bootstrapped/regtested x86_64-linux with no new ODR warnings hit by -Werror. > > Honza > > * ipa-devirt.c (register_odr_type): Be ready for non-odr main variant > of odr type. > * ipa-utils.h (warn_types_mismatch): New. > * lto/lto-symtab.c (warn_type_compatibility_p): Break out from ... > (lto_symtab_merge): ... here. > (lto_symtab_merge_decls_2): Improve warnings. > > Index: ipa-devirt.c > =================================================================== > --- ipa-devirt.c (revision 222391) > +++ ipa-devirt.c (working copy) > @@ -2029,10 +2030,14 @@ register_odr_type (tree type) > if (in_lto_p) > odr_vtable_hash = new odr_vtable_hash_type (23); > } > - /* Arrange things to be nicer and insert main variants first. */ > - if (odr_type_p (TYPE_MAIN_VARIANT (type))) > + /* Arrange things to be nicer and insert main variants first. > + ??? fundamental prerecorded types do not have mangled names; this > + makes it possible that non-ODR type is main_odr_variant of ODR type. > + Things may get smoother if LTO FE set mangled name of those types same > + way as C++ FE does. */ > + if (odr_type_p (main_odr_variant (TYPE_MAIN_VARIANT (type)))) > get_odr_type (TYPE_MAIN_VARIANT (type), true); > - if (TYPE_MAIN_VARIANT (type) != type) > + if (TYPE_MAIN_VARIANT (type) != type && odr_type_p (main_odr_variant (type))) > get_odr_type (type, true); > } > > Index: ipa-utils.h > =================================================================== > --- ipa-utils.h (revision 222391) > +++ ipa-utils.h (working copy) > @@ -84,6 +84,7 @@ bool types_must_be_same_for_odr (tree, t > bool types_odr_comparable (tree, tree, bool strict = false); > cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT, > ipa_polymorphic_call_context); > +void warn_types_mismatch (tree t1, tree t2); > > /* Return vector containing possible targets of polymorphic call E. > If COMPLETEP is non-NULL, store true if the list is complete. > Index: lto/lto-symtab.c > =================================================================== > --- lto/lto-symtab.c (revision 222391) > +++ lto/lto-symtab.c (working copy) > @@ -203,45 +203,16 @@ lto_varpool_replace_node (varpool_node * > vnode->remove (); > } > > -/* Merge two variable or function symbol table entries PREVAILING and ENTRY. > - Return false if the symbols are not fully compatible and a diagnostic > - should be emitted. */ > +/* Return true if we want to output waring about T1 and T2. */ > > static bool > -lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) > +warn_type_compatibility_p (tree prevailing_type, tree type) > { > - tree prevailing_decl = prevailing->decl; > - tree decl = entry->decl; > - tree prevailing_type, type; > - > - if (prevailing_decl == decl) > + /* C++ provide robust way to check for type compatibility via the ODR > + rule. */ > + if (odr_type_p (prevailing_type) && odr_type_p (type) > + && !types_same_for_odr (prevailing_type, type, true)) > return true; > - > - /* Merge decl state in both directions, we may still end up using > - the new decl. */ > - TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl); > - TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl); > - > - /* The linker may ask us to combine two incompatible symbols. > - Detect this case and notify the caller of required diagnostics. */ > - > - if (TREE_CODE (decl) == FUNCTION_DECL) > - { > - if (!types_compatible_p (TREE_TYPE (prevailing_decl), > - TREE_TYPE (decl))) > - /* If we don't have a merged type yet...sigh. The linker > - wouldn't complain if the types were mismatched, so we > - probably shouldn't either. Just use the type from > - whichever decl appears to be associated with the > - definition. If for some odd reason neither decl is, the > - older one wins. */ > - (void) 0; > - > - return true; > - } > - > - /* Now we exclusively deal with VAR_DECLs. */ > - > /* Sharing a global symbol is a strong hint that two types are > compatible. We could use this information to complete > incomplete pointed-to types more aggressively here, ignoring > @@ -254,19 +225,22 @@ lto_symtab_merge (symtab_node *prevailin > ??? In principle we might want to only warn for structurally > incompatible types here, but unless we have protective measures > for TBAA in place that would hide useful information. */ > - prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl)); > - type = TYPE_MAIN_VARIANT (TREE_TYPE (decl)); > + prevailing_type = TYPE_MAIN_VARIANT (prevailing_type); > + type = TYPE_MAIN_VARIANT (type); > > if (!types_compatible_p (prevailing_type, type)) > { > + if (TREE_CODE (prevailing_type) == FUNCTION_TYPE > + || TREE_CODE (type) == METHOD_TYPE) > + return true; > if (COMPLETE_TYPE_P (type)) > - return false; > + return true; > > /* If type is incomplete then avoid warnings in the cases > that TBAA handles just fine. */ > > if (TREE_CODE (prevailing_type) != TREE_CODE (type)) > - return false; > + return true; > > if (TREE_CODE (prevailing_type) == ARRAY_TYPE) > { > @@ -280,10 +254,10 @@ lto_symtab_merge (symtab_node *prevailin > } > > if (TREE_CODE (tem1) != TREE_CODE (tem2)) > - return false; > + return true; > > if (!types_compatible_p (tem1, tem2)) > - return false; > + return true; > } > > /* Fallthru. Compatible enough. */ > @@ -292,6 +266,43 @@ lto_symtab_merge (symtab_node *prevailin > /* ??? We might want to emit a warning here if type qualification > differences were spotted. Do not do this unconditionally though. */ > > + return false; > +} > + > +/* Merge two variable or function symbol table entries PREVAILING and ENTRY. > + Return false if the symbols are not fully compatible and a diagnostic > + should be emitted. */ > + > +static bool > +lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) > +{ > + tree prevailing_decl = prevailing->decl; > + tree decl = entry->decl; > + > + if (prevailing_decl == decl) > + return true; > + > + /* Merge decl state in both directions, we may still end up using > + the new decl. */ > + TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl); > + TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl); > + > + /* The linker may ask us to combine two incompatible symbols. > + Detect this case and notify the caller of required diagnostics. */ > + > + if (TREE_CODE (decl) == FUNCTION_DECL) > + { > + if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl), > + TREE_TYPE (decl))) > + return false; > + > + return true; > + } > + > + if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl), > + TREE_TYPE (decl))) > + return false; > + > /* There is no point in comparing too many details of the decls here. > The type compatibility checks or the completing of types has properly > dealt with most issues. */ > @@ -483,12 +494,18 @@ lto_symtab_merge_decls_2 (symtab_node *f > /* Diagnose all mismatched re-declarations. */ > FOR_EACH_VEC_ELT (mismatches, i, decl) > { > - if (!types_compatible_p (TREE_TYPE (prevailing->decl), > - TREE_TYPE (decl))) > - diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, > - "type of %qD does not match original " > - "declaration", decl); > - > + if (warn_type_compatibility_p (TREE_TYPE (prevailing->decl), > + TREE_TYPE (decl))) > + { > + bool diag; > + diag = warning_at (DECL_SOURCE_LOCATION (decl), 0, > + "type of %qD does not match original " > + "declaration", decl); > + diagnosed_p |= diag; > + if (diag) > + warn_types_mismatch (TREE_TYPE (prevailing->decl), > + TREE_TYPE (decl)); > + } > else if ((DECL_USER_ALIGN (prevailing->decl) > && DECL_USER_ALIGN (decl)) > && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl)) > >
Hi, actually I bootstrapped/regtested without fortran (as I frogot the setting from LTO bootstrap). There are several new warnings in the fortran's testsuite. As far as I can tell, they represent real mismatches. I wonder, do we want to fix the testcases (some fortran-fu would be needed), disable warnings on those or explicitely allow excess warnings (bcause we still have no way to match link-time warnings)? Honza spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_20091028-1_0.o f_lto_20091028-1_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -r -nostdlib -finline-functions -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-20091028-1-01.exe /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90:7:0: warning: type of 'int_gen_ti_header_c' does not match original declaration lto1: note: return value type mismatch lto1: note: type 'int' should match type 'void' /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/20091028-1_1.c:3:5: note: previously declared here spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr40724_0.o f_lto_pr40724_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr40724-01.exe /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr40724_1.f:2:0: warning: type of 'f' does not match original declaration lto1: note: types have different parameter counts /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr40724_0.f:1:0: note: previously declared here spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr41069_0.o f_lto_pr41069_1.o f_lto_pr41069_2.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr41069-01.exe /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_1.f90:4:0: warning: type of 'mltfftsg' does not match original declaration lto1: note: types have different parameter counts /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_1.f90:4:0: warning: type of 'mltfftsg' does not match original declaration lto1: note: types have different parameter counts /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_0.f90:2:0: note: previously declared here spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr41521_0.o f_lto_pr41521_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -g -O -flto -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr41521-11.exe /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41521_0.f90:7:0: warning: type of 'atom' does not match original declaration lto1: note: types have different parameter counts /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41521_1.f90:1:0: note: previously declared here spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr41576_0.o f_lto_pr41576_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O2 -flto -Werror -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr41576-01.exe /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41576_1.f90:4:0: error: type of 'foo' does not match original declaration [-Werror] lto1: note: types have different parameter counts /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41576_0.f90:4:0: note: previously declared here lto1: all warnings being treated as errors lto-wrapper: fatal error: /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../gfortran returned 1 exit status compilation terminated. /usr/bin/ld: fatal error: lto-wrapper failed collect2: error: ld returned 1 exit status compiler exited with status 1 spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr60635_0.o f_lto_pr60635_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr60635-01.exe /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr60635_0.f90:13:0: warning: type of 'bigendc16' does not match original declaration lto1: note: return value type mismatch /usr/include/stdint.h:50:28: note: type 'uint16_t' should match type 'short int' /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr60635_1.c:6:10: note: previously declared here
Hi all, Jan Hubicka wrote: > actually I bootstrapped/regtested without fortran (as I frogot the setting from > LTO bootstrap). There are several new warnings in the fortran's testsuite. > As far as I can tell, they represent real mismatches. I wonder, do we want > to fix the testcases (some fortran-fu would be needed), disable warnings on those > or explicitely allow excess warnings (bcause we still have no way to match > link-time warnings)? See comments/solutions below. I wrote them bottom up. I think one can fix all of them as stated, but I am not 100% sure whether some of the cases explicitly should handle some mismatch - especially not regarding the last one. But at least the rest should be fixable as stated. > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90:7:0: warning: type of 'int_gen_ti_header_c' does not match original declaration > lto1: note: return value type mismatch > lto1: note: type 'int' should match type 'void' > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/20091028-1_1.c:3:5: note: previously declared here Here, one seemingly tries to ignore the return value of a function as it is commonly done under C – except that Fortran strictly divides between void-returning "subroutine"s and non-void-returning "function"s. Thus, one has to declare the function in that case as "subroutine" and cause a mismatch. Assuming the test case doesn't test whether this is gracefully handled, the simplest would be to change the C function to return void - in particular as that this actually happens as there is no "return". > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr40724_1.f:2:0: warning: type of 'f' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr40724_0.f:1:0: note: previously declared here See next items. > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_1.f90:4:0: warning: type of 'mltfftsg' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_1.f90:4:0: warning: type of 'mltfftsg' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_0.f90:2:0: note: previously declared here I would add an interface (cf. next items); however, I wonder whether any of those test cases relies on having no interface. > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41521_0.f90:7:0: warning: type of 'atom' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41521_1.f90:1:0: note: previously declared here Reason: see next item. Solution: Add to pr41521_0.f90: interface subroutine atom(sol,k,eval) real, intent(in) :: sol integer, intent(in) :: k(2) real, intent(out) :: eval(2) end subroutine end interface > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41576_1.f90:4:0: error: type of 'foo' does not match original declaration [-Werror] > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41576_0.f90:4:0: note: previously declared here Here the problem is that gfortran doesn't know the interface of "foo" - and declares it as "foo(...)". What the FE should do is to generate the interface by the usage. [There is some PR for this.] For the test case, one can simply add in pr41576_1.f90 the following: interface subroutine foo() end subroutine end interface > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr60635_0.f90:13:0: warning: type of 'bigendc16' does not match original declaration > /usr/include/stdint.h:50:28: note: type 'uint16_t' should match type 'short int' > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr60635_1.c:6:10: note: previously declared here The problem here is that the C side uses uint16_t; but Fortran doesn't have unsigned integers. If only the return value is the problem, I think one can simply cast it to "(int16_t)". But I don't know whether it then still tests the original issue (it probably does). Tobias
On Tue, 28 Apr 2015, Jan Hubicka wrote: > Hi, > actually I bootstrapped/regtested without fortran (as I frogot the setting from > LTO bootstrap). There are several new warnings in the fortran's testsuite. > As far as I can tell, they represent real mismatches. I wonder, do we want > to fix the testcases (some fortran-fu would be needed), disable warnings on those > or explicitely allow excess warnings (bcause we still have no way to match > link-time warnings)? Please disable the warnigns by default unless -Wodr is given. I also explicitely pointed you to an existing PR with Fortran vs. C interoperability... so you could have double-checked. There is still the FAIL: g++.dg/tree-ssa/pr61034.C -std=gnu++11 scan-tree-dump-times fre2 "free" 18 FAIL: g++.dg/tree-ssa/pr61034.C -std=gnu++14 scan-tree-dump-times fre2 "free" 18 FAIL: g++.dg/tree-ssa/pr61034.C -std=gnu++98 scan-tree-dump-times fre2 "free" from one of your patches. Please make sure you fix testsuite fallout you cause quickly. Richard. > Honza > > spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_20091028-1_0.o f_lto_20091028-1_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -r -nostdlib -finline-functions -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-20091028-1-01.exe > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90:7:0: warning: type of 'int_gen_ti_header_c' does not match original declaration > lto1: note: return value type mismatch > lto1: note: type 'int' should match type 'void' > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/20091028-1_1.c:3:5: note: previously declared here > > spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr40724_0.o f_lto_pr40724_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr40724-01.exe > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr40724_1.f:2:0: warning: type of 'f' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr40724_0.f:1:0: note: previously declared here > > spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr41069_0.o f_lto_pr41069_1.o f_lto_pr41069_2.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr41069-01.exe > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_1.f90:4:0: warning: type of 'mltfftsg' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_1.f90:4:0: warning: type of 'mltfftsg' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41069_0.f90:2:0: note: previously declared here > > spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran3/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr41521_0.o f_lto_pr41521_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -g -O -flto -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr41521-11.exe > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41521_0.f90:7:0: warning: type of 'atom' does not match original declaration > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41521_1.f90:1:0: note: previously declared here > > spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr41576_0.o f_lto_pr41576_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O2 -flto -Werror -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr41576-01.exe > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41576_1.f90:4:0: error: type of 'foo' does not match original declaration [-Werror] > lto1: note: types have different parameter counts > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr41576_0.f90:4:0: note: previously declared here > lto1: all warnings being treated as errors > lto-wrapper: fatal error: /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../gfortran returned 1 exit status > compilation terminated. > /usr/bin/ld: fatal error: lto-wrapper failed > collect2: error: ld returned 1 exit status > compiler exited with status 1 > > spawn /aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../gfortran -B/aux/hubicka/trunk-8/build5/gcc/testsuite/gfortran11/../../ -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/ f_lto_pr60635_0.o f_lto_pr60635_1.o -fno-diagnostics-show-caret -fdiagnostics-color=never -O0 -flto -flto-partition=none -fuse-linker-plugin -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libgfortran/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libatomic/.libs -B/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -L/aux/hubicka/trunk-8/build5/x86_64-unknown-linux-gnu/./libquadmath/.libs -o gfortran-dg-lto-pr60635-01.exe > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr60635_0.f90:13:0: warning: type of 'bigendc16' does not match original declaration > lto1: note: return value type mismatch > /usr/include/stdint.h:50:28: note: type 'uint16_t' should match type 'short int' > /aux/hubicka/trunk-8/gcc/testsuite/gfortran.dg/lto/pr60635_1.c:6:10: note: previously declared here > >
> > Only emitting the warnings with -Wodr looks good to me. I can't see > how we can decide what cases lead to wrong code surprises and what not OK, I will go with -Wodr for all the warnings then, that seems fine to me. > (other than using types_compatible_p ...). Wrong-code can only(?) happen > if we happen to inline in a way that makes the incosistency visible in > a single function. > > > Incrementally I am heading towards proper definition of decl > > compatibility that I can plug into symtab merging and avoid merging > > incompatible decls (so FORTIFY_SOURCE works). > > > > lto-symtab and ipa-icf both have some knowledge of the problem, I want to get > > both right and factor out common logic. > > Sounds good. > > > Other improvement is to preserve the ODR type info when non-ODR variant > > previals so one can diagnose clash in between C++ units even in mixed > > language linktimes. > > Hmm, but then merging ODR with non-ODR variant is already pointing to > a ODR violation? So why do you need to retain that info? non-ODR type is compatible with all ODR types that are structurally equivalent, but these ODR types may not be compatible with each other. For example: a.c struct a {int a;} var; b.C extern struct a {int a;} var; c.C extern struct b {int a;} var; has ODR violatio nbetween b.C and c.C, but because the variable is defined in C source file, we will only check compatibility with non-ODR struct a. My plan is to simply record if the declaration also has ODR type associated with it. But that is for incremental improvement. > > Btw, there is that old PR41227 which has both wrong-code and diagnostic > impact... Thanks, I will take deeper look. I did not know that fortran has way to mark types that are supposed to interpoerate outside fortran units. This may be potentially interesting. Honza
Index: ipa-devirt.c =================================================================== --- ipa-devirt.c (revision 222391) +++ ipa-devirt.c (working copy) @@ -2029,10 +2030,14 @@ register_odr_type (tree type) if (in_lto_p) odr_vtable_hash = new odr_vtable_hash_type (23); } - /* Arrange things to be nicer and insert main variants first. */ - if (odr_type_p (TYPE_MAIN_VARIANT (type))) + /* Arrange things to be nicer and insert main variants first. + ??? fundamental prerecorded types do not have mangled names; this + makes it possible that non-ODR type is main_odr_variant of ODR type. + Things may get smoother if LTO FE set mangled name of those types same + way as C++ FE does. */ + if (odr_type_p (main_odr_variant (TYPE_MAIN_VARIANT (type)))) get_odr_type (TYPE_MAIN_VARIANT (type), true); - if (TYPE_MAIN_VARIANT (type) != type) + if (TYPE_MAIN_VARIANT (type) != type && odr_type_p (main_odr_variant (type))) get_odr_type (type, true); } Index: ipa-utils.h =================================================================== --- ipa-utils.h (revision 222391) +++ ipa-utils.h (working copy) @@ -84,6 +84,7 @@ bool types_must_be_same_for_odr (tree, t bool types_odr_comparable (tree, tree, bool strict = false); cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT, ipa_polymorphic_call_context); +void warn_types_mismatch (tree t1, tree t2); /* Return vector containing possible targets of polymorphic call E. If COMPLETEP is non-NULL, store true if the list is complete. Index: lto/lto-symtab.c =================================================================== --- lto/lto-symtab.c (revision 222391) +++ lto/lto-symtab.c (working copy) @@ -203,45 +203,16 @@ lto_varpool_replace_node (varpool_node * vnode->remove (); } -/* Merge two variable or function symbol table entries PREVAILING and ENTRY. - Return false if the symbols are not fully compatible and a diagnostic - should be emitted. */ +/* Return true if we want to output waring about T1 and T2. */ static bool -lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) +warn_type_compatibility_p (tree prevailing_type, tree type) { - tree prevailing_decl = prevailing->decl; - tree decl = entry->decl; - tree prevailing_type, type; - - if (prevailing_decl == decl) + /* C++ provide robust way to check for type compatibility via the ODR + rule. */ + if (odr_type_p (prevailing_type) && odr_type_p (type) + && !types_same_for_odr (prevailing_type, type, true)) return true; - - /* Merge decl state in both directions, we may still end up using - the new decl. */ - TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl); - TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl); - - /* The linker may ask us to combine two incompatible symbols. - Detect this case and notify the caller of required diagnostics. */ - - if (TREE_CODE (decl) == FUNCTION_DECL) - { - if (!types_compatible_p (TREE_TYPE (prevailing_decl), - TREE_TYPE (decl))) - /* If we don't have a merged type yet...sigh. The linker - wouldn't complain if the types were mismatched, so we - probably shouldn't either. Just use the type from - whichever decl appears to be associated with the - definition. If for some odd reason neither decl is, the - older one wins. */ - (void) 0; - - return true; - } - - /* Now we exclusively deal with VAR_DECLs. */ - /* Sharing a global symbol is a strong hint that two types are compatible. We could use this information to complete incomplete pointed-to types more aggressively here, ignoring @@ -254,19 +225,22 @@ lto_symtab_merge (symtab_node *prevailin ??? In principle we might want to only warn for structurally incompatible types here, but unless we have protective measures for TBAA in place that would hide useful information. */ - prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl)); - type = TYPE_MAIN_VARIANT (TREE_TYPE (decl)); + prevailing_type = TYPE_MAIN_VARIANT (prevailing_type); + type = TYPE_MAIN_VARIANT (type); if (!types_compatible_p (prevailing_type, type)) { + if (TREE_CODE (prevailing_type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + return true; if (COMPLETE_TYPE_P (type)) - return false; + return true; /* If type is incomplete then avoid warnings in the cases that TBAA handles just fine. */ if (TREE_CODE (prevailing_type) != TREE_CODE (type)) - return false; + return true; if (TREE_CODE (prevailing_type) == ARRAY_TYPE) { @@ -280,10 +254,10 @@ lto_symtab_merge (symtab_node *prevailin } if (TREE_CODE (tem1) != TREE_CODE (tem2)) - return false; + return true; if (!types_compatible_p (tem1, tem2)) - return false; + return true; } /* Fallthru. Compatible enough. */ @@ -292,6 +266,43 @@ lto_symtab_merge (symtab_node *prevailin /* ??? We might want to emit a warning here if type qualification differences were spotted. Do not do this unconditionally though. */ + return false; +} + +/* Merge two variable or function symbol table entries PREVAILING and ENTRY. + Return false if the symbols are not fully compatible and a diagnostic + should be emitted. */ + +static bool +lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) +{ + tree prevailing_decl = prevailing->decl; + tree decl = entry->decl; + + if (prevailing_decl == decl) + return true; + + /* Merge decl state in both directions, we may still end up using + the new decl. */ + TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl); + TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl); + + /* The linker may ask us to combine two incompatible symbols. + Detect this case and notify the caller of required diagnostics. */ + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl), + TREE_TYPE (decl))) + return false; + + return true; + } + + if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl), + TREE_TYPE (decl))) + return false; + /* There is no point in comparing too many details of the decls here. The type compatibility checks or the completing of types has properly dealt with most issues. */ @@ -483,12 +494,18 @@ lto_symtab_merge_decls_2 (symtab_node *f /* Diagnose all mismatched re-declarations. */ FOR_EACH_VEC_ELT (mismatches, i, decl) { - if (!types_compatible_p (TREE_TYPE (prevailing->decl), - TREE_TYPE (decl))) - diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, - "type of %qD does not match original " - "declaration", decl); - + if (warn_type_compatibility_p (TREE_TYPE (prevailing->decl), + TREE_TYPE (decl))) + { + bool diag; + diag = warning_at (DECL_SOURCE_LOCATION (decl), 0, + "type of %qD does not match original " + "declaration", decl); + diagnosed_p |= diag; + if (diag) + warn_types_mismatch (TREE_TYPE (prevailing->decl), + TREE_TYPE (decl)); + } else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl)) && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))