Index: cp/parser.c =================================================================== --- cp/parser.c (revision 262300) +++ cp/parser.c (working copy) @@ -28377,12 +28377,15 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq else if (ds == ds_thread) { bool gnu = token_is__thread (token); + gcc_rich_location richloc (location); if (gnu != decl_specs->gnu_thread_keyword_p) - error_at (location, - "both %<__thread%> and % specified"); + { + richloc.add_range (decl_specs->locations[ds_thread], false); + error_at (&richloc, + "both %<__thread%> and % specified"); + } else { - gcc_rich_location richloc (location); richloc.add_fixit_remove (); error_at (&richloc, "duplicate %qD", token->u.value); } Index: testsuite/g++.dg/diagnostic/thread-thread_local.C =================================================================== --- testsuite/g++.dg/diagnostic/thread-thread_local.C (nonexistent) +++ testsuite/g++.dg/diagnostic/thread-thread_local.C (working copy) @@ -0,0 +1,13 @@ +// { dg-options "-fdiagnostics-show-caret" } +// { dg-do compile { target c++11 } } + +thread_local __thread int a; // { dg-error "14:both .__thread. and .thread_local. specified" } +/* { dg-begin-multiline-output "" } + thread_local __thread int a; + ~~~~~~~~~~~~ ^~~~~~~~ + { dg-end-multiline-output "" } */ +__thread thread_local int b; // { dg-error "10:both .__thread. and .thread_local. specified" } +/* { dg-begin-multiline-output "" } + __thread thread_local int b; + ~~~~~~~~ ^~~~~~~~~~~~ + { dg-end-multiline-output "" } */