tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] bug #50847: #line vs. #include "foo.h"


From: Larry Doolittle
Subject: [Tinycc-devel] bug #50847: #line vs. #include "foo.h"
Date: Tue, 25 Apr 2017 12:00:44 -0700
User-agent: Mutt/1.5.21 (2010-09-15)

tinycc community -

I found and submitted tinycc bug #50847: #line directive corrupts #include 
search path
https://savannah.nongnu.org/bugs/index.php?50847

Three comments:

1.  The submission wraps the test case in a tidy (485 byte) tarball.
For lazyweb members who don't want to unpack that, there's really not
much to it.  The bug is triggered by bad.c:
 #line 10 "mythical.c"
 #include "simple.h"
 int foo(bar *b)
 { return b->x == b->y; }
where simple.h provides a typedef for bar, and the bug shows up
when bad.c is in a different directory from where you run the compile.
The command line in demo.sh is "tcc -c dir/bad.c".

2.  The c99 standard is mute on where C compilers are supposed to find
their include files, but the gcc documentation is clear:
https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_2.html
GCC looks for headers requested with #include "file" first in the directory 
containing the current file, then in the same places it would have looked for a 
header requested with angle brackets. For example, if `/usr/include/sys/stat.h' 
contains #include "types.h", GCC looks for `types.h' first in 
`/usr/include/sys', then in its usual search path.
`#line' (see section 6. Line Control) does not change GCC's idea of the 
directory containing the current file.
This is also the behavior of clang.

3.  I put together a brain-dead patch to tinycc mob HEAD,
that touches three lines total and seems to do the job.
It is arguably somewhat wasteful of scratch memory.
Here it is, sorry if the mail pipeline mangles it:

diff --git a/libtcc.c b/libtcc.c
index 99bf783..302ce39 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -581,6 +581,7 @@ ST_FUNC void tcc_open_bf(TCCState *s1, const char 
*filename, int initlen)
     bf->buf_end = bf->buffer + initlen;
     bf->buf_end[0] = CH_EOB; /* put eob symbol */
     pstrcpy(bf->filename, sizeof(bf->filename), filename);
+    pstrcpy(bf->filename2, sizeof(bf->filename2), filename);
 #ifdef _WIN32
     normalize_slashes(bf->filename);
 #endif
diff --git a/tcc.h b/tcc.h
index 5b9d4a3..92b9060 100644
--- a/tcc.h
+++ b/tcc.h
@@ -546,6 +546,7 @@ typedef struct BufferedFile {
     int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
     int include_next_index; /* next search path */
     char filename[1024];    /* filename */
+    char filename2[1024];    /* filename not modified by # line directive */
     unsigned char unget[4];
     unsigned char buffer[1]; /* extra size for CH_EOB char */
 } BufferedFile;
diff --git a/tccpp.c b/tccpp.c
index 7e5cdcf..4495752 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -1791,7 +1791,8 @@ ST_FUNC void preprocess(int is_bof)
                 /* search in file's dir if "header.h" */
                 if (c != '\"')
                     continue;
-                path = file->filename;
+                /* https://savannah.nongnu.org/bugs/index.php?50847 */
+                path = file->filename2;
                 pstrncpy(buf1, path, tcc_basename(path) - path);
 
             } else {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]