From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 112956 invoked by alias); 19 Nov 2018 21:23:15 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 112946 invoked by uid 89); 19 Nov 2018 21:23:15 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=Having, offering, H*Ad:D*gwu.edu, 1299 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 19 Nov 2018 21:23:11 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7DF0F307EA82; Mon, 19 Nov 2018 21:23:10 +0000 (UTC) Received: from c64.redhat.com (ovpn-112-13.phx2.redhat.com [10.3.112.13]) by smtp.corp.redhat.com (Postfix) with ESMTP id 50D155C57B; Mon, 19 Nov 2018 21:23:07 +0000 (UTC) From: David Malcolm To: Jason Merrill Cc: Martin Sebor , Eric Gallager , gcc-patches List , David Malcolm Subject: [PATCH] v3: C/C++: add fix-it hints for missing '&' and '*' (PR c++/87850) Date: Mon, 19 Nov 2018 21:23:00 -0000 Message-Id: <1542662581-41571-1-git-send-email-dmalcolm@redhat.com> In-Reply-To: References: X-IsSubscribed: yes X-SW-Source: 2018-11/txt/msg01658.txt.bz2 On Fri, 2018-11-16 at 13:13 -0500, Jason Merrill wrote: > On Thu, Nov 15, 2018 at 4:48 PM David Malcolm > wrote: > > On Tue, 2018-11-13 at 16:34 -0500, Jason Merrill wrote: > > > On Mon, Nov 12, 2018 at 4:32 PM Martin Sebor > > > wrote: > > > > On 11/11/2018 02:02 PM, David Malcolm wrote: > > > > > On Sun, 2018-11-11 at 11:01 -0700, Martin Sebor wrote: > > > > > > On 11/10/2018 12:01 AM, Eric Gallager wrote: > > > > > > > On 11/9/18, David Malcolm wrote: > > > > > > > > This patch adds a fix-it hint to various pointer-vs- > > > > > > > > non- > > > > > > > > pointer > > > > > > > > diagnostics, suggesting the addition of a leading '&' > > > > > > > > or > > > > > > > > '*'. > > > > > > > > > > > > > > > > For example, note the ampersand fix-it hint in the > > > > > > > > following: > > > > > > > > > > > > > > > > demo.c:5:22: error: invalid conversion from > > > > > > > > 'pthread_key_t' > > > > > > > > {aka > > > > > > > > 'unsigned > > > > > > > > int'} > > > > > > > > to 'pthread_key_t*' {aka 'unsigned int*'} [- > > > > > > > > fpermissive] > > > > > > > > 5 | pthread_key_create(key, NULL); > > > > > > > > | ^~~ > > > > > > > > | | > > > > > > > > | pthread_key_t {aka > > > > > > > > unsigned > > > > > > > > int} > > > > > > > > | & > > > > > > > > > > > > > > Having both the type and the fixit underneath the caret > > > > > > > looks > > > > > > > kind > > > > > > > of confusing > > > > > > > > > > > > I agree it's rather subtle. Keeping the diagnostics > > > > > > separate > > > > > > from > > > > > > the suggested fix should avoid the confusion. > > > > > > > > > > FWIW, the fix-it hint is in a different color (assuming that > > > > > gcc > > > > > is > > > > > invoked in an environment that prints that...) > > > > > > > > I figured it would be, but I'm still not sure it's good design > > > > to be relying on color alone to distinguish between the problem > > > > and the suggested fix. Especially when they are so close to > > > > one > > > > another and the fix is just a single character with no obvious > > > > relationship to the rest of the text on the screen. In other > > > > warnings there's at least the "did you forget the '@'?" part > > > > to give a clue, even though even there the connection between > > > > the "did you forget" and the & several lines down wouldn't > > > > necessarily be immediately apparent. > > > > > > Agreed, something along those lines would help to understand why > > > the > > > compiler is throwing a random & into the diagnostic. > > > > > > Jason > > > > Here's an updated version which adds a note, putting the fix-it > > hint > > on that instead (I attempted adding the text to the initial error, > > but there was something of a combinatorial explosion of messages). > > > > The above example becomes: > > > > demo.c: In function 'int main()': > > demo.c:5:22: error: invalid conversion from 'pthread_key_t' {aka > > 'unsigned int'} > > to 'pthread_key_t*' {aka 'unsigned int*'} [-fpermissive] > > 5 | pthread_key_create(key, NULL); > > | ^~~ > > | | > > | pthread_key_t {aka unsigned int} > > demo.c:5:22: note: possible fix: take the address with '&' > > 5 | pthread_key_create(key, NULL); > > | ^~~ > > | & > > In file included from demo.c:1: > > /usr/include/pthread.h:1122:47: note: initializing argument 1 of > > 'int pthread_key_create(pthread_key_t*, void (*)(void*))' > > 1122 | extern int pthread_key_create (pthread_key_t *__key, > > | ~~~~~~~~~~~~~~~^~~~~ > > > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. > > > > OK for trunk? > > > > gcc/c-family/ChangeLog: > > PR c++/87850 > > * c-common.c: Include "gcc-rich-location.h". > > (maybe_emit_indirection_note): New function. > > * c-common.h (maybe_emit_indirection_note): New decl. > > > > gcc/c/ChangeLog: > > PR c++/87850 > > * c-typeck.c (convert_for_assignment): Call > > maybe_emit_indirection_note for pointer vs non-pointer > > diagnostics. > > > > gcc/cp/ChangeLog: > > PR c++/87850 > > * call.c (convert_like_real): Call > > maybe_emit_indirection_note for "invalid conversion" > > diagnostic. > > > > gcc/testsuite/ChangeLog: > > PR c++/87850 > > * c-c++-common/indirection-fixits.c: New test. > > --- > > gcc/c-family/c-common.c | 33 +++ > > gcc/c-family/c-common.h | 2 + > > gcc/c/c-typeck.c | 10 +- > > gcc/cp/call.c | 2 + > > gcc/testsuite/c-c++-common/indirection-fixits.c | 270 > > ++++++++++++++++++++++++ > > 5 files changed, 315 insertions(+), 2 deletions(-) > > create mode 100644 gcc/testsuite/c-c++-common/indirection-fixits.c > > > > diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c > > index cd88f3a..d5c7c7f 100644 > > --- a/gcc/c-family/c-common.c > > +++ b/gcc/c-family/c-common.c > > @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not > > see > > #include "gimplify.h" > > #include "substring-locations.h" > > #include "spellcheck.h" > > +#include "gcc-rich-location.h" > > #include "selftest.h" > > > > cpp_reader *parse_in; /* Declared in c-pragma.h. */ > > @@ -8405,6 +8406,38 @@ maybe_suggest_missing_token_insertion > > (rich_location *richloc, > > } > > } > > > > +/* Potentially emit a note about likely missing '&' or '*', > > + depending on EXPR and EXPECTED_TYPE. */ > > + > > +void > > +maybe_emit_indirection_note (location_t loc, > > + tree expr, tree expected_type) > > +{ > > + gcc_assert (expr); > > + gcc_assert (expected_type); > > + > > + tree actual_type = TREE_TYPE (expr); > > + > > + /* Missing '&'. */ > > + if (TREE_CODE (expected_type) == POINTER_TYPE > > + && actual_type == TREE_TYPE (expected_type) > > Type comparison should use same_type_p, not ==, so that we deal > properly with typedef variants. OK with that change. > > Jason The above code is in c-family, but same_type_p is specific to C++, so the change is not quite trivial. Here's a v3 of the patch which moves same_type_p from cp/cp-tree.h to c-family/c-common.h, converting it from a macro to an extern decl, with implementations for C and for C++. I used: comptypes (type1, type2) == 1 for the C implementation of same_type_p. The v3 patch uses same_type_p rather than pointer equality, and I added a test case for a typedef of int vs a int. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Is this OK for trunk? Thanks Dave gcc/c-family/ChangeLog: PR c++/87850 * c-common.c: Include "gcc-rich-location.h". (maybe_emit_indirection_note): New function. * c-common.h (maybe_emit_indirection_note): New decl. (same_type_p): New decl gcc/c/ChangeLog: PR c++/87850 * c-typeck.c (same_type_p): New function. (convert_for_assignment): Call maybe_emit_indirection_note for pointer vs non-pointer diagnostics. gcc/cp/ChangeLog: PR c++/87850 * call.c (convert_like_real): Call maybe_emit_indirection_note for "invalid conversion" diagnostic. * cp-tree.h (same_type_p): Delete macro, moving to... * typeck.c (same_type_p): New function. gcc/testsuite/ChangeLog: PR c++/87850 * c-c++-common/indirection-fixits.c: New test. --- gcc/c-family/c-common.c | 33 +++ gcc/c-family/c-common.h | 4 + gcc/c/c-typeck.c | 20 +- gcc/cp/call.c | 2 + gcc/cp/cp-tree.h | 5 - gcc/cp/typeck.c | 10 + gcc/testsuite/c-c++-common/indirection-fixits.c | 299 ++++++++++++++++++++++++ 7 files changed, 366 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/indirection-fixits.c diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index cd88f3a..babe329 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "substring-locations.h" #include "spellcheck.h" +#include "gcc-rich-location.h" #include "selftest.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -8405,6 +8406,38 @@ maybe_suggest_missing_token_insertion (rich_location *richloc, } } +/* Potentially emit a note about likely missing '&' or '*', + depending on EXPR and EXPECTED_TYPE. */ + +void +maybe_emit_indirection_note (location_t loc, + tree expr, tree expected_type) +{ + gcc_assert (expr); + gcc_assert (expected_type); + + tree actual_type = TREE_TYPE (expr); + + /* Missing '&'. */ + if (TREE_CODE (expected_type) == POINTER_TYPE + && same_type_p (actual_type, TREE_TYPE (expected_type)) + && lvalue_p (expr)) + { + gcc_rich_location richloc (loc); + richloc.add_fixit_insert_before ("&"); + inform (&richloc, "possible fix: take the address with %qs", "&"); + } + + /* Missing '*'. */ + if (TREE_CODE (actual_type) == POINTER_TYPE + && same_type_p (TREE_TYPE (actual_type), expected_type)) + { + gcc_rich_location richloc (loc); + richloc.add_fixit_insert_before ("*"); + inform (&richloc, "possible fix: dereference with %qs", "*"); + } +} + #if CHECKING_P namespace selftest { diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 31cc273..e0be104 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1340,8 +1340,12 @@ extern void maybe_add_include_fixit (rich_location *, const char *, bool); extern void maybe_suggest_missing_token_insertion (rich_location *richloc, enum cpp_ttype token_type, location_t prev_token_loc); +extern void maybe_emit_indirection_note (location_t loc, + tree expr, tree expected_type); extern tree braced_list_to_string (tree, tree); +extern bool same_type_p (tree type1, tree type2); + #if CHECKING_P namespace selftest { /* Declarations for specific families of tests within c-family, diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 5d4e973..1ddcf71 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -1003,6 +1003,16 @@ common_type (tree t1, tree t2) return c_common_type (t1, t2); } +/* C implementation of same_type_p. + Returns true iff TYPE1 and TYPE2 are the same type, in the usual + sense of `same'. */ + +bool +same_type_p (tree type1, tree type2) +{ + return comptypes (type1, type2) == 1; +} + /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment or various other operations. Return 2 if they are compatible but a warning may be needed if you use them together. */ @@ -7061,7 +7071,10 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, if (pedwarn (&richloc, OPT_Wint_conversion, "passing argument %d of %qE makes pointer from " "integer without a cast", parmnum, rname)) - inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype); + { + maybe_emit_indirection_note (expr_loc, rhs, type); + inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype); + } } break; case ic_assign: @@ -7097,7 +7110,10 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, if (pedwarn (&richloc, OPT_Wint_conversion, "passing argument %d of %qE makes integer from " "pointer without a cast", parmnum, rname)) - inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype); + { + maybe_emit_indirection_note (expr_loc, rhs, type); + inform_for_arg (fundecl, expr_loc, parmnum, type, rhstype); + } } break; case ic_assign: diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ee099cc..a25d109 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6862,6 +6862,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, complained = permerror (&richloc, "invalid conversion from %qH to %qI", TREE_TYPE (expr), totype); + if (complained) + maybe_emit_indirection_note (loc, expr, totype); } if (complained && fn) inform (get_fndecl_argument_location (fn, argnum), diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f2e6709..57d9eed 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -671,11 +671,6 @@ typedef struct ptrmem_cst * ptrmem_cst_t; #define REINTERPRET_CAST_P(NODE) \ TREE_LANG_FLAG_0 (NOP_EXPR_CHECK (NODE)) -/* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual - sense of `same'. */ -#define same_type_p(TYPE1, TYPE2) \ - comptypes ((TYPE1), (TYPE2), COMPARE_STRICT) - /* Returns nonzero iff NODE is a declaration for the global function `main'. */ #define DECL_MAIN_P(NODE) \ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 7b42d53..eeae9f1 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1448,6 +1448,16 @@ structural_comptypes (tree t1, tree t2, int strict) return comp_type_attributes (t1, t2); } +/* C++ implementation of same_type_p. + Returns true iff TYPE1 and TYPE2 are the same type, in the usual + sense of `same'. */ + +bool +same_type_p (tree type1, tree type2) +{ + return comptypes (type1, type2, COMPARE_STRICT); +} + /* Return true if T1 and T2 are related as allowed by STRICT. STRICT is a bitwise-or of the COMPARE_* flags. */ diff --git a/gcc/testsuite/c-c++-common/indirection-fixits.c b/gcc/testsuite/c-c++-common/indirection-fixits.c new file mode 100644 index 0000000..8987ee9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/indirection-fixits.c @@ -0,0 +1,299 @@ +/* { dg-options "-fdiagnostics-show-caret" } */ + +void takes_int_ptr(int*); +void takes_char_ptr(char*); +void takes_int(int); +int returns_int(void); + +int ivar; +char cvar; +int *int_ptr; +char *char_ptr; + +void test_1 (void) +{ + takes_int_ptr(&ivar); + takes_int_ptr(int_ptr); + takes_char_ptr(&cvar); + takes_char_ptr(char_ptr); + + ivar = 42; + cvar = 'b'; + int_ptr = &ivar; + char_ptr = &cvar; +} + +void test_2 (void) +{ + takes_int_ptr(ivar); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + /* { dg-message "possible fix: take the address with '&'" "" { target *-*-* } .-2 } */ + + /* Expect an '&' fix-it hint. */ + /* { dg-begin-multiline-output "" } + takes_int_ptr(ivar); + ^~~~ + | + int + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + takes_int_ptr(ivar); + ^~~~ + & + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + void takes_int_ptr(int*); + ^~~~ + { dg-end-multiline-output "" } */ +} + +void test_3 (void) +{ + takes_int_ptr(cvar); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Don't expect an '&' fix-it hint. */ + /* { dg-begin-multiline-output "" } + takes_int_ptr(cvar); + ^~~~ + | + char + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + void takes_int_ptr(int*); + ^~~~ + { dg-end-multiline-output "" } */ +} + +void test_4 (void) +{ + takes_char_ptr(ivar); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Don't expect an '&' fix-it hint. */ + /* { dg-begin-multiline-output "" } + takes_char_ptr(ivar); + ^~~~ + | + int + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + void takes_char_ptr(char*); + ^~~~~ + { dg-end-multiline-output "" } */ +} + +void test_5 (void) +{ + takes_char_ptr(cvar); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Expect an '&' fix-it hint. */ + /* { dg-begin-multiline-output "" } + takes_char_ptr(cvar); + ^~~~ + | + char + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + takes_char_ptr(cvar); + ^~~~ + & + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + void takes_char_ptr(char*); + ^~~~~ + { dg-end-multiline-output "" } */ +} + +void test_6 (void) +{ + takes_int(int_ptr); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + /* { dg-message "possible fix: dereference with '*'" "" { target *-*-* } .-2 } */ + + /* Expect a '*' fix-it hint. */ + /* { dg-begin-multiline-output "" } + takes_int(int_ptr); + ^~~~~~~ + | + int * + { dg-end-multiline-output "" { target c } } */ + /* { dg-begin-multiline-output "" } + takes_int(int_ptr); + ^~~~~~~ + | + int* + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + takes_int(int_ptr); + ^~~~~~~ + * + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + void takes_int(int); + ^~~ + { dg-end-multiline-output "" } */ +} + +void test_7 (void) +{ + takes_int(char_ptr); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Don't expect a '*' fix-it hint. */ + /* { dg-begin-multiline-output "" } + takes_int(char_ptr); + ^~~~~~~~ + | + char * + { dg-end-multiline-output "" { target c } } */ + /* { dg-begin-multiline-output "" } + takes_int(char_ptr); + ^~~~~~~~ + | + char* + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + void takes_int(int); + ^~~ + { dg-end-multiline-output "" } */ +} + +void test_8 (void) +{ + ivar = int_ptr; /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Expect a fix-it hint from the C++ FE, but not from C (due to missing + location). */ + /* { dg-begin-multiline-output "" } + ivar = int_ptr; + ^~~~~~~ + | + int* + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + ivar = int_ptr; + ^~~~~~~ + * + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + ivar = int_ptr; + ^ + { dg-end-multiline-output "" { target c } } */ +} + +void test_9 (void) +{ + cvar = int_ptr; /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Don't expect a '*' fix-it hint. */ + /* { dg-begin-multiline-output "" } + cvar = int_ptr; + ^~~~~~~ + | + int* + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + cvar = int_ptr; + ^ + { dg-end-multiline-output "" { target c } } */ +} + +void test_10 (void) +{ + int_ptr = ivar; /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Expect a fix-it hint from the C++ FE, but not from C (due to missing + location). */ + /* { dg-begin-multiline-output "" } + int_ptr = ivar; + ^~~~ + | + int + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + int_ptr = ivar; + ^~~~ + & + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + int_ptr = ivar; + ^ + { dg-end-multiline-output "" { target c } } */ +} + +void test_11 (void) +{ + char_ptr = ivar; /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* Don't expect a fix-it hint, due to mismatching types. */ + /* { dg-begin-multiline-output "" } + char_ptr = ivar; + ^~~~ + | + int + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + char_ptr = ivar; + ^ + { dg-end-multiline-output "" { target c } } */ +} + +/* We shouldn't offer '&' fix-it hints for non-lvalues. */ + +void test_12 (void) +{ + takes_int_ptr (returns_int ()); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + + /* { dg-begin-multiline-output "" } + takes_int_ptr (returns_int ()); + ^~~~~~~~~~~~~~ + | + int + { dg-end-multiline-output "" { target c } } */ + /* { dg-begin-multiline-output "" } + takes_int_ptr (returns_int ()); + ~~~~~~~~~~~~^~ + | + int + { dg-end-multiline-output "" { target c++ } } */ + /* { dg-begin-multiline-output "" } + void takes_int_ptr(int*); + ^~~~ + { dg-end-multiline-output "" } */ +} + +/* Ignore typedefs when offering fix-it hints. */ + +typedef int typedef_int_t; +typedef_int_t typedef_int_t_var; + +void test_13 (void) +{ + takes_int_ptr (typedef_int_t_var); /* { dg-warning "" "" { target c } } */ + /* { dg-error "" "" { target c++ } .-1 } */ + /* { dg-message "possible fix: take the address with '&'" "" { target *-*-* } .-2 } */ + + /* Expect an '&' fix-it hint. */ + /* { dg-begin-multiline-output "" } + takes_int_ptr (typedef_int_t_var); + ^~~~~~~~~~~~~~~~~ + | + typedef_int_t {aka int} + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + takes_int_ptr (typedef_int_t_var); + ^~~~~~~~~~~~~~~~~ + & + { dg-end-multiline-output "" } */ + /* { dg-begin-multiline-output "" } + void takes_int_ptr(int*); + ^~~~ + { dg-end-multiline-output "" } */ +} -- 1.8.5.3