@@ -1352,6 +1352,66 @@ handle_alias_pairs (void)
13521352 if (TREE_CODE (p -> decl ) == FUNCTION_DECL
13531353 && target_node && is_a < cgraph_node * > (target_node ))
13541354 {
1355+ tree t1 = TREE_TYPE (p -> decl );
1356+ tree t2 = TREE_TYPE (target_node -> decl );
1357+
1358+ if (lookup_attribute ("ifunc" , DECL_ATTRIBUTES (p -> decl )))
1359+ {
1360+ t2 = TREE_TYPE (t2 );
1361+ if (POINTER_TYPE_P (t2 ))
1362+ {
1363+ t2 = TREE_TYPE (t2 );
1364+ if (!FUNC_OR_METHOD_TYPE_P (t2 ))
1365+ {
1366+ if (warning_at (DECL_SOURCE_LOCATION (p -> decl ),
1367+ OPT_Wattributes ,
1368+ "%q+D %<ifunc%> resolver should return "
1369+ "a function pointer" ,
1370+ p -> decl ))
1371+ inform (DECL_SOURCE_LOCATION (target_node -> decl ),
1372+ "resolver declaration here" );
1373+
1374+ t2 = NULL_TREE ;
1375+ }
1376+ }
1377+ else
1378+ {
1379+ /* Deal with static member function pointers. */
1380+ if (TREE_CODE (t2 ) == RECORD_TYPE
1381+ && TYPE_FIELDS (t2 )
1382+ && TREE_CODE (TREE_TYPE (TYPE_FIELDS (t2 ))) == POINTER_TYPE
1383+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t2 ))))
1384+ == METHOD_TYPE ))
1385+ t2 = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (t2 )));
1386+ else
1387+ {
1388+ error ("%q+D %<ifunc%> resolver must return a function "
1389+ "pointer" ,
1390+ p -> decl );
1391+ inform (DECL_SOURCE_LOCATION (target_node -> decl ),
1392+ "resolver declaration here" );
1393+
1394+ t2 = NULL_TREE ;
1395+ }
1396+ }
1397+ }
1398+
1399+ if (t2
1400+ && (!FUNC_OR_METHOD_TYPE_P (t2 )
1401+ || (prototype_p (t1 )
1402+ && prototype_p (t2 )
1403+ && !types_compatible_p (t1 , t2 ))))
1404+ {
1405+ /* Warn for incompatibilities. Avoid warning for functions
1406+ without a prototype to make it possible to declare aliases
1407+ without knowing the exact type, as libstdc++ does. */
1408+ if (warning_at (DECL_SOURCE_LOCATION (p -> decl ), OPT_Wattributes ,
1409+ "%q+D alias between functions of incompatible "
1410+ "types %qT and %qT" , p -> decl , t1 , t2 ))
1411+ inform (DECL_SOURCE_LOCATION (target_node -> decl ),
1412+ "aliased declaration here" );
1413+ }
1414+
13551415 cgraph_node * src_node = cgraph_node ::get (p -> decl );
13561416 if (src_node && src_node -> definition )
13571417 src_node -> reset ();
@@ -1366,10 +1426,11 @@ handle_alias_pairs (void)
13661426 }
13671427 else
13681428 {
1369- error ("%q+D alias in between function and variable is not supported" ,
1429+ error ("%q+D alias between function and variable is not supported" ,
13701430 p -> decl );
1371- warning (0 , "%q+D aliased declaration" ,
1372- target_node -> decl );
1431+ inform (DECL_SOURCE_LOCATION (target_node -> decl ),
1432+ "aliased declaration here" );
1433+
13731434 alias_pairs -> unordered_remove (i );
13741435 }
13751436 }
0 commit comments