https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88937
--- Comment #4 from David Malcolm <dmalcolm at gcc dot gnu.org> --- It's clearly wrong to access token->val.node for token->type == CPP_STRING and token->type == CPP_HEADER_NAME. It's effectively casting the length of the header name to a (cpp_hashnode *). For reference, this was introduced in r215752 (2014-10-01) in gcc 5. Patch review was: "[PATCH C++] - SD-6 Implementation Part 1 - __has_include." https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00083.html later revised to: "Re: [PATCH C++] - SD-6 Implementation Part 1 - __has_include." https://gcc.gnu.org/ml/gcc-patches/2014-09/msg02533.html as "patch_feature_test_1b" https://gcc.gnu.org/ml/gcc-patches/2014-09/txtMPDgWoRx_D.txt (approved by Jason here: https://gcc.gnu.org/ml/gcc-patches/2014-09/msg02645.html ) The comment makes no sense in the given context. It looks to me like this was copied-and-pasted from parse_defined, which also has: /* A possible controlling macro of the form #if !defined (). _cpp_parse_expr checks there was no other junk on the line. */ pfile->mi_ind_cmacro = node; where it *does* make sense; it's handling a CPP_NAME i.e. a "defined (SOME_NAME)", and recording the macro SOME_NAME, for handling that syntax for the header-file-guard idiom. Given that __has_include is purely checking for the presence of files (rather than their inclusion), this seems meaningless here, and I think it's probably best to delete that "node" handling from parse_has_include. That said, I've been attempting and failing to turn this into a read-through-the-corrupt-pointer crasher: _cpp_parse_expr, resets the mi_ind_cmacro back, unless we have !has_include("foo.h") 1426 /* The controlling macro expression is only valid if we called lex 3 1427 times: <!> <defined expression> and <EOF>. push_conditional () 1428 checks that we are at top-of-file. */ 1429 if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3)) 1430 pfile->mi_ind_cmacro = 0; and the "macro" is only saved in push_conditional if 2130 if (pfile->mi_valid && pfile->mi_cmacro == 0) 2131 ifs->mi_cmacro = cmacro; and pfile->mi_valid is being cleared in my test cases. Hence I don't *think* it's currently possible for the bogus pointer to be dereferenced.