mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-28 06:14:10 +08:00
libcpp: Diagnose __has_include outside of preprocessor directives [PR93545]
The standard says http://eel.is/c++draft/cpp.cond#7.sentence-2 that __has_include can't appear at arbitrary places in the source. As we have not recognized __has_include* outside of preprocessing directives in the past, accepting it there now would be a regression. The patch does still allow it in #define if it is then used in preprocessing directives, I guess that use isn't strictly valid either, but clang seems to accept it. 2020-02-04 Jakub Jelinek <jakub@redhat.com> * macro.c (builtin_has_include): Diagnose __has_include* use outside of preprocessing directives. * c-c++-common/cpp/has-include-1.c: New test. * c-c++-common/cpp/has-include-next-1.c: New test. * c-c++-common/gomp/has-include-1.c: New test.
This commit is contained in:
parent
c04babd9df
commit
f8d6e448f8
@ -1,5 +1,9 @@
|
||||
2020-02-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* c-c++-common/cpp/has-include-1.c: New test.
|
||||
* c-c++-common/cpp/has-include-next-1.c: New test.
|
||||
* c-c++-common/gomp/has-include-1.c: New test.
|
||||
|
||||
PR preprocessor/93545
|
||||
* c-c++-common/cpp/pr88974.c: Expect another diagnostics during error
|
||||
recovery.
|
||||
|
104
gcc/testsuite/c-c++-common/cpp/has-include-1.c
Normal file
104
gcc/testsuite/c-c++-common/cpp/has-include-1.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#if __has_include ("stdlib.h")
|
||||
#else
|
||||
#error error 1
|
||||
#endif
|
||||
#if __has_include (<stdlib.h>)
|
||||
#else
|
||||
#error error 2
|
||||
#endif
|
||||
#if !__has_include ("stdlib.h")
|
||||
#error error 3
|
||||
#elif !__has_include (<stdlib.h>)
|
||||
#error error 4
|
||||
#endif
|
||||
#if __has_include ("stdlib.h") && __has_include (<stdlib.h>)
|
||||
#else
|
||||
#error error 5
|
||||
#endif
|
||||
#if !defined(__has_include)
|
||||
#error error 6
|
||||
#endif
|
||||
#ifndef __has_include
|
||||
#error error 7
|
||||
#endif
|
||||
#ifdef __has_include
|
||||
#else
|
||||
#error error 8
|
||||
#endif
|
||||
#define m1 __has_include("stdlib.h")
|
||||
#define m2 ("stdlib.h")
|
||||
#define m3 ("has-include-1-nonexistent.h")
|
||||
#define m4 has-include-1-nonexistent-2.h>)
|
||||
#define m5 <stdlib.h>
|
||||
#if !m1
|
||||
#error error 9
|
||||
#endif
|
||||
#if !__has_include m2
|
||||
#error error 10
|
||||
#endif
|
||||
#if __has_include m3
|
||||
#error error 11
|
||||
#endif
|
||||
#if __has_include (<m4
|
||||
#error error 12
|
||||
#endif
|
||||
#if !__has_include (m5)
|
||||
#error error 13
|
||||
#endif
|
||||
__has_include (<stdlib.h>) /* { dg-error "used outside of preprocessing directive" } */
|
||||
m1 /* { dg-error "used outside of preprocessing directive" } */
|
||||
#if 1
|
||||
m1 /* { dg-error "used outside of preprocessing directive" } */
|
||||
#endif
|
||||
#if 0
|
||||
#elif 1
|
||||
m1 /* { dg-error "used outside of preprocessing directive" } */
|
||||
#endif
|
||||
#if 0
|
||||
m1
|
||||
#endif
|
||||
#if 0
|
||||
#elif 0
|
||||
m1
|
||||
#endif
|
||||
#if __has_include "stdlib.h") /* { dg-error "missing" } */
|
||||
#endif
|
||||
#if __has_include (stdlib.h) /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include () /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include ) /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include ("stdlib.h)
|
||||
#endif
|
||||
/* { dg-error "operator|missing\[^\n\r]*after" "" { target *-*-* } .-2 } */
|
||||
/* { dg-warning "missing terminating" "" { target *-*-* } .-3 } */
|
||||
#if __has_include (stdlib.h>) /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include ("stdlib.h" /* { dg-error "missing" } */
|
||||
#endif
|
||||
#if __has_include ( /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include"stdlib.h" /* { dg-error "missing" } */
|
||||
#endif
|
||||
#if __has_include'h' /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include('h' /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include('h') /* { dg-error "operator" } */
|
||||
#endif
|
||||
#define H(h) __has_include(h)
|
||||
#if H(<stdlib.h>)
|
||||
#else
|
||||
#error error 14
|
||||
#endif
|
||||
void
|
||||
foo ()
|
||||
{
|
||||
#pragma omp parallel if (__has_include ("<stdlib.h>"))
|
||||
;
|
||||
}
|
104
gcc/testsuite/c-c++-common/cpp/has-include-next-1.c
Normal file
104
gcc/testsuite/c-c++-common/cpp/has-include-next-1.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* { dg-do preprocess } */
|
||||
|
||||
#if __has_include_next ("stdlib.h")
|
||||
#else
|
||||
#error error 1
|
||||
#endif
|
||||
#if __has_include_next (<stdlib.h>)
|
||||
#else
|
||||
#error error 2
|
||||
#endif
|
||||
#if !__has_include_next ("stdlib.h")
|
||||
#error error 3
|
||||
#elif !__has_include_next (<stdlib.h>)
|
||||
#error error 4
|
||||
#endif
|
||||
#if __has_include_next ("stdlib.h") && __has_include_next (<stdlib.h>)
|
||||
#else
|
||||
#error error 5
|
||||
#endif
|
||||
#if !defined(__has_include_next)
|
||||
#error error 6
|
||||
#endif
|
||||
#ifndef __has_include_next
|
||||
#error error 7
|
||||
#endif
|
||||
#ifdef __has_include_next
|
||||
#else
|
||||
#error error 8
|
||||
#endif
|
||||
#define m1 __has_include_next("stdlib.h")
|
||||
#define m2 ("stdlib.h")
|
||||
#define m3 ("has-include-1-nonexistent.h")
|
||||
#define m4 has-include-1-nonexistent-2.h>)
|
||||
#define m5 <stdlib.h>
|
||||
#if !m1
|
||||
#error error 9
|
||||
#endif
|
||||
#if !__has_include_next m2
|
||||
#error error 10
|
||||
#endif
|
||||
#if __has_include_next m3
|
||||
#error error 11
|
||||
#endif
|
||||
#if __has_include_next (<m4
|
||||
#error error 12
|
||||
#endif
|
||||
#if !__has_include_next (m5)
|
||||
#error error 13
|
||||
#endif
|
||||
__has_include_next (<stdlib.h>) /* { dg-error "used outside of preprocessing directive" } */
|
||||
m1 /* { dg-error "used outside of preprocessing directive" } */
|
||||
#if 1
|
||||
m1 /* { dg-error "used outside of preprocessing directive" } */
|
||||
#endif
|
||||
#if 0
|
||||
#elif 1
|
||||
m1 /* { dg-error "used outside of preprocessing directive" } */
|
||||
#endif
|
||||
#if 0
|
||||
m1
|
||||
#endif
|
||||
#if 0
|
||||
#elif 0
|
||||
m1
|
||||
#endif
|
||||
#if __has_include_next "stdlib.h") /* { dg-error "missing" } */
|
||||
#endif
|
||||
#if __has_include_next (stdlib.h) /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next () /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next ) /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next ("stdlib.h)
|
||||
#endif
|
||||
/* { dg-error "operator|missing\[^\n\r]*after" "" { target *-*-* } .-2 } */
|
||||
/* { dg-warning "missing terminating" "" { target *-*-* } .-3 } */
|
||||
#if __has_include_next (stdlib.h>) /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next ("stdlib.h" /* { dg-error "missing" } */
|
||||
#endif
|
||||
#if __has_include_next ( /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next"stdlib.h" /* { dg-error "missing" } */
|
||||
#endif
|
||||
#if __has_include_next'h' /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next('h' /* { dg-error "operator|missing" } */
|
||||
#endif
|
||||
#if __has_include_next('h') /* { dg-error "operator" } */
|
||||
#endif
|
||||
#define H(h) __has_include_next(h)
|
||||
#if H(<stdlib.h>)
|
||||
#else
|
||||
#error error 14
|
||||
#endif
|
||||
void
|
||||
foo ()
|
||||
{
|
||||
#pragma omp parallel if (__has_include_next ("<stdlib.h>"))
|
||||
;
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
2020-02-04 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* macro.c (builtin_has_include): Diagnose __has_include* use outside
|
||||
of preprocessing directives.
|
||||
|
||||
PR preprocessor/93545
|
||||
* macro.c (cpp_get_token_no_padding): New function.
|
||||
(builtin_has_include): Use it instead of cpp_get_token. Don't check
|
||||
|
@ -359,6 +359,11 @@ builtin_has_include (cpp_reader *pfile, cpp_hashnode *op, bool has_next)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (!pfile->state.in_directive)
|
||||
cpp_error (pfile, CPP_DL_ERROR,
|
||||
"\"%s\" used outside of preprocessing directive",
|
||||
NODE_NAME (op));
|
||||
|
||||
pfile->state.angled_headers = true;
|
||||
const cpp_token *token = cpp_get_token_no_padding (pfile);
|
||||
bool paren = token->type == CPP_OPEN_PAREN;
|
||||
|
Loading…
Reference in New Issue
Block a user