Skip to content

Commit

Permalink
Merge pull request diffblue#2343 from tautschnig/c++-auto
Browse files Browse the repository at this point in the history
C++11 auto type specifier
  • Loading branch information
tautschnig authored Jun 12, 2018
2 parents 278e506 + af83568 commit bd74d87
Show file tree
Hide file tree
Showing 16 changed files with 124 additions and 8 deletions.
2 changes: 1 addition & 1 deletion regression/cpp/auto1/test.desc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
KNOWNBUG
CORE
main.cpp
-std=c++11
^EXIT=0$
Expand Down
7 changes: 7 additions & 0 deletions regression/cpp/auto2/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
int main()
{
#ifndef _MSC_VER
// Visual Studio uses C++14 by default, thus the below would not be valid
auto int x = 42;
#endif
}
8 changes: 8 additions & 0 deletions regression/cpp/auto2/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CORE
main.cpp

^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring
^CONVERSION ERROR$
11 changes: 11 additions & 0 deletions regression/cpp/auto3/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
int main()
{
#ifndef _MSC_VER
// should yield a parse error unless in C++11 (or later) mode
auto x = 42;
const auto y = 42;
const auto &z = y;
#else
intentionally invalid
#endif
}
9 changes: 9 additions & 0 deletions regression/cpp/auto3/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CORE
main.cpp

^EXIT=(64|1)$
^SIGNAL=0$
parse error
--
^warning: ignoring
^CONVERSION ERROR$
6 changes: 6 additions & 0 deletions regression/cpp/auto4/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
int main()
{
auto x = 42;
const auto y = 42;
const auto &z = y;
}
8 changes: 8 additions & 0 deletions regression/cpp/auto4/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CORE
main.cpp
-std=c++11
^EXIT=0$
^SIGNAL=0$
--
^warning: ignoring
^CONVERSION ERROR$
16 changes: 16 additions & 0 deletions src/cpp/cpp_convert_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,3 +591,19 @@ void cpp_convert_plain_type(typet &type)
cpp_convert_type.write(type);
}
}

void cpp_convert_auto(typet &dest, const typet &src)
{
if(dest.id() != ID_merged_type && dest.has_subtype())
{
cpp_convert_auto(dest.subtype(), src);
return;
}

cpp_convert_typet cpp_convert_type(dest);
for(auto &t : cpp_convert_type.other)
if(t.id() == ID_auto)
t = src;

cpp_convert_type.write(dest);
}
2 changes: 2 additions & 0 deletions src/cpp/cpp_convert_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ Author: Daniel Kroening, [email protected]

void cpp_convert_plain_type(typet &);

void cpp_convert_auto(typet &dest, const typet &src);

#endif // CPROVER_CPP_CPP_CONVERT_TYPE_H
3 changes: 2 additions & 1 deletion src/cpp/cpp_declarator_converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ symbolt &cpp_declarator_convertert::convert(
scope=&cpp_typecheck.cpp_scopes.current_scope();

// check the declarator-part of the type, in that scope
cpp_typecheck.typecheck_type(final_type);
if(declarator.value().is_nil() || !cpp_typecheck.has_auto(final_type))
cpp_typecheck.typecheck_type(final_type);
}

is_code=is_code_type(final_type);
Expand Down
1 change: 1 addition & 0 deletions src/cpp/cpp_typecheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ class cpp_typecheckt:public c_typecheck_baset

static bool has_const(const typet &type);
static bool has_volatile(const typet &type);
static bool has_auto(const typet &type);

void typecheck_member_function(
const irep_idt &compound_identifier,
Expand Down
9 changes: 7 additions & 2 deletions src/cpp/cpp_typecheck_code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,9 @@ void cpp_typecheckt::typecheck_decl(codet &code)

bool is_typedef=declaration.is_typedef();

typecheck_type(type);
if(declaration.declarators().empty() || !has_auto(type))
typecheck_type(type);

assert(type.is_not_nil());

if(declaration.declarators().empty() &&
Expand Down Expand Up @@ -409,7 +411,10 @@ void cpp_typecheckt::typecheck_decl(codet &code)
symbol.value.id()!=ID_code)
{
decl_statement.copy_to_operands(symbol.value);
assert(follow(decl_statement.op1().type())==follow(symbol.type));
DATA_INVARIANT(
has_auto(symbol.type) ||
follow(decl_statement.op1().type()) == follow(symbol.type),
"declarator type should match symbol type");
}

new_code.move_to_operands(decl_statement);
Expand Down
16 changes: 16 additions & 0 deletions src/cpp/cpp_typecheck_compound_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,22 @@ bool cpp_typecheckt::has_volatile(const typet &type)
return false;
}

bool cpp_typecheckt::has_auto(const typet &type)
{
if(type.id() == ID_auto)
return true;
else if(type.id() == ID_merged_type || type.id() == ID_frontend_pointer)
{
forall_subtypes(it, type)
if(has_auto(*it))
return true;

return false;
}
else
return false;
}

cpp_scopet &cpp_typecheckt::tag_scope(
const irep_idt &base_name,
bool has_body,
Expand Down
3 changes: 2 additions & 1 deletion src/cpp/cpp_typecheck_declaration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ void cpp_typecheckt::convert_non_template_declaration(
declaration.name_anon_struct_union();

// do the type of the declaration
typecheck_type(declaration_type);
if(declaration.declarators().empty() || !has_auto(declaration_type))
typecheck_type(declaration_type);

// Elaborate any class template instance _unless_ we do a typedef.
// These are only elaborated on usage!
Expand Down
8 changes: 8 additions & 0 deletions src/cpp/cpp_typecheck_initializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Author: Daniel Kroening, [email protected]
#include <util/expr_initializer.h>
#include <util/pointer_offset_size.h>

#include "cpp_convert_type.h"

/// Initialize an object with a value
void cpp_typecheckt::convert_initializer(symbolt &symbol)
{
Expand Down Expand Up @@ -144,6 +146,12 @@ void cpp_typecheckt::convert_initializer(symbolt &symbol)
if(symbol.type.find(ID_size).is_nil())
symbol.type=symbol.value.type();
}
else if(has_auto(symbol.type))
{
cpp_convert_auto(symbol.type, symbol.value.type());
typecheck_type(symbol.type);
implicit_typecast(symbol.value, symbol.type);
}
else
implicit_typecast(symbol.value, symbol.type);

Expand Down
23 changes: 20 additions & 3 deletions src/cpp/parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,7 @@ bool Parser::rDeclaration(cpp_declarationt &declaration)
<< "\n";
#endif

if((cv_q.is_not_nil() || storage_spec.is_auto()) &&
if(cv_q.is_not_nil() &&
((t==TOK_IDENTIFIER && lex.LookAhead(1)=='=') || t=='*'))
return rConstDeclaration(declaration, storage_spec, member_spec, cv_q);
else
Expand Down Expand Up @@ -1585,6 +1585,17 @@ bool Parser::rIntegralDeclaration(
if(!rDeclarators(declaration.declarators(), true))
return false;

// handle trailing return type
if(
declaration.type().id() == ID_auto &&
declaration.declarators().size() == 1 &&
declaration.declarators().front().type().id() == ID_function_type &&
declaration.declarators().front().type().subtype().is_not_nil())
{
declaration.type() = declaration.declarators().front().type().subtype();
declaration.declarators().front().type().subtype().make_nil();
}

#ifdef DEBUG
std::cout << std::string(__indent, ' ')
<< "Parser::rIntegralDeclaration 7\n";
Expand Down Expand Up @@ -1961,7 +1972,7 @@ bool Parser::optStorageSpec(cpp_storage_spect &storage_spec)

if(t==TOK_STATIC ||
t==TOK_EXTERN ||
t==TOK_AUTO ||
(t == TOK_AUTO && !ansi_c_parser.cpp11) ||
t==TOK_REGISTER ||
t==TOK_MUTABLE ||
t==TOK_GCC_ASM ||
Expand Down Expand Up @@ -2224,6 +2235,7 @@ bool Parser::optIntegralTypeOrClassSpec(typet &p)
case TOK_GCC_FLOAT128: type_id=ID_gcc_float128; break;
case TOK_BOOL: type_id=ID_bool; break;
case TOK_CPROVER_BOOL: type_id=ID_proper_bool; break;
case TOK_AUTO: type_id = ID_auto; break;
default: type_id=irep_idt();
}

Expand Down Expand Up @@ -2912,6 +2924,11 @@ bool Parser::rDeclarator(
typet return_type;
if(!rTypeSpecifier(return_type, false))
return false;

if(d_outer.subtype().is_not_nil())
return false;

d_outer.subtype().swap(return_type);
}

if(lex.LookAhead(0)==':')
Expand Down Expand Up @@ -7997,7 +8014,7 @@ bool Parser::rDeclarationStatement(codet &statement)
<< "Parser::rDeclarationStatement 3 " << t << "\n";
#endif

if((cv_q.is_not_nil() || storage_spec.is_auto()) &&
if(cv_q.is_not_nil() &&
((t==TOK_IDENTIFIER && lex.LookAhead(1)=='=') || t=='*'))
{
#ifdef DEBUG
Expand Down

0 comments on commit bd74d87

Please sign in to comment.