diff --git a/src/cpp/cpp_typecheck_expr.cpp b/src/cpp/cpp_typecheck_expr.cpp index 6675545d33d..8fe39c0a23e 100644 --- a/src/cpp/cpp_typecheck_expr.cpp +++ b/src/cpp/cpp_typecheck_expr.cpp @@ -967,13 +967,8 @@ void cpp_typecheckt::typecheck_expr_explicit_constructor_call(exprt &expr) } else { - CHECK_RETURN(expr.type().id() == ID_struct); - - struct_tag_typet tag(expr.type().get(ID_name)); - tag.add_source_location() = expr.source_location(); - exprt e=expr; - new_temporary(e.source_location(), tag, e.operands(), expr); + new_temporary(e.source_location(), e.type(), e.operands(), expr); } } diff --git a/src/cpp/parse.cpp b/src/cpp/parse.cpp index b202aa3b389..3b2109a30b6 100644 --- a/src/cpp/parse.cpp +++ b/src/cpp/parse.cpp @@ -23,7 +23,6 @@ Author: Daniel Kroening, kroening@cs.cmu.edu #include "cpp_member_spec.h" #include "cpp_enum_type.h" -#define DEBUG #ifdef DEBUG #include @@ -6363,7 +6362,10 @@ bool Parser::rAllocateInitializer(exprt &init) postfix.exp : primary.exp | postfix.expr '[' comma.expression ']' + | postfix.expr '[' initializer ']' | postfix.expr '(' function.arguments ')' + | integral.or.class.spec '(' function.arguments ')' + | integral.or.class.spec initializer | postfix.expr '.' var.name | postfix.expr ArrowOp var.name | postfix.expr IncOp @@ -6372,8 +6374,6 @@ bool Parser::rAllocateInitializer(exprt &init) openc++.postfix.expr : postfix.expr '.' userdef.statement | postfix.expr ArrowOp userdef.statement - - Note: function-style casts are accepted as function calls. */ bool Parser::rPostfixExpr(exprt &exp) { @@ -6382,8 +6382,52 @@ bool Parser::rPostfixExpr(exprt &exp) std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 0\n"; #endif - if(!rPrimaryExpr(exp)) - return false; + typet type; + + cpp_token_buffert::post pos=lex.Save(); + // try to see whether this is explicit type conversion, else it has to be + // a primary-expression + if(optIntegralTypeOrClassSpec(type) && + (type.is_not_nil() || rName(type)) && + (lex.LookAhead(0) == '(' || lex.LookAhead(0) == '{')) + { +#ifdef DEBUG + std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 0.1\n"; +#endif + + cpp_tokent tk; + lex.LookAhead(0, tk); + exprt exp2; + if(lex.LookAhead(0)=='{') + { + if(!rInitializeExpr(exp2)) + return false; + } + else + { + // lex.LookAhead(0)=='(' + lex.get_token(tk); + + exprt exp2; + if(!rFunctionArguments(exp2)) + return false; + + cpp_tokent tk2; + if(lex.get_token(tk2)!=')') + return false; + } + + exp=exprt("explicit-constructor-call"); + exp.type().swap(type); + exp.operands().swap(exp2.operands()); + set_location(exp, tk); + } + else + { + lex.Restore(pos); + if(!rPrimaryExpr(exp)) + return false; + } #ifdef DEBUG std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 1\n"; @@ -6399,7 +6443,14 @@ bool Parser::rPostfixExpr(exprt &exp) { case '[': lex.get_token(op); - if(!rCommaExpression(e)) + + if(lex.LookAhead(0) == '{') + { + // C++11 initialisation expression + if(!rInitializeExpr(e)) + return false; + } + else if(!rCommaExpression(e)) return false; #ifdef DEBUG @@ -6447,35 +6498,6 @@ bool Parser::rPostfixExpr(exprt &exp) } break; - case '{': -#ifdef DEBUG - std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 3a\n"; -#endif - - // this is a C++11 extension - if(!rInitializeExpr(e)) - return false; - - if(lex.get_token(cp)!='}') - return false; - -#ifdef DEBUG - std::cout << std::string(__indent, ' ') << "Parser::rPostfixExpr 4a\n"; -#endif - - { - side_effect_expr_function_callt fc( - std::move(exp), {}, typet{}, source_locationt{}); - fc.arguments().reserve(e.operands().size()); - set_location(fc, op); - - Forall_operands(it, e) - fc.arguments().push_back(*it); - e.operands().clear(); // save some - exp.swap(fc); - } - break; - case TOK_INCR: lex.get_token(op); @@ -6746,8 +6768,6 @@ bool Parser::rTypePredicate(exprt &expr) | THIS | var.name | '(' comma.expression ')' - | integral.or.class.spec '(' function.arguments ')' - | integral.or.class.spec initializer | typeid.expr | true | false @@ -6865,12 +6885,6 @@ bool Parser::rPrimaryExpr(exprt &exp) #endif return true; - case '{': // C++11 initialisation expression -#ifdef DEBUG - std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 10\n"; -#endif - return rInitializeExpr(exp); - case TOK_TYPEID: return rTypeidExpr(exp); @@ -6901,60 +6915,6 @@ bool Parser::rPrimaryExpr(exprt &exp) std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 14\n"; #endif { - typet type; - - if(!optIntegralTypeOrClassSpec(type)) - return false; - -#ifdef DEBUG - std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 15\n"; -#endif - - if(type.is_not_nil() && lex.LookAhead(0)==TOK_SCOPE) - { - lex.get_token(tk); - lex.get_token(tk); - - // TODO - } - else if(type.is_not_nil()) - { -#ifdef DEBUG - std::cout << std::string(__indent, ' ') << "Parser::rPrimaryExpr 16\n"; -#endif - if(lex.LookAhead(0)=='{') - { - lex.LookAhead(0, tk); - - exprt exp2; - if(!rInitializeExpr(exp2)) - return false; - - exp=exprt("explicit-constructor-call"); - exp.type().swap(type); - exp.add_to_operands(std::move(exp2)); - set_location(exp, tk); - } - else if(lex.LookAhead(0)=='(') - { - lex.get_token(tk); - - exprt exp2; - if(!rFunctionArguments(exp2)) - return false; - - if(lex.get_token(tk2)!=')') - return false; - - exp=exprt("explicit-constructor-call"); - exp.type().swap(type); - exp.operands().swap(exp2.operands()); - set_location(exp, tk); - } - else - return false; - } - else { if(!rVarName(exp)) return false;