Fix some edge cases for preprocessor, support auto keyword, MSVC compile fix

This commit is contained in:
rdb 2015-10-17 02:54:07 +02:00
parent 94b48d568f
commit 155ae811aa
11 changed files with 1860 additions and 1803 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1723,6 +1723,10 @@ type:
str << *$3;
yyerror("could not determine type of " + str.str(), @3);
}
}
| KW_AUTO
{
$$ = new CPPSimpleType(CPPSimpleType::T_auto);
}
;
@ -1813,6 +1817,10 @@ type_decl:
str << *$3;
yyerror("could not determine type of " + str.str(), @3);
}
}
| KW_AUTO
{
$$ = new CPPSimpleType(CPPSimpleType::T_auto);
}
;
@ -2114,7 +2122,7 @@ namespace_declaration:
}
CPPNamespace *nspace = new CPPNamespace($3, scope, @2.file);
nspace->_inline = true;
nspace->_is_inline = true;
current_scope->add_declaration(nspace, global_scope, current_lexer, @2);
current_scope->define_namespace(nspace);
push_scope(scope);

View File

@ -189,7 +189,7 @@ get_local_name(CPPScope *scope) const {
// Strip off template scopes, since they don't add anything
// particularly meaningful to the local name.
while (my_scope->as_template_scope() != NULL) {
while (my_scope != NULL && my_scope->as_template_scope() != NULL) {
my_scope = my_scope->get_parent_scope();
}

View File

@ -28,7 +28,7 @@ CPPNamespace(CPPIdentifier *ident, CPPScope *scope, const CPPFile &file) :
CPPDeclaration(file),
_ident(ident),
_scope(scope),
_inline(false)
_is_inline(false)
{
}
@ -88,7 +88,7 @@ get_scope() const {
////////////////////////////////////////////////////////////////////
void CPPNamespace::
output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
if (_inline) {
if (_is_inline) {
out << "inline ";
}
if (!complete && _ident != NULL) {

View File

@ -42,7 +42,9 @@ public:
virtual CPPNamespace *as_namespace();
bool _inline;
// We can't call this _inline since that would clash with an MSVC
// built-in keyword declaration.
bool _is_inline;
private:
CPPIdentifier *_ident;

View File

@ -72,7 +72,8 @@ parse_file(const Filename &filename) {
////////////////////////////////////////////////////////////////////
CPPExpression *CPPParser::
parse_expr(const string &expr) {
return CPPPreprocessor::parse_expr(expr, this, this);
YYLTYPE loc = {};
return CPPPreprocessor::parse_expr(expr, this, this, loc);
}
////////////////////////////////////////////////////////////////////

View File

@ -774,6 +774,7 @@ push_file(const CPPFile &file) {
indent(cerr, _files.size() * 2)
<< "Reading " << file << "\n";
}
assert(_last_c == 0);
_files.push_back(InputFile());
InputFile &infile = _files.back();
@ -841,7 +842,8 @@ push_string(const string &input, bool lock_position) {
// string and return the new string.
////////////////////////////////////////////////////////////////////
string CPPPreprocessor::
expand_manifests(const string &input_expr, bool expand_undefined) {
expand_manifests(const string &input_expr, bool expand_undefined,
const YYLTYPE &loc) {
// Get a copy of the expression string we can modify.
string expr = input_expr;
@ -872,11 +874,28 @@ expand_manifests(const string &input_expr, bool expand_undefined) {
manifest_found = true;
} else if (expand_undefined && ident != "true" && ident != "false") {
// It is not found. Expand it to 0.
// It is not found. Expand it to 0, but only if we are currently
// parsing an #if expression.
expr = expr.substr(0, q) + "0" + expr.substr(p);
p = q + 1;
}
}
} else if (expr[p] == '\'' || expr[p] == '"') {
// Skip the next part until we find a closing quotation mark.
char quote = expr[p];
p++;
while (p < expr.size() && expr[p] != quote) {
if (expr[p] == '\\') {
// This might be an escaped quote. Skip an extra char.
p++;
}
p++;
}
if (p >= expr.size()) {
// Unclosed string.
warning("missing terminating " + string(1, quote) + " character", loc);
}
p++;
} else {
p++;
}
@ -903,8 +922,8 @@ expand_manifests(const string &input_expr, bool expand_undefined) {
////////////////////////////////////////////////////////////////////
CPPExpression *CPPPreprocessor::
parse_expr(const string &input_expr, CPPScope *current_scope,
CPPScope *global_scope) {
string expr = expand_manifests(input_expr, false);
CPPScope *global_scope, const YYLTYPE &loc) {
string expr = expand_manifests(input_expr, false, loc);
CPPExpressionParser ep(current_scope, global_scope);
ep._verbose = 0;
@ -1475,7 +1494,7 @@ handle_define_directive(const string &args, const YYLTYPE &loc) {
if (!manifest->_has_parameters) {
string expr_string = manifest->expand();
if (!expr_string.empty()) {
manifest->_expr = parse_expr(expr_string, global_scope, global_scope);
manifest->_expr = parse_expr(expr_string, global_scope, global_scope, loc);
}
}
@ -1554,7 +1573,7 @@ void CPPPreprocessor::
handle_if_directive(const string &args, const YYLTYPE &loc) {
// When expanding manifests, we should replace unknown macros
// with 0.
string expr = expand_manifests(args, true);
string expr = expand_manifests(args, true, loc);
int expression_result = 0;
CPPExpressionParser ep(current_scope, global_scope);
@ -1602,7 +1621,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
// might not filter out quotes and angle brackets properly, we'll
// only expand manifests if we don't begin with a quote or bracket.
if (!expr.empty() && (expr[0] != '"' && expr[0] != '<')) {
expr = expand_manifests(expr, false);
expr = expand_manifests(expr, false, loc);
}
if (!expr.empty()) {
@ -2727,14 +2746,11 @@ get() {
indent(cerr, _files.size() * 2)
<< "End of input stream, restoring to previous input\n";
#endif
int last_c = _files.back()._prev_last_c;
_files.pop_back();
if (last_c != '\0') {
c = last_c;
} else if (!_files.empty()) {
c = _files.back().get();
}
// Synthesize a newline, just in case the file doesn't already
// end with one.
c = '\n';
}
if (c == '\n') {

View File

@ -111,9 +111,10 @@ protected:
bool push_file(const CPPFile &file);
bool push_string(const string &input, bool lock_position);
string expand_manifests(const string &input_expr, bool expand_undefined);
string expand_manifests(const string &input_expr, bool expand_undefined,
const YYLTYPE &loc);
CPPExpression *parse_expr(const string &expr, CPPScope *current_scope,
CPPScope *global_scope);
CPPScope *global_scope, const YYLTYPE &loc);
private:
CPPToken internal_get_next_token();

View File

@ -297,7 +297,7 @@ define_namespace(CPPNamespace *ns) {
_namespaces[name] = ns;
if (ns->_inline) {
if (ns->_is_inline) {
// Add an implicit using declaration for an inline namespace.
_using.insert(ns->get_scope());
}

View File

@ -158,6 +158,10 @@ output(ostream &out, int, CPPScope *, bool) const {
out << "parameter";
break;
case T_auto:
out << "auto";
break;
default:
out << "***invalid type***";
}

View File

@ -55,6 +55,13 @@ public:
// but it initially looks like a function prototype.
//
T_parameter,
// T_auto is also a special type that corresponds to the "auto"
// keyword used in a variable assignment. The type of it is
// automatically determined at a later stage based on the type
// of the expression that is assigned to it.
//
T_auto,
};
enum Flags {