{"thread":{"id":"53248","subject":"Re: a problem with git diff","startedAt":"2020-04-16T16:54:51Z","lastAt":"2020-04-22T09:10:49Z","messageCount":5,"participants":["brian m. carlson","Junio C Hamano","Guy Maurel","Pratyush Yadav"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"395781","messageId":"65cbee30-fa37-1422-98f2-2c2b5aa094bd@maurel.de","threadId":"53248","inReplyTo":null,"subject":"a problem with git diff","fromName":"Guy Maurel","fromEmail":"guy.j@maurel.de","sentAt":"2020-04-16T16:43:40Z","receivedAt":"2020-04-16T16:54:51Z","isPatch":false,"sender":{"key":"guy.j@maurel.de","avatar":null},"body":"Hello!\n\nUsing the appended two files:\n  git diff combine.cpp-2020-04-16-A combine.cpp-2020-04-16-R > git-diff.diff-Y\n\ndoesn't show the same differences as with:\n  meld combine.cpp-2020-04-16-R combine.cpp-2020-04-16-A\n\nHave a look at git-diff.diff-Y at line 210:\n-static void process_returns(void)\n+static void mark_lvalue(chunk_t *pc)\n\nwhich is NOT correct.\n\nWhat is to do?\nThanks\n-- \nGuy Maurel\nSebastian-Fischer-Weg 13\n89077 Ulm\n\n\n/**\n * @file combine.cpp\n * Labels the chunks as needed.\n *\n * @author  Ben Gardner\n * @author  Guy Maurel since version 0.62 for uncrustify4Qt\n *          October 2015, 2016\n * @license GPL v2+\n */\n\n#include \"combine.h\"\n\n#include \"chunk_list.h\"\n#include \"combine_labels.h\"\n#include \"ChunkStack.h\"\n#include \"error_types.h\"\n#include \"flag_parens.h\"\n#include \"lang_pawn.h\"\n#include \"language_tools.h\"\n#include \"log_rules.h\"\n#include \"newlines.h\"\n#include \"prototypes.h\"\n#include \"tokenize_cleanup.h\"\n#include \"unc_ctype.h\"\n#include \"uncrustify.h\"\n#include \"uncrustify_types.h\"\n\n#include <cassert>\n#include <cstdio>\n#include <cstdlib>\n#include <limits>\n#include <map>\n\nusing namespace std;\nusing namespace uncrustify;\n\n\n/**\n * Mark the parens and colons in:\n *   asm volatile ( \"xx\" : \"xx\" (l), \"yy\"(h) : ...  );\n *\n * @param pc  the CT_ASM item\n */\nstatic void flag_asm(chunk_t *pc);\n\n\n/**\n * Combines two tokens into {{ and }} if inside parens and nothing is between\n * either pair.\n */\nstatic void check_double_brace_init(chunk_t *bo1);\n\n\n/**\n * We are on a typedef.\n * If the next word is not enum/union/struct, then the last word before the\n * next ',' or ';' or '__attribute__' is a type.\n *\n * typedef [type...] [*] type [, [*]type] ;\n * typedef <return type>([*]func)();\n * typedef <return type>([*]func)(params);\n * typedef <return type>(__stdcall *func)(); Bug # 633    MS-specific extension\n *                                           include the config-file \"test/config/MS-calling_conventions.cfg\"\n * typedef <return type>func(params);\n * typedef <enum/struct/union> [type] [*] type [, [*]type] ;\n * typedef <enum/struct/union> [type] { ... } [*] type [, [*]type] ;\n */\nstatic void fix_typedef(chunk_t *pc);\n\n\n/**\n * We are on an enum/struct/union tag that is NOT inside a typedef.\n * If there is a {...} and words before the ';', then they are variables.\n *\n * tag { ... } [*] word [, [*]word] ;\n * tag [word/type] { ... } [*] word [, [*]word] ;\n * enum [word/type [: int_type]] { ... } [*] word [, [*]word] ;\n * tag [word/type] [word]; -- this gets caught later.\n * fcn(tag [word/type] [word])\n * a = (tag [word/type] [*])&b;\n *\n * REVISIT: should this be consolidated with the typedef code?\n */\nstatic void fix_enum_struct_union(chunk_t *pc);\n\n\n/**\n * Checks to see if the current paren is part of a cast.\n * We already verified that this doesn't follow function, TYPE, IF, FOR,\n * SWITCH, or WHILE and is followed by WORD, TYPE, STRUCT, ENUM, or UNION.\n *\n * @param start  Pointer to the open paren\n */\nstatic void fix_casts(chunk_t *pc);\n\n\n/**\n * CT_TYPE_CAST follows this pattern:\n * dynamic_cast<...>(...)\n *\n * Mark everything between the <> as a type and set the paren parent\n */\nstatic void fix_type_cast(chunk_t *pc);\n\n\nstatic void process_returns(void);\n\n\n/**\n * Processes a return statement, labeling the parens and marking the parent.\n * May remove or add parens around the return statement\n *\n * @param pc  Pointer to the return chunk\n */\nstatic chunk_t *process_return(chunk_t *pc);\n\n\n/**\n * Process an ObjC 'class'\n * pc is the chunk after '@implementation' or '@interface' or '@protocol'.\n * Change colons, etc. Processes stuff until '@end'.\n * Skips anything in braces.\n */\nstatic void handle_oc_class(chunk_t *pc);\n\n\n/**\n *  Mark Objective-C blocks (aka lambdas or closures)\n *  The syntax and usage is exactly like C function pointers\n *  but instead of an asterisk they have a caret as pointer symbol.\n *  Although it may look expensive this functions is only triggered\n *  on appearance of an OC_BLOCK_CARET for LANG_OC.\n *  repeat(10, ^{ putc('0'+d); });\n *  typedef void (^workBlk_t)(void);\n *\n * @param pc  points to the '^'\n */\nstatic void handle_oc_block_literal(chunk_t *pc);\n\n\n/**\n * Mark Objective-C block types.\n * The syntax and usage is exactly like C function pointers\n * but instead of an asterisk they have a caret as pointer symbol.\n *  typedef void (^workBlk_t)(void);\n *  const char * (^workVar)(void);\n *  -(void)Foo:(void(^)())blk { }\n *\n * This is triggered when the sequence '(' '^' is found.\n *\n * @param pc  points to the '^'\n */\nstatic void handle_oc_block_type(chunk_t *pc);\n\n\n/**\n * Process an ObjC message spec/dec\n *\n * Specs:\n * -(void) foo ARGS;\n *\n * Declaration:\n * -(void) foo ARGS {  }\n *\n * LABEL : (ARGTYPE) ARGNAME\n *\n * ARGS is ': (ARGTYPE) ARGNAME [MOREARGS...]'\n * MOREARGS is ' [ LABEL] : (ARGTYPE) ARGNAME '\n * -(void) foo: (int) arg: {  }\n * -(void) foo: (int) arg: {  }\n * -(void) insertObject:(id)anObject atIndex:(int)index\n */\nstatic void handle_oc_message_decl(chunk_t *pc);\n\n\n/**\n * Process an ObjC message send statement:\n * [ class func: val1 name2: val2 name3: val3] ; // named params\n * [ class func: val1      : val2      : val3] ; // unnamed params\n * [ class <proto> self method ] ; // with protocol\n * [[NSMutableString alloc] initWithString: @\"\" ] // class from msg\n * [func(a,b,c) lastObject ] // class from func\n *\n * Mainly find the matching ']' and ';' and mark the colons.\n *\n * @param pc  points to the open square '['\n */\nstatic void handle_oc_message_send(chunk_t *pc);\n\n\n//! Process @Property values and re-arrange them if necessary\nstatic void handle_oc_property_decl(chunk_t *pc);\n\n//! Process @available annotation\nstatic void handle_oc_available(chunk_t *pc);\n\n/**\n * Process a type that is enclosed in parens in message declarations.\n * TODO: handle block types, which get special formatting\n *\n * @param pc  points to the open paren\n *\n * @return the chunk after the type\n */\nstatic chunk_t *handle_oc_md_type(chunk_t *paren_open, c_token_t ptype, pcf_flags_t flags, bool &did_it);\n\n/**\n * Process an C# [] thingy:\n *    [assembly: xxx]\n *    [AttributeUsage()]\n *    [@X]\n *\n * Set the next chunk to a statement start after the close ']'\n *\n * @param pc  points to the open square '['\n */\nstatic void handle_cs_square_stmt(chunk_t *pc);\n\n\n/**\n * We are on a brace open that is preceded by a word or square close.\n * Set the brace parent to CT_CS_PROPERTY and find the first item in the\n * property and set its parent, too.\n */\nstatic void handle_cs_property(chunk_t *pc);\n\n\n/**\n * We hit a ']' followed by a WORD. This may be a multidimensional array type.\n * Example: int[,,] x;\n * If there is nothing but commas between the open and close, then mark it.\n */\nstatic void handle_cs_array_type(chunk_t *pc);\n\n\n/**\n * We are on the C++ 'template' keyword.\n * What follows should be the following:\n *\n * template <class identifier> function_declaration;\n * template <typename identifier> function_declaration;\n * template <class identifier> class class_declaration;\n * template <typename identifier> class class_declaration;\n *\n * Change the 'class' inside the <> to CT_TYPE.\n * Set the parent to the class after the <> to CT_TEMPLATE.\n * Set the parent of the semicolon to CT_TEMPLATE.\n */\nstatic void handle_cpp_template(chunk_t *pc);\n\n\n/**\n * Verify and then mark C++ lambda expressions.\n * The expected format is '[...](...){...}' or '[...](...) -> type {...}'\n * sq_o is '[' CT_SQUARE_OPEN or '[]' CT_TSQUARE\n * Split the '[]' so we can control the space\n */\nstatic void handle_cpp_lambda(chunk_t *pc);\n\n\n/**\n * We are on the D 'template' keyword.\n * What follows should be the following:\n *\n * template NAME ( TYPELIST ) { BODY }\n *\n * Set the parent of NAME to template, change NAME to CT_TYPE.\n * Set the parent of the parens and braces to CT_TEMPLATE.\n * Scan the body for each type in TYPELIST and change the type to CT_TYPE.\n */\nstatic void handle_d_template(chunk_t *pc);\n\n\n/**\n * A func wrap chunk and what follows should be treated as a function name.\n * Create new text for the chunk and call it a CT_FUNCTION.\n *\n * A type wrap chunk and what follows should be treated as a simple type.\n * Create new text for the chunk and call it a CT_TYPE.\n */\nstatic void handle_wrap(chunk_t *pc);\n\n\n/**\n * A proto wrap chunk and what follows should be treated as a function proto.\n *\n * RETTYPE PROTO_WRAP( NAME, PARAMS ); or RETTYPE PROTO_WRAP( NAME, (PARAMS) );\n * RETTYPE gets changed with make_type().\n * PROTO_WRAP is marked as CT_FUNC_PROTO or CT_FUNC_DEF.\n * NAME is marked as CT_WORD.\n * PARAMS is all marked as prototype parameters.\n */\nstatic void handle_proto_wrap(chunk_t *pc);\n\n\nstatic bool is_oc_block(chunk_t *pc);\n\n\n/**\n * Java assert statements are: \"assert EXP1 [: EXP2] ;\"\n * Mark the parent of the colon and semicolon\n */\nstatic void handle_java_assert(chunk_t *pc);\n\n\nvoid flag_series(chunk_t *start, chunk_t *end, pcf_flags_t set_flags, pcf_flags_t clr_flags, scope_e nav)\n{\n   LOG_FUNC_ENTRY();\n\n   while (start != nullptr && start != end)\n   {\n      chunk_flags_upd(start, clr_flags, set_flags);\n\n      start = chunk_get_next(start, nav);\n\n      if (start == nullptr)\n      {\n         return;\n      }\n   }\n\n   if (end != nullptr)\n   {\n      chunk_flags_upd(end, clr_flags, set_flags);\n   }\n}\n\n\nstatic void flag_asm(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n\n   chunk_t *tmp = chunk_get_next_ncnl(pc, scope_e::PREPROC);\n\n   if (!chunk_is_token(tmp, CT_QUALIFIER))\n   {\n      return;\n   }\n   chunk_t *po = chunk_get_next_ncnl(tmp, scope_e::PREPROC);\n\n   if (!chunk_is_paren_open(po))\n   {\n      return;\n   }\n   chunk_t *end = chunk_skip_to_match(po, scope_e::PREPROC);\n\n   if (end == nullptr)\n   {\n      return;\n   }\n   set_chunk_parent(po, CT_ASM);\n   set_chunk_parent(end, CT_ASM);\n\n   for (  tmp = chunk_get_next_ncnl(po, scope_e::PREPROC);\n          tmp != nullptr\n       && tmp != end;\n          tmp = chunk_get_next_ncnl(tmp, scope_e::PREPROC))\n   {\n      if (chunk_is_token(tmp, CT_COLON))\n      {\n         set_chunk_type(tmp, CT_ASM_COLON);\n      }\n      else if (chunk_is_token(tmp, CT_DC_MEMBER))\n      {\n         // if there is a string on both sides, then this is two ASM_COLONs\n         if (  chunk_is_token(chunk_get_next_ncnl(tmp, scope_e::PREPROC), CT_STRING)\n            && chunk_is_token(chunk_get_prev_ncnlni(tmp, scope_e::PREPROC), CT_STRING)) // Issue #2279\n         {\n            chunk_t nc;\n\n            nc = *tmp;\n\n            tmp->str.resize(1);\n            tmp->orig_col_end = tmp->orig_col + 1;\n            set_chunk_type(tmp, CT_ASM_COLON);\n\n            set_chunk_type(&nc, tmp->type);\n            nc.str.pop_front();\n            nc.orig_col++;\n            nc.column++;\n            chunk_add_after(&nc, tmp);\n         }\n      }\n   }\n\n   tmp = chunk_get_next_ncnl(end, scope_e::PREPROC);\n\n   if (tmp == nullptr)\n   {\n      return;\n   }\n\n   if (chunk_is_token(tmp, CT_SEMICOLON))\n   {\n      set_chunk_parent(tmp, CT_ASM);\n   }\n} // flag_asm\n\n\nvoid do_symbol_check(chunk_t *prev, chunk_t *pc, chunk_t *next)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *tmp;\n\n   // separate the uses of CT_ASSIGN sign '='\n   // into CT_ASSIGN_DEFAULT_ARG, CT_ASSIGN_FUNC_PROTO\n   if (  chunk_is_token(pc, CT_ASSIGN)\n      && get_chunk_parent_type(pc) == CT_FUNC_PROTO\n      && (  pc->flags.test(PCF_IN_FCN_DEF)                            // Issue #2236\n         || pc->flags.test(PCF_IN_CONST_ARGS)))\n   {\n      LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n      log_pcf_flags(LFCNR, pc->flags);\n      set_chunk_type(pc, CT_ASSIGN_DEFAULT_ARG);\n   }\n\n   if (  (  chunk_is_token(prev, CT_FPAREN_CLOSE)\n         || (  (  chunk_is_str(prev, \"const\", 5)\n               || chunk_is_str(prev, \"override\", 8))\n            && chunk_is_token(prev->prev, CT_FPAREN_CLOSE)))\n      && chunk_is_token(pc, CT_ASSIGN)\n      && (  chunk_is_token(next, CT_DEFAULT)\n         || chunk_is_token(next, CT_DELETE)\n         || chunk_is_str(next, \"0\", 1)))\n   {\n      set_chunk_type(pc, CT_ASSIGN_FUNC_PROTO);\n   }\n\n   if (chunk_is_token(pc, CT_OC_AT))\n   {\n      if (  chunk_is_token(next, CT_PAREN_OPEN)\n         || chunk_is_token(next, CT_BRACE_OPEN)\n         || chunk_is_token(next, CT_SQUARE_OPEN))\n      {\n         flag_parens(next, PCF_OC_BOXED, next->type, CT_OC_AT, false);\n      }\n      else\n      {\n         set_chunk_parent(next, CT_OC_AT);\n      }\n   }\n\n   // D stuff\n   if (  language_is_set(LANG_D)\n      && chunk_is_token(pc, CT_QUALIFIER)\n      && chunk_is_str(pc, \"const\", 5)\n      && chunk_is_token(next, CT_PAREN_OPEN))\n   {\n      set_chunk_type(pc, CT_D_CAST);\n      set_paren_parent(next, pc->type);\n   }\n\n   if (  chunk_is_token(next, CT_PAREN_OPEN)\n      && (  chunk_is_token(pc, CT_D_CAST)\n         || chunk_is_token(pc, CT_DELEGATE)\n         || chunk_is_token(pc, CT_ALIGN)))\n   {\n      // mark the parenthesis parent\n      tmp = set_paren_parent(next, pc->type);\n\n      // For a D cast - convert the next item\n      if (  chunk_is_token(pc, CT_D_CAST)\n         && tmp != nullptr)\n      {\n         if (chunk_is_token(tmp, CT_STAR))\n         {\n            set_chunk_type(tmp, CT_DEREF);\n         }\n         else if (chunk_is_token(tmp, CT_AMP))\n         {\n            set_chunk_type(tmp, CT_ADDR);\n         }\n         else if (chunk_is_token(tmp, CT_MINUS))\n         {\n            set_chunk_type(tmp, CT_NEG);\n         }\n         else if (chunk_is_token(tmp, CT_PLUS))\n         {\n            set_chunk_type(tmp, CT_POS);\n         }\n      }\n\n      /*\n       * For a delegate, mark previous words as types and the item after the\n       * close paren as a variable def\n       */\n      if (chunk_is_token(pc, CT_DELEGATE))\n      {\n         if (tmp != nullptr)\n         {\n            set_chunk_parent(tmp, CT_DELEGATE);\n\n            if (tmp->level == tmp->brace_level)\n            {\n               chunk_flags_set(tmp, PCF_VAR_1ST_DEF);\n            }\n         }\n\n         for (tmp = chunk_get_prev_ncnlni(pc); tmp != nullptr; tmp = chunk_get_prev_ncnlni(tmp)) // Issue #2279\n         {\n            if (  chunk_is_semicolon(tmp)\n               || chunk_is_token(tmp, CT_BRACE_OPEN)\n               || chunk_is_token(tmp, CT_VBRACE_OPEN))\n            {\n               break;\n            }\n            make_type(tmp);\n         }\n      }\n\n      if (  chunk_is_token(pc, CT_ALIGN)\n         && tmp != nullptr)\n      {\n         if (chunk_is_token(tmp, CT_BRACE_OPEN))\n         {\n            set_paren_parent(tmp, pc->type);\n         }\n         else if (chunk_is_token(tmp, CT_COLON))\n         {\n            set_chunk_parent(tmp, pc->type);\n         }\n      }\n   } // paren open + cast/align/delegate\n\n   if (chunk_is_token(pc, CT_INVARIANT))\n   {\n      if (chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         set_chunk_parent(next, pc->type);\n         tmp = chunk_get_next(next);\n\n         while (tmp != nullptr)\n         {\n            if (chunk_is_token(tmp, CT_PAREN_CLOSE))\n            {\n               set_chunk_parent(tmp, pc->type);\n               break;\n            }\n            make_type(tmp);\n            tmp = chunk_get_next(tmp);\n         }\n      }\n      else\n      {\n         set_chunk_type(pc, CT_QUALIFIER);\n      }\n   }\n\n   if (  chunk_is_token(prev, CT_BRACE_OPEN)\n      && get_chunk_parent_type(prev) != CT_CS_PROPERTY\n      && (  chunk_is_token(pc, CT_GETSET)\n         || chunk_is_token(pc, CT_GETSET_EMPTY)))\n   {\n      flag_parens(prev, PCF_NONE, CT_NONE, CT_GETSET, false);\n   }\n\n   if (chunk_is_token(pc, CT_ASM))\n   {\n      flag_asm(pc);\n   }\n\n   // clang stuff - A new derived type is introduced to C and, by extension, Objective-C, C++, and Objective-C++\n   if (language_is_set(LANG_C | LANG_CPP | LANG_OC))\n   {\n      if (chunk_is_token(pc, CT_CARET))\n      {\n         if (  pc->flags.test(PCF_EXPR_START)\n            || pc->flags.test(PCF_IN_PREPROC))\n         {\n            handle_oc_block_literal(pc);\n         }\n      }\n   }\n\n   // Objective C stuff\n   if (language_is_set(LANG_OC))\n   {\n      // Check for message declarations\n      if (pc->flags.test(PCF_STMT_START))\n      {\n         if (  (  chunk_is_str(pc, \"-\", 1)\n               || chunk_is_str(pc, \"+\", 1))\n            && chunk_is_str(next, \"(\", 1))\n         {\n            handle_oc_message_decl(pc);\n         }\n      }\n\n      if (  pc->flags.test(PCF_EXPR_START)\n         || pc->flags.test(PCF_IN_PREPROC))\n      {\n         if (chunk_is_token(pc, CT_SQUARE_OPEN))\n         {\n            handle_oc_message_send(pc);\n         }\n      }\n\n      if (chunk_is_token(pc, CT_OC_PROPERTY))\n      {\n         handle_oc_property_decl(pc);\n      }\n\n      if (chunk_is_token(pc, CT_OC_AVAILABLE))\n      {\n         handle_oc_available(pc);\n      }\n   }\n\n   // C# stuff\n   if (language_is_set(LANG_CS))\n   {\n      // '[assembly: xxx]' stuff\n      if (  pc->flags.test(PCF_EXPR_START)\n         && chunk_is_token(pc, CT_SQUARE_OPEN))\n      {\n         handle_cs_square_stmt(pc);\n      }\n\n      if (  chunk_is_token(next, CT_BRACE_OPEN)\n         && get_chunk_parent_type(next) == CT_NONE\n         && (  chunk_is_token(pc, CT_SQUARE_CLOSE)\n            || chunk_is_token(pc, CT_ANGLE_CLOSE)\n            || chunk_is_token(pc, CT_WORD)))\n      {\n         handle_cs_property(next);\n      }\n\n      if (  chunk_is_token(pc, CT_SQUARE_CLOSE)\n         && chunk_is_token(next, CT_WORD))\n      {\n         handle_cs_array_type(pc);\n      }\n\n      if (  (  chunk_is_token(pc, CT_LAMBDA)\n            || chunk_is_token(pc, CT_DELEGATE))\n         && chunk_is_token(next, CT_BRACE_OPEN))\n      {\n         set_paren_parent(next, pc->type);\n      }\n\n      if (chunk_is_token(pc, CT_WHEN) && pc->next->type != CT_SPAREN_OPEN)\n      {\n         set_chunk_type(pc, CT_WORD);\n      }\n   }\n\n   if (  language_is_set(LANG_JAVA)\n      && chunk_is_token(pc, CT_LAMBDA)\n      && chunk_is_token(next, CT_BRACE_OPEN))\n   {\n      set_paren_parent(next, pc->type);\n   }\n\n   if (chunk_is_token(pc, CT_NEW))\n   {\n      chunk_t *ts = nullptr;\n      tmp = next;\n\n      if (chunk_is_token(tmp, CT_TSQUARE))\n      {\n         ts  = tmp;\n         tmp = chunk_get_next_ncnl(tmp);\n      }\n\n      if (  chunk_is_token(tmp, CT_BRACE_OPEN)\n         || chunk_is_token(tmp, CT_PAREN_OPEN))\n      {\n         set_paren_parent(tmp, pc->type);\n\n         if (ts != nullptr)\n         {\n            set_chunk_parent(ts, pc->type);\n         }\n      }\n   }\n\n   // C++11 Lambda stuff\n   if (  language_is_set(LANG_CPP)\n      && (  chunk_is_token(pc, CT_SQUARE_OPEN)\n         || chunk_is_token(pc, CT_TSQUARE)))\n   {\n      handle_cpp_lambda(pc);\n   }\n\n   // FIXME: which language does this apply to?\n   // Issue #2432\n   if (!language_is_set(LANG_OC))\n   {\n      if (  chunk_is_token(pc, CT_ASSIGN)\n         && chunk_is_token(next, CT_SQUARE_OPEN))\n      {\n         set_paren_parent(next, CT_ASSIGN);\n\n         // Mark one-liner assignment\n         tmp = next;\n\n         while ((tmp = chunk_get_next_nc(tmp)) != nullptr)\n         {\n            if (chunk_is_newline(tmp))\n            {\n               break;\n            }\n\n            if (chunk_is_token(tmp, CT_SQUARE_CLOSE) && next->level == tmp->level)\n            {\n               chunk_flags_set(tmp, PCF_ONE_LINER);\n               chunk_flags_set(next, PCF_ONE_LINER);\n               break;\n            }\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_ASSERT))\n   {\n      handle_java_assert(pc);\n   }\n\n   if (chunk_is_token(pc, CT_ANNOTATION))\n   {\n      tmp = chunk_get_next_ncnl(pc);\n\n      if (chunk_is_paren_open(tmp))\n      {\n         set_paren_parent(tmp, CT_ANNOTATION);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_SIZEOF) && language_is_set(LANG_ALLC))\n   {\n      tmp = chunk_get_next_ncnl(pc);\n\n      if (chunk_is_token(tmp, CT_ELLIPSIS))\n      {\n         set_chunk_parent(tmp, CT_SIZEOF);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_DECLTYPE))\n   {\n      tmp = chunk_get_next_ncnl(pc);\n\n      if (chunk_is_paren_open(tmp))\n      {\n         // decltype may be followed by a braced-init-list\n         tmp = set_paren_parent(tmp, CT_DECLTYPE);\n\n         if (chunk_is_opening_brace(tmp))\n         {\n            tmp = set_paren_parent(tmp, CT_BRACED_INIT_LIST);\n\n            if (tmp)\n            {\n               chunk_flags_clr(tmp, PCF_EXPR_START | PCF_STMT_START);\n            }\n         }\n         else\n         {\n            if (chunk_is_token(tmp, CT_WORD))\n            {\n               chunk_flags_set(tmp, PCF_VAR_1ST_DEF);\n            }\n         }\n      }\n   }\n\n   // A [] in C# and D only follows a type\n   if (  chunk_is_token(pc, CT_TSQUARE)\n      && language_is_set(LANG_D | LANG_CS | LANG_VALA))\n   {\n      if (chunk_is_token(prev, CT_WORD))\n      {\n         set_chunk_type(prev, CT_TYPE);\n      }\n\n      if (chunk_is_token(next, CT_WORD))\n      {\n         chunk_flags_set(next, PCF_VAR_1ST_DEF);\n      }\n   }\n\n   if (  chunk_is_token(pc, CT_SQL_EXEC)\n      || chunk_is_token(pc, CT_SQL_BEGIN)\n      || chunk_is_token(pc, CT_SQL_END))\n   {\n      mark_exec_sql(pc);\n   }\n\n   if (chunk_is_token(pc, CT_PROTO_WRAP))\n   {\n      handle_proto_wrap(pc);\n   }\n\n   // Handle the typedef\n   if (chunk_is_token(pc, CT_TYPEDEF))\n   {\n      fix_typedef(pc);\n   }\n\n   if (  chunk_is_token(pc, CT_ENUM)\n      || chunk_is_token(pc, CT_STRUCT)\n      || chunk_is_token(pc, CT_UNION)\n      || (  chunk_is_token(pc, CT_CLASS)\n         && !language_is_set(LANG_D)))\n   {\n      if (prev->type != CT_TYPEDEF)\n      {\n         fix_enum_struct_union(pc);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_EXTERN))\n   {\n      if (chunk_is_paren_open(next))\n      {\n         tmp = flag_parens(next, PCF_NONE, CT_NONE, CT_EXTERN, true);\n\n         if (chunk_is_token(tmp, CT_BRACE_OPEN))\n         {\n            set_paren_parent(tmp, CT_EXTERN);\n         }\n      }\n      else\n      {\n         // next likely is a string (see tokenize_cleanup.cpp)\n         set_chunk_parent(next, CT_EXTERN);\n         tmp = chunk_get_next_ncnl(next);\n\n         if (chunk_is_token(tmp, CT_BRACE_OPEN))\n         {\n            set_paren_parent(tmp, CT_EXTERN);\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_TEMPLATE))\n   {\n      if (language_is_set(LANG_D))\n      {\n         handle_d_template(pc);\n      }\n      else\n      {\n         handle_cpp_template(pc);\n      }\n   }\n\n   if (  chunk_is_token(pc, CT_WORD)\n      && chunk_is_token(next, CT_ANGLE_OPEN)\n      && get_chunk_parent_type(next) == CT_TEMPLATE)\n   {\n      mark_template_func(pc, next);\n   }\n\n   if (  chunk_is_token(pc, CT_SQUARE_CLOSE)\n      && chunk_is_token(next, CT_PAREN_OPEN))\n   {\n      flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_NONE, false);\n   }\n\n   if (chunk_is_token(pc, CT_TYPE_CAST))\n   {\n      fix_type_cast(pc);\n   }\n\n   if (  get_chunk_parent_type(pc) == CT_ASSIGN\n      && (chunk_is_token(pc, CT_BRACE_OPEN) || chunk_is_token(pc, CT_SQUARE_OPEN)))\n   {\n      // Mark everything in here as in assign\n      flag_parens(pc, PCF_IN_ARRAY_ASSIGN, pc->type, CT_NONE, false);\n   }\n\n   if (chunk_is_token(pc, CT_D_TEMPLATE))\n   {\n      set_paren_parent(next, pc->type);\n   }\n\n   /*\n    * A word before an open paren is a function call or definition.\n    * CT_WORD => CT_FUNC_CALL or CT_FUNC_DEF\n    */\n   if (chunk_is_token(next, CT_PAREN_OPEN))\n   {\n      tmp = chunk_get_next_ncnl(next);\n\n      if (  language_is_set(LANG_C | LANG_CPP | LANG_OC)\n         && chunk_is_token(tmp, CT_CARET))\n      {\n         handle_oc_block_type(tmp);\n\n         // This is the case where a block literal is passed as the first argument of a C-style method invocation.\n         if (  (  chunk_is_token(tmp, CT_OC_BLOCK_CARET)\n               || chunk_is_token(tmp, CT_CARET))\n            && chunk_is_token(pc, CT_WORD))\n         {\n            LOG_FMT(LFCN, \"%s(%d): (1) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n                    __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n            set_chunk_type(pc, CT_FUNC_CALL);\n         }\n      }\n      else if (  chunk_is_token(pc, CT_WORD)\n              || chunk_is_token(pc, CT_OPERATOR_VAL))\n      {\n         set_chunk_type(pc, CT_FUNCTION);\n      }\n      else if (chunk_is_token(pc, CT_FIXED))\n      {\n         set_chunk_type(pc, CT_FUNCTION);\n         set_chunk_parent(pc, CT_FIXED);\n      }\n      else if (chunk_is_token(pc, CT_TYPE))\n      {\n         /*\n          * If we are on a type, then we are either on a C++ style cast, an\n          * array reference, a function or we are on a function type.\n          * The only way to tell for sure is to find the close paren and see\n          * if it is followed by an open paren.\n          * \"int(5.6)\"\n          * \"int()\"\n          * \"int(foo)(void)\"\n          *\n          * FIXME: this check can be done better...\n          */\n         LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n\n         bool is_byref_array = false;\n\n         if (language_is_set(LANG_CPP))\n         {\n            // If the open paren is followed by an ampersand, an optional word,\n            // a close parenthesis, and an open square bracket, then it is an\n            // array being passed by reference, not a cast\n            tmp = chunk_get_next_ncnl(next);\n\n            if (chunk_is_token(tmp, CT_AMP))\n            {\n               auto tmp2 = chunk_get_next_ncnl(tmp);\n\n               if (chunk_is_token(tmp2, CT_WORD))\n               {\n                  tmp2 = chunk_get_next_ncnl(tmp2);\n               }\n\n               if (chunk_is_token(tmp2, CT_PAREN_CLOSE))\n               {\n                  tmp2 = chunk_get_next_ncnl(tmp2);\n\n                  if (chunk_is_token(tmp2, CT_SQUARE_OPEN))\n                  {\n                     is_byref_array = true;\n                     set_chunk_type(tmp, CT_BYREF);\n                  }\n               }\n            }\n         }\n\n         if (!is_byref_array)\n         {\n            tmp = chunk_get_next_type(next, CT_PAREN_CLOSE, next->level);\n\n            if (tmp != nullptr)\n            {\n               tmp = chunk_get_next(tmp);\n\n               if (chunk_is_token(tmp, CT_PAREN_OPEN))\n               {\n                  set_chunk_type(pc, CT_FUNCTION);\n               }\n               else\n               {\n                  if (  get_chunk_parent_type(pc) == CT_NONE\n                     && !pc->flags.test(PCF_IN_TYPEDEF))\n                  {\n                     tmp = chunk_get_next_ncnl(next);\n\n                     if (chunk_is_token(tmp, CT_PAREN_CLOSE))\n                     {\n                        // we have TYPE()\n                        set_chunk_type(pc, CT_FUNCTION);\n                     }\n                     else\n                     {\n                        // we have TYPE(...)\n                        set_chunk_type(pc, CT_CPP_CAST);\n                        set_paren_parent(next, CT_CPP_CAST);\n                     }\n                  }\n               }\n            }\n         }\n      }\n   }\n\n   if (language_is_set(LANG_PAWN))\n   {\n      if (  chunk_is_token(pc, CT_FUNCTION)\n         && pc->brace_level > 0)\n      {\n         LOG_FMT(LFCN, \"%s(%d): (2) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n         set_chunk_type(pc, CT_FUNC_CALL);\n      }\n\n      if (  chunk_is_token(pc, CT_STATE)\n         && chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         set_paren_parent(next, pc->type);\n      }\n   }\n   else\n   {\n      if (  (  chunk_is_token(pc, CT_FUNCTION)\n            || chunk_is_token(pc, CT_FUNC_DEF))\n         && (  (get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR)\n            || !is_oc_block(pc)))\n      {\n         mark_function(pc);\n      }\n   }\n\n   // Detect C99 member stuff\n   if (  chunk_is_token(pc, CT_MEMBER)\n      && (  chunk_is_token(prev, CT_COMMA)\n         || chunk_is_token(prev, CT_BRACE_OPEN)))\n   {\n      set_chunk_type(pc, CT_C99_MEMBER);\n      set_chunk_parent(next, CT_C99_MEMBER);\n   }\n\n   // Mark function parens and braces\n   if (  chunk_is_token(pc, CT_FUNC_DEF)\n      || chunk_is_token(pc, CT_FUNC_CALL)\n      || chunk_is_token(pc, CT_FUNC_CALL_USER)\n      || chunk_is_token(pc, CT_FUNC_PROTO))\n   {\n      tmp = next;\n\n      if (chunk_is_token(tmp, CT_SQUARE_OPEN))\n      {\n         tmp = set_paren_parent(tmp, pc->type);\n      }\n      else if (chunk_is_token(tmp, CT_TSQUARE) || get_chunk_parent_type(tmp) == CT_OPERATOR)\n      {\n         tmp = chunk_get_next_ncnl(tmp);\n      }\n\n      if (tmp != nullptr)\n      {\n         if (chunk_is_paren_open(tmp))\n         {\n            tmp = flag_parens(tmp, PCF_NONE, CT_FPAREN_OPEN, pc->type, false);\n\n            if (tmp != nullptr)\n            {\n               if (chunk_is_token(tmp, CT_BRACE_OPEN))\n               {\n                  if (  get_chunk_parent_type(tmp) != CT_DOUBLE_BRACE\n                     && !pc->flags.test(PCF_IN_CONST_ARGS))\n                  {\n                     set_paren_parent(tmp, pc->type);\n                  }\n               }\n               else if (  chunk_is_semicolon(tmp)\n                       && chunk_is_token(pc, CT_FUNC_PROTO))\n               {\n                  set_chunk_parent(tmp, pc->type);\n               }\n            }\n         }\n      }\n   }\n\n   // Mark the parameters in catch()\n   if (chunk_is_token(pc, CT_CATCH) && chunk_is_token(next, CT_SPAREN_OPEN))\n   {\n      fix_fcn_def_params(next);\n   }\n\n   if (chunk_is_token(pc, CT_THROW) && chunk_is_token(prev, CT_FPAREN_CLOSE))\n   {\n      set_chunk_parent(pc, get_chunk_parent_type(prev));\n\n      if (chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         set_paren_parent(next, CT_THROW);\n      }\n   }\n\n   // Mark the braces in: \"for_each_entry(xxx) { }\"\n   if (  chunk_is_token(pc, CT_BRACE_OPEN)\n      && get_chunk_parent_type(pc) != CT_DOUBLE_BRACE\n      && chunk_is_token(prev, CT_FPAREN_CLOSE)\n      && (  get_chunk_parent_type(prev) == CT_FUNC_CALL\n         || get_chunk_parent_type(prev) == CT_FUNC_CALL_USER)\n      && !pc->flags.test(PCF_IN_CONST_ARGS))\n   {\n      LOG_FMT(LFCN, \"%s(%d): (3) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n      set_paren_parent(pc, CT_FUNC_CALL);\n   }\n\n   /*\n    * Check for a close parenthesis followed by an open parenthesis,\n    * which means that we are on a function type declaration (C/C++ only?).\n    * Note that typedefs are already taken care of.\n    */\n   if (  !pc->flags.test_any(PCF_IN_TYPEDEF | PCF_IN_TEMPLATE)\n      && get_chunk_parent_type(pc) != CT_CPP_CAST\n      && get_chunk_parent_type(pc) != CT_C_CAST\n      && !pc->flags.test(PCF_IN_PREPROC)\n      && !is_oc_block(pc)\n      && get_chunk_parent_type(pc) != CT_OC_MSG_DECL\n      && get_chunk_parent_type(pc) != CT_OC_MSG_SPEC\n      && chunk_is_str(pc, \")\", 1)\n      && chunk_is_str(next, \"(\", 1))\n   {\n      if (language_is_set(LANG_D))\n      {\n         flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_FUNC_CALL, false);\n      }\n      else\n      {\n         mark_function_type(pc);\n      }\n   }\n\n   if (  (chunk_is_token(pc, CT_CLASS) || chunk_is_token(pc, CT_STRUCT))\n      && pc->level == pc->brace_level)\n   {\n      if (pc->type != CT_STRUCT || !language_is_set(LANG_C))\n      {\n         mark_class_ctor(pc);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_OC_CLASS))\n   {\n      handle_oc_class(pc);\n   }\n   // TODO: Check for stuff that can only occur at the start of an statement\n\n   if (!language_is_set(LANG_D))\n   {\n      /*\n       * Check a parenthesis pair to see if it is a cast.\n       * Note that SPAREN and FPAREN have already been marked.\n       */\n      if (  chunk_is_token(pc, CT_PAREN_OPEN)\n         && (  get_chunk_parent_type(pc) == CT_NONE\n            || get_chunk_parent_type(pc) == CT_OC_MSG\n            || get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR\n            || get_chunk_parent_type(pc) == CT_CS_SQ_STMT)           // Issue # 1256\n         && (  chunk_is_token(next, CT_WORD)\n            || chunk_is_token(next, CT_TYPE)\n            || chunk_is_token(next, CT_STRUCT)\n            || chunk_is_token(next, CT_QUALIFIER)\n            || chunk_is_token(next, CT_MEMBER)\n            || chunk_is_token(next, CT_DC_MEMBER)\n            || chunk_is_token(next, CT_ENUM)\n            || chunk_is_token(next, CT_UNION))\n         && prev->type != CT_DECLTYPE\n         && prev->type != CT_SIZEOF\n         && get_chunk_parent_type(prev) != CT_SIZEOF\n         && get_chunk_parent_type(prev) != CT_OPERATOR\n         && !pc->flags.test(PCF_IN_TYPEDEF))\n      {\n         fix_casts(pc);\n      }\n   }\n\n   if (language_is_set(LANG_CPP))\n   {\n      chunk_t *nnext = chunk_get_next_ncnl(next);\n\n      // handle parent_type of assigns in special functions (ro5 + pure virtual)\n      if (  pc->flags.test_any(PCF_IN_STRUCT | PCF_IN_CLASS)\n         && chunk_is_token(pc, CT_ASSIGN)\n         && chunk_is_token(nnext, CT_SEMICOLON)\n         && (  chunk_is_token(next, CT_DEFAULT)\n            || chunk_is_token(next, CT_DELETE)\n            || (chunk_is_token(next, CT_NUMBER) && chunk_is_str(next, \"0\", 1))))\n      {\n         const size_t level        = pc->level;\n         bool         found_status = false;\n         chunk_t      *pprev       = chunk_get_prev(pc);\n\n         for ( ; (  pprev != nullptr\n                 && pprev->level >= level\n                 && pprev->type != CT_SEMICOLON\n                 && pprev->type != CT_ACCESS_COLON)\n               ; pprev = chunk_get_prev(pprev))\n         {\n            if (pprev->level != level)\n            {\n               continue;\n            }\n\n            if (chunk_is_token(next, CT_NUMBER))\n            {\n               if (  pprev->type == CT_QUALIFIER\n                  && chunk_is_str(pprev, \"virtual\", 7))\n               {\n                  found_status = true;\n                  break;\n               }\n            }\n            else\n            {\n               if (  pprev->type == CT_FUNC_CLASS_PROTO  // ctor/dtor\n                  || pprev->type == CT_FUNC_PROTO)       // normal function\n               {\n                  found_status = true;\n                  break;\n               }\n            }\n         }\n\n         if (found_status)\n         {\n            set_chunk_parent(pc, pprev->type);\n         }\n      }\n      // Issue #2332\n      bool we_have_a_case_before = false;\n\n      if (chunk_is_token(pc, CT_COLON))\n      {\n         // check if we have a case before\n         chunk_t *switch_before = chunk_get_prev_type(pc, CT_CASE, pc->level);\n\n         if (switch_before != nullptr)\n         {\n            LOG_FMT(LFCNR, \"%s(%d): switch_before->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n                    __func__, __LINE__, switch_before->orig_line, switch_before->orig_col,\n                    switch_before->text(), get_token_name(switch_before->type));\n            we_have_a_case_before = true;\n         }\n      }\n\n      // Detect a braced-init-list\n      if (  chunk_is_token(pc, CT_WORD)\n         || chunk_is_token(pc, CT_TYPE)\n         || chunk_is_token(pc, CT_ASSIGN)\n         || chunk_is_token(pc, CT_RETURN)\n         || chunk_is_token(pc, CT_COMMA)\n         || chunk_is_token(pc, CT_ANGLE_CLOSE)\n         || chunk_is_token(pc, CT_SQUARE_CLOSE)\n         || chunk_is_token(pc, CT_TSQUARE)\n         || chunk_is_token(pc, CT_FPAREN_OPEN)\n         || chunk_is_token(pc, CT_QUESTION)\n         || (  chunk_is_token(pc, CT_COLON)\n            && !we_have_a_case_before)\n         || (  chunk_is_token(pc, CT_BRACE_OPEN)\n            && (  get_chunk_parent_type(pc) == CT_NONE\n               || get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST)))\n      {\n         log_pcf_flags(LFCNR, pc->flags);\n         auto brace_open = chunk_get_next_ncnl(pc);\n\n         if (  chunk_is_token(brace_open, CT_BRACE_OPEN)\n            && (  get_chunk_parent_type(brace_open) == CT_NONE\n               || get_chunk_parent_type(brace_open) == CT_ASSIGN\n               || get_chunk_parent_type(brace_open) == CT_RETURN\n               || get_chunk_parent_type(brace_open) == CT_BRACED_INIT_LIST))\n         {\n            log_pcf_flags(LFCNR, brace_open->flags);\n            auto brace_close = chunk_skip_to_match(next);\n\n            if (chunk_is_token(brace_close, CT_BRACE_CLOSE))\n            {\n               set_chunk_parent(brace_open, CT_BRACED_INIT_LIST);\n               set_chunk_parent(brace_close, CT_BRACED_INIT_LIST);\n\n               tmp = chunk_get_next_ncnl(brace_close);\n\n               if (tmp)\n               {\n                  chunk_flags_clr(tmp, PCF_EXPR_START | PCF_STMT_START);\n               }\n               // TODO: Change pc->type CT_WORD -> CT_TYPE\n               // for the case CT_ASSIGN (and others).\n\n               // TODO: Move this block to the fix_fcn_call_args function.\n               if (chunk_is_token(pc, CT_WORD) && pc->flags.test(PCF_IN_FCN_CALL))\n               {\n                  set_chunk_type(pc, CT_TYPE);\n               }\n            }\n         }\n      }\n   }\n\n   // Check for stuff that can only occur at the start of an expression\n   if (  pc->flags.test(PCF_EXPR_START)\n      || (prev->flags.test(PCF_EXPR_START) && get_chunk_parent_type(pc) == CT_OC_AT))\n   {\n      // Change STAR, MINUS, and PLUS in the easy cases\n      if (chunk_is_token(pc, CT_STAR))\n      {\n         // issue #596\n         // [0x100062020:IN_SPAREN,IN_FOR,STMT_START,EXPR_START,PUNCTUATOR]\n         // prev->type is CT_COLON ==> CT_DEREF\n         if (chunk_is_token(prev, CT_ANGLE_CLOSE))\n         {\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (chunk_is_token(prev, CT_COLON))\n         {\n            set_chunk_type(pc, CT_DEREF);\n         }\n         else\n         {\n            set_chunk_type(pc, CT_DEREF);\n         }\n      }\n\n      if (  language_is_set(LANG_CPP)\n         && chunk_is_token(pc, CT_CARET)\n         && chunk_is_token(prev, CT_ANGLE_CLOSE))\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n\n      if (  language_is_set(LANG_CS)\n         && (chunk_is_token(pc, CT_QUESTION))\n         && (chunk_is_token(prev, CT_ANGLE_CLOSE)))\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n\n      if (chunk_is_token(pc, CT_MINUS))\n      {\n         set_chunk_type(pc, CT_NEG);\n      }\n\n      if (chunk_is_token(pc, CT_PLUS))\n      {\n         set_chunk_type(pc, CT_POS);\n      }\n\n      if (chunk_is_token(pc, CT_INCDEC_AFTER))\n      {\n         set_chunk_type(pc, CT_INCDEC_BEFORE);\n      }\n\n      if (chunk_is_token(pc, CT_AMP))\n      {\n         if (chunk_is_token(prev, CT_ANGLE_CLOSE))             // Issue #2324\n         {\n            set_chunk_type(pc, CT_BYREF);\n         }\n         else\n         {\n            set_chunk_type(pc, CT_ADDR);\n         }\n      }\n\n      if (chunk_is_token(pc, CT_CARET))\n      {\n         if (language_is_set(LANG_C | LANG_CPP | LANG_OC))\n         {\n            // This is likely the start of a block literal\n            handle_oc_block_literal(pc);\n         }\n      }\n   }\n\n   // Detect a variable definition that starts with struct/enum/union/class\n   if (  !pc->flags.test(PCF_IN_TYPEDEF)\n      && get_chunk_parent_type(prev) != CT_CPP_CAST\n      && !prev->flags.test(PCF_IN_FCN_DEF)\n      && (  chunk_is_token(pc, CT_STRUCT)\n         || chunk_is_token(pc, CT_UNION)\n         || chunk_is_token(pc, CT_CLASS)\n         || chunk_is_token(pc, CT_ENUM)))\n   {\n      tmp = chunk_skip_dc_member(next);\n\n      if ((chunk_is_token(tmp, CT_TYPE) || chunk_is_token(tmp, CT_WORD)))\n      {\n         set_chunk_parent(tmp, pc->type);\n         set_chunk_type(tmp, CT_TYPE);\n\n         tmp = chunk_get_next_ncnl(tmp);\n      }\n\n      if (chunk_is_token(tmp, CT_BRACE_OPEN))\n      {\n         tmp = chunk_skip_to_match(tmp);\n\n         if (tmp != nullptr)\n         {\n            tmp = chunk_get_next_ncnl(tmp);\n         }\n      }\n\n      if (  tmp != nullptr\n         && (chunk_is_ptr_operator(tmp) || chunk_is_token(tmp, CT_WORD)))\n      {\n         mark_variable_definition(tmp);\n      }\n   }\n\n   /*\n    * Change the parenthesis pair after a function/macro-function\n    * CT_PAREN_OPEN => CT_FPAREN_OPEN\n    */\n   if (chunk_is_token(pc, CT_MACRO_FUNC))\n   {\n      flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_MACRO_FUNC, false);\n   }\n\n   if (  chunk_is_token(pc, CT_MACRO_OPEN)\n      || chunk_is_token(pc, CT_MACRO_ELSE)\n      || chunk_is_token(pc, CT_MACRO_CLOSE))\n   {\n      if (chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, pc->type, false);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_DELETE) && chunk_is_token(next, CT_TSQUARE))\n   {\n      set_chunk_parent(next, CT_DELETE);\n   }\n\n   // Change CT_STAR to CT_PTR_TYPE or CT_ARITH or CT_DEREF\n   if (  chunk_is_token(pc, CT_STAR)\n      || (language_is_set(LANG_CPP) && chunk_is_token(pc, CT_CARET)))\n   {\n      if (chunk_is_paren_close(next) || chunk_is_token(next, CT_COMMA))\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n      else if (language_is_set(LANG_OC) && chunk_is_token(next, CT_STAR))\n      {\n         /*\n          * Change pointer-to-pointer types in OC_MSG_DECLs\n          * from ARITH <===> DEREF to PTR_TYPE <===> PTR_TYPE\n          */\n         set_chunk_type(pc, CT_PTR_TYPE);\n         set_chunk_parent(pc, get_chunk_parent_type(prev));\n\n         set_chunk_type(next, CT_PTR_TYPE);\n         set_chunk_parent(next, get_chunk_parent_type(pc));\n      }\n      else if (  chunk_is_token(pc, CT_STAR)\n              && (  chunk_is_token(prev, CT_DECLTYPE)\n                 || chunk_is_token(prev, CT_SIZEOF)\n                 || chunk_is_token(prev, CT_DELETE)\n                 || (pc && get_chunk_parent_type(pc) == CT_SIZEOF)))\n      {\n         set_chunk_type(pc, CT_DEREF);\n      }\n      else if (  (  chunk_is_token(prev, CT_WORD)\n                 && chunk_ends_type(prev)\n                 && !prev->flags.test(PCF_IN_FCN_CTOR))\n              || chunk_is_token(prev, CT_DC_MEMBER)\n              || chunk_is_token(prev, CT_PTR_TYPE))\n      {\n         LOG_FMT(LFCNR, \"%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\\n   \",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type));\n         log_pcf_flags(LFCNR, pc->flags);\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n      else if (chunk_is_token(next, CT_SQUARE_OPEN) && !language_is_set(LANG_OC))  // issue # 408\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n      else if (chunk_is_token(pc, CT_STAR))\n      {\n         // Add check for CT_DC_MEMBER CT_WORD CT_STAR sequence\n         // to convert CT_WORD into CT_TYPE\n         // and CT_STAR into CT_PTR_TYPE\n         // look for an assign backward to distinguish between\n         //    double result = Constants::PI * factor;\n         // and\n         //    ::some::name * foo;\n         if (  chunk_is_token(prev, CT_WORD)\n            && chunk_is_token(prev->prev, CT_DC_MEMBER)\n            && language_is_set(LANG_CPP))\n         {\n            // Issue 1402\n            bool assign_found = false;\n            tmp = pc;\n\n            while (tmp != nullptr)\n            {\n               if (chunk_is_token(tmp, CT_SEMICOLON))\n               {\n                  break;\n               }\n               else if (chunk_is_token(tmp, CT_ASSIGN))\n               {\n                  assign_found = true;\n                  break;\n               }\n               tmp = chunk_get_prev_ncnlni(tmp); // Issue #2279\n            }\n\n            if (assign_found)\n            {\n               // double result = Constants::PI * factor;\n               set_chunk_type(pc, CT_ARITH);\n            }\n            else\n            {\n               //    ::some::name * foo;\n               set_chunk_type(prev, CT_TYPE);\n               set_chunk_type(pc, CT_PTR_TYPE);\n            }\n         }\n\n         /*\n          * A star can have three meanings\n          * 1. CT_DEREF    = pointer dereferencing\n          * 2. CT_PTR_TYPE = pointer definition\n          * 3. CT_ARITH    = arithmetic multiplication\n          *\n          * most PCF_PUNCTUATOR chunks except a paren close would make this\n          * a deref. A paren close may end a cast or may be part of a macro fcn.\n          */\n         if (chunk_is_token(prev, CT_TYPE))\n         {\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (  chunk_is_token(pc->next, CT_SEMICOLON)      // Issue #2319\n                 || (  chunk_is_token(pc->next, CT_STAR)\n                    && chunk_is_token(pc->next->next, CT_SEMICOLON)))\n         {\n            // example:\n            //    using AbstractLinkPtr = AbstractLink*;\n            //    using AbstractLinkPtrPtr = AbstractLink**;\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (  (  get_chunk_parent_type(pc) == CT_FUNC_DEF\n                    && (chunk_is_opening_brace(next) || chunk_is_star(pc->next)))\n                 || (next->type == CT_QUALIFIER))               // Issue #2648\n         {\n            // example:\n            // auto getComponent(Color *color) -> Component * {\n            // auto getComponent(Color *color) -> Component ** {\n            // auto getComponent(Color *color) -> Component * _Nonnull\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (  chunk_is_token(pc->next, CT_SEMICOLON)      // Issue #2319\n                 || (  chunk_is_token(pc->next, CT_STAR)\n                    && chunk_is_token(pc->next->next, CT_STAR)))\n         {\n            // more pointers are NOT yet possible\n            fprintf(stderr, \"Too many pointers\\n\");\n            fprintf(stderr, \"at line %zu, column %zu.\\n\", pc->orig_line, pc->orig_col);\n            fprintf(stderr, \"Please make a report.\\n\");\n            log_flush(true);\n            exit(EX_SOFTWARE);\n         }\n         else\n         {\n            // Issue 1402\n            set_chunk_type(pc,\n                           (  prev->flags.test(PCF_PUNCTUATOR)\n                           && (  !chunk_is_paren_close(prev)\n                              || chunk_is_token(prev, CT_SPAREN_CLOSE)\n                              || get_chunk_parent_type(prev) == CT_MACRO_FUNC)\n                           && prev->type != CT_SQUARE_CLOSE\n                           && prev->type != CT_DC_MEMBER) ? CT_DEREF : CT_ARITH);\n         }\n\n         if (pc->flags.test(PCF_IN_TYPEDEF))  // Issue #1255/#633\n         {\n            tmp = pc;\n\n            while (tmp != nullptr)\n            {\n               if (  chunk_is_token(tmp, CT_SEMICOLON)\n                  || chunk_is_token(tmp, CT_BRACE_OPEN))\n               {\n                  break;\n               }\n               else if (chunk_is_token(tmp, CT_TYPEDEF))\n               {\n                  set_chunk_type(pc, CT_PTR_TYPE);\n               }\n               tmp = chunk_get_prev_ncnlni(tmp); // Issue #2279\n            }\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_AMP))\n   {\n      if (chunk_is_token(prev, CT_DELETE))\n      {\n         set_chunk_type(pc, CT_ADDR);\n      }\n      else if (chunk_is_token(prev, CT_TYPE))\n      {\n         set_chunk_type(pc, CT_BYREF);\n      }\n      else if (chunk_is_token(next, CT_FPAREN_CLOSE) || chunk_is_token(next, CT_COMMA))\n      {\n         // fix the bug #654\n         // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &)));\n         set_chunk_type(pc, CT_BYREF);\n      }\n      else if (get_chunk_parent_type(pc) == CT_USING_ALIAS)\n      {\n         // fix the Issue # 1689\n         // using reference = value_type &;\n         set_chunk_type(pc->prev, CT_TYPE);\n         set_chunk_type(pc, CT_BYREF);\n      }\n      else\n      {\n         // Issue # 1398\n         if (  pc->flags.test(PCF_IN_FCN_DEF)\n            && chunk_is_token(prev, CT_WORD)\n            && chunk_is_token(pc, CT_AMP)\n            && chunk_is_token(next, CT_WORD))\n         {\n            /*\n             * Change CT_WORD before CT_AMP before CT_WORD to CT_TYPE\n             */\n            set_chunk_type(prev, CT_TYPE);\n         }\n         else\n         {\n            set_chunk_type(pc, CT_ARITH);\n\n            if (chunk_is_token(prev, CT_WORD))\n            {\n               tmp = chunk_get_prev_ncnlni(prev); // Issue #2279\n\n               if (tmp != nullptr)\n               {\n                  if (  chunk_is_semicolon(tmp)\n                     || chunk_is_token(tmp, CT_BRACE_OPEN)\n                     || chunk_is_token(tmp, CT_QUALIFIER))\n                  {\n                     set_chunk_type(pc, CT_BYREF);\n                     set_chunk_type(prev, CT_TYPE);\n\n                     if (!(  chunk_is_token(next, CT_OPERATOR)\n                          || chunk_is_token(next, CT_TYPE)\n                          || chunk_is_token(next, CT_DC_MEMBER)))\n                     {\n                        LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', set PCF_VAR_1ST\\n\",\n                                __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n                        chunk_flags_set(next, PCF_VAR_1ST);\n                     }\n                  }\n                  else if (chunk_is_token(tmp, CT_DC_MEMBER))\n                  {\n                     set_chunk_type(prev, CT_TYPE);\n\n                     if (!chunk_is_token(next, CT_TYPE))            // Issue #2103\n                     {\n                        set_chunk_type(pc, CT_BYREF);\n                     }\n                  }\n               }\n            }\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_MINUS) || chunk_is_token(pc, CT_PLUS))\n   {\n      if (  chunk_is_token(prev, CT_POS)\n         || chunk_is_token(prev, CT_NEG)\n         || chunk_is_token(prev, CT_ARITH))\n      {\n         set_chunk_type(pc, (pc->type == CT_MINUS) ? CT_NEG : CT_POS);\n      }\n      else if (chunk_is_token(prev, CT_OC_CLASS))\n      {\n         set_chunk_type(pc, (chunk_is_token(pc, CT_MINUS)) ? CT_NEG : CT_POS);\n      }\n      else\n      {\n         set_chunk_type(pc, CT_ARITH);\n      }\n   }\n\n   /*\n    * Bug # 634\n    * Check for extern \"C\" NSString* i;\n    * NSString is a type\n    * change CT_WORD => CT_TYPE     for pc\n    * change CT_STAR => CT_PTR_TYPE for pc-next\n    */\n   if (chunk_is_token(pc, CT_WORD))     // here NSString\n   {\n      if (pc->next != nullptr)          // here *\n      {\n         if (pc->next->type == CT_STAR) // here *\n         {\n            // compare text with \"C\" to find extern \"C\" instructions\n            if (pc->prev != nullptr)\n            {\n               if (pc->prev->type == CT_STRING)\n               {\n                  if (unc_text::compare(pc->prev->text(), \"\\\"C\\\"\") == 0)\n                  {\n                     if (pc->prev->prev->type == CT_EXTERN)\n                     {\n                        set_chunk_type(pc, CT_TYPE);            // change CT_WORD => CT_TYPE\n                        set_chunk_type(pc->next, CT_PTR_TYPE);  // change CT_STAR => CT_PTR_TYPE\n                     }\n                  }\n               }\n            }\n\n            // Issue #322 STDMETHOD(GetValues)(BSTR bsName, REFDATA** pData);\n            if (  (pc->next->next != nullptr)\n               && pc->next->next->type == CT_STAR\n               && pc->flags.test(PCF_IN_CONST_ARGS))\n            {\n               // change CT_STAR => CT_PTR_TYPE\n               set_chunk_type(pc->next, CT_PTR_TYPE);\n               set_chunk_type(pc->next->next, CT_PTR_TYPE);\n            }\n\n            // Issue #222 whatever3 *(func_ptr)( whatever4 *foo2, ...\n            if (  (pc->next->next != nullptr)\n               && pc->next->next->type == CT_WORD\n               && pc->flags.test(PCF_IN_FCN_DEF))\n            {\n               // look for the opening parenthesis\n               // Issue 1403\n               tmp = chunk_get_prev_type(pc, CT_FPAREN_OPEN, pc->level - 1);\n\n               if (  tmp != nullptr\n                  && get_chunk_parent_type(tmp) != CT_FUNC_CTOR_VAR)\n               {\n                  set_chunk_type(pc->next, CT_PTR_TYPE);\n               }\n            }\n         }\n      }\n   }\n\n   /*\n    * Bug # 634\n    * Check for __attribute__((visibility (\"default\"))) NSString* i;\n    * NSString is a type\n    * change CT_WORD => CT_TYPE     for pc\n    * change CT_STAR => CT_PTR_TYPE for pc-next\n    */\n   if (chunk_is_token(pc, CT_WORD))     // here NSString\n   {\n      if (pc->next != nullptr)          // here *\n      {\n         if (pc->next->type == CT_STAR) // here *\n         {\n            tmp = pc;\n\n            while ((tmp != nullptr))\n            {\n               if (chunk_is_token(tmp, CT_ATTRIBUTE))\n               {\n                  LOG_FMT(LFCNR, \"%s(%d): ATTRIBUTE found, type is %s, text() '%s'\\n\",\n                          __func__, __LINE__, get_token_name(tmp->type), tmp->text());\n                  LOG_FMT(LFCNR, \"for token, type is %s, text() '%s'\\n\", get_token_name(pc->type), pc->text());\n                  // change CT_WORD => CT_TYPE\n                  set_chunk_type(pc, CT_TYPE);\n                  // change CT_STAR => CT_PTR_TYPE\n                  set_chunk_type(pc->next, CT_PTR_TYPE);\n               }\n\n               if (tmp->flags.test(PCF_STMT_START))\n               {\n                  // we are at beginning of the line\n                  break;\n               }\n               tmp = chunk_get_prev(tmp);\n            }\n         }\n      }\n   }\n\n   /*\n    * Issue # 1689\n    * Check for using reference = value_type&;\n    * is it a Type alias, alias template?\n    */\n   if (chunk_is_token(pc, CT_USING))\n   {\n      // look for CT_ASSIGN before CT_SEMICOLON at the end of the statement\n      bool    assign_found = false;\n      bool    is_preproc   = pc->flags.test(PCF_IN_PREPROC);\n      chunk_t *temp;\n\n      for (temp = pc; temp != nullptr; temp = chunk_get_next_ncnl(temp))\n      {\n         LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', type is %s\\n\",\n                 __func__, __LINE__, temp->orig_line, temp->orig_col, temp->text(), get_token_name(temp->type));\n\n         if (chunk_is_token(temp, CT_ASSIGN))\n         {\n            assign_found = true;\n            break;\n         }\n\n         if (  chunk_is_token(temp, CT_SEMICOLON)\n            || (  is_preproc\n               && (  !temp->flags.test(PCF_IN_PREPROC)\n                  || chunk_is_token(temp, CT_PREPROC))))\n         {\n            break;\n         }\n      }\n\n      if (assign_found)\n      {\n         // it is a Type alias, alias template\n         for (temp = pc; temp != nullptr; temp = chunk_get_next_ncnl(temp))\n         {\n            if (get_chunk_parent_type(temp) == CT_NONE)\n            {\n               set_chunk_parent(temp, CT_USING_ALIAS);\n            }\n\n            if (  chunk_is_token(temp, CT_SEMICOLON)\n               || (  is_preproc\n                  && (  !temp->flags.test(PCF_IN_PREPROC)\n                     || chunk_is_token(temp, CT_PREPROC))))\n            {\n               break;\n            }\n         }\n      }\n   }\n\n   // Issue #548: inline T && someFunc(foo * *p, bar && q) { }\n   if (  pc->type == CT_BOOL\n      && !pc->flags.test(PCF_IN_PREPROC)\n      && chunk_is_str(pc, \"&&\", 2)\n      && chunk_ends_type(pc->prev))\n   {\n      set_chunk_type(pc, CT_BYREF);\n   }\n\n   // Issue #1704\n   if (  chunk_is_token(pc, CT_INCDEC_AFTER)\n      && pc->flags.test(PCF_IN_PREPROC))\n   {\n      chunk_t *tmp_2 = chunk_get_next(pc);\n      log_pcf_flags(LFTYPE, pc->flags);\n\n      if (chunk_is_token(tmp_2, CT_WORD))\n      {\n         set_chunk_type(pc, CT_INCDEC_BEFORE);\n      }\n   }\n} // do_symbol_check\n\n\nstatic void check_double_brace_init(chunk_t *bo1)\n{\n   LOG_FUNC_ENTRY();\n   LOG_FMT(LJDBI, \"%s(%d): orig_line is %zu, orig_col is %zu\", __func__, __LINE__, bo1->orig_line, bo1->orig_col);\n   chunk_t *pc = chunk_get_prev_ncnlni(bo1);   // Issue #2279\n\n   if (pc == nullptr)\n   {\n      return;\n   }\n\n   if (chunk_is_paren_close(pc))\n   {\n      chunk_t *bo2 = chunk_get_next(bo1);\n\n      if (bo2 == nullptr)\n      {\n         return;\n      }\n\n      if (chunk_is_token(bo2, CT_BRACE_OPEN))\n      {\n         // found a potential double brace\n         chunk_t *bc2 = chunk_skip_to_match(bo2);\n\n         if (bc2 == nullptr)\n         {\n            return;\n         }\n         chunk_t *bc1 = chunk_get_next(bc2);\n\n         if (bc1 == nullptr)\n         {\n            return;\n         }\n\n         if (chunk_is_token(bc1, CT_BRACE_CLOSE))\n         {\n            LOG_FMT(LJDBI, \" - end, orig_line is %zu, orig_col is %zu\\n\", bc2->orig_line, bc2->orig_col);\n            // delete bo2 and bc1\n            bo1->str         += bo2->str;\n            bo1->orig_col_end = bo2->orig_col_end;\n            chunk_del(bo2);\n            set_chunk_parent(bo1, CT_DOUBLE_BRACE);\n\n            bc2->str         += bc1->str;\n            bc2->orig_col_end = bc1->orig_col_end;\n            chunk_del(bc1);\n            set_chunk_parent(bc2, CT_DOUBLE_BRACE);\n            return;\n         }\n      }\n   }\n   LOG_FMT(LJDBI, \" - no\\n\");\n} // check_double_brace_init\n\n\nvoid fix_symbols(void)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *pc;\n   chunk_t dummy;\n\n   cpd.unc_stage = unc_stage_e::FIX_SYMBOLS;\n\n   mark_define_expressions();\n\n   bool is_cpp  = language_is_set(LANG_CPP);\n   bool is_java = language_is_set(LANG_JAVA);\n\n   for (pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnl(pc))\n   {\n      if (  chunk_is_token(pc, CT_FUNC_WRAP)\n         || chunk_is_token(pc, CT_TYPE_WRAP))\n      {\n         handle_wrap(pc);\n      }\n\n      if (chunk_is_token(pc, CT_ASSIGN))\n      {\n         mark_lvalue(pc);\n      }\n      // a brace immediately preceeded by word in C++11 is an initializer list though it may also\n      // by a type casting initializer list if the word is really a type; sadly unucustify knows\n      // only builtin types and knows nothing of user-defined types\n      chunk_t *prev = chunk_get_prev_ncnlni(pc);   // Issue #2279\n\n      if (  is_cpp\n         && chunk_is_token(pc, CT_BRACE_OPEN)\n         && (  chunk_is_token(prev, CT_WORD)\n            || chunk_is_token(prev, CT_TYPE)))\n      {\n         mark_lvalue(pc);\n      }\n\n      if (  is_java\n         && chunk_is_token(pc, CT_BRACE_OPEN))\n      {\n         check_double_brace_init(pc);\n      }\n\n      if (chunk_is_token(pc, CT_ATTRIBUTE))\n      {\n         chunk_t *next = chunk_get_next_ncnl(pc, scope_e::PREPROC);\n\n         if (  next != nullptr\n            && chunk_is_token(next, CT_PAREN_OPEN))\n         {\n            flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_ATTRIBUTE, false);\n         }\n      }\n   }\n\n   pc = chunk_get_head();\n\n   if (pc == nullptr)\n   {\n      return;\n   }\n\n   if (  chunk_is_newline(pc)\n      || chunk_is_comment(pc))\n   {\n      pc = chunk_get_next_ncnl(pc);\n   }\n\n   while (pc != nullptr)\n   {\n      if (chunk_is_token(pc, CT_IGNORED))\n      {\n         pc = chunk_get_next_ncnl(pc);\n         continue;\n      }\n      LOG_FMT(LFCNR, \"%s(%d): pc->orig_line       is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type));\n      chunk_t *prev = chunk_get_prev_ncnlni(pc, scope_e::PREPROC);   // Issue #2279\n\n      if (prev == nullptr)\n      {\n         prev = &dummy;\n      }\n      else\n      {\n         // Issue #2279\n         LOG_FMT(LFCNR, \"%s(%d): prev(ni)->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n                 __func__, __LINE__, prev->orig_line, prev->orig_col, prev->text(), get_token_name(prev->type));\n      }\n      chunk_t *next = chunk_get_next_ncnl(pc, scope_e::PREPROC);\n\n      if (next == nullptr)\n      {\n         next = &dummy;\n      }\n      else\n      {\n         // Issue #2279\n         LOG_FMT(LFCNR, \"%s(%d): next->orig_line     is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n                 __func__, __LINE__, next->orig_line, next->orig_col, next->text(), get_token_name(next->type));\n      }\n      LOG_FMT(LFCNR, \"%s(%d): do_symbol_check(%s, %s, %s)\\n\",\n              __func__, __LINE__, prev->text(), pc->text(), next->text());\n      do_symbol_check(prev, pc, next);\n      pc = chunk_get_next_ncnl(pc);\n   }\n   pawn_add_virtual_semicolons();\n   process_returns();\n\n   /*\n    * 2nd pass - handle variable definitions\n    * REVISIT: We need function params marked to do this (?)\n    */\n   pc = chunk_get_head();\n   int square_level = -1;\n\n   while (pc != nullptr)\n   {\n      LOG_FMT(LFCNR, \"%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s, parent_type is %s\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type), get_token_name(pc->parent_type));\n\n      // Can't have a variable definition inside [ ]\n      if (square_level < 0)\n      {\n         if (chunk_is_token(pc, CT_SQUARE_OPEN))\n         {\n            square_level = pc->level;\n         }\n      }\n      else\n      {\n         if (pc->level <= static_cast<size_t>(square_level))\n         {\n            square_level = -1;\n         }\n      }\n\n      if (  chunk_is_token(pc, CT_EXTERN)\n         && language_is_set(LANG_ALLC))\n      {\n         chunk_t *next = chunk_get_next_ncnl(pc);\n\n         if (chunk_is_token(next, CT_STRING))\n         {\n            chunk_t *tmp = chunk_get_next_ncnl(next);\n\n            while (tmp != nullptr)\n            {\n               if (  (chunk_is_token(tmp, CT_TYPE))\n                  || (chunk_is_token(tmp, CT_BRACE_OPEN))\n                  || (chunk_is_token(tmp, CT_ATTRIBUTE)))\n               {\n                  break;\n               }\n\n               if (chunk_is_token(tmp, CT_WORD))\n               {\n                  chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);\n                  break;\n               }\n               tmp = chunk_get_next_ncnl(tmp);\n            }\n         }\n      }\n\n      if (  chunk_is_token(pc, CT_ATTRIBUTE)\n         && language_is_set(LANG_ALLC))\n      {\n         chunk_t *tmp = skip_attribute_next(pc);\n\n         if (chunk_is_token(tmp, CT_WORD))\n         {\n            chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);\n         }\n      }\n\n      if (  chunk_is_token(pc, CT_BRACE_OPEN)                       // Issue #2332\n         && get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST)\n      {\n         LOG_FMT(LFCNR, \"%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', look for CT_BRACE_OPEN\\n\",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n         pc = chunk_get_next_type(pc, CT_BRACE_CLOSE, pc->level);\n      }\n      /*\n       * A variable definition is possible after at the start of a statement\n       * that starts with: DC_MEMBER, QUALIFIER, TYPE, or WORD\n       */\n      // Issue #2279\n      // Issue #2478\n      LOG_FMT(LFCNR, \"%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s, parent_type is %s\\n   \",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type), get_token_name(pc->parent_type));\n      log_pcf_flags(LFCNR, pc->flags);\n\n      if (  (square_level < 0)\n         && pc->flags.test(PCF_STMT_START)\n         && (  chunk_is_token(pc, CT_QUALIFIER)\n            || chunk_is_token(pc, CT_TYPE)\n            || chunk_is_token(pc, CT_TYPENAME)\n            || chunk_is_token(pc, CT_DC_MEMBER)                         // Issue #2478\n            || chunk_is_token(pc, CT_WORD))\n         && get_chunk_parent_type(pc) != CT_ENUM\n         && !pc->flags.test(PCF_IN_ENUM))\n      {\n         pc = fix_variable_definition(pc);\n      }\n      else\n      {\n         pc = chunk_get_next_ncnl(pc);\n      }\n   }\n} // fix_symbols\n\n\nstatic void process_returns(void)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *pc;\n\n   pc = chunk_get_head();\n\n   while (pc != nullptr)\n   {\n      if (pc->type != CT_RETURN)\n      {\n         pc = chunk_get_next_type(pc, CT_RETURN, -1);\n         continue;\n      }\n      pc = process_return(pc);\n   }\n}\n\n\nstatic chunk_t *process_return(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *next;\n   chunk_t *temp;\n   chunk_t *semi;\n   chunk_t *cpar;\n   chunk_t chunk;\n\n   // grab next and bail if it is a semicolon\n   next = chunk_ppa_get_next_ncnl(pc);\n\n   if (  next == nullptr || chunk_is_semicolon(next)\n      || chunk_is_token(next, CT_NEWLINE))\n   {\n      return(next);\n   }\n   log_rule_B(\"nl_return_expr\");\n\n   if (  options::nl_return_expr() != IARF_IGNORE\n      && !pc->flags.test(PCF_IN_PREPROC))\n   {\n      newline_iarf(pc, options::nl_return_expr());\n   }\n\n   if (chunk_is_token(next, CT_PAREN_OPEN))\n   {\n      // See if the return is fully paren'd\n      cpar = chunk_get_next_type(next, CT_PAREN_CLOSE, next->level);\n\n      if (cpar == nullptr)\n      {\n         return(nullptr);\n      }\n      semi = chunk_ppa_get_next_ncnl(cpar);\n\n      if (semi == nullptr)\n      {\n         return(nullptr);\n      }\n\n      if (chunk_is_token(semi, CT_NEWLINE) || chunk_is_semicolon(semi))\n      {\n         log_rule_B(\"mod_paren_on_return\");\n\n         if (options::mod_paren_on_return() == IARF_REMOVE)\n         {\n            LOG_FMT(LRETURN, \"%s(%d): removing parens on orig_line %zu\\n\",\n                    __func__, __LINE__, pc->orig_line);\n\n            // lower the level of everything\n            for (temp = next; temp != cpar; temp = chunk_get_next(temp))\n            {\n               if (temp->level == 0)\n               {\n                  fprintf(stderr, \"%s(%d): temp->level is ZERO, cannot be decremented, at line %zu, column %zu\\n\",\n                          __func__, __LINE__, temp->orig_line, temp->orig_col);\n                  log_flush(true);\n                  exit(EX_SOFTWARE);\n               }\n               temp->level--;\n            }\n\n            // delete the parenthesis\n            chunk_del(next);\n            chunk_del(cpar);\n\n            // back up following chunks\n            temp = semi;\n\n            while (temp != nullptr && temp->type != CT_NEWLINE)\n            {\n               temp->column       = temp->column - 2;\n               temp->orig_col     = temp->orig_col - 2;\n               temp->orig_col_end = temp->orig_col_end - 2;\n               temp               = chunk_get_next(temp);\n            }\n         }\n         else\n         {\n            LOG_FMT(LRETURN, \"%s(%d): keeping parens on orig_line %zu\\n\",\n                    __func__, __LINE__, pc->orig_line);\n\n            // mark & keep them\n            set_chunk_parent(next, CT_RETURN);\n            set_chunk_parent(cpar, CT_RETURN);\n         }\n         return(semi);\n      }\n   }\n   // We don't have a fully paren'd return. Should we add some?\n   log_rule_B(\"mod_paren_on_return\");\n\n   if (!(options::mod_paren_on_return() & IARF_ADD))\n   {\n      return(next);\n   }\n\n   // Issue #1917\n   // Never add parens to a braced init list; that breaks the code\n   //   return {args...};    // C++11 type elision; okay\n   //   return ({args...});  // ill-formed\n   if (  language_is_set(LANG_CPP) && chunk_is_token(next, CT_BRACE_OPEN)\n      && get_chunk_parent_type(next) == CT_BRACED_INIT_LIST)\n   {\n      LOG_FMT(LRETURN, \"%s(%d): not adding parens around braced initializer\"\n              \" on orig_line %zd\\n\",\n              __func__, __LINE__, pc->orig_line);\n      return(next);\n   }\n   // find the next semicolon on the same level\n   semi = next;\n\n   if (pc->flags.test(PCF_IN_PREPROC))\n   {\n      while ((semi = semi->next) != nullptr)\n      {\n         if (!semi->flags.test(PCF_IN_PREPROC))\n         {\n            break;\n         }\n\n         if (semi->level < pc->level)\n         {\n            return(semi);\n         }\n\n         if (chunk_is_semicolon(semi) && pc->level == semi->level)\n         {\n            break;\n         }\n      }\n   }\n   else\n   {\n      while ((semi = chunk_get_next(semi)) != nullptr)\n      {\n         if (semi->level < pc->level)\n         {\n            return(semi);\n         }\n\n         if (chunk_is_semicolon(semi) && pc->level == semi->level)\n         {\n            break;\n         }\n      }\n   }\n\n   if (semi)\n   {\n      // add the parenthesis\n      set_chunk_type(&chunk, CT_PAREN_OPEN);\n      set_chunk_parent(&chunk, CT_RETURN);\n      chunk.str         = \"(\";\n      chunk.level       = pc->level;\n      chunk.brace_level = pc->brace_level;\n      chunk.orig_line   = pc->orig_line;\n      chunk.orig_col    = next->orig_col - 1;\n      chunk.flags       = pc->flags & PCF_COPY_FLAGS;\n      chunk_add_before(&chunk, next);\n\n      set_chunk_type(&chunk, CT_PAREN_CLOSE);\n      chunk.str       = \")\";\n      chunk.orig_line = semi->orig_line;\n      chunk.orig_col  = semi->orig_col - 1;\n      cpar            = chunk_add_before(&chunk, semi);\n\n      LOG_FMT(LRETURN, \"%s(%d): added parens on orig_line %zu\\n\",\n              __func__, __LINE__, pc->orig_line);\n\n      for (temp = next; temp != cpar; temp = chunk_get_next(temp))\n      {\n         temp->level++;\n      }\n   }\n   return(semi);\n} // process_return\n\n\nstatic bool is_ucase_str(const char *str, size_t len)\n{\n   while (len-- > 0)\n   {\n      if (unc_toupper(*str) != *str)\n      {\n         return(false);\n      }\n      str++;\n   }\n   return(true);\n}\n\n\nstatic bool is_oc_block(chunk_t *pc)\n{\n   return(  pc != nullptr\n         && (  get_chunk_parent_type(pc) == CT_OC_BLOCK_TYPE\n            || get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR\n            || get_chunk_parent_type(pc) == CT_OC_BLOCK_ARG\n            || get_chunk_parent_type(pc) == CT_OC_BLOCK\n            || chunk_is_token(pc, CT_OC_BLOCK_CARET)\n            || (pc->next != nullptr && pc->next->type == CT_OC_BLOCK_CARET)\n            || (pc->prev != nullptr && pc->prev->type == CT_OC_BLOCK_CARET)));\n}\n\n\nstatic void fix_casts(chunk_t *start)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t    *pc;\n   chunk_t    *prev;\n   chunk_t    *first;\n   chunk_t    *after;\n   chunk_t    *last = nullptr;\n   chunk_t    *paren_close;\n   const char *verb      = \"likely\";\n   const char *detail    = \"\";\n   size_t     count      = 0;\n   int        word_count = 0;\n   bool       nope;\n   bool       doubtful_cast = false;\n\n\n   LOG_FMT(LCASTS, \"%s(%d): start->text() is '%s', orig_line is %zu, orig_col is %zu\\n\",\n           __func__, __LINE__, start->text(), start->orig_line, start->orig_col);\n\n   prev = chunk_get_prev_ncnlni(start);   // Issue #2279\n\n   if (prev == nullptr)\n   {\n      return;\n   }\n\n   if (chunk_is_token(prev, CT_PP_DEFINED))\n   {\n      LOG_FMT(LCASTS, \"%s(%d):  -- not a cast - after defined\\n\",\n              __func__, __LINE__);\n      return;\n   }\n\n   if (chunk_is_token(prev, CT_ANGLE_CLOSE))\n   {\n      LOG_FMT(LCASTS, \"%s(%d):  -- not a cast - after > (template)\\n\",\n              __func__, __LINE__);\n      return;\n   }\n   // Make sure there is only WORD, TYPE, and '*' or '^' before the close paren\n   pc    = chunk_get_next_ncnl(start);\n   first = pc;\n\n   while (  pc != nullptr\n         && (  chunk_is_type(pc)\n            || chunk_is_token(pc, CT_WORD)\n            || chunk_is_token(pc, CT_QUALIFIER)\n            || chunk_is_token(pc, CT_DC_MEMBER)\n            || chunk_is_token(pc, CT_PP)\n            || chunk_is_token(pc, CT_STAR)\n            || chunk_is_token(pc, CT_QUESTION)\n            || chunk_is_token(pc, CT_CARET)\n            || chunk_is_token(pc, CT_TSQUARE)\n            || (  (  chunk_is_token(pc, CT_ANGLE_OPEN)\n                  || chunk_is_token(pc, CT_ANGLE_CLOSE))\n               && language_is_set(LANG_OC | LANG_JAVA))\n            || (  (  chunk_is_token(pc, CT_QUESTION)\n                  || chunk_is_token(pc, CT_COMMA)\n                  || chunk_is_token(pc, CT_MEMBER))\n               && language_is_set(LANG_JAVA))\n            || chunk_is_token(pc, CT_AMP)))\n   {\n      LOG_FMT(LCASTS, \"%s(%d): pc->text() is '%s', orig_line is %zu, orig_col is %zu, type is %s\\n\",\n              __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col, get_token_name(pc->type));\n\n      if (chunk_is_token(pc, CT_WORD) || (chunk_is_token(last, CT_ANGLE_CLOSE) && chunk_is_token(pc, CT_DC_MEMBER)))\n      {\n         word_count++;\n      }\n      else if (chunk_is_token(pc, CT_DC_MEMBER) || chunk_is_token(pc, CT_MEMBER) || chunk_is_token(pc, CT_PP))\n      {\n         // might be negativ, such as with:\n         // a = val + (CFoo::bar_t)7;\n         word_count--;\n      }\n      last = pc;\n      pc   = chunk_get_next_ncnl(pc);\n      count++;\n   }\n\n   if (  pc == nullptr\n      || pc->type != CT_PAREN_CLOSE\n      || chunk_is_token(prev, CT_OC_CLASS))\n   {\n      LOG_FMT(LCASTS, \"%s(%d):  -- not a cast, hit type is %s\\n\",\n              __func__, __LINE__, pc == nullptr ? \"NULL\" : get_token_name(pc->type));\n      return;\n   }\n\n   if (word_count > 1)\n   {\n      LOG_FMT(LCASTS, \"%s(%d):  -- too many words: %d\\n\",\n              __func__, __LINE__, word_count);\n      return;\n   }\n   paren_close = pc;\n\n   // If last is a type or star/caret, we have a cast for sure\n   if (  chunk_is_token(last, CT_STAR)\n      || chunk_is_token(last, CT_CARET)\n      || chunk_is_token(last, CT_PTR_TYPE)\n      || chunk_is_token(last, CT_TYPE)\n      || (chunk_is_token(last, CT_ANGLE_CLOSE) && language_is_set(LANG_OC | LANG_JAVA)))\n   {\n      verb = \"for sure\";\n   }\n   else if (count == 1)\n   {\n      /*\n       * We are on a potential cast of the form \"(word)\".\n       * We don't know if the word is a type. So lets guess based on some\n       * simple rules:\n       *  - if all caps, likely a type\n       *  - if it ends in _t, likely a type\n       *  - if it's objective-c and the type is id, likely valid\n       */\n      verb = \"guessed\";\n\n      if (  (last->len() > 3)\n         && (last->str[last->len() - 2] == '_')\n         && (last->str[last->len() - 1] == 't'))\n      {\n         detail = \" -- '_t'\";\n      }\n      else if (is_ucase_str(last->text(), last->len()))\n      {\n         detail = \" -- upper case\";\n      }\n      else if (language_is_set(LANG_OC) && chunk_is_str(last, \"id\", 2))\n      {\n         detail = \" -- Objective-C id\";\n      }\n      else\n      {\n         // If we can't tell for sure whether this is a cast, decide against it\n         detail        = \" -- mixed case\";\n         doubtful_cast = true;\n      }\n      /*\n       * If the next item is a * or &, the next item after that can't be a\n       * number or string.\n       *\n       * If the next item is a +, the next item has to be a number.\n       *\n       * If the next item is a -, the next item can't be a string.\n       *\n       * For this to be a cast, the close paren must be followed by:\n       *  - constant (number or string)\n       *  - paren open\n       *  - word\n       *\n       * Find the next non-open paren item.\n       */\n      pc    = chunk_get_next_ncnl(paren_close);\n      after = pc;\n\n      do\n      {\n         after = chunk_get_next_ncnl(after);\n      } while (chunk_is_token(after, CT_PAREN_OPEN));\n\n      if (after == nullptr)\n      {\n         LOG_FMT(LCASTS, \"%s(%d):  -- not a cast - hit NULL\\n\",\n                 __func__, __LINE__);\n         return;\n      }\n      nope = false;\n\n      if (chunk_is_ptr_operator(pc))\n      {\n         // star (*) and address (&) are ambiguous\n         if (  chunk_is_token(after, CT_NUMBER_FP)\n            || chunk_is_token(after, CT_NUMBER)\n            || chunk_is_token(after, CT_STRING)\n            || doubtful_cast)\n         {\n            nope = true;\n         }\n      }\n      else if (chunk_is_token(pc, CT_MINUS))\n      {\n         // (UINT8)-1 or (foo)-1 or (FOO)-'a'\n         if (chunk_is_token(after, CT_STRING) || doubtful_cast)\n         {\n            nope = true;\n         }\n      }\n      else if (chunk_is_token(pc, CT_PLUS))\n      {\n         // (UINT8)+1 or (foo)+1\n         if (  (after->type != CT_NUMBER && after->type != CT_NUMBER_FP)\n            || doubtful_cast)\n         {\n            nope = true;\n         }\n      }\n      else if (  pc->type != CT_NUMBER_FP\n              && pc->type != CT_NUMBER\n              && pc->type != CT_WORD\n              && pc->type != CT_THIS\n              && pc->type != CT_TYPE\n              && pc->type != CT_PAREN_OPEN\n              && pc->type != CT_STRING\n              && pc->type != CT_DECLTYPE\n              && pc->type != CT_SIZEOF\n              && get_chunk_parent_type(pc) != CT_SIZEOF\n              && pc->type != CT_FUNC_CALL\n              && pc->type != CT_FUNC_CALL_USER\n              && pc->type != CT_FUNCTION\n              && pc->type != CT_BRACE_OPEN\n              && (!(  chunk_is_token(pc, CT_SQUARE_OPEN)\n                   && language_is_set(LANG_OC))))\n      {\n         LOG_FMT(LCASTS, \"%s(%d):  -- not a cast - followed by text() '%s', type is %s\\n\",\n                 __func__, __LINE__, pc->text(), get_token_name(pc->type));\n         return;\n      }\n\n      if (nope)\n      {\n         LOG_FMT(LCASTS, \"%s(%d):  -- not a cast - text() '%s' followed by type %s\\n\",\n                 __func__, __LINE__, pc->text(), get_token_name(after->type));\n         return;\n      }\n   }\n   // if the 'cast' is followed by a semicolon, comma, bool or close parenthesis, it isn't\n   pc = chunk_get_next_ncnl(paren_close);\n\n   if (pc == nullptr)\n   {\n      return;\n   }\n\n   if (  chunk_is_semicolon(pc)\n      || chunk_is_token(pc, CT_COMMA)\n      || chunk_is_token(pc, CT_BOOL)               // Issue #2151\n      || chunk_is_paren_close(pc))\n   {\n      LOG_FMT(LCASTS, \"%s(%d):  -- not a cast - followed by type %s\\n\",\n              __func__, __LINE__, get_token_name(pc->type));\n      return;\n   }\n   set_chunk_parent(start, CT_C_CAST);\n   set_chunk_parent(paren_close, CT_C_CAST);\n\n   LOG_FMT(LCASTS, \"%s(%d):  -- %s c-cast: (\",\n           __func__, __LINE__, verb);\n\n   for (pc = first;\n        pc != nullptr && pc != paren_close;\n        pc = chunk_get_next_ncnl(pc))\n   {\n      set_chunk_parent(pc, CT_C_CAST);\n      make_type(pc);\n      LOG_FMT(LCASTS, \" %s\", pc->text());\n   }\n\n   LOG_FMT(LCASTS, \" )%s\\n\", detail);\n\n   // Mark the next item as an expression start\n   pc = chunk_get_next_ncnl(paren_close);\n\n   if (pc != nullptr)\n   {\n      chunk_flags_set(pc, PCF_EXPR_START);\n\n      if (chunk_is_opening_brace(pc))\n      {\n         set_paren_parent(pc, get_chunk_parent_type(start));\n      }\n   }\n} // fix_casts\n\n\nstatic void fix_type_cast(chunk_t *start)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *pc;\n\n   pc = chunk_get_next_ncnl(start);\n\n   if (pc == nullptr || pc->type != CT_ANGLE_OPEN)\n   {\n      return;\n   }\n\n   while (  ((pc = chunk_get_next_ncnl(pc)) != nullptr)\n         && pc->level >= start->level)\n   {\n      if (pc->level == start->level && chunk_is_token(pc, CT_ANGLE_CLOSE))\n      {\n         pc = chunk_get_next_ncnl(pc);\n\n         if (pc == nullptr)\n         {\n            return;\n         }\n\n         if (chunk_is_str(pc, \"(\", 1))\n         {\n            set_paren_parent(pc, CT_TYPE_CAST);\n         }\n         return;\n      }\n      make_type(pc);\n   }\n}\n\n\nstatic void fix_enum_struct_union(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t     *next;\n   chunk_t     *prev        = nullptr;\n   pcf_flags_t flags        = PCF_VAR_1ST_DEF;\n   auto const  in_fcn_paren = pc->flags & PCF_IN_FCN_DEF;\n\n   // Make sure this wasn't a cast\n   if (get_chunk_parent_type(pc) == CT_C_CAST)\n   {\n      return;\n   }\n   // the next item is either a type or open brace\n   next = chunk_get_next_ncnl(pc);\n\n   // the enum-key might be enum, enum class or enum struct (TODO)\n   if (chunk_is_token(next, CT_ENUM_CLASS))\n   {\n      next = chunk_get_next_ncnl(next); // get the next one\n   }\n\n   if (language_is_set(LANG_CPP))\n   {\n      next = skip_attribute_next(next); // get the next one\n   }\n\n   // the next item is either a type, an attribute (TODO), an identifier, a colon or open brace\n   if (chunk_is_token(next, CT_TYPE) || chunk_is_token(next, CT_WORD) || chunk_is_token(next, CT_COLON))\n   {\n      // i.e. \"enum xyz : unsigned int { ... };\"\n      // i.e. \"enum class xyz : unsigned int { ... };\"\n      // i.e. \"enum : unsigned int { ... };\"\n      // xyz is a type\n\n      // save the type if it exists\n      if (!chunk_is_token(next, CT_COLON))\n      {\n         set_chunk_parent(next, pc->type);\n         prev = next;\n         next = chunk_get_next_ncnl(next);\n      }\n\n      if (next == nullptr)\n      {\n         return;\n      }\n      set_chunk_parent(next, pc->type);\n      auto const is_struct_or_class =\n         (chunk_is_token(pc, CT_STRUCT) || chunk_is_token(pc, CT_CLASS));\n\n      // next up is either a colon, open brace, or open parenthesis (pawn)\n      if (language_is_set(LANG_PAWN) && chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         next = set_paren_parent(next, CT_ENUM);\n      }\n      else if (chunk_is_token(next, CT_COLON))\n      {\n         if (chunk_is_token(pc, CT_ENUM))\n         {\n            // enum TYPE : INT_TYPE { ... };\n            next = chunk_get_next_ncnl(next);\n\n            if (next != nullptr)\n            {\n               make_type(next);\n               next = chunk_get_next_ncnl(next);\n\n               // enum TYPE : unsigned int { ... };\n               if (chunk_is_token(next, CT_TYPE))\n               {\n                  // get the next part of the type\n                  next = chunk_get_next_ncnl(next);\n               }\n            }\n         }\n         else if (is_struct_or_class)\n         {\n            next = skip_parent_types(next);\n         }\n      }\n      else if (is_struct_or_class && chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         // Fix #1267 structure attributes\n         // struct __attribute__(align(x)) struct_name;\n         // skip to matching parenclose and make next token as type.\n         next = chunk_skip_to_match(next);\n         next = chunk_get_next_ncnl(next);\n         set_chunk_type(next, CT_TYPE);\n         set_chunk_parent(next, pc->type);\n      }\n\n      if (chunk_is_token(next, CT_SEMICOLON)) // c++ forward declaration\n      {\n         set_chunk_parent(next, pc->type);\n         flag_series(pc, prev, PCF_INCOMPLETE);\n         return;\n      }\n   }\n\n   if (chunk_is_token(next, CT_BRACE_OPEN))\n   {\n      auto const flag = [pc] {\n         switch (pc->type)\n         {\n         case CT_ENUM:\n            return(PCF_IN_ENUM);\n\n         case CT_STRUCT:\n            return(PCF_IN_STRUCT);\n\n         case CT_CLASS:\n            return(PCF_IN_CLASS);\n\n         default:\n            return(PCF_NONE);\n         }\n      }();\n\n      flag_parens(next, flag, CT_NONE, CT_NONE, false);\n\n      if (  chunk_is_token(pc, CT_UNION)\n         || chunk_is_token(pc, CT_STRUCT)\n         || chunk_is_token(pc, CT_CLASS))\n      {\n         mark_struct_union_body(next);\n      }\n      // Skip to the closing brace\n      set_chunk_parent(next, pc->type);\n      next   = chunk_get_next_type(next, CT_BRACE_CLOSE, pc->level);\n      flags |= PCF_VAR_INLINE;\n\n      if (next != nullptr)\n      {\n         set_chunk_parent(next, pc->type);\n         next = chunk_get_next_ncnl(next);\n      }\n      prev = nullptr;\n   }\n   // reset var name parent type\n   else if (next && prev)\n   {\n      set_chunk_parent(prev, CT_NONE);\n   }\n\n   if (next == nullptr || chunk_is_token(next, CT_PAREN_CLOSE))\n   {\n      return;\n   }\n\n   if (!chunk_is_semicolon(next))\n   {\n      // Pawn does not require a semicolon after an enum\n      if (language_is_set(LANG_PAWN))\n      {\n         return;\n      }\n\n      /*\n       * D does not require a semicolon after an enum, but we add one to make\n       * other code happy.\n       */\n      if (language_is_set(LANG_D))\n      {\n         next = pawn_add_vsemi_after(chunk_get_prev_ncnlni(next));   // Issue #2279\n      }\n   }\n\n   // We are either pointing to a ';' or a variable\n   while (  next != nullptr\n         && !chunk_is_semicolon(next)\n         && next->type != CT_ASSIGN\n         && !(in_fcn_paren ^ (next->flags & PCF_IN_FCN_DEF)).test_any())\n   {\n      if (next->level == pc->level)\n      {\n         if (chunk_is_token(next, CT_WORD))\n         {\n            chunk_flags_set(next, flags);\n            flags &= ~PCF_VAR_1ST;   // clear the first flag for the next items\n            LOG_FMT(LCASTS, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', set PCF_VAR_1ST\\n\",\n                    __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n         }\n\n         if (  chunk_is_token(next, CT_STAR)\n            || (language_is_set(LANG_CPP) && chunk_is_token(next, CT_CARET)))\n         {\n            set_chunk_type(next, CT_PTR_TYPE);\n         }\n\n         // If we hit a comma in a function param, we are done\n         if (  (chunk_is_token(next, CT_COMMA) || chunk_is_token(next, CT_FPAREN_CLOSE))\n            && (next->flags.test_any(PCF_IN_FCN_DEF | PCF_IN_FCN_CALL)))\n         {\n            return;\n         }\n      }\n      next = chunk_get_next_ncnl(next);\n   }\n\n   if (  next != nullptr\n      && chunk_is_token(next, CT_SEMICOLON))\n   {\n      set_chunk_parent(next, pc->type);\n   }\n} // fix_enum_struct_union\n\n\nstatic void fix_typedef(chunk_t *start)\n{\n   LOG_FUNC_ENTRY();\n\n   if (start == nullptr)\n   {\n      return;\n   }\n   LOG_FMT(LTYPEDEF, \"%s(%d): typedef @ orig_line %zu, orig_col %zu\\n\",\n           __func__, __LINE__, start->orig_line, start->orig_col);\n\n   chunk_t *the_type = nullptr;\n   chunk_t *last_op  = nullptr;\n\n   /*\n    * Mark everything in the typedef and scan for \")(\", which makes it a\n    * function type\n    */\n   for (chunk_t *next = chunk_get_next_ncnl(start, scope_e::PREPROC)\n        ; next != nullptr && next->level >= start->level\n        ; next = chunk_get_next_ncnl(next, scope_e::PREPROC))\n   {\n      chunk_flags_set(next, PCF_IN_TYPEDEF);\n\n      if (start->level == next->level)\n      {\n         if (chunk_is_semicolon(next))\n         {\n            set_chunk_parent(next, CT_TYPEDEF);\n            break;\n         }\n\n         if (chunk_is_token(next, CT_ATTRIBUTE))\n         {\n            break;\n         }\n\n         if (language_is_set(LANG_D) && chunk_is_token(next, CT_ASSIGN))\n         {\n            set_chunk_parent(next, CT_TYPEDEF);\n            break;\n         }\n         make_type(next);\n\n         if (chunk_is_token(next, CT_TYPE))\n         {\n            the_type = next;\n         }\n         chunk_flags_clr(next, PCF_VAR_1ST_DEF);\n\n         if (*next->str.c_str() == '(')\n         {\n            last_op = next;\n         }\n      }\n   }\n\n   // avoid interpreting typedef NS_ENUM (NSInteger, MyEnum) as a function def\n   if (  last_op != nullptr\n      && !(language_is_set(LANG_OC) && get_chunk_parent_type(last_op) == CT_ENUM))\n   {\n      flag_parens(last_op, PCF_NONE, CT_FPAREN_OPEN, CT_TYPEDEF, false);\n      fix_fcn_def_params(last_op);\n\n      the_type = chunk_get_prev_ncnlni(last_op, scope_e::PREPROC);   // Issue #2279\n\n      if (the_type == nullptr)\n      {\n         return;\n      }\n      chunk_t *open_paren = nullptr;\n\n      if (chunk_is_paren_close(the_type))\n      {\n         open_paren = chunk_skip_to_match_rev(the_type);\n         mark_function_type(the_type);\n         the_type = chunk_get_prev_ncnlni(the_type, scope_e::PREPROC);   // Issue #2279\n\n         if (the_type == nullptr)\n         {\n            return;\n         }\n      }\n      else\n      {\n         // must be: \"typedef <return type>func(params);\"\n         set_chunk_type(the_type, CT_FUNC_TYPE);\n      }\n      set_chunk_parent(the_type, CT_TYPEDEF);\n\n      LOG_FMT(LTYPEDEF, \"%s(%d): fcn typedef text() '%s', on orig_line %zu\\n\",\n              __func__, __LINE__, the_type->text(), the_type->orig_line);\n\n      // If we are aligning on the open parenthesis, grab that instead\n      log_rule_B(\"align_typedef_func\");\n\n      if (open_paren != nullptr && options::align_typedef_func() == 1)\n      {\n         the_type = open_paren;\n      }\n      log_rule_B(\"align_typedef_func\");\n\n      if (options::align_typedef_func() != 0)\n      {\n         LOG_FMT(LTYPEDEF, \"%s(%d):  -- align anchor on text() %s, @ orig_line %zu, orig_col %zu\\n\",\n                 __func__, __LINE__, the_type->text(), the_type->orig_line, the_type->orig_col);\n         chunk_flags_set(the_type, PCF_ANCHOR);\n      }\n      // already did everything we need to do\n      return;\n   }\n   /*\n    * Skip over enum/struct/union stuff, as we know it isn't a return type\n    * for a function type\n    */\n   chunk_t *after = chunk_get_next_ncnl(start, scope_e::PREPROC);\n\n   if (after == nullptr)\n   {\n      return;\n   }\n\n   if (  after->type != CT_ENUM\n      && after->type != CT_STRUCT\n      && after->type != CT_UNION)\n   {\n      if (the_type != nullptr)\n      {\n         // We have just a regular typedef\n         LOG_FMT(LTYPEDEF, \"%s(%d): regular typedef text() %s, on orig_line %zu\\n\",\n                 __func__, __LINE__, the_type->text(), the_type->orig_line);\n         chunk_flags_set(the_type, PCF_ANCHOR);\n      }\n      return;\n   }\n   // We have a struct/union/enum, next should be either a type or {\n   chunk_t *next = chunk_get_next_ncnl(after, scope_e::PREPROC);\n\n   if (next == nullptr)\n   {\n      return;\n   }\n\n   if (chunk_is_token(next, CT_TYPE))\n   {\n      next = chunk_get_next_ncnl(next, scope_e::PREPROC);\n\n      if (next == nullptr)\n      {\n         return;\n      }\n   }\n\n   if (chunk_is_token(next, CT_BRACE_OPEN))\n   {\n      // Skip to the closing brace\n      chunk_t *br_c = chunk_get_next_type(next, CT_BRACE_CLOSE, next->level, scope_e::PREPROC);\n\n      if (br_c != nullptr)\n      {\n         const c_token_t tag = after->type;\n         set_chunk_parent(next, tag);\n         set_chunk_parent(br_c, tag);\n\n         if (tag == CT_ENUM)\n         {\n            flag_series(after, br_c, PCF_IN_ENUM);\n         }\n         else if (tag == CT_STRUCT)\n         {\n            flag_series(after, br_c, PCF_IN_STRUCT);\n         }\n      }\n   }\n\n   if (the_type != nullptr)\n   {\n      LOG_FMT(LTYPEDEF, \"%s(%d): %s typedef text() %s, on orig_line %zu\\n\",\n              __func__, __LINE__, get_token_name(after->type), the_type->text(),\n              the_type->orig_line);\n      chunk_flags_set(the_type, PCF_ANCHOR);\n   }\n} // fix_typedef\n\n\n//static void mark_variable_stack(ChunkStack &cs, log_sev_t sev)\n//{\n//   UNUSED(sev);\n//   LOG_FUNC_ENTRY();\n//\n//   // throw out the last word and mark the rest\n//   chunk_t *var_name = cs.Pop_Back();\n//\n//   if (var_name && var_name->prev->type == CT_DC_MEMBER)\n//   {\n//      cs.Push_Back(var_name);\n//   }\n//\n//   if (var_name != nullptr)\n//   {\n//      LOG_FMT(LFCNP, \"%s(%d): parameter on orig_line %zu, orig_col %zu:\\n\",\n//              __func__, __LINE__, var_name->orig_line, var_name->orig_col);\n//\n//      size_t  word_cnt = 0;\n//      chunk_t *word_type;\n//\n//      while ((word_type = cs.Pop_Back()) != nullptr)\n//      {\n//         if (chunk_is_token(word_type, CT_WORD) || chunk_is_token(word_type, CT_TYPE))\n//         {\n//            LOG_FMT(LFCNP, \"%s(%d): parameter on orig_line %zu, orig_col %zu: <%s> as TYPE\\n\",\n//                    __func__, __LINE__, var_name->orig_line, var_name->orig_col, word_type->text());\n//            set_chunk_type(word_type, CT_TYPE);\n//            chunk_flags_set(word_type, PCF_VAR_TYPE);\n//         }\n//         word_cnt++;\n//      }\n//\n//      if (chunk_is_token(var_name, CT_WORD))\n//      {\n//         if (word_cnt > 0)\n//         {\n//            LOG_FMT(LFCNP, \"%s(%d): parameter on orig_line %zu, orig_col %zu: <%s> as VAR\\n\",\n//                    __func__, __LINE__, var_name->orig_line, var_name->orig_col, var_name->text());\n//            chunk_flags_set(var_name, PCF_VAR_DEF);\n//         }\n//         else\n//         {\n//            LOG_FMT(LFCNP, \"%s(%d): parameter on orig_line %zu, orig_col %zu: <%s> as TYPE\\n\",\n//                    __func__, __LINE__, var_name->orig_line, var_name->orig_col, var_name->text());\n//            set_chunk_type(var_name, CT_TYPE);\n//            chunk_flags_set(var_name, PCF_VAR_TYPE);\n//         }\n//      }\n//   }\n//} // mark_variable_stack\n\n\n//static void fix_fcn_def_params(chunk_t *start)\n//{\n//   LOG_FUNC_ENTRY();\n//\n//   if (start == nullptr)\n//   {\n//      return;\n//   }\n//   LOG_FMT(LFCNP, \"%s(%d): text() '%s', type is %s, on orig_line %zu, level is %zu\\n\",\n//           __func__, __LINE__, start->text(), get_token_name(start->type), start->orig_line, start->level);\n//\n//   while (start != nullptr && !chunk_is_paren_open(start))\n//   {\n//      start = chunk_get_next_ncnl(start);\n//   }\n//\n//   if (start == nullptr)// Coverity CID 76003, 1100782\n//   {\n//      return;\n//   }\n//   // ensure start chunk holds a single '(' character\n//   assert((start->len() == 1) && (start->str[0] == '('));\n//\n//   ChunkStack cs;\n//   size_t     level = start->level + 1;\n//   chunk_t    *pc   = start;\n//\n//   while ((pc = chunk_get_next_ncnl(pc)) != nullptr)\n//   {\n//      if (  ((start->len() == 1) && (start->str[0] == ')'))\n//         || pc->level < level)\n//      {\n//         LOG_FMT(LFCNP, \"%s(%d): bailed on text() '%s', on orig_line %zu\\n\",\n//                 __func__, __LINE__, pc->text(), pc->orig_line);\n//         break;\n//      }\n//      LOG_FMT(LFCNP, \"%s(%d): %s, text() '%s' on orig_line %zu, level %zu\\n\",\n//              __func__, __LINE__, (pc->level > level) ? \"skipping\" : \"looking at\",\n//              pc->text(), pc->orig_line, pc->level);\n//\n//      if (pc->level > level)\n//      {\n//         continue;\n//      }\n//\n//      if (chunk_is_star(pc) || chunk_is_msref(pc) || chunk_is_nullable(pc))\n//      {\n//         set_chunk_type(pc, CT_PTR_TYPE);\n//         cs.Push_Back(pc);\n//      }\n//      else if (  chunk_is_token(pc, CT_AMP)\n//              || (language_is_set(LANG_CPP) && chunk_is_str(pc, \"&&\", 2)))\n//      {\n//         set_chunk_type(pc, CT_BYREF);\n//         cs.Push_Back(pc);\n//      }\n//      else if (chunk_is_token(pc, CT_TYPE_WRAP))\n//      {\n//         cs.Push_Back(pc);\n//      }\n//      else if (chunk_is_token(pc, CT_WORD) || chunk_is_token(pc, CT_TYPE))\n//      {\n//         cs.Push_Back(pc);\n//      }\n//      else if (chunk_is_token(pc, CT_COMMA) || chunk_is_token(pc, CT_ASSIGN))\n//      {\n//         mark_variable_stack(cs, LFCNP);\n//\n//         if (chunk_is_token(pc, CT_ASSIGN))\n//         {\n//            // Mark assignment for default param spacing\n//            set_chunk_parent(pc, CT_FUNC_PROTO);\n//         }\n//      }\n//   }\n//   mark_variable_stack(cs, LFCNP);\n//} // fix_fcn_def_params\n\n\nstatic void handle_cpp_template(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n\n   chunk_t *tmp = chunk_get_next_ncnl(pc);\n\n   if (tmp->type != CT_ANGLE_OPEN)\n   {\n      return;\n   }\n   set_chunk_parent(tmp, CT_TEMPLATE);\n\n   size_t level = tmp->level;\n\n   while ((tmp = chunk_get_next(tmp)) != nullptr)\n   {\n      if (chunk_is_token(tmp, CT_CLASS) || chunk_is_token(tmp, CT_STRUCT))\n      {\n         set_chunk_type(tmp, CT_TYPE);\n      }\n      else if (chunk_is_token(tmp, CT_ANGLE_CLOSE) && tmp->level == level)\n      {\n         set_chunk_parent(tmp, CT_TEMPLATE);\n         break;\n      }\n   }\n\n   if (tmp != nullptr)\n   {\n      tmp = chunk_get_next_ncnl(tmp);\n\n      if (chunk_is_token(tmp, CT_CLASS) || chunk_is_token(tmp, CT_STRUCT))\n      {\n         set_chunk_parent(tmp, CT_TEMPLATE);\n\n         // REVISIT: This may be a bit risky - might need to track the { };\n         tmp = chunk_get_next_type(tmp, CT_SEMICOLON, tmp->level);\n\n         if (tmp != nullptr)\n         {\n            set_chunk_parent(tmp, CT_TEMPLATE);\n         }\n      }\n   }\n} // handle_cpp_template\n\n\nstatic void handle_cpp_lambda(chunk_t *sq_o)\n{\n   LOG_FUNC_ENTRY();\n\n   chunk_t *ret = nullptr;\n\n   // abort if type of the previous token is not contained in this whitelist\n   chunk_t *prev = chunk_get_prev_ncnlni(sq_o);   // Issue #2279\n\n   if (  prev == nullptr\n      || (  prev->type != CT_ASSIGN\n         && prev->type != CT_COMMA\n         && prev->type != CT_PAREN_OPEN   // allow Js like self invoking lambda syntax: ([](){})();\n         && prev->type != CT_FPAREN_OPEN\n         && prev->type != CT_SQUARE_OPEN\n         && prev->type != CT_BRACE_OPEN\n         && prev->type != CT_SEMICOLON\n         && prev->type != CT_RETURN))\n   {\n      return;\n   }\n   chunk_t *sq_c = sq_o; // assuming '[]'\n\n   if (chunk_is_token(sq_o, CT_SQUARE_OPEN))\n   {\n      // make sure there is a ']'\n      sq_c = chunk_skip_to_match(sq_o);\n\n      if (!sq_c)\n      {\n         return;\n      }\n   }\n   chunk_t *pa_o = chunk_get_next_ncnl(sq_c);\n\n   // check to see if there is a lambda-specifier in the pa_o chunk;\n   // assuming chunk is CT_EXECUTION_CONTEXT, ignore lambda-specifier\n   while (pa_o->type == CT_EXECUTION_CONTEXT)\n   {\n      // set pa_o to next chunk after this specifier\n      pa_o = chunk_get_next_ncnl(pa_o);\n   }\n\n   if (pa_o == nullptr)\n   {\n      return;\n   }\n   chunk_t *pa_c = nullptr;\n\n   // lambda-declarator '( params )' is optional\n   if (chunk_is_token(pa_o, CT_PAREN_OPEN))\n   {\n      // and now find the ')'\n      pa_c = chunk_skip_to_match(pa_o);\n\n      if (pa_c == nullptr)\n      {\n         return;\n      }\n   }\n   // Check for 'mutable' keyword: '[]() mutable {}' or []() mutable -> ret {}\n   chunk_t *br_o = pa_c ? chunk_get_next_ncnl(pa_c) : pa_o;\n\n   if (chunk_is_str(br_o, \"mutable\", 7))\n   {\n      br_o = chunk_get_next_ncnl(br_o);\n   }\n   //TODO: also check for exception and attribute between [] ... {}\n\n   // skip possible arrow syntax: '-> ret'\n   if (chunk_is_str(br_o, \"->\", 2))\n   {\n      ret = br_o;\n      // REVISIT: really should check the stuff we are skipping\n      br_o = chunk_get_next_type(br_o, CT_BRACE_OPEN, br_o->level);\n   }\n\n   if (  br_o == nullptr\n      || br_o->type != CT_BRACE_OPEN)\n   {\n      return;\n   }\n   // and now find the '}'\n   chunk_t *br_c = chunk_skip_to_match(br_o);\n\n   if (br_c == nullptr)\n   {\n      return;\n   }\n\n   // This looks like a lambda expression\n   if (chunk_is_token(sq_o, CT_TSQUARE))\n   {\n      // split into two chunks\n      chunk_t nc;\n\n      nc = *sq_o;\n      set_chunk_type(sq_o, CT_SQUARE_OPEN);\n      sq_o->str.resize(1);\n      /*\n       * bug # 664\n       *\n       * The original orig_col of CT_SQUARE_CLOSE is stored at orig_col_end\n       * of CT_TSQUARE. CT_SQUARE_CLOSE orig_col and orig_col_end values\n       * are calculate from orig_col_end of CT_TSQUARE.\n       */\n      nc.orig_col        = sq_o->orig_col_end - 1;\n      nc.column          = static_cast<int>(nc.orig_col);\n      nc.orig_col_end    = sq_o->orig_col_end;\n      sq_o->orig_col_end = sq_o->orig_col + 1;\n\n      set_chunk_type(&nc, CT_SQUARE_CLOSE);\n      nc.str.pop_front();\n      sq_c = chunk_add_after(&nc, sq_o);\n   }\n   set_chunk_parent(sq_o, CT_CPP_LAMBDA);\n   set_chunk_parent(sq_c, CT_CPP_LAMBDA);\n\n   if (pa_c != nullptr)\n   {\n      set_chunk_type(pa_o, CT_FPAREN_OPEN);\n      set_chunk_parent(pa_o, CT_CPP_LAMBDA);\n      set_chunk_type(pa_c, CT_FPAREN_CLOSE);\n      set_chunk_parent(pa_c, CT_CPP_LAMBDA);\n   }\n   set_chunk_parent(br_o, CT_CPP_LAMBDA);\n   set_chunk_parent(br_c, CT_CPP_LAMBDA);\n\n   if (ret != nullptr)\n   {\n      set_chunk_type(ret, CT_CPP_LAMBDA_RET);\n      ret = chunk_get_next_ncnl(ret);\n\n      while (ret != br_o)\n      {\n         make_type(ret);\n         ret = chunk_get_next_ncnl(ret);\n      }\n   }\n\n   if (pa_c != nullptr)\n   {\n      fix_fcn_def_params(pa_o);\n   }\n   //handle self calling lambda paren\n   chunk_t *call_pa_o = chunk_get_next_ncnl(br_c);\n\n   if (chunk_is_token(call_pa_o, CT_PAREN_OPEN))\n   {\n      chunk_t *call_pa_c = chunk_skip_to_match(call_pa_o);\n\n      if (call_pa_c != nullptr)\n      {\n         set_chunk_type(call_pa_o, CT_FPAREN_OPEN);\n         set_chunk_parent(call_pa_o, CT_FUNC_CALL);\n         set_chunk_type(call_pa_c, CT_FPAREN_CLOSE);\n         set_chunk_parent(call_pa_c, CT_FUNC_CALL);\n      }\n   }\n} // handle_cpp_lambda\n\n\nstatic void handle_d_template(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n\n   chunk_t *name = chunk_get_next_ncnl(pc);\n   chunk_t *po   = chunk_get_next_ncnl(name);\n\n   //if (!name || (name->type != CT_WORD && name->type != CT_WORD))  Coverity CID 76000 Same on both sides, 2016-03-16\n   if (!name || name->type != CT_WORD)\n   {\n      // TODO: log an error, expected NAME\n      return;\n   }\n\n   if (  po == nullptr\n      || po->type != CT_PAREN_OPEN)\n   {\n      // TODO: log an error, expected '('\n      return;\n   }\n   set_chunk_type(name, CT_TYPE);\n   set_chunk_parent(name, CT_TEMPLATE);\n   set_chunk_parent(po, CT_TEMPLATE);\n\n   ChunkStack cs;\n   chunk_t    *tmp = get_d_template_types(cs, po);\n\n   if (  tmp == nullptr\n      || tmp->type != CT_PAREN_CLOSE)\n   {\n      // TODO: log an error, expected ')'\n      return;\n   }\n   set_chunk_parent(tmp, CT_TEMPLATE);\n\n   tmp = chunk_get_next_ncnl(tmp);\n\n   if (tmp->type != CT_BRACE_OPEN)\n   {\n      // TODO: log an error, expected '{'\n      return;\n   }\n   set_chunk_parent(tmp, CT_TEMPLATE);\n   po = tmp;\n\n   tmp = po;\n\n   while (  ((tmp = chunk_get_next_ncnl(tmp)) != nullptr)\n         && tmp->level > po->level)\n   {\n      if (chunk_is_token(tmp, CT_WORD) && chunkstack_match(cs, tmp))\n      {\n         set_chunk_type(tmp, CT_TYPE);\n      }\n   }\n//   if (!chunk_is_token(tmp, CT_BRACE_CLOSE))\n//   {\n//      // TODO: log an error, expected '}'\n//   }\n   set_chunk_parent(tmp, CT_TEMPLATE);\n} // handle_d_template\n\n\nchunk_t *skip_template_next(chunk_t *ang_open)\n{\n   if (chunk_is_token(ang_open, CT_ANGLE_OPEN))\n   {\n      chunk_t *pc = chunk_get_next_type(ang_open, CT_ANGLE_CLOSE, ang_open->level);\n      return(chunk_get_next_ncnl(pc));\n   }\n   return(ang_open);\n}\n\n\nstatic void handle_oc_class(chunk_t *pc)\n{\n   enum class angle_state_e : unsigned int\n   {\n      NONE  = 0,\n      OPEN  = 1, // '<' found\n      CLOSE = 2, // '>' found\n   };\n\n   LOG_FUNC_ENTRY();\n   chunk_t       *tmp;\n   bool          hit_scope     = false;\n   bool          passed_name   = false; // Did we pass the name of the class and now there can be only protocols, not generics\n   int           generic_level = 0;     // level of depth of generic\n   angle_state_e as            = angle_state_e::NONE;\n\n   LOG_FMT(LOCCLASS, \"%s(%d): start [%s] [%s] line %zu\\n\",\n           __func__, __LINE__, pc->text(), get_token_name(get_chunk_parent_type(pc)), pc->orig_line);\n\n   if (get_chunk_parent_type(pc) == CT_OC_PROTOCOL)\n   {\n      tmp = chunk_get_next_ncnl(pc);\n\n      if (chunk_is_semicolon(tmp))\n      {\n         set_chunk_parent(tmp, get_chunk_parent_type(pc));\n         LOG_FMT(LOCCLASS, \"%s(%d):   bail on semicolon\\n\", __func__, __LINE__);\n         return;\n      }\n   }\n   tmp = pc;\n\n   while ((tmp = chunk_get_next_nnl(tmp)) != nullptr)\n   {\n      LOG_FMT(LOCCLASS, \"%s(%d):       orig_line is %zu, [%s]\\n\",\n              __func__, __LINE__, tmp->orig_line, tmp->text());\n\n      if (chunk_is_token(tmp, CT_OC_END))\n      {\n         break;\n      }\n\n      if (chunk_is_token(tmp, CT_PAREN_OPEN))\n      {\n         passed_name = true;\n      }\n\n      if (chunk_is_str(tmp, \"<\", 1))\n      {\n         set_chunk_type(tmp, CT_ANGLE_OPEN);\n\n         if (passed_name)\n         {\n            set_chunk_parent(tmp, CT_OC_PROTO_LIST);\n         }\n         else\n         {\n            set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);\n            generic_level++;\n         }\n         as = angle_state_e::OPEN;\n      }\n\n      if (chunk_is_str(tmp, \">\", 1))\n      {\n         set_chunk_type(tmp, CT_ANGLE_CLOSE);\n\n         if (passed_name)\n         {\n            set_chunk_parent(tmp, CT_OC_PROTO_LIST);\n            as = angle_state_e::CLOSE;\n         }\n         else\n         {\n            set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);\n\n            if (generic_level == 0)\n            {\n               fprintf(stderr, \"%s(%d): generic_level is ZERO, cannot be decremented, at line %zu, column %zu\\n\",\n                       __func__, __LINE__, tmp->orig_line, tmp->orig_col);\n               log_flush(true);\n               exit(EX_SOFTWARE);\n            }\n            generic_level--;\n\n            if (generic_level == 0)\n            {\n               as = angle_state_e::CLOSE;\n            }\n         }\n      }\n\n      if (chunk_is_str(tmp, \">>\", 2))\n      {\n         set_chunk_type(tmp, CT_ANGLE_CLOSE);\n         set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);\n         split_off_angle_close(tmp);\n         generic_level -= 1;\n\n         if (generic_level == 0)\n         {\n            as = angle_state_e::CLOSE;\n         }\n      }\n\n      if (  chunk_is_token(tmp, CT_BRACE_OPEN)\n         && get_chunk_parent_type(tmp) != CT_ASSIGN)\n      {\n         as = angle_state_e::CLOSE;\n         set_chunk_parent(tmp, CT_OC_CLASS);\n         tmp = chunk_get_next_type(tmp, CT_BRACE_CLOSE, tmp->level);\n\n         if (  tmp != nullptr\n            && get_chunk_parent_type(tmp) != CT_ASSIGN)\n         {\n            set_chunk_parent(tmp, CT_OC_CLASS);\n         }\n      }\n      else if (chunk_is_token(tmp, CT_COLON))\n      {\n         if (as != angle_state_e::OPEN)\n         {\n            passed_name = true;\n         }\n         set_chunk_type(tmp, hit_scope ? CT_OC_COLON : CT_CLASS_COLON);\n\n         if (chunk_is_token(tmp, CT_CLASS_COLON))\n         {\n            set_chunk_parent(tmp, CT_OC_CLASS);\n         }\n      }\n      else if (chunk_is_str(tmp, \"-\", 1) || chunk_is_str(tmp, \"+\", 1))\n      {\n         as = angle_state_e::CLOSE;\n\n         if (chunk_is_newline(chunk_get_prev(tmp)))\n         {\n            set_chunk_type(tmp, CT_OC_SCOPE);\n            chunk_flags_set(tmp, PCF_STMT_START);\n            hit_scope = true;\n         }\n      }\n\n      if (as == angle_state_e::OPEN)\n      {\n         if (passed_name)\n         {\n            set_chunk_parent(tmp, CT_OC_PROTO_LIST);\n         }\n         else\n         {\n            set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);\n         }\n      }\n   }\n\n   if (chunk_is_token(tmp, CT_BRACE_OPEN))\n   {\n      tmp = chunk_get_next_type(tmp, CT_BRACE_CLOSE, tmp->level);\n\n      if (tmp != nullptr)\n      {\n         set_chunk_parent(tmp, CT_OC_CLASS);\n      }\n   }\n} // handle_oc_class\n\n\nstatic void handle_oc_block_literal(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *prev = chunk_get_prev_ncnlni(pc);   // Issue #2279\n   chunk_t *next = chunk_get_next_ncnl(pc);\n\n   if (  pc == nullptr\n      || prev == nullptr\n      || next == nullptr)\n   {\n      return; // let's be paranoid\n   }\n   /*\n    * block literal: '^ RTYPE ( ARGS ) { }'\n    * RTYPE and ARGS are optional\n    */\n   LOG_FMT(LOCBLK, \"%s(%d): block literal @ orig_line is %zu, orig_col is %zu\\n\",\n           __func__, __LINE__, pc->orig_line, pc->orig_col);\n\n   chunk_t *apo = nullptr; // arg paren open\n   chunk_t *bbo = nullptr; // block brace open\n   chunk_t *bbc;           // block brace close\n\n   LOG_FMT(LOCBLK, \"%s(%d):  + scan\", __func__, __LINE__);\n   chunk_t *tmp;\n\n   for (tmp = next; tmp; tmp = chunk_get_next_ncnl(tmp))\n   {\n      /* handle '< protocol >' */\n      if (chunk_is_str(tmp, \"<\", 1))\n      {\n         chunk_t *ao = tmp;\n         chunk_t *ac = chunk_get_next_str(ao, \">\", 1, ao->level);\n\n         if (ac)\n         {\n            set_chunk_type(ao, CT_ANGLE_OPEN);\n            set_chunk_parent(ao, CT_OC_PROTO_LIST);\n            set_chunk_type(ac, CT_ANGLE_CLOSE);\n            set_chunk_parent(ac, CT_OC_PROTO_LIST);\n\n            for (tmp = chunk_get_next(ao); tmp != ac; tmp = chunk_get_next(tmp))\n            {\n               tmp->level += 1;\n               set_chunk_parent(tmp, CT_OC_PROTO_LIST);\n            }\n         }\n         tmp = chunk_get_next_ncnl(ac);\n      }\n      LOG_FMT(LOCBLK, \" '%s'\", tmp->text());\n\n      if (tmp->level < pc->level || chunk_is_token(tmp, CT_SEMICOLON))\n      {\n         LOG_FMT(LOCBLK, \"[DONE]\");\n         break;\n      }\n\n      if (tmp->level == pc->level)\n      {\n         if (chunk_is_paren_open(tmp))\n         {\n            apo = tmp;\n            LOG_FMT(LOCBLK, \"[PAREN]\");\n         }\n\n         if (chunk_is_token(tmp, CT_BRACE_OPEN))\n         {\n            LOG_FMT(LOCBLK, \"[BRACE]\");\n            bbo = tmp;\n            break;\n         }\n      }\n   }\n\n   // make sure we have braces\n   bbc = chunk_skip_to_match(bbo);\n\n   if (  bbo == nullptr\n      || bbc == nullptr)\n   {\n      LOG_FMT(LOCBLK, \" -- no braces found\\n\");\n      return;\n   }\n   LOG_FMT(LOCBLK, \"\\n\");\n\n   // we are on a block literal for sure\n   set_chunk_type(pc, CT_OC_BLOCK_CARET);\n   set_chunk_parent(pc, CT_OC_BLOCK_EXPR);\n\n   // handle the optional args\n   chunk_t *lbp; // last before paren - end of return type, if any\n\n   if (apo)\n   {\n      chunk_t *apc = chunk_skip_to_match(apo);  // arg parenthesis close\n\n      if (chunk_is_paren_close(apc))\n      {\n         LOG_FMT(LOCBLK, \" -- marking parens @ apo->orig_line is %zu, apo->orig_col is %zu and apc->orig_line is %zu, apc->orig_col is %zu\\n\",\n                 apo->orig_line, apo->orig_col, apc->orig_line, apc->orig_col);\n         flag_parens(apo, PCF_OC_ATYPE, CT_FPAREN_OPEN, CT_OC_BLOCK_EXPR, true);\n         fix_fcn_def_params(apo);\n      }\n      lbp = chunk_get_prev_ncnlni(apo);   // Issue #2279\n   }\n   else\n   {\n      lbp = chunk_get_prev_ncnlni(bbo);   // Issue #2279\n   }\n\n   // mark the return type, if any\n   while (lbp != pc)\n   {\n      LOG_FMT(LOCBLK, \" -- lbp %s[%s]\\n\", lbp->text(), get_token_name(lbp->type));\n      make_type(lbp);\n      chunk_flags_set(lbp, PCF_OC_RTYPE);\n      set_chunk_parent(lbp, CT_OC_BLOCK_EXPR);\n      lbp = chunk_get_prev_ncnlni(lbp);   // Issue #2279\n   }\n   // mark the braces\n   set_chunk_parent(bbo, CT_OC_BLOCK_EXPR);\n   set_chunk_parent(bbc, CT_OC_BLOCK_EXPR);\n} // handle_oc_block_literal\n\n\nstatic void handle_oc_block_type(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n\n   if (pc == nullptr)\n   {\n      return;\n   }\n\n   if (pc->flags.test(PCF_IN_TYPEDEF))\n   {\n      LOG_FMT(LOCBLK, \"%s(%d): skip block type @ orig_line is %zu, orig_col is %zu, -- in typedef\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col);\n      return;\n   }\n   // make sure we have '( ^'\n   chunk_t *tpo = chunk_get_prev_ncnlni(pc); // type paren open   Issue #2279\n\n   if (chunk_is_paren_open(tpo))\n   {\n      /*\n       * block type: 'RTYPE (^LABEL)(ARGS)'\n       * LABEL is optional.\n       */\n      chunk_t *tpc = chunk_skip_to_match(tpo);   // type close paren (after '^')\n      chunk_t *nam = chunk_get_prev_ncnlni(tpc); // name (if any) or '^'   Issue #2279\n      chunk_t *apo = chunk_get_next_ncnl(tpc);   // arg open paren\n      chunk_t *apc = chunk_skip_to_match(apo);   // arg close paren\n\n      /*\n       * If this is a block literal instead of a block type, 'nam'\n       * will actually be the closing bracket of the block. We run into\n       * this situation if a block literal is enclosed in parentheses.\n       */\n      if (chunk_is_closing_brace(nam))\n      {\n         return(handle_oc_block_literal(pc));\n      }\n\n      // Check apo is '(' or else this might be a block literal. Issue 2643.\n      if (!chunk_is_paren_open(apo))\n      {\n         return(handle_oc_block_literal(pc));\n      }\n\n      if (chunk_is_paren_close(apc))\n      {\n         chunk_t   *aft = chunk_get_next_ncnl(apc);\n         c_token_t pt;\n\n         if (chunk_is_str(nam, \"^\", 1))\n         {\n            set_chunk_type(nam, CT_PTR_TYPE);\n            pt = CT_FUNC_TYPE;\n         }\n         else if (  chunk_is_token(aft, CT_ASSIGN)\n                 || chunk_is_token(aft, CT_SEMICOLON))\n         {\n            set_chunk_type(nam, CT_FUNC_VAR);\n            pt = CT_FUNC_VAR;\n         }\n         else\n         {\n            set_chunk_type(nam, CT_FUNC_TYPE);\n            pt = CT_FUNC_TYPE;\n         }\n         LOG_FMT(LOCBLK, \"%s(%d): block type @ orig_line is %zu, orig_col is %zu, text() '%s'[%s]\\n\",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, nam->text(), get_token_name(nam->type));\n         set_chunk_type(pc, CT_PTR_TYPE);\n         set_chunk_parent(pc, pt);  //CT_OC_BLOCK_TYPE;\n         set_chunk_type(tpo, CT_TPAREN_OPEN);\n         set_chunk_parent(tpo, pt); //CT_OC_BLOCK_TYPE;\n         set_chunk_type(tpc, CT_TPAREN_CLOSE);\n         set_chunk_parent(tpc, pt); //CT_OC_BLOCK_TYPE;\n         set_chunk_type(apo, CT_FPAREN_OPEN);\n         set_chunk_parent(apo, CT_FUNC_PROTO);\n         set_chunk_type(apc, CT_FPAREN_CLOSE);\n         set_chunk_parent(apc, CT_FUNC_PROTO);\n         fix_fcn_def_params(apo);\n         mark_function_return_type(nam, chunk_get_prev_ncnlni(tpo), pt);   // Issue #2279\n      }\n   }\n} // handle_oc_block_type\n\n\nstatic chunk_t *handle_oc_md_type(chunk_t *paren_open, c_token_t ptype, pcf_flags_t flags, bool &did_it)\n{\n   chunk_t *paren_close;\n\n   if (  !chunk_is_paren_open(paren_open)\n      || ((paren_close = chunk_skip_to_match(paren_open)) == nullptr))\n   {\n      did_it = false;\n      return(paren_open);\n   }\n   did_it = true;\n\n   set_chunk_parent(paren_open, ptype);\n   chunk_flags_set(paren_open, flags);\n   set_chunk_parent(paren_close, ptype);\n   chunk_flags_set(paren_close, flags);\n\n   for (chunk_t *cur = chunk_get_next_ncnl(paren_open);\n        cur != paren_close;\n        cur = chunk_get_next_ncnl(cur))\n   {\n      LOG_FMT(LOCMSGD, \" <%s|%s>\", cur->text(), get_token_name(cur->type));\n      chunk_flags_set(cur, flags);\n      make_type(cur);\n   }\n\n   // returning the chunk after the paren close\n   return(chunk_get_next_ncnl(paren_close));\n}\n\n\nstatic void handle_oc_message_decl(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n\n   bool did_it;\n   //bool      in_paren  = false;\n   //int       paren_cnt = 0;\n   //int       arg_cnt   = 0;\n\n   // Figure out if this is a spec or decl\n   chunk_t *tmp = pc;\n\n   while ((tmp = chunk_get_next(tmp)) != nullptr)\n   {\n      if (tmp->level < pc->level)\n      {\n         // should not happen\n         return;\n      }\n\n      if (chunk_is_token(tmp, CT_SEMICOLON) || chunk_is_token(tmp, CT_BRACE_OPEN))\n      {\n         break;\n      }\n   }\n\n   if (tmp == nullptr)\n   {\n      return;\n   }\n   c_token_t pt = (tmp->type == CT_SEMICOLON) ? CT_OC_MSG_SPEC : CT_OC_MSG_DECL;\n\n   set_chunk_type(pc, CT_OC_SCOPE);\n   set_chunk_parent(pc, pt);\n\n   LOG_FMT(LOCMSGD, \"%s(%d): %s @ orig_line is %zu, orig_col is %zu -\",\n           __func__, __LINE__, get_token_name(pt), pc->orig_line, pc->orig_col);\n\n   // format: -(TYPE) NAME [: (TYPE)NAME\n\n   // handle the return type\n   tmp = handle_oc_md_type(chunk_get_next_ncnl(pc), pt, PCF_OC_RTYPE, did_it);\n\n   if (!did_it)\n   {\n      LOG_FMT(LOCMSGD, \" -- missing type parens\\n\");\n      return;\n   }\n\n   // expect the method name/label\n   if (!chunk_is_token(tmp, CT_WORD))\n   {\n      LOG_FMT(LOCMSGD, \" -- missing method name\\n\");\n      return;\n   }  // expect the method name/label\n\n   chunk_t *label = tmp;\n\n   set_chunk_type(tmp, pt);\n   set_chunk_parent(tmp, pt);\n   pc = chunk_get_next_ncnl(tmp);\n\n   LOG_FMT(LOCMSGD, \" [%s]%s\", pc->text(), get_token_name(pc->type));\n\n   // if we have a colon next, we have args\n   if (chunk_is_token(pc, CT_COLON) || chunk_is_token(pc, CT_OC_COLON))\n   {\n      pc = label;\n\n      while (true)\n      {\n         // skip optional label\n         if (chunk_is_token(pc, CT_WORD) || chunk_is_token(pc, pt))\n         {\n            set_chunk_parent(pc, pt);\n            pc = chunk_get_next_ncnl(pc);\n         }\n\n         // a colon must be next\n         if (!chunk_is_str(pc, \":\", 1))\n         {\n            break;\n         }\n         set_chunk_type(pc, CT_OC_COLON);\n         set_chunk_parent(pc, pt);\n         pc = chunk_get_next_ncnl(pc);\n\n         // next is the type in parens\n         LOG_FMT(LOCMSGD, \"  (%s)\", pc->text());\n         tmp = handle_oc_md_type(pc, pt, PCF_OC_ATYPE, did_it);\n\n         if (!did_it)\n         {\n            LOG_FMT(LWARN, \"%s(%d): orig_line is %zu, orig_col is %zu expected type\\n\",\n                    __func__, __LINE__, pc->orig_line, pc->orig_col);\n            break;\n         }\n         // attributes for a method parameter sit between the parameter type and the parameter name\n         pc = skip_attribute_next(tmp);\n         // we should now be on the arg name\n         chunk_flags_set(pc, PCF_VAR_DEF);\n         LOG_FMT(LOCMSGD, \" arg[%s]\", pc->text());\n         pc = chunk_get_next_ncnl(pc);\n      }\n   }\n   LOG_FMT(LOCMSGD, \" end[%s]\", pc->text());\n\n   if (chunk_is_token(pc, CT_BRACE_OPEN))\n   {\n      set_chunk_parent(pc, pt);\n      pc = chunk_skip_to_match(pc);\n\n      if (pc != nullptr)\n      {\n         set_chunk_parent(pc, pt);\n      }\n   }\n   else if (chunk_is_token(pc, CT_SEMICOLON))\n   {\n      set_chunk_parent(pc, pt);\n   }\n   LOG_FMT(LOCMSGD, \"\\n\");\n} // handle_oc_message_decl\n\n\nstatic void handle_oc_message_send(chunk_t *os)\n{\n   LOG_FUNC_ENTRY();\n\n   chunk_t *cs = chunk_get_next(os);\n\n   while (cs != nullptr && cs->level > os->level)\n   {\n      cs = chunk_get_next(cs);\n   }\n\n   if (cs == nullptr || cs->type != CT_SQUARE_CLOSE)\n   {\n      return;\n   }\n   LOG_FMT(LOCMSG, \"%s(%d): orig_line is %zu, orig_col is %zu\\n\",\n           __func__, __LINE__, os->orig_line, os->orig_col);\n\n   chunk_t *tmp = chunk_get_next_ncnl(cs);\n\n   if (chunk_is_semicolon(tmp))\n   {\n      set_chunk_parent(tmp, CT_OC_MSG);\n   }\n   // expect a word first thing or [...]\n   tmp = chunk_get_next_ncnl(os);\n\n   if (  chunk_is_token(tmp, CT_SQUARE_OPEN) || chunk_is_token(tmp, CT_PAREN_OPEN)\n      || (chunk_is_token(tmp, CT_OC_AT)))\n   {\n      chunk_t *tt = chunk_get_next_ncnl(tmp);\n\n      if ((chunk_is_token(tmp, CT_OC_AT)) && tt)\n      {\n         if (  (chunk_is_token(tt, CT_PAREN_OPEN))\n            || (chunk_is_token(tt, CT_BRACE_OPEN))\n            || (chunk_is_token(tt, CT_SQUARE_OPEN)))\n         {\n            tmp = tt;\n         }\n         else\n         {\n            LOG_FMT(LOCMSG, \"%s(%d): tmp->orig_line is %zu, tmp->orig_col is %zu, expected identifier, not '%s' [%s]\\n\",\n                    __func__, __LINE__, tmp->orig_line, tmp->orig_col,\n                    tmp->text(), get_token_name(tmp->type));\n            return;\n         }\n      }\n      tmp = chunk_skip_to_match(tmp);\n   }\n   else if (  tmp->type != CT_WORD\n           && tmp->type != CT_TYPE\n           && tmp->type != CT_THIS\n           && tmp->type != CT_STAR\n           && tmp->type != CT_STRING)\n   {\n      LOG_FMT(LOCMSG, \"%s(%d): orig_line is %zu, orig_col is %zu, expected identifier, not '%s' [%s]\\n\",\n              __func__, __LINE__, tmp->orig_line, tmp->orig_col,\n              tmp->text(), get_token_name(tmp->type));\n      return;\n   }\n   else\n   {\n      if (chunk_is_star(tmp)) // Issue #2722\n      {\n         set_chunk_type(tmp, CT_PTR_TYPE);\n         tmp = chunk_get_next_ncnl(tmp);\n      }\n      chunk_t *tt = chunk_get_next_ncnl(tmp);\n\n      if (chunk_is_paren_open(tt))\n      {\n         LOG_FMT(LFCN, \"%s(%d): (18) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n                 __func__, __LINE__, tmp->orig_line, tmp->orig_col, tmp->text());\n         set_chunk_type(tmp, CT_FUNC_CALL);\n         tmp = chunk_get_prev_ncnlni(set_paren_parent(tt, CT_FUNC_CALL));   // Issue #2279\n      }\n      else\n      {\n         set_chunk_type(tmp, CT_OC_MSG_CLASS);\n      }\n   }\n   set_chunk_parent(os, CT_OC_MSG);\n   chunk_flags_set(os, PCF_IN_OC_MSG);\n   set_chunk_parent(cs, CT_OC_MSG);\n   chunk_flags_set(cs, PCF_IN_OC_MSG);\n\n   // handle '< protocol >'\n   tmp = chunk_get_next_ncnl(tmp);\n\n   if (chunk_is_str(tmp, \"<\", 1))\n   {\n      chunk_t *ao = tmp;\n      chunk_t *ac = chunk_get_next_str(ao, \">\", 1, ao->level);\n\n      if (ac)\n      {\n         set_chunk_type(ao, CT_ANGLE_OPEN);\n         set_chunk_parent(ao, CT_OC_PROTO_LIST);\n         set_chunk_type(ac, CT_ANGLE_CLOSE);\n         set_chunk_parent(ac, CT_OC_PROTO_LIST);\n\n         for (tmp = chunk_get_next(ao); tmp != ac; tmp = chunk_get_next(tmp))\n         {\n            tmp->level += 1;\n            set_chunk_parent(tmp, CT_OC_PROTO_LIST);\n         }\n      }\n      tmp = chunk_get_next_ncnl(ac);\n   }\n   // handle 'object.property' and 'collection[index]'\n   else\n   {\n      while (tmp)\n      {\n         if (chunk_is_token(tmp, CT_MEMBER))  // move past [object.prop1.prop2\n         {\n            chunk_t *typ = chunk_get_next_ncnl(tmp);\n\n            if (chunk_is_token(typ, CT_WORD) || chunk_is_token(typ, CT_TYPE))\n            {\n               tmp = chunk_get_next_ncnl(typ);\n            }\n            else\n            {\n               break;\n            }\n         }\n         else if (chunk_is_token(tmp, CT_SQUARE_OPEN))  // move past [collection[index]\n         {\n            chunk_t *tcs = chunk_get_next_ncnl(tmp);\n\n            while (tcs != nullptr && tcs->level > tmp->level)\n            {\n               tcs = chunk_get_next_ncnl(tcs);\n            }\n\n            if (chunk_is_token(tcs, CT_SQUARE_CLOSE))\n            {\n               tmp = chunk_get_next_ncnl(tcs);\n            }\n            else\n            {\n               break;\n            }\n         }\n         else\n         {\n            break;\n         }\n      }\n   }\n\n   // [(self.foo.bar) method]\n   if (chunk_is_paren_open(tmp))\n   {\n      tmp = chunk_get_next_ncnl(chunk_skip_to_match(tmp));\n   }\n\n   if (chunk_is_token(tmp, CT_WORD) || chunk_is_token(tmp, CT_TYPE))\n   {\n      set_chunk_type(tmp, CT_OC_MSG_FUNC);\n   }\n   chunk_t *prev = nullptr;\n\n   for (tmp = chunk_get_next(os); tmp != cs; tmp = chunk_get_next(tmp))\n   {\n      chunk_flags_set(tmp, PCF_IN_OC_MSG);\n\n      if (tmp->level == cs->level + 1)\n      {\n         if (chunk_is_token(tmp, CT_COLON))\n         {\n            set_chunk_type(tmp, CT_OC_COLON);\n\n            if (chunk_is_token(prev, CT_WORD) || chunk_is_token(prev, CT_TYPE))\n            {\n               // Might be a named param, check previous block\n               chunk_t *pp = chunk_get_prev(prev);\n\n               if (  pp != nullptr\n                  && pp->type != CT_OC_COLON\n                  && pp->type != CT_ARITH\n                  && pp->type != CT_CARET)\n               {\n                  set_chunk_type(prev, CT_OC_MSG_NAME);\n                  set_chunk_parent(tmp, CT_OC_MSG_NAME);\n               }\n            }\n         }\n      }\n      prev = tmp;\n   }\n} // handle_oc_message_send\n\n\nstatic void handle_oc_available(chunk_t *os)\n{\n   os = chunk_get_next(os);\n\n   while (os != nullptr)\n   {\n      c_token_t origType = os->type;\n      set_chunk_type(os, CT_OC_AVAILABLE_VALUE);\n\n      if (origType == CT_PAREN_CLOSE)\n      {\n         break;\n      }\n      os = chunk_get_next(os);\n   }\n}\n\n\nstatic void handle_oc_property_decl(chunk_t *os)\n{\n   log_rule_B(\"mod_sort_oc_properties\");\n\n   if (options::mod_sort_oc_properties())\n   {\n      typedef std::vector<chunk_t *> ChunkGroup;\n\n      chunk_t                 *next       = chunk_get_next(os);\n      chunk_t                 *open_paren = nullptr;\n\n      std::vector<ChunkGroup> class_chunks;       // class\n      std::vector<ChunkGroup> thread_chunks;      // atomic, nonatomic\n      std::vector<ChunkGroup> readwrite_chunks;   // readwrite, readonly\n      std::vector<ChunkGroup> ref_chunks;         // retain, copy, assign, weak, strong, unsafe_unretained\n      std::vector<ChunkGroup> getter_chunks;      // getter\n      std::vector<ChunkGroup> setter_chunks;      // setter\n      std::vector<ChunkGroup> nullability_chunks; // nonnull, nullable, null_unspecified, null_resettable\n      std::vector<ChunkGroup> other_chunks;       // any words other than above\n\n      if (chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         open_paren = next;\n         next       = chunk_get_next(next);\n\n         /*\n          * Determine location of the property attributes\n          * NOTE: Did not do this in the combine.cpp do_symbol_check as\n          * I was not sure what the ramifications of adding a new type\n          * for each of the below types would be. It did break some items\n          * when I attempted to add them so this is my hack for now.\n          */\n         while (next != nullptr && next->type != CT_PAREN_CLOSE)\n         {\n            if (chunk_is_token(next, CT_OC_PROPERTY_ATTR))\n            {\n               if (  chunk_is_str(next, \"atomic\", 6)\n                  || chunk_is_str(next, \"nonatomic\", 9))\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  thread_chunks.push_back(chunkGroup);\n               }\n               else if (  chunk_is_str(next, \"readonly\", 8)\n                       || chunk_is_str(next, \"readwrite\", 9))\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  readwrite_chunks.push_back(chunkGroup);\n               }\n               else if (  chunk_is_str(next, \"assign\", 6)\n                       || chunk_is_str(next, \"retain\", 6)\n                       || chunk_is_str(next, \"copy\", 4)\n                       || chunk_is_str(next, \"strong\", 6)\n                       || chunk_is_str(next, \"weak\", 4)\n                       || chunk_is_str(next, \"unsafe_unretained\", 17))\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  ref_chunks.push_back(chunkGroup);\n               }\n               else if (chunk_is_str(next, \"getter\", 6))\n               {\n                  ChunkGroup chunkGroup;\n\n                  do\n                  {\n                     chunkGroup.push_back(next);\n                     next = chunk_get_next(next);\n                  } while (  next\n                          && next->type != CT_COMMA\n                          && next->type != CT_PAREN_CLOSE);\n\n                  next = next->prev;\n\n                  // coverity CID 160946\n                  if (next == nullptr)\n                  {\n                     break;\n                  }\n                  getter_chunks.push_back(chunkGroup);\n               }\n               else if (chunk_is_str(next, \"setter\", 6))\n               {\n                  ChunkGroup chunkGroup;\n\n                  do\n                  {\n                     chunkGroup.push_back(next);\n                     next = chunk_get_next(next);\n                  } while (  next\n                          && next->type != CT_COMMA\n                          && next->type != CT_PAREN_CLOSE);\n\n                  next = chunk_get_prev(next);\n\n                  if (next == nullptr)\n                  {\n                     break;\n                  }\n                  setter_chunks.push_back(chunkGroup);\n               }\n               else if (  chunk_is_str(next, \"nullable\", 8)\n                       || chunk_is_str(next, \"nonnull\", 7)\n                       || chunk_is_str(next, \"null_resettable\", 15)\n                       || chunk_is_str(next, \"null_unspecified\", 16))\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  nullability_chunks.push_back(chunkGroup);\n               }\n               else if (chunk_is_str(next, \"class\", 5))\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  class_chunks.push_back(chunkGroup);\n               }\n               else\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  other_chunks.push_back(chunkGroup);\n               }\n            }\n            else if (chunk_is_word(next))\n            {\n               if (chunk_is_str(next, \"class\", 5))\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  class_chunks.push_back(chunkGroup);\n               }\n               else\n               {\n                  ChunkGroup chunkGroup;\n                  chunkGroup.push_back(next);\n                  other_chunks.push_back(chunkGroup);\n               }\n            }\n            next = chunk_get_next(next);\n         }\n         log_rule_B(\"mod_sort_oc_property_class_weight\");\n         int class_w = options::mod_sort_oc_property_class_weight();\n         log_rule_B(\"mod_sort_oc_property_thread_safe_weight\");\n         int thread_w = options::mod_sort_oc_property_thread_safe_weight();\n         log_rule_B(\"mod_sort_oc_property_readwrite_weight\");\n         int readwrite_w = options::mod_sort_oc_property_readwrite_weight();\n         log_rule_B(\"mod_sort_oc_property_reference_weight\");\n         int ref_w = options::mod_sort_oc_property_reference_weight();\n         log_rule_B(\"mod_sort_oc_property_getter_weight\");\n         int getter_w = options::mod_sort_oc_property_getter_weight();\n         log_rule_B(\"mod_sort_oc_property_setter_weight\");\n         int setter_w = options::mod_sort_oc_property_setter_weight();\n         log_rule_B(\"mod_sort_oc_property_nullability_weight\");\n         int nullability_w = options::mod_sort_oc_property_nullability_weight();\n\n         //\n         std::multimap<int, std::vector<ChunkGroup> > sorted_chunk_map;\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(class_w, class_chunks));\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(thread_w, thread_chunks));\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(readwrite_w, readwrite_chunks));\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(ref_w, ref_chunks));\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(getter_w, getter_chunks));\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(setter_w, setter_chunks));\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(nullability_w, nullability_chunks));\n         sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(std::numeric_limits<int>::min(), other_chunks));\n\n         chunk_t *curr_chunk = open_paren;\n\n         for (multimap<int, std::vector<ChunkGroup> >::reverse_iterator it = sorted_chunk_map.rbegin(); it != sorted_chunk_map.rend(); ++it)\n         {\n            std::vector<ChunkGroup> chunk_groups = (*it).second;\n\n            for (auto chunk_group : chunk_groups)\n            {\n               for (auto chunk : chunk_group)\n               {\n                  chunk->orig_prev_sp = 0;\n\n                  if (chunk != curr_chunk)\n                  {\n                     chunk_move_after(chunk, curr_chunk);\n                     curr_chunk = chunk;\n                  }\n                  else\n                  {\n                     curr_chunk = chunk_get_next(curr_chunk);\n                  }\n               }\n\n               // add the parenthesis\n               chunk_t endchunk;\n               set_chunk_type(&endchunk, CT_COMMA);\n               set_chunk_parent(&endchunk, get_chunk_parent_type(curr_chunk));\n               endchunk.str         = \",\";\n               endchunk.level       = curr_chunk->level;\n               endchunk.brace_level = curr_chunk->brace_level;\n               endchunk.orig_line   = curr_chunk->orig_line;\n               endchunk.orig_col    = curr_chunk->orig_col;\n               endchunk.column      = curr_chunk->orig_col_end + 1;\n               endchunk.flags       = curr_chunk->flags & PCF_COPY_FLAGS;\n               chunk_add_after(&endchunk, curr_chunk);\n               curr_chunk = curr_chunk->next;\n            }\n         }\n\n         // Remove the extra comma's that we did not move\n         while (curr_chunk && curr_chunk->type != CT_PAREN_CLOSE)\n         {\n            chunk_t *rm_chunk = curr_chunk;\n            curr_chunk = chunk_get_next(curr_chunk);\n            chunk_del(rm_chunk);\n         }\n      }\n   }\n   chunk_t *tmp = chunk_get_next_ncnl(os);\n\n   if (chunk_is_paren_open(tmp))\n   {\n      tmp = chunk_get_next_ncnl(chunk_skip_to_match(tmp));\n   }\n   fix_variable_definition(tmp);\n} // handle_oc_property_decl\n\n\nstatic void handle_cs_square_stmt(chunk_t *os)\n{\n   LOG_FUNC_ENTRY();\n\n   chunk_t *cs = chunk_get_next(os);\n\n   while (cs != nullptr && cs->level > os->level)\n   {\n      cs = chunk_get_next(cs);\n   }\n\n   if (cs == nullptr || cs->type != CT_SQUARE_CLOSE)\n   {\n      return;\n   }\n   set_chunk_parent(os, CT_CS_SQ_STMT);\n   set_chunk_parent(cs, CT_CS_SQ_STMT);\n\n   chunk_t *tmp;\n\n   for (tmp = chunk_get_next(os); tmp != cs; tmp = chunk_get_next(tmp))\n   {\n      set_chunk_parent(tmp, CT_CS_SQ_STMT);\n\n      if (chunk_is_token(tmp, CT_COLON))\n      {\n         set_chunk_type(tmp, CT_CS_SQ_COLON);\n      }\n   }\n\n   tmp = chunk_get_next_ncnl(cs);\n\n   if (tmp != nullptr)\n   {\n      chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);\n   }\n}\n\n\nstatic void handle_cs_property(chunk_t *bro)\n{\n   LOG_FUNC_ENTRY();\n\n   set_paren_parent(bro, CT_CS_PROPERTY);\n\n   bool    did_prop = false;\n   chunk_t *pc      = bro;\n\n   while ((pc = chunk_get_prev_ncnlni(pc)) != nullptr)   // Issue #2279\n   {\n      if (pc->level == bro->level)\n      {\n         //prevent scanning back past 'new' in expressions like new List<int> {1,2,3}\n         // Issue # 1620, UNI-24090.cs\n         if (chunk_is_token(pc, CT_NEW))\n         {\n            break;\n         }\n\n         if (  !did_prop\n            && (chunk_is_token(pc, CT_WORD) || chunk_is_token(pc, CT_THIS)))\n         {\n            set_chunk_type(pc, CT_CS_PROPERTY);\n            did_prop = true;\n         }\n         else\n         {\n            set_chunk_parent(pc, CT_CS_PROPERTY);\n            make_type(pc);\n         }\n\n         if (pc->flags.test(PCF_STMT_START))\n         {\n            break;\n         }\n      }\n   }\n}\n\n\nstatic void handle_cs_array_type(chunk_t *pc)\n{\n   chunk_t *prev;\n\n   for (prev = chunk_get_prev(pc);\n        chunk_is_token(prev, CT_COMMA);\n        prev = chunk_get_prev(prev))\n   {\n      // empty\n   }\n\n   if (chunk_is_token(prev, CT_SQUARE_OPEN))\n   {\n      while (pc != prev)\n      {\n         set_chunk_parent(pc, CT_TYPE);\n         pc = chunk_get_prev(pc);\n      }\n      set_chunk_parent(prev, CT_TYPE);\n   }\n}\n\n\nstatic void handle_wrap(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *opp  = chunk_get_next(pc);\n   chunk_t *name = chunk_get_next(opp);\n   chunk_t *clp  = chunk_get_next(name);\n\n   log_rule_B(\"sp_func_call_paren\");\n   log_rule_B(\"sp_cpp_cast_paren\");\n   iarf_e pav = (pc->type == CT_FUNC_WRAP) ?\n                options::sp_func_call_paren() :\n                options::sp_cpp_cast_paren();\n\n   log_rule_B(\"sp_inside_fparen\");\n   log_rule_B(\"sp_inside_paren_cast\");\n   iarf_e av = (pc->type == CT_FUNC_WRAP) ?\n               options::sp_inside_fparen() :\n               options::sp_inside_paren_cast();\n\n   if (  chunk_is_token(clp, CT_PAREN_CLOSE)\n      && chunk_is_token(opp, CT_PAREN_OPEN)\n      && (chunk_is_token(name, CT_WORD) || chunk_is_token(name, CT_TYPE)))\n   {\n      const char *psp = (pav & IARF_ADD) ? \" \" : \"\";\n      const char *fsp = (av & IARF_ADD) ? \" \" : \"\";\n\n      pc->str.append(psp);\n      pc->str.append(\"(\");\n      pc->str.append(fsp);\n      pc->str.append(name->str);\n      pc->str.append(fsp);\n      pc->str.append(\")\");\n\n      set_chunk_type(pc, (pc->type == CT_FUNC_WRAP) ? CT_FUNCTION : CT_TYPE);\n\n      pc->orig_col_end = pc->orig_col + pc->len();\n\n      chunk_del(opp);\n      chunk_del(name);\n      chunk_del(clp);\n   }\n} // handle_wrap\n\n\nstatic void handle_proto_wrap(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *opp  = chunk_get_next_ncnl(pc);\n   chunk_t *name = chunk_get_next_ncnl(opp);\n   chunk_t *tmp  = chunk_get_next_ncnl(chunk_get_next_ncnl(name));\n   chunk_t *clp  = chunk_skip_to_match(opp);\n   chunk_t *cma  = chunk_get_next_ncnl(clp);\n\n   if (  !opp\n      || !name\n      || !clp\n      || !cma\n      || !tmp\n      || (name->type != CT_WORD && name->type != CT_TYPE)\n      || opp->type != CT_PAREN_OPEN)\n   {\n      return;\n   }\n\n   if (chunk_is_token(cma, CT_SEMICOLON))\n   {\n      set_chunk_type(pc, CT_FUNC_PROTO);\n   }\n   else if (chunk_is_token(cma, CT_BRACE_OPEN))\n   {\n      LOG_FMT(LFCN, \"%s(%d): (19) SET TO CT_FUNC_DEF: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n      set_chunk_type(pc, CT_FUNC_DEF);\n   }\n   else\n   {\n      return;\n   }\n   set_chunk_parent(opp, pc->type);\n   set_chunk_parent(clp, pc->type);\n\n   set_chunk_parent(tmp, CT_PROTO_WRAP);\n\n   if (chunk_is_token(tmp, CT_PAREN_OPEN))\n   {\n      fix_fcn_def_params(tmp);\n   }\n   else\n   {\n      fix_fcn_def_params(opp);\n      set_chunk_type(name, CT_WORD);\n   }\n   tmp = chunk_skip_to_match(tmp);\n\n   if (tmp)\n   {\n      set_chunk_parent(tmp, CT_PROTO_WRAP);\n   }\n   // Mark return type (TODO: move to own function)\n   tmp = pc;\n\n   while ((tmp = chunk_get_prev_ncnlni(tmp)) != nullptr)   // Issue #2279\n   {\n      if (  !chunk_is_type(tmp)\n         && tmp->type != CT_OPERATOR\n         && tmp->type != CT_WORD\n         && tmp->type != CT_ADDR)\n      {\n         break;\n      }\n      set_chunk_parent(tmp, pc->type);\n      make_type(tmp);\n   }\n} // handle_proto_wrap\n\n\n/**\n * Java assert statements are: \"assert EXP1 [: EXP2] ;\"\n * Mark the parent of the colon and semicolon\n */\nstatic void handle_java_assert(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n   bool    did_colon = false;\n   chunk_t *tmp      = pc;\n\n   while ((tmp = chunk_get_next(tmp)) != nullptr)\n   {\n      if (tmp->level == pc->level)\n      {\n         if (!did_colon && chunk_is_token(tmp, CT_COLON))\n         {\n            did_colon = true;\n            set_chunk_parent(tmp, pc->type);\n         }\n\n         if (chunk_is_token(tmp, CT_SEMICOLON))\n         {\n            set_chunk_parent(tmp, pc->type);\n            break;\n         }\n      }\n   }\n}\n\n\n/**\n * @file combine.cpp\n * Labels the chunks as needed.\n *\n * @author  Ben Gardner\n * @author  Guy Maurel since version 0.62 for uncrustify4Qt\n *          October 2015, 2016\n * @license GPL v2+\n */\n\n#include \"combine.h\"\n\n#include \"chunk_list.h\"\n#include \"combine_labels.h\"\n#include \"ChunkStack.h\"\n#include \"error_types.h\"\n#include \"flag_parens.h\"\n#include \"lang_pawn.h\"\n#include \"language_tools.h\"\n#include \"log_rules.h\"\n#include \"newlines.h\"\n#include \"prototypes.h\"\n#include \"tokenize_cleanup.h\"\n#include \"unc_ctype.h\"\n#include \"uncrustify.h\"\n#include \"uncrustify_types.h\"\n\n#include <cassert>\n#include <cstdio>\n#include <cstdlib>\n#include <limits>\n#include <map>\n\nusing namespace std;\nusing namespace uncrustify;\n\n\n/**\n * Mark the parens and colons in:\n *   asm volatile ( \"xx\" : \"xx\" (l), \"yy\"(h) : ...  );\n *\n * @param pc  the CT_ASM item\n */\nstatic void flag_asm(chunk_t *pc);\n\n\n/**\n * Combines two tokens into {{ and }} if inside parens and nothing is between\n * either pair.\n */\nstatic void check_double_brace_init(chunk_t *bo1);\n\n\n/**\n * We are on a typedef.\n * If the next word is not enum/union/struct, then the last word before the\n * next ',' or ';' or '__attribute__' is a type.\n *\n * typedef [type...] [*] type [, [*]type] ;\n * typedef <return type>([*]func)();\n * typedef <return type>([*]func)(params);\n * typedef <return type>(__stdcall *func)(); Bug # 633    MS-specific extension\n *                                           include the config-file \"test/config/MS-calling_conventions.cfg\"\n * typedef <return type>func(params);\n * typedef <enum/struct/union> [type] [*] type [, [*]type] ;\n * typedef <enum/struct/union> [type] { ... } [*] type [, [*]type] ;\n */\nstatic void fix_typedef(chunk_t *pc);\n\n\n/**\n * We are on an enum/struct/union tag that is NOT inside a typedef.\n * If there is a {...} and words before the ';', then they are variables.\n *\n * tag { ... } [*] word [, [*]word] ;\n * tag [word/type] { ... } [*] word [, [*]word] ;\n * enum [word/type [: int_type]] { ... } [*] word [, [*]word] ;\n * tag [word/type] [word]; -- this gets caught later.\n * fcn(tag [word/type] [word])\n * a = (tag [word/type] [*])&b;\n *\n * REVISIT: should this be consolidated with the typedef code?\n */\nstatic void fix_enum_struct_union(chunk_t *pc);\n\n\n/**\n * Checks to see if the current paren is part of a cast.\n * We already verified that this doesn't follow function, TYPE, IF, FOR,\n * SWITCH, or WHILE and is followed by WORD, TYPE, STRUCT, ENUM, or UNION.\n *\n * @param start  Pointer to the open paren\n */\nstatic void fix_casts(chunk_t *pc);\n\n\n/**\n * CT_TYPE_CAST follows this pattern:\n * dynamic_cast<...>(...)\n *\n * Mark everything between the <> as a type and set the paren parent\n */\nstatic void fix_type_cast(chunk_t *pc);\n\n\nstatic void process_returns(void);\n\n\n/**\n * Processes a return statement, labeling the parens and marking the parent.\n * May remove or add parens around the return statement\n *\n * @param pc  Pointer to the return chunk\n */\nstatic chunk_t *process_return(chunk_t *pc);\n\n\n/**\n * TODO: add doc cmt\n *\n */\nstatic pcf_flags_t mark_where_chunk(chunk_t *pc, c_token_t parent_type, pcf_flags_t flags);\n\n\n/**\n * We're on a 'class' or 'struct'.\n * Scan for CT_FUNCTION with a string that matches pclass->str\n */\nstatic void mark_class_ctor(chunk_t *pclass);\n\n\nstatic void mark_cpp_constructor(chunk_t *pc);\n\n\n/**\n *  Just hit an assign. Go backwards until we hit an open brace/paren/square or\n * semicolon (TODO: other limiter?) and mark as a LValue.\n */\nstatic void mark_lvalue(chunk_t *pc);\n\n\n/**\n * We are on a word followed by a angle open which is part of a template.\n * If the angle close is followed by a open paren, then we are on a template\n * function def or a template function call:\n *   Vector2<float>(...) [: ...[, ...]] { ... }\n * Or we could be on a variable def if it's followed by a word:\n *   Renderer<rgb32> rend;\n */\nstatic void mark_template_func(chunk_t *pc, chunk_t *pc_next);\n\n\n/**\n * Just mark every CT_WORD until a semicolon as CT_SQL_WORD.\n * Adjust the levels if pc is CT_SQL_BEGIN\n */\nstatic void mark_exec_sql(chunk_t *pc);\n\n\n/**\n * Process an ObjC 'class'\n * pc is the chunk after '@implementation' or '@interface' or '@protocol'.\n * Change colons, etc. Processes stuff until '@end'.\n * Skips anything in braces.\n */\nstatic void handle_oc_class(chunk_t *pc);\n\n\n/**\n *  Mark Objective-C blocks (aka lambdas or closures)\n *  The syntax and usage is exactly like C function pointers\n *  but instead of an asterisk they have a caret as pointer symbol.\n *  Although it may look expensive this functions is only triggered\n *  on appearance of an OC_BLOCK_CARET for LANG_OC.\n *  repeat(10, ^{ putc('0'+d); });\n *  typedef void (^workBlk_t)(void);\n *\n * @param pc  points to the '^'\n */\nstatic void handle_oc_block_literal(chunk_t *pc);\n\n\n/**\n * Mark Objective-C block types.\n * The syntax and usage is exactly like C function pointers\n * but instead of an asterisk they have a caret as pointer symbol.\n *  typedef void (^workBlk_t)(void);\n *  const char * (^workVar)(void);\n *  -(void)Foo:(void(^)())blk { }\n *\n * This is triggered when the sequence '(' '^' is found.\n *\n * @param pc  points to the '^'\n */\nstatic void handle_oc_block_type(chunk_t *pc);\n\n\n/**\n * Process an ObjC message spec/dec\n *\n * Specs:\n * -(void) foo ARGS;\n *\n * Declaration:\n * -(void) foo ARGS {  }\n *\n * LABEL : (ARGTYPE) ARGNAME\n *\n * ARGS is ': (ARGTYPE) ARGNAME [MOREARGS...]'\n * MOREARGS is ' [ LABEL] : (ARGTYPE) ARGNAME '\n * -(void) foo: (int) arg: {  }\n * -(void) foo: (int) arg: {  }\n * -(void) insertObject:(id)anObject atIndex:(int)index\n */\nstatic void handle_oc_message_decl(chunk_t *pc);\n\n\n/**\n * Process an ObjC message send statement:\n * [ class func: val1 name2: val2 name3: val3] ; // named params\n * [ class func: val1      : val2      : val3] ; // unnamed params\n * [ class <proto> self method ] ; // with protocol\n * [[NSMutableString alloc] initWithString: @\"\" ] // class from msg\n * [func(a,b,c) lastObject ] // class from func\n *\n * Mainly find the matching ']' and ';' and mark the colons.\n *\n * @param pc  points to the open square '['\n */\nstatic void handle_oc_message_send(chunk_t *pc);\n\n\n//! Process @Property values and re-arrange them if necessary\nstatic void handle_oc_property_decl(chunk_t *pc);\n\n//! Process @available annotation\nstatic void handle_oc_available(chunk_t *pc);\n\n/**\n * Process a type that is enclosed in parens in message declarations.\n * TODO: handle block types, which get special formatting\n *\n * @param pc  points to the open paren\n *\n * @return the chunk after the type\n */\nstatic chunk_t *handle_oc_md_type(chunk_t *paren_open, c_token_t ptype, pcf_flags_t flags, bool &did_it);\n\n/**\n * Process an C# [] thingy:\n *    [assembly: xxx]\n *    [AttributeUsage()]\n *    [@X]\n *\n * Set the next chunk to a statement start after the close ']'\n *\n * @param pc  points to the open square '['\n */\nstatic void handle_cs_square_stmt(chunk_t *pc);\n\n\n/**\n * We are on a brace open that is preceded by a word or square close.\n * Set the brace parent to CT_CS_PROPERTY and find the first item in the\n * property and set its parent, too.\n */\nstatic void handle_cs_property(chunk_t *pc);\n\n\n/**\n * We hit a ']' followed by a WORD. This may be a multidimensional array type.\n * Example: int[,,] x;\n * If there is nothing but commas between the open and close, then mark it.\n */\nstatic void handle_cs_array_type(chunk_t *pc);\n\n\n/**\n * We are on the C++ 'template' keyword.\n * What follows should be the following:\n *\n * template <class identifier> function_declaration;\n * template <typename identifier> function_declaration;\n * template <class identifier> class class_declaration;\n * template <typename identifier> class class_declaration;\n *\n * Change the 'class' inside the <> to CT_TYPE.\n * Set the parent to the class after the <> to CT_TEMPLATE.\n * Set the parent of the semicolon to CT_TEMPLATE.\n */\nstatic void handle_cpp_template(chunk_t *pc);\n\n\n/**\n * Verify and then mark C++ lambda expressions.\n * The expected format is '[...](...){...}' or '[...](...) -> type {...}'\n * sq_o is '[' CT_SQUARE_OPEN or '[]' CT_TSQUARE\n * Split the '[]' so we can control the space\n */\nstatic void handle_cpp_lambda(chunk_t *pc);\n\n\n/**\n * We are on the D 'template' keyword.\n * What follows should be the following:\n *\n * template NAME ( TYPELIST ) { BODY }\n *\n * Set the parent of NAME to template, change NAME to CT_TYPE.\n * Set the parent of the parens and braces to CT_TEMPLATE.\n * Scan the body for each type in TYPELIST and change the type to CT_TYPE.\n */\nstatic void handle_d_template(chunk_t *pc);\n\n\n/**\n * A func wrap chunk and what follows should be treated as a function name.\n * Create new text for the chunk and call it a CT_FUNCTION.\n *\n * A type wrap chunk and what follows should be treated as a simple type.\n * Create new text for the chunk and call it a CT_TYPE.\n */\nstatic void handle_wrap(chunk_t *pc);\n\n\n/**\n * A proto wrap chunk and what follows should be treated as a function proto.\n *\n * RETTYPE PROTO_WRAP( NAME, PARAMS ); or RETTYPE PROTO_WRAP( NAME, (PARAMS) );\n * RETTYPE gets changed with make_type().\n * PROTO_WRAP is marked as CT_FUNC_PROTO or CT_FUNC_DEF.\n * NAME is marked as CT_WORD.\n * PARAMS is all marked as prototype parameters.\n */\nstatic void handle_proto_wrap(chunk_t *pc);\n\n\nstatic bool is_oc_block(chunk_t *pc);\n\n\n/**\n * Java assert statements are: \"assert EXP1 [: EXP2] ;\"\n * Mark the parent of the colon and semicolon\n */\nstatic void handle_java_assert(chunk_t *pc);\n\n\n/**\n * Parse off the types in the D template args, adds to cs\n * returns the close_paren\n */\nstatic chunk_t *get_d_template_types(ChunkStack &cs, chunk_t *open_paren);\n\n\nstatic bool chunkstack_match(ChunkStack &cs, chunk_t *pc);\n\n\nvoid make_type(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n\n   if (pc != nullptr)\n   {\n      if (chunk_is_token(pc, CT_WORD))\n      {\n         set_chunk_type(pc, CT_TYPE);\n      }\n      else if (  (  chunk_is_star(pc)\n                 || chunk_is_msref(pc)\n                 || chunk_is_nullable(pc))\n              && chunk_is_type(pc->prev))                              // Issue # 2640\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n      else if (  chunk_is_addr(pc)\n              && !chunk_is_token(pc->prev, CT_SQUARE_OPEN))            // Issue # 2166\n      {\n         set_chunk_type(pc, CT_BYREF);\n      }\n   }\n}\n\n\nvoid flag_series(chunk_t *start, chunk_t *end, pcf_flags_t set_flags, pcf_flags_t clr_flags, scope_e nav)\n{\n   LOG_FUNC_ENTRY();\n\n   while (start != nullptr && start != end)\n   {\n      chunk_flags_upd(start, clr_flags, set_flags);\n\n      start = chunk_get_next(start, nav);\n\n      if (start == nullptr)\n      {\n         return;\n      }\n   }\n\n   if (end != nullptr)\n   {\n      chunk_flags_upd(end, clr_flags, set_flags);\n   }\n}\n\n\nchunk_t *set_paren_parent(chunk_t *start, c_token_t parent)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *end;\n\n   end = chunk_skip_to_match(start, scope_e::PREPROC);\n\n   if (end != nullptr)\n   {\n      LOG_FMT(LFLPAREN, \"%s(%d): %zu:%zu '%s' and %zu:%zu '%s' type is %s, parent_type is %s\",\n              __func__, __LINE__, start->orig_line, start->orig_col, start->text(),\n              end->orig_line, end->orig_col, end->text(),\n              get_token_name(start->type), get_token_name(parent));\n      log_func_stack_inline(LFLPAREN);\n      set_chunk_parent(start, parent);\n      set_chunk_parent(end, parent);\n   }\n   LOG_FMT(LFLPAREN, \"%s(%d):\\n\", __func__, __LINE__);\n   return(chunk_get_next_ncnl(end, scope_e::PREPROC));\n}\n\n\nstatic void flag_asm(chunk_t *pc)\n{\n   LOG_FUNC_ENTRY();\n\n   chunk_t *tmp = chunk_get_next_ncnl(pc, scope_e::PREPROC);\n\n   if (!chunk_is_token(tmp, CT_QUALIFIER))\n   {\n      return;\n   }\n   chunk_t *po = chunk_get_next_ncnl(tmp, scope_e::PREPROC);\n\n   if (!chunk_is_paren_open(po))\n   {\n      return;\n   }\n   chunk_t *end = chunk_skip_to_match(po, scope_e::PREPROC);\n\n   if (end == nullptr)\n   {\n      return;\n   }\n   set_chunk_parent(po, CT_ASM);\n   set_chunk_parent(end, CT_ASM);\n\n   for (  tmp = chunk_get_next_ncnl(po, scope_e::PREPROC);\n          tmp != nullptr\n       && tmp != end;\n          tmp = chunk_get_next_ncnl(tmp, scope_e::PREPROC))\n   {\n      if (chunk_is_token(tmp, CT_COLON))\n      {\n         set_chunk_type(tmp, CT_ASM_COLON);\n      }\n      else if (chunk_is_token(tmp, CT_DC_MEMBER))\n      {\n         // if there is a string on both sides, then this is two ASM_COLONs\n         if (  chunk_is_token(chunk_get_next_ncnl(tmp, scope_e::PREPROC), CT_STRING)\n            && chunk_is_token(chunk_get_prev_ncnlni(tmp, scope_e::PREPROC), CT_STRING)) // Issue #2279\n         {\n            chunk_t nc;\n\n            nc = *tmp;\n\n            tmp->str.resize(1);\n            tmp->orig_col_end = tmp->orig_col + 1;\n            set_chunk_type(tmp, CT_ASM_COLON);\n\n            set_chunk_type(&nc, tmp->type);\n            nc.str.pop_front();\n            nc.orig_col++;\n            nc.column++;\n            chunk_add_after(&nc, tmp);\n         }\n      }\n   }\n\n   tmp = chunk_get_next_ncnl(end, scope_e::PREPROC);\n\n   if (tmp == nullptr)\n   {\n      return;\n   }\n\n   if (chunk_is_token(tmp, CT_SEMICOLON))\n   {\n      set_chunk_parent(tmp, CT_ASM);\n   }\n} // flag_asm\n\n\nstatic bool chunk_ends_type(chunk_t *start)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *pc       = start;\n   bool    ret       = false;\n   size_t  cnt       = 0;\n   bool    last_expr = false;\n   bool    last_lval = false;\n\n   for ( ; pc != nullptr; pc = chunk_get_prev_ncnlni(pc)) // Issue #2279\n   {\n      LOG_FMT(LFTYPE, \"%s(%d): type is %s, text() '%s', orig_line %zu, orig_col %zu\\n   \",\n              __func__, __LINE__, get_token_name(pc->type), pc->text(),\n              pc->orig_line, pc->orig_col);\n      log_pcf_flags(LFTYPE, pc->flags);\n\n      if (  chunk_is_token(pc, CT_WORD)\n         || chunk_is_token(pc, CT_TYPE)\n         || chunk_is_token(pc, CT_PTR_TYPE)\n         || chunk_is_token(pc, CT_STAR)\n         || chunk_is_token(pc, CT_STRUCT)\n         || chunk_is_token(pc, CT_DC_MEMBER)\n         || chunk_is_token(pc, CT_PP)\n         || chunk_is_token(pc, CT_QUALIFIER)\n         || (  language_is_set(LANG_CPP | LANG_OC)                       // Issue #2727\n            && get_chunk_parent_type(pc) == CT_TEMPLATE\n            && (  chunk_is_token(pc, CT_ANGLE_OPEN)\n               || chunk_is_token(pc, CT_ANGLE_CLOSE)))\n         || (  language_is_set(LANG_CS)\n            && (chunk_is_token(pc, CT_MEMBER))))\n      {\n         cnt++;\n         last_expr = pc->flags.test(PCF_EXPR_START)\n                     && !pc->flags.test(PCF_IN_FCN_CALL);\n         last_lval = pc->flags.test(PCF_LVALUE);\n         continue;\n      }\n\n      if (  (  chunk_is_semicolon(pc)\n            && !pc->flags.test(PCF_IN_FOR))\n         || chunk_is_token(pc, CT_TYPEDEF)\n         || chunk_is_token(pc, CT_BRACE_OPEN)\n         || chunk_is_token(pc, CT_BRACE_CLOSE)\n         || chunk_is_token(pc, CT_VBRACE_CLOSE)\n         || chunk_is_token(pc, CT_FPAREN_CLOSE)\n         || chunk_is_forin(pc)\n         || chunk_is_token(pc, CT_MACRO)\n         || chunk_is_token(pc, CT_PP_IF)\n         || chunk_is_token(pc, CT_PP_ELSE)\n         || chunk_is_token(pc, CT_PP_ENDIF)\n         || (  (  chunk_is_token(pc, CT_COMMA)\n               && !pc->flags.test(PCF_IN_FCN_CALL))\n            && last_expr)\n         || (  chunk_is_token(pc, CT_SPAREN_OPEN)\n            && last_lval))\n      {\n         ret = cnt > 0;\n      }\n      break;\n   }\n\n   if (pc == nullptr)\n   {\n      // first token\n      ret = true;\n   }\n   LOG_FMT(LFTYPE, \"%s(%d): first token verdict: %s\\n\",\n           __func__, __LINE__, ret ? \"yes\" : \"no\");\n\n   return(ret);\n} // chunk_ends_type\n\n\nvoid do_symbol_check(chunk_t *prev, chunk_t *pc, chunk_t *next)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *tmp;\n\n   // separate the uses of CT_ASSIGN sign '='\n   // into CT_ASSIGN_DEFAULT_ARG, CT_ASSIGN_FUNC_PROTO\n   if (  chunk_is_token(pc, CT_ASSIGN)\n      && get_chunk_parent_type(pc) == CT_FUNC_PROTO\n      && (  pc->flags.test(PCF_IN_FCN_DEF)                            // Issue #2236\n         || pc->flags.test(PCF_IN_CONST_ARGS)))\n   {\n      LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n      log_pcf_flags(LFCNR, pc->flags);\n      set_chunk_type(pc, CT_ASSIGN_DEFAULT_ARG);\n   }\n\n   if (  (  chunk_is_token(prev, CT_FPAREN_CLOSE)\n         || (  (  chunk_is_str(prev, \"const\", 5)\n               || chunk_is_str(prev, \"override\", 8))\n            && chunk_is_token(prev->prev, CT_FPAREN_CLOSE)))\n      && chunk_is_token(pc, CT_ASSIGN)\n      && (  chunk_is_token(next, CT_DEFAULT)\n         || chunk_is_token(next, CT_DELETE)\n         || chunk_is_str(next, \"0\", 1)))\n   {\n      set_chunk_type(pc, CT_ASSIGN_FUNC_PROTO);\n   }\n\n   if (chunk_is_token(pc, CT_OC_AT))\n   {\n      if (  chunk_is_token(next, CT_PAREN_OPEN)\n         || chunk_is_token(next, CT_BRACE_OPEN)\n         || chunk_is_token(next, CT_SQUARE_OPEN))\n      {\n         flag_parens(next, PCF_OC_BOXED, next->type, CT_OC_AT, false);\n      }\n      else\n      {\n         set_chunk_parent(next, CT_OC_AT);\n      }\n   }\n\n   // D stuff\n   if (  language_is_set(LANG_D)\n      && chunk_is_token(pc, CT_QUALIFIER)\n      && chunk_is_str(pc, \"const\", 5)\n      && chunk_is_token(next, CT_PAREN_OPEN))\n   {\n      set_chunk_type(pc, CT_D_CAST);\n      set_paren_parent(next, pc->type);\n   }\n\n   if (  chunk_is_token(next, CT_PAREN_OPEN)\n      && (  chunk_is_token(pc, CT_D_CAST)\n         || chunk_is_token(pc, CT_DELEGATE)\n         || chunk_is_token(pc, CT_ALIGN)))\n   {\n      // mark the parenthesis parent\n      tmp = set_paren_parent(next, pc->type);\n\n      // For a D cast - convert the next item\n      if (  chunk_is_token(pc, CT_D_CAST)\n         && tmp != nullptr)\n      {\n         if (chunk_is_token(tmp, CT_STAR))\n         {\n            set_chunk_type(tmp, CT_DEREF);\n         }\n         else if (chunk_is_token(tmp, CT_AMP))\n         {\n            set_chunk_type(tmp, CT_ADDR);\n         }\n         else if (chunk_is_token(tmp, CT_MINUS))\n         {\n            set_chunk_type(tmp, CT_NEG);\n         }\n         else if (chunk_is_token(tmp, CT_PLUS))\n         {\n            set_chunk_type(tmp, CT_POS);\n         }\n      }\n\n      /*\n       * For a delegate, mark previous words as types and the item after the\n       * close paren as a variable def\n       */\n      if (chunk_is_token(pc, CT_DELEGATE))\n      {\n         if (tmp != nullptr)\n         {\n            set_chunk_parent(tmp, CT_DELEGATE);\n\n            if (tmp->level == tmp->brace_level)\n            {\n               chunk_flags_set(tmp, PCF_VAR_1ST_DEF);\n            }\n         }\n\n         for (tmp = chunk_get_prev_ncnlni(pc); tmp != nullptr; tmp = chunk_get_prev_ncnlni(tmp)) // Issue #2279\n         {\n            if (  chunk_is_semicolon(tmp)\n               || chunk_is_token(tmp, CT_BRACE_OPEN)\n               || chunk_is_token(tmp, CT_VBRACE_OPEN))\n            {\n               break;\n            }\n            make_type(tmp);\n         }\n      }\n\n      if (  chunk_is_token(pc, CT_ALIGN)\n         && tmp != nullptr)\n      {\n         if (chunk_is_token(tmp, CT_BRACE_OPEN))\n         {\n            set_paren_parent(tmp, pc->type);\n         }\n         else if (chunk_is_token(tmp, CT_COLON))\n         {\n            set_chunk_parent(tmp, pc->type);\n         }\n      }\n   } // paren open + cast/align/delegate\n\n   if (chunk_is_token(pc, CT_INVARIANT))\n   {\n      if (chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         set_chunk_parent(next, pc->type);\n         tmp = chunk_get_next(next);\n\n         while (tmp != nullptr)\n         {\n            if (chunk_is_token(tmp, CT_PAREN_CLOSE))\n            {\n               set_chunk_parent(tmp, pc->type);\n               break;\n            }\n            make_type(tmp);\n            tmp = chunk_get_next(tmp);\n         }\n      }\n      else\n      {\n         set_chunk_type(pc, CT_QUALIFIER);\n      }\n   }\n\n   if (  chunk_is_token(prev, CT_BRACE_OPEN)\n      && get_chunk_parent_type(prev) != CT_CS_PROPERTY\n      && (  chunk_is_token(pc, CT_GETSET)\n         || chunk_is_token(pc, CT_GETSET_EMPTY)))\n   {\n      flag_parens(prev, PCF_NONE, CT_NONE, CT_GETSET, false);\n   }\n\n   if (chunk_is_token(pc, CT_ASM))\n   {\n      flag_asm(pc);\n   }\n\n   // clang stuff - A new derived type is introduced to C and, by extension, Objective-C, C++, and Objective-C++\n   if (language_is_set(LANG_C | LANG_CPP | LANG_OC))\n   {\n      if (chunk_is_token(pc, CT_CARET))\n      {\n         if (  pc->flags.test(PCF_EXPR_START)\n            || pc->flags.test(PCF_IN_PREPROC))\n         {\n            handle_oc_block_literal(pc);\n         }\n      }\n   }\n\n   // Objective C stuff\n   if (language_is_set(LANG_OC))\n   {\n      // Check for message declarations\n      if (pc->flags.test(PCF_STMT_START))\n      {\n         if (  (  chunk_is_str(pc, \"-\", 1)\n               || chunk_is_str(pc, \"+\", 1))\n            && chunk_is_str(next, \"(\", 1))\n         {\n            handle_oc_message_decl(pc);\n         }\n      }\n\n      if (  pc->flags.test(PCF_EXPR_START)\n         || pc->flags.test(PCF_IN_PREPROC))\n      {\n         if (chunk_is_token(pc, CT_SQUARE_OPEN))\n         {\n            handle_oc_message_send(pc);\n         }\n      }\n\n      if (chunk_is_token(pc, CT_OC_PROPERTY))\n      {\n         handle_oc_property_decl(pc);\n      }\n\n      if (chunk_is_token(pc, CT_OC_AVAILABLE))\n      {\n         handle_oc_available(pc);\n      }\n   }\n\n   // C# stuff\n   if (language_is_set(LANG_CS))\n   {\n      // '[assembly: xxx]' stuff\n      if (  pc->flags.test(PCF_EXPR_START)\n         && chunk_is_token(pc, CT_SQUARE_OPEN))\n      {\n         handle_cs_square_stmt(pc);\n      }\n\n      if (  chunk_is_token(next, CT_BRACE_OPEN)\n         && get_chunk_parent_type(next) == CT_NONE\n         && (  chunk_is_token(pc, CT_SQUARE_CLOSE)\n            || chunk_is_token(pc, CT_ANGLE_CLOSE)\n            || chunk_is_token(pc, CT_WORD)))\n      {\n         handle_cs_property(next);\n      }\n\n      if (  chunk_is_token(pc, CT_SQUARE_CLOSE)\n         && chunk_is_token(next, CT_WORD))\n      {\n         handle_cs_array_type(pc);\n      }\n\n      if (  (  chunk_is_token(pc, CT_LAMBDA)\n            || chunk_is_token(pc, CT_DELEGATE))\n         && chunk_is_token(next, CT_BRACE_OPEN))\n      {\n         set_paren_parent(next, pc->type);\n      }\n\n      if (chunk_is_token(pc, CT_WHEN) && pc->next->type != CT_SPAREN_OPEN)\n      {\n         set_chunk_type(pc, CT_WORD);\n      }\n   }\n\n   if (  language_is_set(LANG_JAVA)\n      && chunk_is_token(pc, CT_LAMBDA)\n      && chunk_is_token(next, CT_BRACE_OPEN))\n   {\n      set_paren_parent(next, pc->type);\n   }\n\n   if (chunk_is_token(pc, CT_NEW))\n   {\n      chunk_t *ts = nullptr;\n      tmp = next;\n\n      if (chunk_is_token(tmp, CT_TSQUARE))\n      {\n         ts  = tmp;\n         tmp = chunk_get_next_ncnl(tmp);\n      }\n\n      if (  chunk_is_token(tmp, CT_BRACE_OPEN)\n         || chunk_is_token(tmp, CT_PAREN_OPEN))\n      {\n         set_paren_parent(tmp, pc->type);\n\n         if (ts != nullptr)\n         {\n            set_chunk_parent(ts, pc->type);\n         }\n      }\n   }\n\n   // C++11 Lambda stuff\n   if (  language_is_set(LANG_CPP)\n      && (  chunk_is_token(pc, CT_SQUARE_OPEN)\n         || chunk_is_token(pc, CT_TSQUARE)))\n   {\n      handle_cpp_lambda(pc);\n   }\n\n   // FIXME: which language does this apply to?\n   // Issue #2432\n   if (!language_is_set(LANG_OC))\n   {\n      if (  chunk_is_token(pc, CT_ASSIGN)\n         && chunk_is_token(next, CT_SQUARE_OPEN))\n      {\n         set_paren_parent(next, CT_ASSIGN);\n\n         // Mark one-liner assignment\n         tmp = next;\n\n         while ((tmp = chunk_get_next_nc(tmp)) != nullptr)\n         {\n            if (chunk_is_newline(tmp))\n            {\n               break;\n            }\n\n            if (chunk_is_token(tmp, CT_SQUARE_CLOSE) && next->level == tmp->level)\n            {\n               chunk_flags_set(tmp, PCF_ONE_LINER);\n               chunk_flags_set(next, PCF_ONE_LINER);\n               break;\n            }\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_ASSERT))\n   {\n      handle_java_assert(pc);\n   }\n\n   if (chunk_is_token(pc, CT_ANNOTATION))\n   {\n      tmp = chunk_get_next_ncnl(pc);\n\n      if (chunk_is_paren_open(tmp))\n      {\n         set_paren_parent(tmp, CT_ANNOTATION);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_SIZEOF) && language_is_set(LANG_ALLC))\n   {\n      tmp = chunk_get_next_ncnl(pc);\n\n      if (chunk_is_token(tmp, CT_ELLIPSIS))\n      {\n         set_chunk_parent(tmp, CT_SIZEOF);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_DECLTYPE))\n   {\n      tmp = chunk_get_next_ncnl(pc);\n\n      if (chunk_is_paren_open(tmp))\n      {\n         // decltype may be followed by a braced-init-list\n         tmp = set_paren_parent(tmp, CT_DECLTYPE);\n\n         if (chunk_is_opening_brace(tmp))\n         {\n            tmp = set_paren_parent(tmp, CT_BRACED_INIT_LIST);\n\n            if (tmp)\n            {\n               chunk_flags_clr(tmp, PCF_EXPR_START | PCF_STMT_START);\n            }\n         }\n         else\n         {\n            if (chunk_is_token(tmp, CT_WORD))\n            {\n               chunk_flags_set(tmp, PCF_VAR_1ST_DEF);\n            }\n         }\n      }\n   }\n\n   // A [] in C# and D only follows a type\n   if (  chunk_is_token(pc, CT_TSQUARE)\n      && language_is_set(LANG_D | LANG_CS | LANG_VALA))\n   {\n      if (chunk_is_token(prev, CT_WORD))\n      {\n         set_chunk_type(prev, CT_TYPE);\n      }\n\n      if (chunk_is_token(next, CT_WORD))\n      {\n         chunk_flags_set(next, PCF_VAR_1ST_DEF);\n      }\n   }\n\n   if (  chunk_is_token(pc, CT_SQL_EXEC)\n      || chunk_is_token(pc, CT_SQL_BEGIN)\n      || chunk_is_token(pc, CT_SQL_END))\n   {\n      mark_exec_sql(pc);\n   }\n\n   if (chunk_is_token(pc, CT_PROTO_WRAP))\n   {\n      handle_proto_wrap(pc);\n   }\n\n   // Handle the typedef\n   if (chunk_is_token(pc, CT_TYPEDEF))\n   {\n      fix_typedef(pc);\n   }\n\n   if (  chunk_is_token(pc, CT_ENUM)\n      || chunk_is_token(pc, CT_STRUCT)\n      || chunk_is_token(pc, CT_UNION)\n      || (  chunk_is_token(pc, CT_CLASS)\n         && !language_is_set(LANG_D)))\n   {\n      if (prev->type != CT_TYPEDEF)\n      {\n         fix_enum_struct_union(pc);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_EXTERN))\n   {\n      if (chunk_is_paren_open(next))\n      {\n         tmp = flag_parens(next, PCF_NONE, CT_NONE, CT_EXTERN, true);\n\n         if (chunk_is_token(tmp, CT_BRACE_OPEN))\n         {\n            set_paren_parent(tmp, CT_EXTERN);\n         }\n      }\n      else\n      {\n         // next likely is a string (see tokenize_cleanup.cpp)\n         set_chunk_parent(next, CT_EXTERN);\n         tmp = chunk_get_next_ncnl(next);\n\n         if (chunk_is_token(tmp, CT_BRACE_OPEN))\n         {\n            set_paren_parent(tmp, CT_EXTERN);\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_TEMPLATE))\n   {\n      if (language_is_set(LANG_D))\n      {\n         handle_d_template(pc);\n      }\n      else\n      {\n         handle_cpp_template(pc);\n      }\n   }\n\n   if (  chunk_is_token(pc, CT_WORD)\n      && chunk_is_token(next, CT_ANGLE_OPEN)\n      && get_chunk_parent_type(next) == CT_TEMPLATE)\n   {\n      mark_template_func(pc, next);\n   }\n\n   if (  chunk_is_token(pc, CT_SQUARE_CLOSE)\n      && chunk_is_token(next, CT_PAREN_OPEN))\n   {\n      flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_NONE, false);\n   }\n\n   if (chunk_is_token(pc, CT_TYPE_CAST))\n   {\n      fix_type_cast(pc);\n   }\n\n   if (  get_chunk_parent_type(pc) == CT_ASSIGN\n      && (chunk_is_token(pc, CT_BRACE_OPEN) || chunk_is_token(pc, CT_SQUARE_OPEN)))\n   {\n      // Mark everything in here as in assign\n      flag_parens(pc, PCF_IN_ARRAY_ASSIGN, pc->type, CT_NONE, false);\n   }\n\n   if (chunk_is_token(pc, CT_D_TEMPLATE))\n   {\n      set_paren_parent(next, pc->type);\n   }\n\n   /*\n    * A word before an open paren is a function call or definition.\n    * CT_WORD => CT_FUNC_CALL or CT_FUNC_DEF\n    */\n   if (chunk_is_token(next, CT_PAREN_OPEN))\n   {\n      tmp = chunk_get_next_ncnl(next);\n\n      if (  language_is_set(LANG_C | LANG_CPP | LANG_OC)\n         && chunk_is_token(tmp, CT_CARET))\n      {\n         handle_oc_block_type(tmp);\n\n         // This is the case where a block literal is passed as the first argument of a C-style method invocation.\n         if (  (  chunk_is_token(tmp, CT_OC_BLOCK_CARET)\n               || chunk_is_token(tmp, CT_CARET))\n            && chunk_is_token(pc, CT_WORD))\n         {\n            LOG_FMT(LFCN, \"%s(%d): (1) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n                    __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n            set_chunk_type(pc, CT_FUNC_CALL);\n         }\n      }\n      else if (  chunk_is_token(pc, CT_WORD)\n              || chunk_is_token(pc, CT_OPERATOR_VAL))\n      {\n         set_chunk_type(pc, CT_FUNCTION);\n      }\n      else if (chunk_is_token(pc, CT_FIXED))\n      {\n         set_chunk_type(pc, CT_FUNCTION);\n         set_chunk_parent(pc, CT_FIXED);\n      }\n      else if (chunk_is_token(pc, CT_TYPE))\n      {\n         /*\n          * If we are on a type, then we are either on a C++ style cast, an\n          * array reference, a function or we are on a function type.\n          * The only way to tell for sure is to find the close paren and see\n          * if it is followed by an open paren.\n          * \"int(5.6)\"\n          * \"int()\"\n          * \"int(foo)(void)\"\n          *\n          * FIXME: this check can be done better...\n          */\n         LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n\n         bool is_byref_array = false;\n\n         if (language_is_set(LANG_CPP))\n         {\n            // If the open paren is followed by an ampersand, an optional word,\n            // a close parenthesis, and an open square bracket, then it is an\n            // array being passed by reference, not a cast\n            tmp = chunk_get_next_ncnl(next);\n\n            if (chunk_is_token(tmp, CT_AMP))\n            {\n               auto tmp2 = chunk_get_next_ncnl(tmp);\n\n               if (chunk_is_token(tmp2, CT_WORD))\n               {\n                  tmp2 = chunk_get_next_ncnl(tmp2);\n               }\n\n               if (chunk_is_token(tmp2, CT_PAREN_CLOSE))\n               {\n                  tmp2 = chunk_get_next_ncnl(tmp2);\n\n                  if (chunk_is_token(tmp2, CT_SQUARE_OPEN))\n                  {\n                     is_byref_array = true;\n                     set_chunk_type(tmp, CT_BYREF);\n                  }\n               }\n            }\n         }\n\n         if (!is_byref_array)\n         {\n            tmp = chunk_get_next_type(next, CT_PAREN_CLOSE, next->level);\n\n            if (tmp != nullptr)\n            {\n               tmp = chunk_get_next(tmp);\n\n               if (chunk_is_token(tmp, CT_PAREN_OPEN))\n               {\n                  set_chunk_type(pc, CT_FUNCTION);\n               }\n               else\n               {\n                  if (  get_chunk_parent_type(pc) == CT_NONE\n                     && !pc->flags.test(PCF_IN_TYPEDEF))\n                  {\n                     tmp = chunk_get_next_ncnl(next);\n\n                     if (chunk_is_token(tmp, CT_PAREN_CLOSE))\n                     {\n                        // we have TYPE()\n                        set_chunk_type(pc, CT_FUNCTION);\n                     }\n                     else\n                     {\n                        // we have TYPE(...)\n                        set_chunk_type(pc, CT_CPP_CAST);\n                        set_paren_parent(next, CT_CPP_CAST);\n                     }\n                  }\n               }\n            }\n         }\n      }\n   }\n\n   if (language_is_set(LANG_PAWN))\n   {\n      if (  chunk_is_token(pc, CT_FUNCTION)\n         && pc->brace_level > 0)\n      {\n         LOG_FMT(LFCN, \"%s(%d): (2) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n         set_chunk_type(pc, CT_FUNC_CALL);\n      }\n\n      if (  chunk_is_token(pc, CT_STATE)\n         && chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         set_paren_parent(next, pc->type);\n      }\n   }\n   else\n   {\n      if (  (  chunk_is_token(pc, CT_FUNCTION)\n            || chunk_is_token(pc, CT_FUNC_DEF))\n         && (  (get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR)\n            || !is_oc_block(pc)))\n      {\n         mark_function(pc);\n      }\n   }\n\n   // Detect C99 member stuff\n   if (  chunk_is_token(pc, CT_MEMBER)\n      && (  chunk_is_token(prev, CT_COMMA)\n         || chunk_is_token(prev, CT_BRACE_OPEN)))\n   {\n      set_chunk_type(pc, CT_C99_MEMBER);\n      set_chunk_parent(next, CT_C99_MEMBER);\n   }\n\n   // Mark function parens and braces\n   if (  chunk_is_token(pc, CT_FUNC_DEF)\n      || chunk_is_token(pc, CT_FUNC_CALL)\n      || chunk_is_token(pc, CT_FUNC_CALL_USER)\n      || chunk_is_token(pc, CT_FUNC_PROTO))\n   {\n      tmp = next;\n\n      if (chunk_is_token(tmp, CT_SQUARE_OPEN))\n      {\n         tmp = set_paren_parent(tmp, pc->type);\n      }\n      else if (chunk_is_token(tmp, CT_TSQUARE) || get_chunk_parent_type(tmp) == CT_OPERATOR)\n      {\n         tmp = chunk_get_next_ncnl(tmp);\n      }\n\n      if (tmp != nullptr)\n      {\n         if (chunk_is_paren_open(tmp))\n         {\n            tmp = flag_parens(tmp, PCF_NONE, CT_FPAREN_OPEN, pc->type, false);\n\n            if (tmp != nullptr)\n            {\n               if (chunk_is_token(tmp, CT_BRACE_OPEN))\n               {\n                  if (  get_chunk_parent_type(tmp) != CT_DOUBLE_BRACE\n                     && !pc->flags.test(PCF_IN_CONST_ARGS))\n                  {\n                     set_paren_parent(tmp, pc->type);\n                  }\n               }\n               else if (  chunk_is_semicolon(tmp)\n                       && chunk_is_token(pc, CT_FUNC_PROTO))\n               {\n                  set_chunk_parent(tmp, pc->type);\n               }\n            }\n         }\n      }\n   }\n\n   // Mark the parameters in catch()\n   if (chunk_is_token(pc, CT_CATCH) && chunk_is_token(next, CT_SPAREN_OPEN))\n   {\n      fix_fcn_def_params(next);\n   }\n\n   if (chunk_is_token(pc, CT_THROW) && chunk_is_token(prev, CT_FPAREN_CLOSE))\n   {\n      set_chunk_parent(pc, get_chunk_parent_type(prev));\n\n      if (chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         set_paren_parent(next, CT_THROW);\n      }\n   }\n\n   // Mark the braces in: \"for_each_entry(xxx) { }\"\n   if (  chunk_is_token(pc, CT_BRACE_OPEN)\n      && get_chunk_parent_type(pc) != CT_DOUBLE_BRACE\n      && chunk_is_token(prev, CT_FPAREN_CLOSE)\n      && (  get_chunk_parent_type(prev) == CT_FUNC_CALL\n         || get_chunk_parent_type(prev) == CT_FUNC_CALL_USER)\n      && !pc->flags.test(PCF_IN_CONST_ARGS))\n   {\n      LOG_FMT(LFCN, \"%s(%d): (3) SET TO CT_FUNC_CALL: orig_line is %zu, orig_col is %zu, text() '%s'\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n      set_paren_parent(pc, CT_FUNC_CALL);\n   }\n\n   /*\n    * Check for a close parenthesis followed by an open parenthesis,\n    * which means that we are on a function type declaration (C/C++ only?).\n    * Note that typedefs are already taken care of.\n    */\n   if (  !pc->flags.test_any(PCF_IN_TYPEDEF | PCF_IN_TEMPLATE)\n      && get_chunk_parent_type(pc) != CT_CPP_CAST\n      && get_chunk_parent_type(pc) != CT_C_CAST\n      && !pc->flags.test(PCF_IN_PREPROC)\n      && !is_oc_block(pc)\n      && get_chunk_parent_type(pc) != CT_OC_MSG_DECL\n      && get_chunk_parent_type(pc) != CT_OC_MSG_SPEC\n      && chunk_is_str(pc, \")\", 1)\n      && chunk_is_str(next, \"(\", 1))\n   {\n      if (language_is_set(LANG_D))\n      {\n         flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_FUNC_CALL, false);\n      }\n      else\n      {\n         mark_function_type(pc);\n      }\n   }\n\n   if (  (chunk_is_token(pc, CT_CLASS) || chunk_is_token(pc, CT_STRUCT))\n      && pc->level == pc->brace_level)\n   {\n      if (pc->type != CT_STRUCT || !language_is_set(LANG_C))\n      {\n         mark_class_ctor(pc);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_OC_CLASS))\n   {\n      handle_oc_class(pc);\n   }\n   // TODO: Check for stuff that can only occur at the start of an statement\n\n   if (!language_is_set(LANG_D))\n   {\n      /*\n       * Check a parenthesis pair to see if it is a cast.\n       * Note that SPAREN and FPAREN have already been marked.\n       */\n      if (  chunk_is_token(pc, CT_PAREN_OPEN)\n         && (  get_chunk_parent_type(pc) == CT_NONE\n            || get_chunk_parent_type(pc) == CT_OC_MSG\n            || get_chunk_parent_type(pc) == CT_OC_BLOCK_EXPR\n            || get_chunk_parent_type(pc) == CT_CS_SQ_STMT)           // Issue # 1256\n         && (  chunk_is_token(next, CT_WORD)\n            || chunk_is_token(next, CT_TYPE)\n            || chunk_is_token(next, CT_STRUCT)\n            || chunk_is_token(next, CT_QUALIFIER)\n            || chunk_is_token(next, CT_MEMBER)\n            || chunk_is_token(next, CT_DC_MEMBER)\n            || chunk_is_token(next, CT_ENUM)\n            || chunk_is_token(next, CT_UNION))\n         && prev->type != CT_DECLTYPE\n         && prev->type != CT_SIZEOF\n         && get_chunk_parent_type(prev) != CT_SIZEOF\n         && get_chunk_parent_type(prev) != CT_OPERATOR\n         && !pc->flags.test(PCF_IN_TYPEDEF))\n      {\n         fix_casts(pc);\n      }\n   }\n\n   if (language_is_set(LANG_CPP))\n   {\n      chunk_t *nnext = chunk_get_next_ncnl(next);\n\n      // handle parent_type of assigns in special functions (ro5 + pure virtual)\n      if (  pc->flags.test_any(PCF_IN_STRUCT | PCF_IN_CLASS)\n         && chunk_is_token(pc, CT_ASSIGN)\n         && chunk_is_token(nnext, CT_SEMICOLON)\n         && (  chunk_is_token(next, CT_DEFAULT)\n            || chunk_is_token(next, CT_DELETE)\n            || (chunk_is_token(next, CT_NUMBER) && chunk_is_str(next, \"0\", 1))))\n      {\n         const size_t level        = pc->level;\n         bool         found_status = false;\n         chunk_t      *pprev       = chunk_get_prev(pc);\n\n         for ( ; (  pprev != nullptr\n                 && pprev->level >= level\n                 && pprev->type != CT_SEMICOLON\n                 && pprev->type != CT_ACCESS_COLON)\n               ; pprev = chunk_get_prev(pprev))\n         {\n            if (pprev->level != level)\n            {\n               continue;\n            }\n\n            if (chunk_is_token(next, CT_NUMBER))\n            {\n               if (  pprev->type == CT_QUALIFIER\n                  && chunk_is_str(pprev, \"virtual\", 7))\n               {\n                  found_status = true;\n                  break;\n               }\n            }\n            else\n            {\n               if (  pprev->type == CT_FUNC_CLASS_PROTO  // ctor/dtor\n                  || pprev->type == CT_FUNC_PROTO)       // normal function\n               {\n                  found_status = true;\n                  break;\n               }\n            }\n         }\n\n         if (found_status)\n         {\n            set_chunk_parent(pc, pprev->type);\n         }\n      }\n      // Issue #2332\n      bool we_have_a_case_before = false;\n\n      if (chunk_is_token(pc, CT_COLON))\n      {\n         // check if we have a case before\n         chunk_t *switch_before = chunk_get_prev_type(pc, CT_CASE, pc->level);\n\n         if (switch_before != nullptr)\n         {\n            LOG_FMT(LFCNR, \"%s(%d): switch_before->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n                    __func__, __LINE__, switch_before->orig_line, switch_before->orig_col,\n                    switch_before->text(), get_token_name(switch_before->type));\n            we_have_a_case_before = true;\n         }\n      }\n\n      // Detect a braced-init-list\n      if (  chunk_is_token(pc, CT_WORD)\n         || chunk_is_token(pc, CT_TYPE)\n         || chunk_is_token(pc, CT_ASSIGN)\n         || chunk_is_token(pc, CT_RETURN)\n         || chunk_is_token(pc, CT_COMMA)\n         || chunk_is_token(pc, CT_ANGLE_CLOSE)\n         || chunk_is_token(pc, CT_SQUARE_CLOSE)\n         || chunk_is_token(pc, CT_TSQUARE)\n         || chunk_is_token(pc, CT_FPAREN_OPEN)\n         || chunk_is_token(pc, CT_QUESTION)\n         || (  chunk_is_token(pc, CT_COLON)\n            && !we_have_a_case_before)\n         || (  chunk_is_token(pc, CT_BRACE_OPEN)\n            && (  get_chunk_parent_type(pc) == CT_NONE\n               || get_chunk_parent_type(pc) == CT_BRACED_INIT_LIST)))\n      {\n         log_pcf_flags(LFCNR, pc->flags);\n         auto brace_open = chunk_get_next_ncnl(pc);\n\n         if (  chunk_is_token(brace_open, CT_BRACE_OPEN)\n            && (  get_chunk_parent_type(brace_open) == CT_NONE\n               || get_chunk_parent_type(brace_open) == CT_ASSIGN\n               || get_chunk_parent_type(brace_open) == CT_RETURN\n               || get_chunk_parent_type(brace_open) == CT_BRACED_INIT_LIST))\n         {\n            log_pcf_flags(LFCNR, brace_open->flags);\n            auto brace_close = chunk_skip_to_match(next);\n\n            if (chunk_is_token(brace_close, CT_BRACE_CLOSE))\n            {\n               set_chunk_parent(brace_open, CT_BRACED_INIT_LIST);\n               set_chunk_parent(brace_close, CT_BRACED_INIT_LIST);\n\n               tmp = chunk_get_next_ncnl(brace_close);\n\n               if (tmp)\n               {\n                  chunk_flags_clr(tmp, PCF_EXPR_START | PCF_STMT_START);\n               }\n               // TODO: Change pc->type CT_WORD -> CT_TYPE\n               // for the case CT_ASSIGN (and others).\n\n               // TODO: Move this block to the fix_fcn_call_args function.\n               if (chunk_is_token(pc, CT_WORD) && pc->flags.test(PCF_IN_FCN_CALL))\n               {\n                  set_chunk_type(pc, CT_TYPE);\n               }\n            }\n         }\n      }\n   }\n\n   // Check for stuff that can only occur at the start of an expression\n   if (  pc->flags.test(PCF_EXPR_START)\n      || (prev->flags.test(PCF_EXPR_START) && get_chunk_parent_type(pc) == CT_OC_AT))\n   {\n      // Change STAR, MINUS, and PLUS in the easy cases\n      if (chunk_is_token(pc, CT_STAR))\n      {\n         // issue #596\n         // [0x100062020:IN_SPAREN,IN_FOR,STMT_START,EXPR_START,PUNCTUATOR]\n         // prev->type is CT_COLON ==> CT_DEREF\n         if (chunk_is_token(prev, CT_ANGLE_CLOSE))\n         {\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (chunk_is_token(prev, CT_COLON))\n         {\n            set_chunk_type(pc, CT_DEREF);\n         }\n         else\n         {\n            set_chunk_type(pc, CT_DEREF);\n         }\n      }\n\n      if (  language_is_set(LANG_CPP)\n         && chunk_is_token(pc, CT_CARET)\n         && chunk_is_token(prev, CT_ANGLE_CLOSE))\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n\n      if (  language_is_set(LANG_CS)\n         && (chunk_is_token(pc, CT_QUESTION))\n         && (chunk_is_token(prev, CT_ANGLE_CLOSE)))\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n\n      if (chunk_is_token(pc, CT_MINUS))\n      {\n         set_chunk_type(pc, CT_NEG);\n      }\n\n      if (chunk_is_token(pc, CT_PLUS))\n      {\n         set_chunk_type(pc, CT_POS);\n      }\n\n      if (chunk_is_token(pc, CT_INCDEC_AFTER))\n      {\n         set_chunk_type(pc, CT_INCDEC_BEFORE);\n      }\n\n      if (chunk_is_token(pc, CT_AMP))\n      {\n         if (chunk_is_token(prev, CT_ANGLE_CLOSE))             // Issue #2324\n         {\n            set_chunk_type(pc, CT_BYREF);\n         }\n         else\n         {\n            set_chunk_type(pc, CT_ADDR);\n         }\n      }\n\n      if (chunk_is_token(pc, CT_CARET))\n      {\n         if (language_is_set(LANG_C | LANG_CPP | LANG_OC))\n         {\n            // This is likely the start of a block literal\n            handle_oc_block_literal(pc);\n         }\n      }\n   }\n\n   // Detect a variable definition that starts with struct/enum/union/class\n   if (  !pc->flags.test(PCF_IN_TYPEDEF)\n      && get_chunk_parent_type(prev) != CT_CPP_CAST\n      && !prev->flags.test(PCF_IN_FCN_DEF)\n      && (  chunk_is_token(pc, CT_STRUCT)\n         || chunk_is_token(pc, CT_UNION)\n         || chunk_is_token(pc, CT_CLASS)\n         || chunk_is_token(pc, CT_ENUM)))\n   {\n      tmp = chunk_skip_dc_member(next);\n\n      if ((chunk_is_token(tmp, CT_TYPE) || chunk_is_token(tmp, CT_WORD)))\n      {\n         set_chunk_parent(tmp, pc->type);\n         set_chunk_type(tmp, CT_TYPE);\n\n         tmp = chunk_get_next_ncnl(tmp);\n      }\n\n      if (chunk_is_token(tmp, CT_BRACE_OPEN))\n      {\n         tmp = chunk_skip_to_match(tmp);\n\n         if (tmp != nullptr)\n         {\n            tmp = chunk_get_next_ncnl(tmp);\n         }\n      }\n\n      if (  tmp != nullptr\n         && (chunk_is_ptr_operator(tmp) || chunk_is_token(tmp, CT_WORD)))\n      {\n         mark_variable_definition(tmp);\n      }\n   }\n\n   /*\n    * Change the parenthesis pair after a function/macro-function\n    * CT_PAREN_OPEN => CT_FPAREN_OPEN\n    */\n   if (chunk_is_token(pc, CT_MACRO_FUNC))\n   {\n      flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_MACRO_FUNC, false);\n   }\n\n   if (  chunk_is_token(pc, CT_MACRO_OPEN)\n      || chunk_is_token(pc, CT_MACRO_ELSE)\n      || chunk_is_token(pc, CT_MACRO_CLOSE))\n   {\n      if (chunk_is_token(next, CT_PAREN_OPEN))\n      {\n         flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, pc->type, false);\n      }\n   }\n\n   if (chunk_is_token(pc, CT_DELETE) && chunk_is_token(next, CT_TSQUARE))\n   {\n      set_chunk_parent(next, CT_DELETE);\n   }\n\n   // Change CT_STAR to CT_PTR_TYPE or CT_ARITH or CT_DEREF\n   if (  chunk_is_token(pc, CT_STAR)\n      || (language_is_set(LANG_CPP) && chunk_is_token(pc, CT_CARET)))\n   {\n      if (chunk_is_paren_close(next) || chunk_is_token(next, CT_COMMA))\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n      else if (language_is_set(LANG_OC) && chunk_is_token(next, CT_STAR))\n      {\n         /*\n          * Change pointer-to-pointer types in OC_MSG_DECLs\n          * from ARITH <===> DEREF to PTR_TYPE <===> PTR_TYPE\n          */\n         set_chunk_type(pc, CT_PTR_TYPE);\n         set_chunk_parent(pc, get_chunk_parent_type(prev));\n\n         set_chunk_type(next, CT_PTR_TYPE);\n         set_chunk_parent(next, get_chunk_parent_type(pc));\n      }\n      else if (  chunk_is_token(pc, CT_STAR)\n              && (  chunk_is_token(prev, CT_DECLTYPE)\n                 || chunk_is_token(prev, CT_SIZEOF)\n                 || chunk_is_token(prev, CT_DELETE)\n                 || (pc && get_chunk_parent_type(pc) == CT_SIZEOF)))\n      {\n         set_chunk_type(pc, CT_DEREF);\n      }\n      else if (  (  chunk_is_token(prev, CT_WORD)\n                 && chunk_ends_type(prev)\n                 && !prev->flags.test(PCF_IN_FCN_CTOR))\n              || chunk_is_token(prev, CT_DC_MEMBER)\n              || chunk_is_token(prev, CT_PTR_TYPE))\n      {\n         LOG_FMT(LFCNR, \"%s(%d): pc->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\\n   \",\n                 __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type));\n         log_pcf_flags(LFCNR, pc->flags);\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n      else if (chunk_is_token(next, CT_SQUARE_OPEN) && !language_is_set(LANG_OC))  // issue # 408\n      {\n         set_chunk_type(pc, CT_PTR_TYPE);\n      }\n      else if (chunk_is_token(pc, CT_STAR))\n      {\n         // Add check for CT_DC_MEMBER CT_WORD CT_STAR sequence\n         // to convert CT_WORD into CT_TYPE\n         // and CT_STAR into CT_PTR_TYPE\n         // look for an assign backward to distinguish between\n         //    double result = Constants::PI * factor;\n         // and\n         //    ::some::name * foo;\n         if (  chunk_is_token(prev, CT_WORD)\n            && chunk_is_token(prev->prev, CT_DC_MEMBER)\n            && language_is_set(LANG_CPP))\n         {\n            // Issue 1402\n            bool assign_found = false;\n            tmp = pc;\n\n            while (tmp != nullptr)\n            {\n               if (chunk_is_token(tmp, CT_SEMICOLON))\n               {\n                  break;\n               }\n               else if (chunk_is_token(tmp, CT_ASSIGN))\n               {\n                  assign_found = true;\n                  break;\n               }\n               tmp = chunk_get_prev_ncnlni(tmp); // Issue #2279\n            }\n\n            if (assign_found)\n            {\n               // double result = Constants::PI * factor;\n               set_chunk_type(pc, CT_ARITH);\n            }\n            else\n            {\n               //    ::some::name * foo;\n               set_chunk_type(prev, CT_TYPE);\n               set_chunk_type(pc, CT_PTR_TYPE);\n            }\n         }\n\n         /*\n          * A star can have three meanings\n          * 1. CT_DEREF    = pointer dereferencing\n          * 2. CT_PTR_TYPE = pointer definition\n          * 3. CT_ARITH    = arithmetic multiplication\n          *\n          * most PCF_PUNCTUATOR chunks except a paren close would make this\n          * a deref. A paren close may end a cast or may be part of a macro fcn.\n          */\n         if (chunk_is_token(prev, CT_TYPE))\n         {\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (  chunk_is_token(pc->next, CT_SEMICOLON)      // Issue #2319\n                 || (  chunk_is_token(pc->next, CT_STAR)\n                    && chunk_is_token(pc->next->next, CT_SEMICOLON)))\n         {\n            // example:\n            //    using AbstractLinkPtr = AbstractLink*;\n            //    using AbstractLinkPtrPtr = AbstractLink**;\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (  (  get_chunk_parent_type(pc) == CT_FUNC_DEF\n                    && (chunk_is_opening_brace(next) || chunk_is_star(pc->next)))\n                 || (next->type == CT_QUALIFIER))               // Issue #2648\n         {\n            // example:\n            // auto getComponent(Color *color) -> Component * {\n            // auto getComponent(Color *color) -> Component ** {\n            // auto getComponent(Color *color) -> Component * _Nonnull\n            set_chunk_type(pc, CT_PTR_TYPE);\n         }\n         else if (  chunk_is_token(pc->next, CT_SEMICOLON)      // Issue #2319\n                 || (  chunk_is_token(pc->next, CT_STAR)\n                    && chunk_is_token(pc->next->next, CT_STAR)))\n         {\n            // more pointers are NOT yet possible\n            fprintf(stderr, \"Too many pointers\\n\");\n            fprintf(stderr, \"at line %zu, column %zu.\\n\", pc->orig_line, pc->orig_col);\n            fprintf(stderr, \"Please make a report.\\n\");\n            log_flush(true);\n            exit(EX_SOFTWARE);\n         }\n         else\n         {\n            // Issue 1402\n            set_chunk_type(pc,\n                           (  prev->flags.test(PCF_PUNCTUATOR)\n                           && (  !chunk_is_paren_close(prev)\n                              || chunk_is_token(prev, CT_SPAREN_CLOSE)\n                              || get_chunk_parent_type(prev) == CT_MACRO_FUNC)\n                           && prev->type != CT_SQUARE_CLOSE\n                           && prev->type != CT_DC_MEMBER) ? CT_DEREF : CT_ARITH);\n         }\n\n         if (pc->flags.test(PCF_IN_TYPEDEF))  // Issue #1255/#633\n         {\n            tmp = pc;\n\n            while (tmp != nullptr)\n            {\n               if (  chunk_is_token(tmp, CT_SEMICOLON)\n                  || chunk_is_token(tmp, CT_BRACE_OPEN))\n               {\n                  break;\n               }\n               else if (chunk_is_token(tmp, CT_TYPEDEF))\n               {\n                  set_chunk_type(pc, CT_PTR_TYPE);\n               }\n               tmp = chunk_get_prev_ncnlni(tmp); // Issue #2279\n            }\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_AMP))\n   {\n      if (chunk_is_token(prev, CT_DELETE))\n      {\n         set_chunk_type(pc, CT_ADDR);\n      }\n      else if (chunk_is_token(prev, CT_TYPE))\n      {\n         set_chunk_type(pc, CT_BYREF);\n      }\n      else if (chunk_is_token(next, CT_FPAREN_CLOSE) || chunk_is_token(next, CT_COMMA))\n      {\n         // fix the bug #654\n         // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &)));\n         set_chunk_type(pc, CT_BYREF);\n      }\n      else if (get_chunk_parent_type(pc) == CT_USING_ALIAS)\n      {\n         // fix the Issue # 1689\n         // using reference = value_type &;\n         set_chunk_type(pc->prev, CT_TYPE);\n         set_chunk_type(pc, CT_BYREF);\n      }\n      else\n      {\n         // Issue # 1398\n         if (  pc->flags.test(PCF_IN_FCN_DEF)\n            && chunk_is_token(prev, CT_WORD)\n            && chunk_is_token(pc, CT_AMP)\n            && chunk_is_token(next, CT_WORD))\n         {\n            /*\n             * Change CT_WORD before CT_AMP before CT_WORD to CT_TYPE\n             */\n            set_chunk_type(prev, CT_TYPE);\n         }\n         else\n         {\n            set_chunk_type(pc, CT_ARITH);\n\n            if (chunk_is_token(prev, CT_WORD))\n            {\n               tmp = chunk_get_prev_ncnlni(prev); // Issue #2279\n\n               if (tmp != nullptr)\n               {\n                  if (  chunk_is_semicolon(tmp)\n                     || chunk_is_token(tmp, CT_BRACE_OPEN)\n                     || chunk_is_token(tmp, CT_QUALIFIER))\n                  {\n                     set_chunk_type(pc, CT_BYREF);\n                     set_chunk_type(prev, CT_TYPE);\n\n                     if (!(  chunk_is_token(next, CT_OPERATOR)\n                          || chunk_is_token(next, CT_TYPE)\n                          || chunk_is_token(next, CT_DC_MEMBER)))\n                     {\n                        LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', set PCF_VAR_1ST\\n\",\n                                __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text());\n                        chunk_flags_set(next, PCF_VAR_1ST);\n                     }\n                  }\n                  else if (chunk_is_token(tmp, CT_DC_MEMBER))\n                  {\n                     set_chunk_type(prev, CT_TYPE);\n\n                     if (!chunk_is_token(next, CT_TYPE))            // Issue #2103\n                     {\n                        set_chunk_type(pc, CT_BYREF);\n                     }\n                  }\n               }\n            }\n         }\n      }\n   }\n\n   if (chunk_is_token(pc, CT_MINUS) || chunk_is_token(pc, CT_PLUS))\n   {\n      if (  chunk_is_token(prev, CT_POS)\n         || chunk_is_token(prev, CT_NEG)\n         || chunk_is_token(prev, CT_ARITH))\n      {\n         set_chunk_type(pc, (pc->type == CT_MINUS) ? CT_NEG : CT_POS);\n      }\n      else if (chunk_is_token(prev, CT_OC_CLASS))\n      {\n         set_chunk_type(pc, (chunk_is_token(pc, CT_MINUS)) ? CT_NEG : CT_POS);\n      }\n      else\n      {\n         set_chunk_type(pc, CT_ARITH);\n      }\n   }\n\n   /*\n    * Bug # 634\n    * Check for extern \"C\" NSString* i;\n    * NSString is a type\n    * change CT_WORD => CT_TYPE     for pc\n    * change CT_STAR => CT_PTR_TYPE for pc-next\n    */\n   if (chunk_is_token(pc, CT_WORD))     // here NSString\n   {\n      if (pc->next != nullptr)          // here *\n      {\n         if (pc->next->type == CT_STAR) // here *\n         {\n            // compare text with \"C\" to find extern \"C\" instructions\n            if (pc->prev != nullptr)\n            {\n               if (pc->prev->type == CT_STRING)\n               {\n                  if (unc_text::compare(pc->prev->text(), \"\\\"C\\\"\") == 0)\n                  {\n                     if (pc->prev->prev->type == CT_EXTERN)\n                     {\n                        set_chunk_type(pc, CT_TYPE);            // change CT_WORD => CT_TYPE\n                        set_chunk_type(pc->next, CT_PTR_TYPE);  // change CT_STAR => CT_PTR_TYPE\n                     }\n                  }\n               }\n            }\n\n            // Issue #322 STDMETHOD(GetValues)(BSTR bsName, REFDATA** pData);\n            if (  (pc->next->next != nullptr)\n               && pc->next->next->type == CT_STAR\n               && pc->flags.test(PCF_IN_CONST_ARGS))\n            {\n               // change CT_STAR => CT_PTR_TYPE\n               set_chunk_type(pc->next, CT_PTR_TYPE);\n               set_chunk_type(pc->next->next, CT_PTR_TYPE);\n            }\n\n            // Issue #222 whatever3 *(func_ptr)( whatever4 *foo2, ...\n            if (  (pc->next->next != nullptr)\n               && pc->next->next->type == CT_WORD\n               && pc->flags.test(PCF_IN_FCN_DEF))\n            {\n               // look for the opening parenthesis\n               // Issue 1403\n               tmp = chunk_get_prev_type(pc, CT_FPAREN_OPEN, pc->level - 1);\n\n               if (  tmp != nullptr\n                  && get_chunk_parent_type(tmp) != CT_FUNC_CTOR_VAR)\n               {\n                  set_chunk_type(pc->next, CT_PTR_TYPE);\n               }\n            }\n         }\n      }\n   }\n\n   /*\n    * Bug # 634\n    * Check for __attribute__((visibility (\"default\"))) NSString* i;\n    * NSString is a type\n    * change CT_WORD => CT_TYPE     for pc\n    * change CT_STAR => CT_PTR_TYPE for pc-next\n    */\n   if (chunk_is_token(pc, CT_WORD))     // here NSString\n   {\n      if (pc->next != nullptr)          // here *\n      {\n         if (pc->next->type == CT_STAR) // here *\n         {\n            tmp = pc;\n\n            while ((tmp != nullptr))\n            {\n               if (chunk_is_token(tmp, CT_ATTRIBUTE))\n               {\n                  LOG_FMT(LFCNR, \"%s(%d): ATTRIBUTE found, type is %s, text() '%s'\\n\",\n                          __func__, __LINE__, get_token_name(tmp->type), tmp->text());\n                  LOG_FMT(LFCNR, \"for token, type is %s, text() '%s'\\n\", get_token_name(pc->type), pc->text());\n                  // change CT_WORD => CT_TYPE\n                  set_chunk_type(pc, CT_TYPE);\n                  // change CT_STAR => CT_PTR_TYPE\n                  set_chunk_type(pc->next, CT_PTR_TYPE);\n               }\n\n               if (tmp->flags.test(PCF_STMT_START))\n               {\n                  // we are at beginning of the line\n                  break;\n               }\n               tmp = chunk_get_prev(tmp);\n            }\n         }\n      }\n   }\n\n   /*\n    * Issue # 1689\n    * Check for using reference = value_type&;\n    * is it a Type alias, alias template?\n    */\n   if (chunk_is_token(pc, CT_USING))\n   {\n      // look for CT_ASSIGN before CT_SEMICOLON at the end of the statement\n      bool    assign_found = false;\n      bool    is_preproc   = pc->flags.test(PCF_IN_PREPROC);\n      chunk_t *temp;\n\n      for (temp = pc; temp != nullptr; temp = chunk_get_next_ncnl(temp))\n      {\n         LOG_FMT(LFCNR, \"%s(%d): orig_line is %zu, orig_col is %zu, text() '%s', type is %s\\n\",\n                 __func__, __LINE__, temp->orig_line, temp->orig_col, temp->text(), get_token_name(temp->type));\n\n         if (chunk_is_token(temp, CT_ASSIGN))\n         {\n            assign_found = true;\n            break;\n         }\n\n         if (  chunk_is_token(temp, CT_SEMICOLON)\n            || (  is_preproc\n               && (  !temp->flags.test(PCF_IN_PREPROC)\n                  || chunk_is_token(temp, CT_PREPROC))))\n         {\n            break;\n         }\n      }\n\n      if (assign_found)\n      {\n         // it is a Type alias, alias template\n         for (temp = pc; temp != nullptr; temp = chunk_get_next_ncnl(temp))\n         {\n            if (get_chunk_parent_type(temp) == CT_NONE)\n            {\n               set_chunk_parent(temp, CT_USING_ALIAS);\n            }\n\n            if (  chunk_is_token(temp, CT_SEMICOLON)\n               || (  is_preproc\n                  && (  !temp->flags.test(PCF_IN_PREPROC)\n                     || chunk_is_token(temp, CT_PREPROC))))\n            {\n               break;\n            }\n         }\n      }\n   }\n\n   // Issue #548: inline T && someFunc(foo * *p, bar && q) { }\n   if (  pc->type == CT_BOOL\n      && !pc->flags.test(PCF_IN_PREPROC)\n      && chunk_is_str(pc, \"&&\", 2)\n      && chunk_ends_type(pc->prev))\n   {\n      set_chunk_type(pc, CT_BYREF);\n   }\n\n   // Issue #1704\n   if (  chunk_is_token(pc, CT_INCDEC_AFTER)\n      && pc->flags.test(PCF_IN_PREPROC))\n   {\n      chunk_t *tmp_2 = chunk_get_next(pc);\n      log_pcf_flags(LFTYPE, pc->flags);\n\n      if (chunk_is_token(tmp_2, CT_WORD))\n      {\n         set_chunk_type(pc, CT_INCDEC_BEFORE);\n      }\n   }\n} // do_symbol_check\n\n\nstatic void check_double_brace_init(chunk_t *bo1)\n{\n   LOG_FUNC_ENTRY();\n   LOG_FMT(LJDBI, \"%s(%d): orig_line is %zu, orig_col is %zu\", __func__, __LINE__, bo1->orig_line, bo1->orig_col);\n   chunk_t *pc = chunk_get_prev_ncnlni(bo1);   // Issue #2279\n\n   if (pc == nullptr)\n   {\n      return;\n   }\n\n   if (chunk_is_paren_close(pc))\n   {\n      chunk_t *bo2 = chunk_get_next(bo1);\n\n      if (bo2 == nullptr)\n      {\n         return;\n      }\n\n      if (chunk_is_token(bo2, CT_BRACE_OPEN))\n      {\n         // found a potential double brace\n         chunk_t *bc2 = chunk_skip_to_match(bo2);\n\n         if (bc2 == nullptr)\n         {\n            return;\n         }\n         chunk_t *bc1 = chunk_get_next(bc2);\n\n         if (bc1 == nullptr)\n         {\n            return;\n         }\n\n         if (chunk_is_token(bc1, CT_BRACE_CLOSE))\n         {\n            LOG_FMT(LJDBI, \" - end, orig_line is %zu, orig_col is %zu\\n\", bc2->orig_line, bc2->orig_col);\n            // delete bo2 and bc1\n            bo1->str         += bo2->str;\n            bo1->orig_col_end = bo2->orig_col_end;\n            chunk_del(bo2);\n            set_chunk_parent(bo1, CT_DOUBLE_BRACE);\n\n            bc2->str         += bc1->str;\n            bc2->orig_col_end = bc1->orig_col_end;\n            chunk_del(bc1);\n            set_chunk_parent(bc2, CT_DOUBLE_BRACE);\n            return;\n         }\n      }\n   }\n   LOG_FMT(LJDBI, \" - no\\n\");\n} // check_double_brace_init\n\n\nvoid fix_symbols(void)\n{\n   LOG_FUNC_ENTRY();\n   chunk_t *pc;\n   chunk_t dummy;\n\n   cpd.unc_stage = unc_stage_e::FIX_SYMBOLS;\n\n   mark_define_expressions();\n\n   bool is_cpp  = language_is_set(LANG_CPP);\n   bool is_java = language_is_set(LANG_JAVA);\n\n   for (pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnl(pc))\n   {\n      if (  chunk_is_token(pc, CT_FUNC_WRAP)\n         || chunk_is_token(pc, CT_TYPE_WRAP))\n      {\n         handle_wrap(pc);\n      }\n\n      if (chunk_is_token(pc, CT_ASSIGN))\n      {\n         mark_lvalue(pc);\n      }\n      // a brace immediately preceeded by word in C++11 is an initializer list though it may also\n      // by a type casting initializer list if the word is really a type; sadly unucustify knows\n      // only builtin types and knows nothing of user-defined types\n      chunk_t *prev = chunk_get_prev_ncnlni(pc);   // Issue #2279\n\n      if (  is_cpp\n         && chunk_is_token(pc, CT_BRACE_OPEN)\n         && (  chunk_is_token(prev, CT_WORD)\n            || chunk_is_token(prev, CT_TYPE)))\n      {\n         mark_lvalue(pc);\n      }\n\n      if (  is_java\n         && chunk_is_token(pc, CT_BRACE_OPEN))\n      {\n         check_double_brace_init(pc);\n      }\n\n      if (chunk_is_token(pc, CT_ATTRIBUTE))\n      {\n         chunk_t *next = chunk_get_next_ncnl(pc, scope_e::PREPROC);\n\n         if (  next != nullptr\n            && chunk_is_token(next, CT_PAREN_OPEN))\n         {\n            flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_ATTRIBUTE, false);\n         }\n      }\n   }\n\n   pc = chunk_get_head();\n\n   if (pc == nullptr)\n   {\n      return;\n   }\n\n   if (  chunk_is_newline(pc)\n      || chunk_is_comment(pc))\n   {\n      pc = chunk_get_next_ncnl(pc);\n   }\n\n   while (pc != nullptr)\n   {\n      if (chunk_is_token(pc, CT_IGNORED))\n      {\n         pc = chunk_get_next_ncnl(pc);\n         continue;\n      }\n      LOG_FMT(LFCNR, \"%s(%d): pc->orig_line       is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n              __func__, __LINE__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type));\n      chunk_t *prev = chunk_get_prev_ncnlni(pc, scope_e::PREPROC);   // Issue #2279\n\n      if (prev == nullptr)\n      {\n         prev = &dummy;\n      }\n      else\n      {\n         // Issue #2279\n         LOG_FMT(LFCNR, \"%s(%d): prev(ni)->orig_line is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n                 __func__, __LINE__, prev->orig_line, prev->orig_col, prev->text(), get_token_name(prev->type));\n      }\n      chunk_t *next = chunk_get_next_ncnl(pc, scope_e::PREPROC);\n\n      if (next == nullptr)\n      {\n         next = &dummy;\n      }\n      else\n      {\n         // Issue #2279\n         LOG_FMT(LFCNR, \"%s(%d): next->orig_line     is %zu, orig_col is %zu, text() is '%s', type is %s\\n\",\n         "},{"id":"395636","messageId":"20200416225502.GJ2751707@camp.crustytoothpaste.net","threadId":"53248","inReplyTo":"65cbee30-fa37-1422-98f2-2c2b5aa094bd@maurel.de","subject":"Re: a problem with git diff","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2020-04-16T22:55:02Z","receivedAt":"2020-04-16T22:55:46Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2020-04-16 at 16:43:40, Guy Maurel wrote:\n> Hello!\n> \n> Using the appended two files:\n>   git diff combine.cpp-2020-04-16-A combine.cpp-2020-04-16-R > git-diff.diff-Y\n> \n> doesn't show the same differences as with:\n>   meld combine.cpp-2020-04-16-R combine.cpp-2020-04-16-A\n> \n> Have a look at git-diff.diff-Y at line 210:\n> -static void process_returns(void)\n> +static void mark_lvalue(chunk_t *pc)\n> \n> which is NOT correct.\n\nIt looks like there's some additional code that gets inserted before the\nprocess_returns function.  In this case, the diff is accurate in that\napplying it to the old file will result in the new file, but it's not\nvery helpful.\n\nThe reason is that the default diff algorithm, myers, looks for common\nlines and finds them in the blank lines in both process_returns and the\nnew code above it.  It then writes the diff as a set of deletions of the\nlines in process_returns and an addition of the lines in the new code,\nplus a final addition of the process_returns function.  While correct,\nthis is, as you noted, confusing.\n\nIf you're looking for a more helpful output, you can use\n--diff-algorithm=patience (or diff.algorithm=patience), which results\nin a diff output that more logically matches what most humans would like\nto see.  You can also use the histogram diff algorithm, which is based\non patience but has some additional heuristics.  Which one produces\nbetter output differs depending on the circumstance.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"395668","messageId":"20200417203323.GK2751707@camp.crustytoothpaste.net","threadId":"53248","inReplyTo":"24a180f6-cc7e-fe5b-e810-0fc717d601ea@maurel.de","subject":"Re: a problem with git diff","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2020-04-17T20:33:23Z","receivedAt":"2020-04-17T20:33:31Z","isPatch":false,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2020-04-17 at 12:23:35, Guy Maurel wrote:\n> Hello again!\n> \n> Using .git/config with\n> [diff]\n>         algorithm = patience\n> \n> doesn't work with \"git gui\"\n> What is to do?\n\nI don't know because I don't use git-gui.  If you would, please keep the\nlist in CC, so that other folks who do know the answer can chime in.\n-- \nbrian m. carlson: Houston, Texas, US\nOpenPGP: https://keybase.io/bk2204\n"},{"id":"395670","messageId":"xmqqh7xhvlvg.fsf@gitster.c.googlers.com","threadId":"53248","inReplyTo":"20200417203323.GK2751707@camp.crustytoothpaste.net","subject":"Re: a problem with git diff","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2020-04-17T21:32:51Z","receivedAt":"2020-04-17T21:33:00Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"brian m. carlson\" <sandals@crustytoothpaste.net> writes:\n\n> I don't know because I don't use git-gui.  If you would, please keep the\n> list in CC, so that other folks who do know the answer can chime in.\n\nI do not use git-gui, either, but IIRC, it stayed away from\nscripting around Porcelain commands, so it is not all that\nsurprising that it does not use diff.algorithm.\n\nThere is gui.diffopts configuration used in git-gui/lib/diff.tcl::\n\n\tlappend cmd -p\n\tlappend cmd --color\n\tset cmd [concat $cmd $repo_config(gui.diffopts)]\n\tif {$repo_config(gui.diffcontext) >= 1} {\n\t\tlappend cmd \"-U$repo_config(gui.diffcontext)\"\n\t}\n\nso perhaps you can pass --patience via that configuration?  I.e.\n\n\t[gui]\n\t\tdiffopts = --patience\n\nin .git/config?\n"},{"id":"395890","messageId":"20200422091040.dmmdqih5ni3gfaac@yadavpratyush.com","threadId":"53248","inReplyTo":"20200417203323.GK2751707@camp.crustytoothpaste.net","subject":"Re: a problem with git diff","fromName":"Pratyush Yadav","fromEmail":"me@yadavpratyush.com","sentAt":"2020-04-22T09:10:40Z","receivedAt":"2020-04-22T09:10:49Z","isPatch":false,"sender":{"key":"me@yadavpratyush.com","avatar":"https://avatars.githubusercontent.com/u/8817931?v=4"},"body":"On 17/04/20 08:33PM, brian m. carlson wrote:\n> On 2020-04-17 at 12:23:35, Guy Maurel wrote:\n> > Hello again!\n> > \n> > Using .git/config with\n> > [diff]\n> >         algorithm = patience\n> > \n> > doesn't work with \"git gui\"\n> > What is to do?\n \nThe bug has been reported on this list before. I will try to fix it when \nI can find the time. In the meantime, please use Junio's suggestion as a \nworkaround.\n\n> I don't know because I don't use git-gui.  If you would, please keep the\n> list in CC, so that other folks who do know the answer can chime in.\n\n-- \nRegards,\nPratyush Yadav\n"}]}