From c9272d1877b4f5b7bacc7efc6542a304ab6f0ced Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 7 Jan 2021 22:36:31 +0000 Subject: [PATCH 1/2] C front-end: labelled declarations are only supported by Visual Studio In order to support GCC's label attributes even when the semicolon is omitted, distinguish GCC and Visual Studio modes when parsing labelled statements. See https://github.com/gcc-mirror/gcc/blob/master/gcc/c/c-parser.cc#L6070 for GCC's limitation, which we now mimic. (We already supported attributes followed by a semicolon, which GCC's documentation mandates, but the Linux kernel doesn't always follow this rule.) Fixed regression tests that had declarations immediately following a label. --- regression/ansi-c/label1/main.c | 14 ++++ regression/ansi-c/label1/test.desc | 15 +++++ regression/cbmc/destructors/main.c | 4 +- .../symex_should_exclude_null_pointers/main.c | 4 +- .../symex_should_filter_value_sets/main.c | 8 +-- regression/cbmc/unwind_counters2/main.c | 7 +- regression/cbmc/unwind_counters3/main.c | 7 +- regression/cbmc/unwind_counters4/main.c | 2 +- regression/goto-instrument/labels1/main.c | 3 +- .../goto-instrument/safe-dereferences/main.c | 4 +- src/ansi-c/parser.y | 40 +++++++++-- src/ansi-c/scanner.l | 6 +- src/cpp/parse.cpp | 67 +++++++++++-------- 13 files changed, 126 insertions(+), 55 deletions(-) create mode 100644 regression/ansi-c/label1/main.c create mode 100644 regression/ansi-c/label1/test.desc diff --git a/regression/ansi-c/label1/main.c b/regression/ansi-c/label1/main.c new file mode 100644 index 00000000000..065a8ae72b9 --- /dev/null +++ b/regression/ansi-c/label1/main.c @@ -0,0 +1,14 @@ +extern void foo(int *, unsigned int); + +int main() +{ +#ifdef _MSC_VER +label: + int x; +#elif defined(__GNUC__) + int *p; + unsigned int u; +label: + __attribute__((unused)) foo(p, u); +#endif +} diff --git a/regression/ansi-c/label1/test.desc b/regression/ansi-c/label1/test.desc new file mode 100644 index 00000000000..96d9aa3f8d0 --- /dev/null +++ b/regression/ansi-c/label1/test.desc @@ -0,0 +1,15 @@ +CORE +main.c + +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +^CONVERSION ERROR$ +-- +GCC does not permit labelling declarations as they are not considered +statements, and would result in ambiguity in case of label attributes. We used +to run into this problem, treating the function call in this test as a KnR +function declaration. + +Visual Studio, on the other hand, happily accepts labelled declarations. diff --git a/regression/cbmc/destructors/main.c b/regression/cbmc/destructors/main.c index c2bae335acc..02c30cff883 100644 --- a/regression/cbmc/destructors/main.c +++ b/regression/cbmc/destructors/main.c @@ -6,7 +6,7 @@ int main(int argc, char **argv) { const float *pc = (const float []){1e0, 1e1, 1e2}; -start: +start:; test newAlloc0 = {0}; if(argv[0]) { @@ -20,7 +20,7 @@ int main(int argc, char **argv) { if (argv[2]) { test newAlloc3 = {3}; -nested_if: + nested_if:; test newAlloc5 = {5}; if (argv[3]) { diff --git a/regression/cbmc/symex_should_exclude_null_pointers/main.c b/regression/cbmc/symex_should_exclude_null_pointers/main.c index 3ccab5c9585..1fee7a0ba35 100644 --- a/regression/cbmc/symex_should_exclude_null_pointers/main.c +++ b/regression/cbmc/symex_should_exclude_null_pointers/main.c @@ -38,7 +38,7 @@ int main(int argc, char **argv) { int *ptr4 = maybe_null; goto check; -deref: +deref:; int deref4 = *ptr4; goto end_test4; @@ -46,7 +46,7 @@ int main(int argc, char **argv) { __CPROVER_assume(ptr4 != 0); goto deref; -end_test4: +end_test4:; // Should be judged unsafe by LSPA and safe by value-set filtering // (guarded by confluence): diff --git a/regression/cbmc/symex_should_filter_value_sets/main.c b/regression/cbmc/symex_should_filter_value_sets/main.c index 6f9910184c3..e34479cd981 100644 --- a/regression/cbmc/symex_should_filter_value_sets/main.c +++ b/regression/cbmc/symex_should_filter_value_sets/main.c @@ -61,7 +61,7 @@ int main(int argc, char **argv) int *p7 = ptr_to_a_or_b; goto check7; -divide7: +divide7:; int c7 = *p7; goto end_test7; @@ -69,12 +69,12 @@ int main(int argc, char **argv) __CPROVER_assume(p7 != &a); goto divide7; -end_test7: +end_test7:; int *p8 = ptr_to_a_or_b; goto check8; -divide8: +divide8:; int c8 = *p8; goto end_test8; @@ -82,7 +82,7 @@ int main(int argc, char **argv) __CPROVER_assume(*p8 != 2); goto divide8; -end_test8: +end_test8:; // Should work (value-set filtered by confluence of if and else): int *p9 = ptr_to_a_or_b; diff --git a/regression/cbmc/unwind_counters2/main.c b/regression/cbmc/unwind_counters2/main.c index 447015074c9..404c7aba1e5 100644 --- a/regression/cbmc/unwind_counters2/main.c +++ b/regression/cbmc/unwind_counters2/main.c @@ -1,8 +1,9 @@ int main() { l2: goto l1; - l1: int x=5; - goto l2; + l1:; + int x = 5; + goto l2; - return 0; + return 0; } diff --git a/regression/cbmc/unwind_counters3/main.c b/regression/cbmc/unwind_counters3/main.c index caa1d607594..b9651b7c479 100644 --- a/regression/cbmc/unwind_counters3/main.c +++ b/regression/cbmc/unwind_counters3/main.c @@ -2,8 +2,9 @@ int main() { int i=0; l2: if(i==1) int y=0; - l1: int x=5; - goto l2; + l1:; + int x = 5; + goto l2; - return 0; + return 0; } diff --git a/regression/cbmc/unwind_counters4/main.c b/regression/cbmc/unwind_counters4/main.c index 4440ea97105..b7f1edafbad 100644 --- a/regression/cbmc/unwind_counters4/main.c +++ b/regression/cbmc/unwind_counters4/main.c @@ -8,7 +8,7 @@ int main() y = 10; goto label; x = 1; // dead code, makes sure the above goto is not removed - label: + label:; _Bool nondet; if(nondet) __CPROVER_assert(y != 10, "violated via first loop"); diff --git a/regression/goto-instrument/labels1/main.c b/regression/goto-instrument/labels1/main.c index b1affadab6f..509cec5fe71 100644 --- a/regression/goto-instrument/labels1/main.c +++ b/regression/goto-instrument/labels1/main.c @@ -24,8 +24,9 @@ int main() x = 42; label_four: assert(foo() == 1); + fptr_t fp; label_five: - fptr_t fp = foo; + fp = foo; assert(fp() == 1); label_six: return *p; diff --git a/regression/goto-instrument/safe-dereferences/main.c b/regression/goto-instrument/safe-dereferences/main.c index f691ee75569..f71e7f63c97 100644 --- a/regression/goto-instrument/safe-dereferences/main.c +++ b/regression/goto-instrument/safe-dereferences/main.c @@ -30,7 +30,7 @@ int main(int argc, char **argv) { int *ptr4 = &x; goto check; -deref: +deref:; int deref4 = *ptr4; goto end_test4; @@ -38,7 +38,7 @@ int main(int argc, char **argv) { __CPROVER_assume(ptr4 != 0); goto deref; -end_test4: +end_test4:; // Shouldn't work yet despite being safe (guarded by confluence): int *ptr5 = &x; diff --git a/src/ansi-c/parser.y b/src/ansi-c/parser.y index b2cb9f21416..6d3889308a5 100644 --- a/src/ansi-c/parser.y +++ b/src/ansi-c/parser.y @@ -118,7 +118,8 @@ extern char *yyansi_ctext; /*** scanner parsed tokens (these have a value!) ***/ -%token TOK_IDENTIFIER +%token TOK_GCC_IDENTIFIER +%token TOK_MSC_IDENTIFIER %token TOK_TYPEDEFNAME %token TOK_INTEGER %token TOK_FLOATING @@ -293,7 +294,8 @@ grammar: /*** Token with values **************************************************/ identifier: - TOK_IDENTIFIER + TOK_GCC_IDENTIFIER + | TOK_MSC_IDENTIFIER | TOK_CPROVER_ID TOK_STRING { // construct an identifier from a string that would otherwise not be a @@ -1362,7 +1364,7 @@ atomic_type_specifier: ; msc_decl_identifier: - TOK_IDENTIFIER + TOK_MSC_IDENTIFIER { parser_stack($$).id(parser_stack($$).get(ID_identifier)); } @@ -2285,9 +2287,14 @@ designator: /*** Statements *********************************************************/ statement: + declaration_statement + | statement_attribute + | stmt_not_decl_or_attr + ; + +stmt_not_decl_or_attr: labeled_statement | compound_statement - | declaration_statement | expression_statement | selection_statement | iteration_statement @@ -2297,7 +2304,6 @@ statement: | msc_asm_statement | msc_seh_statement | cprover_exception_statement - | statement_attribute ; declaration_statement: @@ -2309,8 +2315,30 @@ declaration_statement: } ; +gcc_attribute_specifier_opt: + /* empty */ + { + init($$); + } + | gcc_attribute_specifier + ; + +msc_label_identifier: + TOK_MSC_IDENTIFIER + | TOK_TYPEDEFNAME + ; + labeled_statement: - identifier_or_typedef_name ':' statement + TOK_GCC_IDENTIFIER ':' gcc_attribute_specifier_opt stmt_not_decl_or_attr + { + // we ignore the GCC attribute + $$=$2; + statement($$, ID_label); + irep_idt identifier=PARSER.lookup_label(parser_stack($1).get(ID_C_base_name)); + parser_stack($$).set(ID_label, identifier); + mto($$, $4); + } + | msc_label_identifier ':' statement { $$=$2; statement($$, ID_label); diff --git a/src/ansi-c/scanner.l b/src/ansi-c/scanner.l index 48a30605e3b..be94316d75f 100644 --- a/src/ansi-c/scanner.l +++ b/src/ansi-c/scanner.l @@ -86,7 +86,8 @@ int make_identifier() { parser_stack(yyansi_clval).id(ID_symbol); parser_stack(yyansi_clval).set(ID_C_base_name, final_base_name); - return TOK_IDENTIFIER; + return PARSER.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO ? + TOK_MSC_IDENTIFIER : TOK_GCC_IDENTIFIER; } else { @@ -112,7 +113,8 @@ int make_identifier() else { parser_stack(yyansi_clval).id(ID_symbol); - return TOK_IDENTIFIER; + return PARSER.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO ? + TOK_MSC_IDENTIFIER : TOK_GCC_IDENTIFIER; } } } diff --git a/src/cpp/parse.cpp b/src/cpp/parse.cpp index 66442cbace4..019e0dcf335 100644 --- a/src/cpp/parse.cpp +++ b/src/cpp/parse.cpp @@ -410,6 +410,11 @@ class Parser // NOLINT(readability/identifiers) unsigned int max_errors; }; +static bool is_identifier(int token) +{ + return token == TOK_GCC_IDENTIFIER || token == TOK_MSC_IDENTIFIER; +} + new_scopet &Parser::add_id(const irept &cpp_name, new_scopet::kindt kind) { irep_idt id; @@ -569,7 +574,7 @@ bool Parser::rDefinition(cpp_itemt &item) else if(t==TOK_INLINE && lex.LookAhead(1)==TOK_NAMESPACE) return rNamespaceSpec(item.make_namespace_spec()); else if(t==TOK_USING && - lex.LookAhead(1)==TOK_IDENTIFIER && + is_identifier(lex.LookAhead(1)) && lex.LookAhead(2)=='=') return rTypedefUsing(item.make_declaration()); else if(t==TOK_USING) @@ -642,7 +647,7 @@ bool Parser::rTypedefUsing(cpp_declarationt &declaration) declaration.type()=typet(ID_typedef); - if(lex.get_token(tk)!=TOK_IDENTIFIER) + if(!is_identifier(lex.get_token(tk))) return false; cpp_declaratort name; @@ -751,7 +756,7 @@ bool Parser::isTypeSpecifier() { int t=lex.LookAhead(0); - if(t==TOK_IDENTIFIER || t==TOK_SCOPE + if(is_identifier(t) || t==TOK_SCOPE || t==TOK_CONSTEXPR || t==TOK_CONST || t==TOK_VOLATILE || t==TOK_RESTRICT || t==TOK_CHAR || t==TOK_INT || t==TOK_SHORT || t==TOK_LONG || t==TOK_CHAR16_T || t==TOK_CHAR32_T @@ -838,7 +843,7 @@ bool Parser::rNamespaceSpec(cpp_namespace_spect &namespace_spec) // namespace might be anonymous if(lex.LookAhead(0) != '{') { - if(lex.get_token(tk2)==TOK_IDENTIFIER) + if(is_identifier(lex.get_token(tk2))) name=tk2.data.get(ID_C_base_name); else return false; @@ -1187,7 +1192,7 @@ bool Parser::rTempArgDeclaration(cpp_declarationt &declaration) has_ellipsis=true; } - if(lex.LookAhead(0) == TOK_IDENTIFIER) + if(is_identifier(lex.LookAhead(0))) { cpp_tokent tk2; lex.get_token(tk2); @@ -1243,7 +1248,7 @@ bool Parser::rTempArgDeclaration(cpp_declarationt &declaration) cpp_tokent tk1, tk2; if(lex.get_token(tk1)!=TOK_CLASS || - lex.get_token(tk2)!=TOK_IDENTIFIER) + !is_identifier(lex.get_token(tk2))) return false; // Ptree cspec=new PtreeClassSpec(new LeafReserved(tk1), @@ -1458,7 +1463,7 @@ bool Parser::rDeclaration(cpp_declarationt &declaration) #endif if(cv_q.is_not_nil() && - ((t==TOK_IDENTIFIER && lex.LookAhead(1)=='=') || t=='*')) + ((is_identifier(t) && lex.LookAhead(1)=='=') || t=='*')) return rConstDeclaration(declaration); else return rOtherDeclaration(declaration, storage_spec, member_spec, cv_q); @@ -1874,7 +1879,7 @@ bool Parser::isConstructorDecl() return false; // it's a declarator else if(isPtrToMember(1)) return false; // declarator (::*) - else if(t==TOK_IDENTIFIER) + else if(is_identifier(t)) { // Ambiguous. Do some more look-ahead. if(lex.LookAhead(2)==')' && @@ -1898,7 +1903,7 @@ bool Parser::isPtrToMember(int i) if(t0==TOK_SCOPE) t0=lex.LookAhead(i++); - while(t0==TOK_IDENTIFIER) + while(is_identifier(t0)) { int t=lex.LookAhead(i++); if(t=='<') @@ -3078,7 +3083,7 @@ bool Parser::rDeclarator( name.swap(declarator2.name()); } else if(kind!=kCastDeclarator && - (kind==kDeclarator || t==TOK_IDENTIFIER || t==TOK_SCOPE)) + (kind==kDeclarator || is_identifier(t) || t==TOK_SCOPE)) { #ifdef DEBUG std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 6\n"; @@ -3536,7 +3541,7 @@ bool Parser::rName(irept &name) #endif lex.get_token(tk); // Skip template token, next will be identifier - if(lex.LookAhead(0)!=TOK_IDENTIFIER) + if(!is_identifier(lex.LookAhead(0))) return false; break; @@ -3558,7 +3563,8 @@ bool Parser::rName(irept &name) } break; - case TOK_IDENTIFIER: + case TOK_GCC_IDENTIFIER: + case TOK_MSC_IDENTIFIER: #ifdef DEBUG std::cout << std::string(__indent, ' ') << "Parser::rName 5\n"; #endif @@ -3590,7 +3596,7 @@ bool Parser::rName(irept &name) lex.get_token(tk); // identifier must be next - if(lex.LookAhead(0)!=TOK_IDENTIFIER) + if(!is_identifier(lex.LookAhead(0))) return false; components.push_back(irept("~")); @@ -3807,7 +3813,7 @@ bool Parser::rPtrToMember(irept &ptr_to_mem) case TOK_TEMPLATE: lex.get_token(tk); // Skip template token, next will be identifier - if(lex.LookAhead(0)!=TOK_IDENTIFIER) + if(!is_identifier(lex.LookAhead(0))) return false; break; @@ -3825,7 +3831,8 @@ bool Parser::rPtrToMember(irept &ptr_to_mem) } break; - case TOK_IDENTIFIER: + case TOK_GCC_IDENTIFIER: + case TOK_MSC_IDENTIFIER: lex.get_token(tk); components.push_back(cpp_namet::namet(tk.data.get(ID_C_base_name))); set_location(components.back(), tk); @@ -3855,7 +3862,7 @@ bool Parser::rPtrToMember(irept &ptr_to_mem) return true; } - if(lex.LookAhead(0) != TOK_IDENTIFIER) + if(!is_identifier(lex.LookAhead(0))) return false; break; @@ -4383,7 +4390,7 @@ bool Parser::rEnumBody(irept &body) if(lex.LookAhead(0)=='}') return true; - if(lex.get_token(tk)!=TOK_IDENTIFIER) + if(!is_identifier(lex.get_token(tk))) return false; body.get_sub().push_back(irept()); @@ -4720,7 +4727,7 @@ bool Parser::rClassMember(cpp_itemt &member) else if(t==TOK_TEMPLATE) return rTemplateDecl(member.make_declaration()); else if(t==TOK_USING && - lex.LookAhead(1)==TOK_IDENTIFIER && + is_identifier(lex.LookAhead(1)) && lex.LookAhead(2)=='=') return rTypedefUsing(member.make_declaration()); else if(t==TOK_USING) @@ -5576,7 +5583,7 @@ bool Parser::rTypeNameOrFunctionType(typet &tname) // TODO -- cruel hack for Clang's type_traits: // struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), // true, false> - if(lex.LookAhead(0)==TOK_IDENTIFIER && + if(is_identifier(lex.LookAhead(0)) && lex.LookAhead(1)==TOK_SCOPE && lex.LookAhead(2)=='*' && lex.LookAhead(3)==')' && @@ -5588,7 +5595,7 @@ bool Parser::rTypeNameOrFunctionType(typet &tname) lex.get_token(); lex.get_token(); } - else if(lex.LookAhead(0)==TOK_IDENTIFIER && + else if(is_identifier(lex.LookAhead(0)) && lex.LookAhead(1)==')' && lex.LookAhead(2)=='(') { @@ -5598,7 +5605,7 @@ bool Parser::rTypeNameOrFunctionType(typet &tname) lex.get_token(); } else if(lex.LookAhead(0)=='*' && - lex.LookAhead(1)==TOK_IDENTIFIER && + is_identifier(lex.LookAhead(1)) && lex.LookAhead(2)==')' && lex.LookAhead(3)=='(') { @@ -6976,11 +6983,12 @@ bool Parser::rVarNameCore(exprt &name) #endif lex.get_token(tk); // Skip template token, next will be identifier - if(lex.LookAhead(0)!=TOK_IDENTIFIER) + if(!is_identifier(lex.LookAhead(0))) return false; break; - case TOK_IDENTIFIER: + case TOK_GCC_IDENTIFIER: + case TOK_MSC_IDENTIFIER: #ifdef DEBUG std::cout << std::string(__indent, ' ') << "Parser::rVarNameCore 3\n"; #endif @@ -7030,7 +7038,7 @@ bool Parser::rVarNameCore(exprt &name) lex.get_token(tk); - if(lex.LookAhead(0)!=TOK_IDENTIFIER) + if(!is_identifier(lex.LookAhead(0))) return false; components.push_back(irept("~")); @@ -7067,7 +7075,7 @@ bool Parser::moreVarName() if(lex.LookAhead(0)==TOK_SCOPE) { int t=lex.LookAhead(1); - if(t==TOK_IDENTIFIER || t=='~' || t==TOK_OPERATOR || t==TOK_TEMPLATE) + if(is_identifier(t) || t=='~' || t==TOK_OPERATOR || t==TOK_TEMPLATE) return true; } @@ -7388,7 +7396,7 @@ optionalt Parser::rStatement() { lex.get_token(tk1); - if(lex.get_token(tk2)!=TOK_IDENTIFIER) + if(!is_identifier(lex.get_token(tk2))) return {}; if(lex.get_token(tk3)!=';') @@ -7475,7 +7483,8 @@ optionalt Parser::rStatement() case TOK_MSC_IF_NOT_EXISTS: return rMSC_if_existsStatement(); - case TOK_IDENTIFIER: + case TOK_GCC_IDENTIFIER: + case TOK_MSC_IDENTIFIER: if(lex.LookAhead(1)==':') // label statement { // the label @@ -7497,7 +7506,7 @@ optionalt Parser::rStatement() case TOK_USING: { - if(lex.LookAhead(1)==TOK_IDENTIFIER && + if(is_identifier(lex.LookAhead(1)) && lex.LookAhead(2)=='=') { cpp_declarationt declaration; @@ -8230,7 +8239,7 @@ optionalt Parser::rDeclarationStatement() #endif if(cv_q.is_not_nil() && - ((t==TOK_IDENTIFIER && lex.LookAhead(1)=='=') || t=='*')) + ((is_identifier(t) && lex.LookAhead(1)=='=') || t=='*')) { #ifdef DEBUG std::cout << std::string(__indent, ' ') From a5f789a3c435af74ba151f4ea409bc84c797b201 Mon Sep 17 00:00:00 2001 From: Michael Tautschnig Date: Thu, 7 Jan 2021 22:45:26 +0000 Subject: [PATCH 2/2] Clang-format modified lines in parse.cpp Also added braces where an if condition spans multiple lines, and replace one case of if(...) return true; return false; by return (...); --- src/cpp/parse.cpp | 127 +++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/src/cpp/parse.cpp b/src/cpp/parse.cpp index 019e0dcf335..99527bbdecc 100644 --- a/src/cpp/parse.cpp +++ b/src/cpp/parse.cpp @@ -573,10 +573,12 @@ bool Parser::rDefinition(cpp_itemt &item) return rNamespaceSpec(item.make_namespace_spec()); else if(t==TOK_INLINE && lex.LookAhead(1)==TOK_NAMESPACE) return rNamespaceSpec(item.make_namespace_spec()); - else if(t==TOK_USING && - is_identifier(lex.LookAhead(1)) && - lex.LookAhead(2)=='=') + else if( + t == TOK_USING && is_identifier(lex.LookAhead(1)) && + lex.LookAhead(2) == '=') + { return rTypedefUsing(item.make_declaration()); + } else if(t==TOK_USING) return rUsing(item.make_using()); else if(t==TOK_STATIC_ASSERT) @@ -756,27 +758,19 @@ bool Parser::isTypeSpecifier() { int t=lex.LookAhead(0); - if(is_identifier(t) || t==TOK_SCOPE - || t==TOK_CONSTEXPR || t==TOK_CONST || t==TOK_VOLATILE || t==TOK_RESTRICT - || t==TOK_CHAR || t==TOK_INT || t==TOK_SHORT || t==TOK_LONG - || t==TOK_CHAR16_T || t==TOK_CHAR32_T - || t==TOK_WCHAR_T || t==TOK_COMPLEX // new !!! - || t==TOK_SIGNED || t==TOK_UNSIGNED || t==TOK_FLOAT || t==TOK_DOUBLE - || t==TOK_INT8 || t==TOK_INT16 || t==TOK_INT32 || t==TOK_INT64 - || t==TOK_GCC_INT128 - || t==TOK_PTR32 || t==TOK_PTR64 - || t==TOK_GCC_FLOAT80 || t==TOK_GCC_FLOAT128 - || t==TOK_VOID || t==TOK_BOOL || t==TOK_CPROVER_BOOL - || t==TOK_CLASS || t==TOK_STRUCT || t==TOK_UNION || t==TOK_ENUM - || t==TOK_INTERFACE - || t==TOK_TYPENAME - || t==TOK_TYPEOF - || t==TOK_DECLTYPE - || t==TOK_UNDERLYING_TYPE - ) - return true; - - return false; + return is_identifier(t) || t == TOK_SCOPE || t == TOK_CONSTEXPR || + t == TOK_CONST || t == TOK_VOLATILE || t == TOK_RESTRICT || + t == TOK_CHAR || t == TOK_INT || t == TOK_SHORT || t == TOK_LONG || + t == TOK_CHAR16_T || t == TOK_CHAR32_T || t == TOK_WCHAR_T || + t == TOK_COMPLEX // new !!! + || t == TOK_SIGNED || t == TOK_UNSIGNED || t == TOK_FLOAT || + t == TOK_DOUBLE || t == TOK_INT8 || t == TOK_INT16 || t == TOK_INT32 || + t == TOK_INT64 || t == TOK_GCC_INT128 || t == TOK_PTR32 || + t == TOK_PTR64 || t == TOK_GCC_FLOAT80 || t == TOK_GCC_FLOAT128 || + t == TOK_VOID || t == TOK_BOOL || t == TOK_CPROVER_BOOL || + t == TOK_CLASS || t == TOK_STRUCT || t == TOK_UNION || t == TOK_ENUM || + t == TOK_INTERFACE || t == TOK_TYPENAME || t == TOK_TYPEOF || + t == TOK_DECLTYPE || t == TOK_UNDERLYING_TYPE; } /* @@ -1247,8 +1241,7 @@ bool Parser::rTempArgDeclaration(cpp_declarationt &declaration) cpp_tokent tk1, tk2; - if(lex.get_token(tk1)!=TOK_CLASS || - !is_identifier(lex.get_token(tk2))) + if(lex.get_token(tk1) != TOK_CLASS || !is_identifier(lex.get_token(tk2))) return false; // Ptree cspec=new PtreeClassSpec(new LeafReserved(tk1), @@ -1462,9 +1455,12 @@ bool Parser::rDeclaration(cpp_declarationt &declaration) << '\n'; #endif - if(cv_q.is_not_nil() && - ((is_identifier(t) && lex.LookAhead(1)=='=') || t=='*')) + if( + cv_q.is_not_nil() && + ((is_identifier(t) && lex.LookAhead(1) == '=') || t == '*')) + { return rConstDeclaration(declaration); + } else return rOtherDeclaration(declaration, storage_spec, member_spec, cv_q); } @@ -3082,8 +3078,9 @@ bool Parser::rDeclarator( d_inner.swap(declarator2.type()); name.swap(declarator2.name()); } - else if(kind!=kCastDeclarator && - (kind==kDeclarator || is_identifier(t) || t==TOK_SCOPE)) + else if( + kind != kCastDeclarator && + (kind == kDeclarator || is_identifier(t) || t == TOK_SCOPE)) { #ifdef DEBUG std::cout << std::string(__indent, ' ') << "Parser::rDeclarator2 6\n"; @@ -3818,31 +3815,33 @@ bool Parser::rPtrToMember(irept &ptr_to_mem) break; case '<': - { - irept args; - if(!rTemplateArgs(args)) - return false; + { + irept args; + if(!rTemplateArgs(args)) + return false; - components.push_back(irept(ID_template_args)); - components.back().add(ID_arguments).swap(args); + components.push_back(irept(ID_template_args)); + components.back().add(ID_arguments).swap(args); + + if(lex.LookAhead(0) != TOK_SCOPE) + return false; - if(lex.LookAhead(0)!=TOK_SCOPE) - return false; - } break; + } case TOK_GCC_IDENTIFIER: case TOK_MSC_IDENTIFIER: + { lex.get_token(tk); components.push_back(cpp_namet::namet(tk.data.get(ID_C_base_name))); set_location(components.back(), tk); - { - int t=lex.LookAhead(0); - if(t!=TOK_SCOPE && t!='<') - return false; - } + int t = lex.LookAhead(0); + if(t != TOK_SCOPE && t != '<') + return false; + break; + } case TOK_SCOPE: lex.get_token(tk); @@ -4726,10 +4725,12 @@ bool Parser::rClassMember(cpp_itemt &member) return rTypedef(member.make_declaration()); else if(t==TOK_TEMPLATE) return rTemplateDecl(member.make_declaration()); - else if(t==TOK_USING && - is_identifier(lex.LookAhead(1)) && - lex.LookAhead(2)=='=') + else if( + t == TOK_USING && is_identifier(lex.LookAhead(1)) && + lex.LookAhead(2) == '=') + { return rTypedefUsing(member.make_declaration()); + } else if(t==TOK_USING) return rUsing(member.make_using()); else if(t==TOK_STATIC_ASSERT) @@ -5583,11 +5584,10 @@ bool Parser::rTypeNameOrFunctionType(typet &tname) // TODO -- cruel hack for Clang's type_traits: // struct __member_pointer_traits_imp<_Rp (_Class::*)(_Param..., ...), // true, false> - if(is_identifier(lex.LookAhead(0)) && - lex.LookAhead(1)==TOK_SCOPE && - lex.LookAhead(2)=='*' && - lex.LookAhead(3)==')' && - lex.LookAhead(4)=='(') + if( + is_identifier(lex.LookAhead(0)) && lex.LookAhead(1) == TOK_SCOPE && + lex.LookAhead(2) == '*' && lex.LookAhead(3) == ')' && + lex.LookAhead(4) == '(') { lex.get_token(); lex.get_token(); @@ -5595,19 +5595,18 @@ bool Parser::rTypeNameOrFunctionType(typet &tname) lex.get_token(); lex.get_token(); } - else if(is_identifier(lex.LookAhead(0)) && - lex.LookAhead(1)==')' && - lex.LookAhead(2)=='(') + else if( + is_identifier(lex.LookAhead(0)) && lex.LookAhead(1) == ')' && + lex.LookAhead(2) == '(') { lex.get_token(op); type.set(ID_identifier, op.data.get(ID_C_base_name)); lex.get_token(); lex.get_token(); } - else if(lex.LookAhead(0)=='*' && - is_identifier(lex.LookAhead(1)) && - lex.LookAhead(2)==')' && - lex.LookAhead(3)=='(') + else if( + lex.LookAhead(0) == '*' && is_identifier(lex.LookAhead(1)) && + lex.LookAhead(2) == ')' && lex.LookAhead(3) == '(') { lex.get_token(op); lex.get_token(op); @@ -7075,7 +7074,7 @@ bool Parser::moreVarName() if(lex.LookAhead(0)==TOK_SCOPE) { int t=lex.LookAhead(1); - if(is_identifier(t) || t=='~' || t==TOK_OPERATOR || t==TOK_TEMPLATE) + if(is_identifier(t) || t == '~' || t == TOK_OPERATOR || t == TOK_TEMPLATE) return true; } @@ -7506,8 +7505,7 @@ optionalt Parser::rStatement() case TOK_USING: { - if(is_identifier(lex.LookAhead(1)) && - lex.LookAhead(2)=='=') + if(is_identifier(lex.LookAhead(1)) && lex.LookAhead(2) == '=') { cpp_declarationt declaration; if(!rTypedefUsing(declaration)) @@ -8238,8 +8236,9 @@ optionalt Parser::rDeclarationStatement() << "Parser::rDeclarationStatement 3 " << t << '\n'; #endif - if(cv_q.is_not_nil() && - ((is_identifier(t) && lex.LookAhead(1)=='=') || t=='*')) + if( + cv_q.is_not_nil() && + ((is_identifier(t) && lex.LookAhead(1) == '=') || t == '*')) { #ifdef DEBUG std::cout << std::string(__indent, ' ')