cznic / cc Goto Github PK
View Code? Open in Web Editor NEWgithub.com/cznic/cc has moved to modernc.org/cc
Home Page: https://godoc.org/modernc.org/cc
License: BSD 3-Clause "New" or "Revised" License
github.com/cznic/cc has moved to modernc.org/cc
Home Page: https://godoc.org/modernc.org/cc
License: BSD 3-Clause "New" or "Revised" License
typedef unsigned long PaStreamCallbackFlags;
#define paInputUnderflow ((PaStreamCallbackFlags) 0x00000001)
The paInputUnderflow
macro gets nil Value
in macro map (map[int]*cc.Macro
).
Digging into:
macro.Value, macro.Type = p.lx.parsePPConstExpr0(rl, p)
...leads to the sloppy slope in the code :)
for i, tok := range l.toks {
if tok.Rune == IDENTIFIER {
if p.macros.m[tok.Val] != nil {
l.report.ErrTok(tok, "expected constant expression")
return nil, nil
}
tok.Rune = INTCONST
tok.Val = id0
l.toks[i] = tok
}
}
Which can't handle typecasts and parens well, so yyParse
gets confused on extra parens:
l.state = lsConstExpr0
if err := yyParse(l); err == 0 {
e := l.constantExpression
return e.Value, e.Type
} else {
// butt hurt!
log.Println("bad parse:", l.toks)
}
Fix for #9 introduced a new bug. CC can no more handle
#define m()
m()
The reason is that to properly handle, for example
#define n(x) #x
char s[] = n();
the fix introduced inserting empty arguments to fn-like macros. However, in case of m
above, now the number of actual and formal arguments differs.
Repro case
void f() {
int i, j;
i ^= j;
}
typedef union{int foo; double bar} u;
void f(u) {}
void g() {
int i;
f(i);
}
is valid C, but the type checker rejects it.
Repro case
float f;
int i = 42 + f;
Cf. Predefined identifiers, 6.4.2.2.
For example
#define m(x) #x
char s[] = m();
will fail.
Now it produces an identifier, because the left argument of ##
, if present, always determines the resulting token type. In this case the resulting token type is neither the type of the arguments. This behavior is not mentioned in the specification but it's the only one making sense. The same applies to long string constants.
Repro case
long long n = 1LL << 2LL;
void(*[65])(int)
element is now void()(int)
, but should be void(*)(int)
.
Complex function defintions like eg.
// Declare f as function (char) returning pointer to function (int) returning long.
//
// http://cdecl.ridiculousfish.com/?q=long+%28*f%28char%29%29+%28int%29%3B
//
long (*f(char c))(int i) { char d = c; }
will fail with c
undefined.
Repro case
int c = L'x';
Would improve compatibility with/emulation of GCC.
Repro case
#define cat(x, y) x ## y
cat(int,) i;
Preprocessor output
int ## i;
Hi, please review commits b58b670, 0aefe3d and 37d1391 in the cgogen
branch. These are only changes I made to keep things running, so finishing them off will mean a full sync with upstream master of the CC, that'd be a very happy moment for me.
So, the patch regarding TypeSpecifier() *TypeSpecifier
allows me to walk enums and get their members, since there is no native support of enums in Type
yet.
Then, there is no implemented sizeOf / alignOf / structAlignOf
for enums, so I added a few methods to walk enum and get the top type (because it could upgrade from uint32
up to int64
). And use its values according to the model. This is very naive and may not work as per C specs, just for a consideration and as a temporary solution.
Both commits above are not for merging!
But the latest one is about a missing case in MustConvert
, it gets triggered in cases like:
#define ABC 1000.0f
That seems to be all.
Repro case
enum e { a };
e v = (e)42;
panic: internal error: uint64
goroutine 1 [running]:
panic(0x3636a0, 0xc820475170)
/usr/local/go/src/runtime/panic.go:464 +0x3e6
github.com/cznic/cc.(*Expression).eval(0xc82098c540, 0xc8203563c0, 0x0, 0x0, 0x0, 0x0)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/ast2.go:798 +0x56b3
github.com/cznic/cc.(*ExpressionList).eval(0xc820622730, 0xc8203563c0, 0x0, 0x0, 0x0, 0x0)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/ast2.go:1457 +0x9d
Also, it's a IDENTIFIER_LPAREN
instead of IDENTIFIER
as in the case of object-like macros.
@xlab The fix may/probably will break cgogen, sorry, but it's a bug and have to be fixed.
Repro case
enum { a } e;
int i = a + a;
6.10.3.4 Rescanning and further replacement
- 1 After all parameters in the replacement list have been substituted and # and ##
processing has taken place, all placemarker preprocessing tokens are removed. Then, the
resulting preprocessing token sequence is rescanned, along with all subsequent
preprocessing tokens of the source file, for more macro names to replace.- 2 If the name of the macro being replaced is found during this scan of the replacement list
(not including the rest of the source file’s preprocessing tokens), it is not replaced.
...
Currently sanitize
, ie. checking for recursive macros, is performed during argument expansion, not "After all parameters in the replacement list have been substituted and # and ##
processing has taken place". This causes expansion of NLMSG_ALIGN
from <netlink.h>
, in some older versions of it, to fail.
void f(int n) {
int a[n];
...
}
is valid.
Repro case
short a;
unsigned short b;
unsigned short c = a + b;
int f(a, p)
int a;
char* p;
{
// ...
}
Parameters a
, p
are not getting declared so the type of f
is not compatible with int(int,char*)
.
Repro case
short i = (short)1LL;
Hi! It's not a bug, rather my typo that looks like this:
#ifdef __cplusplus
extern "C";
EOF
Not a big deal, but CC crashes with a weird panic that doesn't contribute to finding the root cause.
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x10 pc=0x1ba214]
goroutine 18 [running]:
panic(0x3a8cc0, 0xc820010110)
/usr/local/go/src/runtime/panic.go:481 +0x3e6
github.com/cznic/cc.(*pp).preprocessingFile(0xc82020a140, 0x0)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/cpp.go:982 +0x44
github.com/cznic/cc.Parse.func1(0xc820394120, 0xc82038c5a0, 0xc820390860, 0x68e520, 0xc820075770, 0xc820385ae0, 0xc820396200, 0xc820099780, 0x3, 0x4, ...)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/cc.go:472 +0x350
created by github.com/cznic/cc.Parse
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/cc.go:474 +0xa47
make: *** [all] Error 2
Repro case
#include <stddef.h>
char s[1];
char* p;
ptrdiff_t d = s - p;
Repro case
char s[];
char* p = s + 3;
Running debian linux, executing exactly the code you posted in maddyblue/moggio#50, I get this error:
/usr/include/x86_64-linux-gnu/bits/byteswap.h:46:1: unexpected '{', expected one of [',', ';', '=']
Here's the first part of that file. Line 46 is the first {
in the file.
/* Macros to swap the order of bytes in integer values.
Copyright (C) 1997-2015 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#if !defined _BYTESWAP_H && !defined _NETINET_IN_H && !defined _ENDIAN_H
# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
#endif
#ifndef _BITS_BYTESWAP_H
#define _BITS_BYTESWAP_H 1
#include <features.h>
#include <bits/types.h>
#include <bits/wordsize.h>
/* Swap bytes in 16 bit value. */
#define __bswap_constant_16(x) \
((unsigned short int) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
/* Get __bswap_16. */
#include <bits/byteswap-16.h>
/* Swap bytes in 32 bit value. */
#define __bswap_constant_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#ifdef __GNUC__
# if __GNUC_PREREQ (4, 3)
static __inline unsigned int
__bswap_32 (unsigned int __bsx)
{
return __builtin_bswap32 (__bsx);
}
# elif __GNUC__ >= 2
# if __WORDSIZE == 64 || (defined __i486__ || defined __pentium__ \
|| defined __pentiumpro__ || defined __pentium4__ \
|| defined __k8__ || defined __athlon__ \
|| defined __k6__ || defined __nocona__ \
|| defined __core2__ || defined __geode__ \
|| defined __amdfam10__)
/* To swap the bytes in a word the i486 processors and up provide the
`bswap' opcode. On i386 we have to use three instructions. */
# define __bswap_32(x) \
(__extension__ \
({ unsigned int __v, __x = (x); \
if (__builtin_constant_p (__x)) \
__v = __bswap_constant_32 (__x); \
else \
__asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \
__v; }))
# else
# define __bswap_32(x) \
(__extension__ \
({ unsigned int __v, __x = (x); \
if (__builtin_constant_p (__x)) \
__v = __bswap_constant_32 (__x); \
else \
__asm__ ("rorw $8, %w0;" \
"rorl $16, %0;" \
"rorw $8, %w0" \
: "=r" (__v) \
: "0" (__x) \
: "cc"); \
__v; }))
# endif
# else
# define __bswap_32(x) \
(__extension__ \
({ unsigned int __x = (x); __bswap_constant_32 (__x); }))
# endif
#else
static __inline unsigned int
__bswap_32 (unsigned int __bsx)
{
return __bswap_constant_32 (__bsx);
}
#endif
Repro case
long long n = ~0LL;
enum e { ... } f;
e v = 1 ? f : 0;
is valid C code but is now rejected.
TODO.
I'm creating a ticket for the discussion we had by email. So the problem is that HostConfig aims for cpp
and does not respect any overrides via CPP
env variable for example.
func HostConfig(opts ...string) (predefined string, includePaths, sysIncludePaths []string, err error) {
args := append(append([]string{"-dM"}, opts...), "/dev/null")
pre, err := exec.Command("cpp", args...).Output()
if err != nil {
return "", nil, nil, err
}
...
My suggestion is to do it like this:
cppPath := "cpp"
if path, ok := os.LookupEnv("CPP"); ok {
cpPath = path
}
pre, err := exec.Command(cppPath, ...
Repro case
enum { a } e;
int i = 3 + e;
Having this enum:
enum {
AINPUT_SOURCE_UNKNOWN = 0x00000000,
AINPUT_SOURCE_ANY = 0xffffff00,
};
It seems that CC tries to handle 0xffffff00
as int32
, you previously have said:
I've made enum types have always the properties of C int. The reason is that the C99 specification mandates that the enum const expression value must be representable as C int.
But from C99 §6.7.2.2/4:
Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined but shall be capable of representing the values of all the members of the enumeration.
So in this case it must be treated as uint32
and be represented with no issues.
panic: internal error unsigned long, ULong
goroutine 1 [running]:
panic(0x362fe0, 0xc82024f310)
/usr/local/go/src/runtime/panic.go:464 +0x3e6
github.com/cznic/cc.(*Model).MustConvert(0x630b20, 0x2fa4e0, 0xc82024f2b4, 0x707a60, 0xc820482720, 0x0, 0x0)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/model.go:591 +0xa57
github.com/cznic/cc.(*Expression).eval(0xc8207a0c00, 0xc8203583c0, 0x0, 0x0, 0x0, 0x0)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/ast2.go:729 +0x38eb
Reproduction case
struct {
_Bool;
};
Example
void f(void(*)(int));
void g(int);
void h() {
f((void(*)()g));
}
currently results in argument type check fail, but the specs permit this:
6.2.7, 3
- If only one type is a function type with a parameter type list (a function prototype),
the composite type is a function prototype with the parameter type list.
Repro case
unsigned long long = 1ULL << 2ULL;
--- FAIL: TestPreprocessor (1.99s)
all_test.go:558:
got testdata/dev/sqlite3/shell.c:4052:13: STRINGLITERAL "\"nArg<= (int)(sizeof( azArg )/sizeof( azArg [0]))\""
exp /tmp/cc-test-311690362:8670:4: STRINGLITERAL "\"nArg<=(int)(sizeof(azArg)/sizeof(azArg[0]))\""
FAIL
exit status 1
FAIL github.com/cznic/cc 2.026s
https://github.com/golang/go/wiki/CodeReviewComments#mixed-caps
This is also something that golint would report.
panic: ULong ULong
goroutine 1 [running]:
panic(0x363840, 0xc820481260)
/usr/local/go/src/runtime/panic.go:464 +0x3e6
github.com/cznic/cc.(*Model).binOpType(0x631b20, 0x708b28, 0xc82095e180, 0x708b28, 0xc820357680, 0x0, 0x0)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/model.go:1068 +0x486
github.com/cznic/cc.(*Model).binOp(0x631b20, 0xc8203543c0, 0x70d540, 0xc820958780, 0x70d540, 0xc820958a80, 0x0, 0x0, 0x0, 0x0, ...)
/Users/xlab/Documents/dev/go/src/github.com/cznic/cc/model.go:892 +0x12e
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.