From patchwork Fri Aug 20 16:59:27 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: prevent doubled diagnostics on symbol alias pairs Date: Fri, 20 Aug 2010 06:59:27 -0000 From: Olivier Hainque X-Patchwork-Id: 62292 Message-Id: <20100820165926.GA22223@cardhu.act-europe.fr> To: gcc-patches@gcc.gnu.org Cc: hainque@adacore.com Hello, Compiling this code: /* au.c */ extern int var __attribute__ ((alias ("undef"))); on e.g. x86-linux, the current mainline compiler emits the "aliased to undefined" diagnostic twice: << au.c:1:12: error: 'var' aliased to undefined symbol 'undef' au.c:1:12: error: 'var' aliased to undefined symbol 'undef' >> This is caused by the compiler going through finish_aliases_1 from several places for different or iterative purposes. The attached patch is a suggestion to address this by teaching the circuitry to remember which diags it has emitted for alias_pairs already. Bootstrapped and regression tested on x86_64-suse-linux. OK ? Thanks in advance, With Kind Regards, Olivier 2010-08-20 Olivier Hainque * tree.h (alias_diag_flags): New enum. (alias_pair): Add an 'emitted_diags' field. * varasm.c (finish_aliases_1): Honor and update p->emitted_diags. (assemble_alias): Initialize emitted_diags of new pairs. Index: tree.h =================================================================== --- tree.h (revision 163326) +++ tree.h (working copy) @@ -184,10 +184,21 @@ of an alias. This requires that the decl have been defined. Aliases that precede their definition have to be queued for later processing. */ +/* The deferred processing proceeds in several passes. We memorize the + diagnostics emitted for a pair to prevent repeating messages when the + queue gets re-scanned after possible updates. */ + +typedef enum { + ALIAS_DIAG_NONE = 0x0, + ALIAS_DIAG_TO_UNDEF = 0x1, + ALIAS_DIAG_TO_EXTERN = 0x2 +} alias_diag_flags; + typedef struct GTY(()) alias_pair { tree decl; - tree target; + tree target; + int emitted_diags; /* alias_diags already emitted for this pair. */ } alias_pair; /* Define gc'd vector type. */ Index: varasm.c =================================================================== --- varasm.c (revision 163326) +++ varasm.c (working copy) @@ -5444,19 +5444,27 @@ target_decl = find_decl_and_mark_needed (p->decl, p->target); if (target_decl == NULL) { - if (! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))) - error ("%q+D aliased to undefined symbol %qE", - p->decl, p->target); + if (! (p->emitted_diags & ALIAS_DIAG_TO_UNDEF) + && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))) + { + error ("%q+D aliased to undefined symbol %qE", + p->decl, p->target); + p->emitted_diags |= ALIAS_DIAG_TO_UNDEF; + } } - else if (DECL_EXTERNAL (target_decl) - /* We use local aliases for C++ thunks to force the tailcall - to bind locally. Of course this is a hack - to keep it - working do the following (which is not strictly correct). */ - && (! TREE_CODE (target_decl) == FUNCTION_DECL - || ! DECL_VIRTUAL_P (target_decl)) + else if (! (p->emitted_diags & ALIAS_DIAG_TO_EXTERN) + && DECL_EXTERNAL (target_decl) + /* We use local aliases for C++ thunks to force the tailcall + to bind locally. This is a hack - to keep it working do + the following (which is not strictly correct). */ + && (! TREE_CODE (target_decl) == FUNCTION_DECL + || ! DECL_VIRTUAL_P (target_decl)) && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))) - error ("%q+D aliased to external symbol %qE", - p->decl, p->target); + { + error ("%q+D aliased to external symbol %qE", + p->decl, p->target); + p->emitted_diags |= ALIAS_DIAG_TO_EXTERN; + } } } @@ -5549,6 +5557,7 @@ alias_pair *p = VEC_safe_push (alias_pair, gc, alias_pairs, NULL); p->decl = decl; p->target = target; + p->emitted_diags = ALIAS_DIAG_NONE; } }