PageRenderTime 80ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/src/combine.cpp

http://github.com/bengardner/uncrustify
C++ | 6211 lines | 4734 code | 653 blank | 824 comment | 1959 complexity | 8b08d7a3f9f4571f94efa23d9bc9df84 MD5 | raw file
Possible License(s): GPL-2.0
  1. /**
  2. * @file combine.cpp
  3. * Labels the chunks as needed.
  4. *
  5. * @author Ben Gardner
  6. * @author Guy Maurel since version 0.62 for uncrustify4Qt
  7. * October 2015, 2016
  8. * @license GPL v2+
  9. */
  10. #include "combine.h"
  11. #include "uncrustify_types.h"
  12. #include "chunk_list.h"
  13. #include "ChunkStack.h"
  14. #include "uncrustify.h"
  15. #include "lang_pawn.h"
  16. #include "newlines.h"
  17. #include "prototypes.h"
  18. #include "tokenize_cleanup.h"
  19. #include <cstdio>
  20. #include <cstdlib>
  21. #include "unc_ctype.h"
  22. #include <cassert>
  23. /**
  24. * Flags everything from the open paren to the close paren.
  25. *
  26. * @param po Pointer to the open parenthesis
  27. * @return The token after the close paren
  28. */
  29. static chunk_t *flag_parens(chunk_t *po, UINT64 flags, c_token_t opentype, c_token_t parenttype, bool parent_all);
  30. /**
  31. * Mark the parens and colons in:
  32. * asm volatile ( "xx" : "xx" (l), "yy"(h) : ... );
  33. *
  34. * @param pc the CT_ASM item
  35. */
  36. static void flag_asm(chunk_t *pc);
  37. /**
  38. * Scan backwards to see if we might be on a type declaration
  39. */
  40. static bool chunk_ends_type(chunk_t *start);
  41. /**
  42. * skip to the final word/type in a :: chain
  43. * pc is either a word or a ::
  44. */
  45. static chunk_t *skip_dc_member(chunk_t *start);
  46. /**
  47. * Skips to the start of the next statement.
  48. */
  49. static chunk_t *skip_to_next_statement(chunk_t *pc);
  50. /**
  51. * Skips everything until a comma or semicolon at the same level.
  52. * Returns the semicolon, comma, or close brace/paren or NULL.
  53. */
  54. static chunk_t *skip_expression(chunk_t *start);
  55. /**
  56. * Skips the D 'align()' statement and the colon, if present.
  57. * align(2) int foo; -- returns 'int'
  58. * align(4): -- returns 'int'
  59. * int bar;
  60. */
  61. static chunk_t *skip_align(chunk_t *start);
  62. /**
  63. * Combines two tokens into {{ and }} if inside parens and nothing is between
  64. * either pair.
  65. */
  66. static void check_double_brace_init(chunk_t *bo1);
  67. /**
  68. * Simply change any STAR to PTR_TYPE and WORD to TYPE
  69. *
  70. * @param start points to the open paren
  71. */
  72. static void fix_fcn_def_params(chunk_t *pc);
  73. /**
  74. * We are on a typedef.
  75. * If the next word is not enum/union/struct, then the last word before the
  76. * next ',' or ';' or '__attribute__' is a type.
  77. *
  78. * typedef [type...] [*] type [, [*]type] ;
  79. * typedef <return type>([*]func)();
  80. * typedef <return type>([*]func)(params);
  81. * typedef <return type>(__stdcall *func)(); Bug # 633 MS-specific extension
  82. * include the config-file "test/config/MS-calling_conventions.cfg"
  83. * typedef <return type>func(params);
  84. * typedef <enum/struct/union> [type] [*] type [, [*]type] ;
  85. * typedef <enum/struct/union> [type] { ... } [*] type [, [*]type] ;
  86. */
  87. static void fix_typedef(chunk_t *pc);
  88. /**
  89. * We are on an enum/struct/union tag that is NOT inside a typedef.
  90. * If there is a {...} and words before the ';', then they are variables.
  91. *
  92. * tag { ... } [*] word [, [*]word] ;
  93. * tag [word/type] { ... } [*] word [, [*]word] ;
  94. * enum [word/type [: int_type]] { ... } [*] word [, [*]word] ;
  95. * tag [word/type] [word]; -- this gets caught later.
  96. * fcn(tag [word/type] [word])
  97. * a = (tag [word/type] [*])&b;
  98. *
  99. * REVISIT: should this be consolidated with the typedef code?
  100. */
  101. static void fix_enum_struct_union(chunk_t *pc);
  102. /**
  103. * Checks to see if the current paren is part of a cast.
  104. * We already verified that this doesn't follow function, TYPE, IF, FOR,
  105. * SWITCH, or WHILE and is followed by WORD, TYPE, STRUCT, ENUM, or UNION.
  106. *
  107. * @param start Pointer to the open paren
  108. */
  109. static void fix_casts(chunk_t *pc);
  110. /**
  111. * CT_TYPE_CAST follows this pattern:
  112. * dynamic_cast<...>(...)
  113. *
  114. * Mark everything between the <> as a type and set the paren parent
  115. */
  116. static void fix_type_cast(chunk_t *pc);
  117. /**
  118. * We are on the start of a sequence that could be a var def
  119. * - FPAREN_OPEN (parent == CT_FOR)
  120. * - BRACE_OPEN
  121. * - SEMICOLON
  122. */
  123. static chunk_t *fix_var_def(chunk_t *pc);
  124. /**
  125. * We are on a function word. we need to:
  126. * - find out if this is a call or prototype or implementation
  127. * - mark return type
  128. * - mark parameter types
  129. * - mark brace pair
  130. *
  131. * REVISIT:
  132. * This whole function is a mess.
  133. * It needs to be reworked to eliminate duplicate logic and determine the
  134. * function type more directly.
  135. * 1. Skip to the close paren and see what is after.
  136. * a. semicolon - function call or function proto
  137. * b. open brace - function call (ie, list_for_each) or function def
  138. * c. open paren - function type or chained function call
  139. * d. qualifier - function def or proto, continue to semicolon or open brace
  140. * 2. Examine the 'parameters' to see if it can be a proto/def
  141. * 3. Examine what is before the function name to see if it is a proto or call
  142. * Constructor/destructor detection should have already been done when the
  143. * 'class' token was encountered (see mark_class_ctor).
  144. */
  145. static void mark_function(chunk_t *pc);
  146. /**
  147. * Checks to see if a series of chunks could be a C++ parameter
  148. * FOO foo(5, &val);
  149. *
  150. * WORD means CT_WORD or CT_TYPE
  151. *
  152. * "WORD WORD" ==> true
  153. * "QUALIFIER ??" ==> true
  154. * "TYPE" ==> true
  155. * "WORD" ==> true
  156. * "WORD.WORD" ==> true
  157. * "WORD::WORD" ==> true
  158. * "WORD * WORD" ==> true
  159. * "WORD & WORD" ==> true
  160. * "NUMBER" ==> false
  161. * "STRING" ==> false
  162. * "OPEN PAREN" ==> false
  163. *
  164. * @param start the first chunk to look at
  165. * @param end the chunk after the last one to look at
  166. */
  167. static bool can_be_full_param(chunk_t *start, chunk_t *end);
  168. /**
  169. * Changes the return type to type and set the parent.
  170. *
  171. * @param pc the last chunk of the return type
  172. * @param parent_type CT_NONE (no change) or the new parent type
  173. */
  174. static void mark_function_return_type(chunk_t *fname, chunk_t *pc, c_token_t parent_type);
  175. /**
  176. * Process a function type that is not in a typedef.
  177. * pc points to the first close paren.
  178. *
  179. * void (*func)(params);
  180. * const char * (*func)(params);
  181. * const char * (^func)(params); -- Objective C
  182. *
  183. * @param pc Points to the first closing paren
  184. * @return whether a function type was processed
  185. */
  186. static bool mark_function_type(chunk_t *pc);
  187. /**
  188. * Examines the stuff between braces { }.
  189. * There should only be variable definitions and methods.
  190. * Skip the methods, as they will get handled elsewhere.
  191. */
  192. static void mark_struct_union_body(chunk_t *start);
  193. /**
  194. * We are on the first word of a variable definition.
  195. * Mark all the variable names with PCF_VAR_1ST and PCF_VAR_DEF as appropriate.
  196. * Also mark any '*' encountered as a CT_PTR_TYPE.
  197. * Skip over []. Go until a ';' is hit.
  198. *
  199. * Example input:
  200. * int a = 3, b, c = 2; ## called with 'a'
  201. * foo_t f = {1, 2, 3}, g = {5, 6, 7}; ## called with 'f'
  202. * struct {...} *a, *b; ## called with 'a' or '*'
  203. * myclass a(4);
  204. */
  205. static chunk_t *mark_variable_definition(chunk_t *start);
  206. /**
  207. * Marks statement starts in a macro body.
  208. * REVISIT: this may already be done
  209. */
  210. static void mark_define_expressions(void);
  211. static void process_returns(void);
  212. /**
  213. * Processes a return statement, labeling the parens and marking the parent.
  214. * May remove or add parens around the return statement
  215. *
  216. * @param pc Pointer to the return chunk
  217. */
  218. static chunk_t *process_return(chunk_t *pc);
  219. /**
  220. * We're on a 'class' or 'struct'.
  221. * Scan for CT_FUNCTION with a string that matches pclass->str
  222. */
  223. static void mark_class_ctor(chunk_t *pclass);
  224. /**
  225. * We're on a 'namespace' skip the word and then set the parent of the braces.
  226. */
  227. static void mark_namespace(chunk_t *pns);
  228. static void mark_cpp_constructor(chunk_t *pc);
  229. /**
  230. * Just hit an assign. Go backwards until we hit an open brace/paren/square or
  231. * semicolon (TODO: other limiter?) and mark as a LValue.
  232. */
  233. static void mark_lvalue(chunk_t *pc);
  234. /**
  235. * We are on a word followed by a angle open which is part of a template.
  236. * If the angle close is followed by a open paren, then we are on a template
  237. * function def or a template function call:
  238. * Vector2<float>(...) [: ...[, ...]] { ... }
  239. * Or we could be on a variable def if it's followed by a word:
  240. * Renderer<rgb32> rend;
  241. */
  242. static void mark_template_func(chunk_t *pc, chunk_t *pc_next);
  243. /**
  244. * Just mark every CT_WORD until a semicolon as CT_SQL_WORD.
  245. * Adjust the levels if pc is CT_SQL_BEGIN
  246. */
  247. static void mark_exec_sql(chunk_t *pc);
  248. /**
  249. * Process an ObjC 'class'
  250. * pc is the chunk after '@implementation' or '@interface' or '@protocol'.
  251. * Change colons, etc. Processes stuff until '@end'.
  252. * Skips anything in braces.
  253. */
  254. static void handle_oc_class(chunk_t *pc);
  255. /**
  256. * Mark Objective-C blocks (aka lambdas or closures)
  257. * The syntax and usage is exactly like C function pointers
  258. * but instead of an asterisk they have a caret as pointer symbol.
  259. * Although it may look expensive this functions is only triggered
  260. * on appearance of an OC_BLOCK_CARET for LANG_OC.
  261. * repeat(10, ^{ putc('0'+d); });
  262. * typedef void (^workBlk_t)(void);
  263. *
  264. * @param pc points to the '^'
  265. */
  266. static void handle_oc_block_literal(chunk_t *pc);
  267. /**
  268. * Mark Objective-C block types.
  269. * The syntax and usage is exactly like C function pointers
  270. * but instead of an asterisk they have a caret as pointer symbol.
  271. * typedef void (^workBlk_t)(void);
  272. * const char * (^workVar)(void);
  273. * -(void)Foo:(void(^)())blk { }
  274. *
  275. * This is triggered when the sequence '(' '^' is found.
  276. *
  277. * @param pc points to the '^'
  278. */
  279. static void handle_oc_block_type(chunk_t *pc);
  280. /**
  281. * Process an ObjC message spec/dec
  282. *
  283. * Specs:
  284. * -(void) foo ARGS;
  285. *
  286. * Decl:
  287. * -(void) foo ARGS { }
  288. *
  289. * LABEL : (ARGTYPE) ARGNAME
  290. *
  291. * ARGS is ': (ARGTYPE) ARGNAME [MOREARGS...]'
  292. * MOREARGS is ' [ LABEL] : (ARGTYPE) ARGNAME '
  293. * -(void) foo: (int) arg: { }
  294. * -(void) foo: (int) arg: { }
  295. * -(void) insertObject:(id)anObject atIndex:(int)index
  296. */
  297. static void handle_oc_message_decl(chunk_t *pc);
  298. /**
  299. * Process an ObjC message send statement:
  300. * [ class func: val1 name2: val2 name3: val3] ; // named params
  301. * [ class func: val1 : val2 : val3] ; // unnamed params
  302. * [ class <proto> self method ] ; // with protocol
  303. * [[NSMutableString alloc] initWithString: @"" ] // class from msg
  304. * [func(a,b,c) lastObject ] // class from func
  305. *
  306. * Mainly find the matching ']' and ';' and mark the colons.
  307. *
  308. * @param os points to the open square '['
  309. */
  310. static void handle_oc_message_send(chunk_t *pc);
  311. /**
  312. * Process @Property values and re-arrange them if necessary
  313. */
  314. static void handle_oc_property_decl(chunk_t *pc);
  315. /**
  316. * Process a type that is enclosed in parens in message decls.
  317. * TODO: handle block types, which get special formatting
  318. *
  319. * @param pc points to the open paren
  320. * @return the chunk after the type
  321. */
  322. static chunk_t *handle_oc_md_type(chunk_t *paren_open, c_token_t ptype, UINT64 flags, bool &did_it);
  323. /**
  324. * Process an C# [] thingy:
  325. * [assembly: xxx]
  326. * [AttributeUsage()]
  327. * [@X]
  328. *
  329. * Set the next chunk to a statement start after the close ']'
  330. *
  331. * @param os points to the open square '['
  332. */
  333. static void handle_cs_square_stmt(chunk_t *pc);
  334. /**
  335. * We are on a brace open that is preceded by a word or square close.
  336. * Set the brace parent to CT_CS_PROPERTY and find the first item in the
  337. * property and set its parent, too.
  338. */
  339. static void handle_cs_property(chunk_t *pc);
  340. /**
  341. * We hit a ']' followed by a WORD. This may be a multidimensional array type.
  342. * Example: int[,,] x;
  343. * If there is nothing but commas between the open and close, then mark it.
  344. */
  345. static void handle_cs_array_type(chunk_t *pc);
  346. /**
  347. * We are on the C++ 'template' keyword.
  348. * What follows should be the following:
  349. *
  350. * template <class identifier> function_declaration;
  351. * template <typename identifier> function_declaration;
  352. * template <class identifier> class class_declaration;
  353. * template <typename identifier> class class_declaration;
  354. *
  355. * Change the 'class' inside the <> to CT_TYPE.
  356. * Set the parent to the class after the <> to CT_TEMPLATE.
  357. * Set the parent of the semicolon to CT_TEMPLATE.
  358. */
  359. static void handle_cpp_template(chunk_t *pc);
  360. /**
  361. * Verify and then mark C++ lambda expressions.
  362. * The expected format is '[...](...){...}' or '[...](...) -> type {...}'
  363. * sq_o is '[' CT_SQUARE_OPEN or '[]' CT_TSQUARE
  364. * Split the '[]' so we can control the space
  365. */
  366. static void handle_cpp_lambda(chunk_t *pc);
  367. /**
  368. * We are on the D 'template' keyword.
  369. * What follows should be the following:
  370. *
  371. * template NAME ( TYPELIST ) { BODY }
  372. *
  373. * Set the parent of NAME to template, change NAME to CT_TYPE.
  374. * Set the parent of the parens and braces to CT_TEMPLATE.
  375. * Scan the body for each type in TYPELIST and change the type to CT_TYPE.
  376. */
  377. static void handle_d_template(chunk_t *pc);
  378. /**
  379. * A func wrap chunk and what follows should be treated as a function name.
  380. * Create new text for the chunk and call it a CT_FUNCTION.
  381. *
  382. * A type wrap chunk and what follows should be treated as a simple type.
  383. * Create new text for the chunk and call it a CT_TYPE.
  384. */
  385. static void handle_wrap(chunk_t *pc);
  386. /**
  387. * A proto wrap chunk and what follows should be treated as a function proto.
  388. *
  389. * RETTYPE PROTO_WRAP( NAME, PARAMS ); or RETTYPE PROTO_WRAP( NAME, (PARAMS) );
  390. * RETTYPE gets changed with make_type().
  391. * PROTO_WRAP is marked as CT_FUNC_PROTO or CT_FUNC_DEF.
  392. * NAME is marked as CT_WORD.
  393. * PARAMS is all marked as prototype parameters.
  394. */
  395. static void handle_proto_wrap(chunk_t *pc);
  396. static bool is_oc_block(chunk_t *pc);
  397. /**
  398. * Java assert statements are: "assert EXP1 [: EXP2] ;"
  399. * Mark the parent of the colon and semicolon
  400. */
  401. static void handle_java_assert(chunk_t *pc);
  402. /**
  403. * Parse off the types in the D template args, adds to cs
  404. * returns the close_paren
  405. */
  406. static chunk_t *get_d_template_types(ChunkStack &cs, chunk_t *open_paren);
  407. static bool chunkstack_match(ChunkStack &cs, chunk_t *pc);
  408. enum PLBfound
  409. {
  410. FOUND_ANGLE_CLOSE = 0, // '>' found
  411. NO_PROTOCOL_FOUND = 1, // no protocol found,
  412. FOUND_ANGLE_OPEN = 2 // '<' found
  413. };
  414. void make_type(chunk_t *pc)
  415. {
  416. LOG_FUNC_ENTRY();
  417. if (pc != NULL)
  418. {
  419. if (pc->type == CT_WORD)
  420. {
  421. set_chunk_type(pc, CT_TYPE);
  422. }
  423. else if (chunk_is_star(pc) || chunk_is_msref(pc))
  424. {
  425. set_chunk_type(pc, CT_PTR_TYPE);
  426. }
  427. else if (chunk_is_addr(pc))
  428. {
  429. set_chunk_type(pc, CT_BYREF);
  430. }
  431. }
  432. }
  433. void flag_series(chunk_t *start, chunk_t *end, UINT64 set_flags, UINT64 clr_flags, chunk_nav_t nav)
  434. {
  435. LOG_FUNC_ENTRY();
  436. while (start && (start != end))
  437. {
  438. chunk_flags_upd(start, clr_flags, set_flags);
  439. start = chunk_get_next(start, nav);
  440. }
  441. if (end)
  442. {
  443. chunk_flags_upd(end, clr_flags, set_flags);
  444. }
  445. }
  446. static chunk_t *flag_parens(chunk_t *po, UINT64 flags, c_token_t opentype,
  447. c_token_t parenttype, bool parent_all)
  448. {
  449. LOG_FUNC_ENTRY();
  450. chunk_t *paren_close;
  451. paren_close = chunk_skip_to_match(po, CNAV_PREPROC);
  452. if (paren_close == NULL)
  453. {
  454. LOG_FMT(LERR, "flag_parens: no match for [%s] at [%zu:%zu]",
  455. po->text(), po->orig_line, po->orig_col);
  456. log_func_stack_inline(LERR);
  457. cpd.error_count++;
  458. return(NULL);
  459. }
  460. LOG_FMT(LFLPAREN, "flag_parens: %zu:%zu [%s] and %zu:%zu [%s] type=%s ptype=%s",
  461. po->orig_line, po->orig_col, po->text(),
  462. paren_close->orig_line, paren_close->orig_col, paren_close->text(),
  463. get_token_name(opentype), get_token_name(parenttype));
  464. //log_func_stack_inline(LSETTYP);
  465. log_func_stack_inline(LFLPAREN);
  466. if (po != paren_close)
  467. {
  468. if ((flags != 0) ||
  469. (parent_all && (parenttype != CT_NONE)))
  470. {
  471. chunk_t *pc;
  472. for (pc = chunk_get_next(po, CNAV_PREPROC);
  473. pc != paren_close;
  474. pc = chunk_get_next(pc, CNAV_PREPROC))
  475. {
  476. chunk_flags_set(pc, flags);
  477. if (parent_all)
  478. {
  479. set_chunk_parent(pc, parenttype);
  480. }
  481. }
  482. }
  483. if (opentype != CT_NONE)
  484. {
  485. set_chunk_type(po, opentype);
  486. set_chunk_type(paren_close, (c_token_t)(opentype + 1));
  487. }
  488. if (parenttype != CT_NONE)
  489. {
  490. set_chunk_parent(po, parenttype);
  491. set_chunk_parent(paren_close, parenttype);
  492. }
  493. }
  494. return(chunk_get_next_ncnl(paren_close, CNAV_PREPROC));
  495. } // flag_parens
  496. /**
  497. * Sets the parent of the open paren/brace/square/angle and the closing.
  498. * Note - it is assumed that pc really does point to an open item and the
  499. * close must be open + 1.
  500. *
  501. * @param start The open paren
  502. * @param parent The type to assign as the parent
  503. * @return The chunk after the close paren
  504. */
  505. chunk_t *set_paren_parent(chunk_t *start, c_token_t parent)
  506. {
  507. LOG_FUNC_ENTRY();
  508. chunk_t *end;
  509. end = chunk_skip_to_match(start, CNAV_PREPROC);
  510. if (end != NULL)
  511. {
  512. LOG_FMT(LFLPAREN, "set_paren_parent: %zu:%zu [%s] and %zu:%zu [%s] type=%s ptype=%s",
  513. start->orig_line, start->orig_col, start->text(),
  514. end->orig_line, end->orig_col, end->text(),
  515. get_token_name(start->type), get_token_name(parent));
  516. log_func_stack_inline(LFLPAREN);
  517. set_chunk_parent(start, parent);
  518. set_chunk_parent(end, parent);
  519. }
  520. return(chunk_get_next_ncnl(end, CNAV_PREPROC));
  521. }
  522. static void flag_asm(chunk_t *pc)
  523. {
  524. LOG_FUNC_ENTRY();
  525. chunk_t *tmp = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  526. if (!chunk_is_token(tmp, CT_QUALIFIER))
  527. {
  528. return;
  529. }
  530. chunk_t *po = chunk_get_next_ncnl(tmp, CNAV_PREPROC);
  531. if (!chunk_is_paren_open(po))
  532. {
  533. return;
  534. }
  535. chunk_t *end = chunk_skip_to_match(po, CNAV_PREPROC);
  536. if (!end)
  537. {
  538. return;
  539. }
  540. set_chunk_parent(po, CT_ASM);
  541. set_chunk_parent(end, CT_ASM);
  542. for (tmp = chunk_get_next_ncnl(po, CNAV_PREPROC);
  543. tmp != end;
  544. tmp = chunk_get_next_ncnl(tmp, CNAV_PREPROC))
  545. {
  546. if (tmp->type == CT_COLON)
  547. {
  548. set_chunk_type(tmp, CT_ASM_COLON);
  549. }
  550. else if (tmp->type == CT_DC_MEMBER)
  551. {
  552. /* if there is a string on both sides, then this is two ASM_COLONs */
  553. if (chunk_is_token(chunk_get_next_ncnl(tmp, CNAV_PREPROC), CT_STRING) &&
  554. chunk_is_token(chunk_get_prev_ncnl(tmp, CNAV_PREPROC), CT_STRING))
  555. {
  556. chunk_t nc;
  557. nc = *tmp;
  558. tmp->str.resize(1);
  559. tmp->orig_col_end = tmp->orig_col + 1;
  560. set_chunk_type(tmp, CT_ASM_COLON);
  561. nc.type = tmp->type;
  562. nc.str.pop_front();
  563. nc.orig_col++;
  564. nc.column++;
  565. chunk_add_after(&nc, tmp);
  566. }
  567. }
  568. }
  569. tmp = chunk_get_next_ncnl(end, CNAV_PREPROC);
  570. if (chunk_is_token(tmp, CT_SEMICOLON))
  571. {
  572. set_chunk_parent(tmp, CT_ASM);
  573. }
  574. } // flag_asm
  575. static bool chunk_ends_type(chunk_t *start)
  576. {
  577. LOG_FUNC_ENTRY();
  578. chunk_t *pc = start;
  579. bool ret = false;
  580. size_t cnt = 0;
  581. bool last_lval = false;
  582. for (/* nada */; pc != NULL; pc = chunk_get_prev_ncnl(pc))
  583. {
  584. LOG_FMT(LFTYPE, "%s: [%s] %s flags %" PRIx64 " on line %zu, col %zu\n",
  585. __func__, get_token_name(pc->type), pc->text(),
  586. pc->flags, pc->orig_line, pc->orig_col);
  587. if ((pc->type == CT_WORD) ||
  588. (pc->type == CT_TYPE) ||
  589. (pc->type == CT_PTR_TYPE) ||
  590. (pc->type == CT_STRUCT) ||
  591. (pc->type == CT_DC_MEMBER) ||
  592. (pc->type == CT_QUALIFIER))
  593. {
  594. cnt++;
  595. last_lval = (pc->flags & PCF_LVALUE) != 0; // forcing value to bool
  596. continue;
  597. }
  598. if ((chunk_is_semicolon(pc) && ((pc->flags & PCF_IN_FOR) == 0)) ||
  599. (pc->type == CT_TYPEDEF) ||
  600. (pc->type == CT_BRACE_OPEN) ||
  601. (pc->type == CT_BRACE_CLOSE) ||
  602. chunk_is_forin(pc) ||
  603. ((pc->type == CT_SPAREN_OPEN) && last_lval))
  604. {
  605. ret = cnt > 0;
  606. }
  607. break;
  608. }
  609. if (pc == NULL)
  610. {
  611. /* first token */
  612. ret = true;
  613. }
  614. LOG_FMT(LFTYPE, "%s verdict: %s\n", __func__, ret ? "yes" : "no");
  615. return(ret);
  616. } // chunk_ends_type
  617. static chunk_t *skip_dc_member(chunk_t *start)
  618. {
  619. LOG_FUNC_ENTRY();
  620. if (!start)
  621. {
  622. return(NULL);
  623. }
  624. chunk_t *pc = start;
  625. chunk_t *next = (pc->type == CT_DC_MEMBER) ? pc : chunk_get_next_ncnl(pc);
  626. while (next && (next->type == CT_DC_MEMBER))
  627. {
  628. pc = chunk_get_next_ncnl(next);
  629. next = chunk_get_next_ncnl(pc);
  630. }
  631. return(pc);
  632. }
  633. /**
  634. * This is called on every chunk.
  635. * First on all non-preprocessor chunks and then on each preprocessor chunk.
  636. * It does all the detection and classifying.
  637. * This is only called by fix_symbols.
  638. * The three parameters never get the value NULL.
  639. * it is not necessary to test.
  640. */
  641. void do_symbol_check(chunk_t *prev, chunk_t *pc, chunk_t *next)
  642. {
  643. LOG_FUNC_ENTRY();
  644. chunk_t *tmp;
  645. #ifdef DEBUG
  646. LOG_FMT(LGUY, "(%d) ", __LINE__);
  647. #endif
  648. if (pc->type == CT_NEWLINE)
  649. {
  650. LOG_FMT(LGUY, "%s: %zu:%zu CT_NEWLINE\n", __func__, pc->orig_line, pc->orig_col);
  651. }
  652. else if (pc->type == CT_VBRACE_OPEN)
  653. {
  654. LOG_FMT(LGUY, "%s: %zu:%zu CT_VBRACE_OPEN\n", __func__, pc->orig_line, pc->orig_col);
  655. }
  656. else if (pc->type == CT_VBRACE_CLOSE)
  657. {
  658. LOG_FMT(LGUY, "%s: %zu:%zu CT_VBRACE_CLOSE\n", __func__, pc->orig_line, pc->orig_col);
  659. }
  660. else
  661. {
  662. LOG_FMT(LGUY, "%s: %zu:%zu %s:%s\n",
  663. __func__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type));
  664. }
  665. // LOG_FMT(LSYS, " %3d > ['%s' %s] ['%s' %s] ['%s' %s]\n",
  666. // pc->orig_line,
  667. // prev->text(), get_token_name(prev->type),
  668. // pc->text(), get_token_name(pc->type),
  669. // next->text(), get_token_name(next->type));
  670. if (pc->type == CT_OC_AT)
  671. {
  672. if ((next->type == CT_PAREN_OPEN) ||
  673. (next->type == CT_BRACE_OPEN) ||
  674. (next->type == CT_SQUARE_OPEN))
  675. {
  676. flag_parens(next, PCF_OC_BOXED, next->type, CT_OC_AT, false);
  677. }
  678. else
  679. {
  680. set_chunk_parent(next, CT_OC_AT);
  681. }
  682. }
  683. /* D stuff */
  684. if ((cpd.lang_flags & LANG_D) &&
  685. (pc->type == CT_QUALIFIER) &&
  686. chunk_is_str(pc, "const", 5) &&
  687. (next->type == CT_PAREN_OPEN))
  688. {
  689. set_chunk_type(pc, CT_D_CAST);
  690. set_paren_parent(next, pc->type);
  691. }
  692. if ((next->type == CT_PAREN_OPEN) &&
  693. ((pc->type == CT_D_CAST) ||
  694. (pc->type == CT_DELEGATE) ||
  695. (pc->type == CT_ALIGN)))
  696. {
  697. /* mark the parenthesis parent */
  698. tmp = set_paren_parent(next, pc->type);
  699. /* For a D cast - convert the next item */
  700. if ((pc->type == CT_D_CAST) && (tmp != NULL))
  701. {
  702. if (tmp->type == CT_STAR)
  703. {
  704. set_chunk_type(tmp, CT_DEREF);
  705. }
  706. else if (tmp->type == CT_AMP)
  707. {
  708. set_chunk_type(tmp, CT_ADDR);
  709. }
  710. else if (tmp->type == CT_MINUS)
  711. {
  712. set_chunk_type(tmp, CT_NEG);
  713. }
  714. else if (tmp->type == CT_PLUS)
  715. {
  716. set_chunk_type(tmp, CT_POS);
  717. }
  718. }
  719. /* For a delegate, mark previous words as types and the item after the
  720. * close paren as a variable def
  721. */
  722. if (pc->type == CT_DELEGATE)
  723. {
  724. if (tmp != NULL)
  725. {
  726. set_chunk_parent(tmp, CT_DELEGATE);
  727. if (tmp->level == tmp->brace_level)
  728. {
  729. chunk_flags_set(tmp, PCF_VAR_1ST_DEF);
  730. }
  731. }
  732. for (tmp = chunk_get_prev_ncnl(pc); tmp != NULL; tmp = chunk_get_prev_ncnl(tmp))
  733. {
  734. if (chunk_is_semicolon(tmp) ||
  735. (tmp->type == CT_BRACE_OPEN) ||
  736. (tmp->type == CT_VBRACE_OPEN))
  737. {
  738. break;
  739. }
  740. make_type(tmp);
  741. }
  742. }
  743. if ((pc->type == CT_ALIGN) && (tmp != NULL))
  744. {
  745. if (tmp->type == CT_BRACE_OPEN)
  746. {
  747. set_paren_parent(tmp, pc->type);
  748. }
  749. else if (tmp->type == CT_COLON)
  750. {
  751. set_chunk_parent(tmp, pc->type);
  752. }
  753. }
  754. } /* paren open + cast/align/delegate */
  755. if (pc->type == CT_INVARIANT)
  756. {
  757. if (next->type == CT_PAREN_OPEN)
  758. {
  759. set_chunk_parent(next, pc->type);
  760. tmp = chunk_get_next(next);
  761. while (tmp != NULL)
  762. {
  763. if (tmp->type == CT_PAREN_CLOSE)
  764. {
  765. set_chunk_parent(tmp, pc->type);
  766. break;
  767. }
  768. make_type(tmp);
  769. tmp = chunk_get_next(tmp);
  770. }
  771. }
  772. else
  773. {
  774. set_chunk_type(pc, CT_QUALIFIER);
  775. }
  776. }
  777. if ((prev->type == CT_BRACE_OPEN) &&
  778. (prev->parent_type != CT_CS_PROPERTY) &&
  779. ((pc->type == CT_GETSET) || (pc->type == CT_GETSET_EMPTY)))
  780. {
  781. flag_parens(prev, 0, CT_NONE, CT_GETSET, false);
  782. }
  783. if (pc->type == CT_ASM)
  784. {
  785. flag_asm(pc);
  786. }
  787. /* Objective C stuff */
  788. if (cpd.lang_flags & LANG_OC)
  789. {
  790. /* Check for message declarations */
  791. if (pc->flags & PCF_STMT_START)
  792. {
  793. if ((chunk_is_str(pc, "-", 1) || chunk_is_str(pc, "+", 1)) &&
  794. chunk_is_str(next, "(", 1))
  795. {
  796. handle_oc_message_decl(pc);
  797. }
  798. }
  799. if (pc->flags & PCF_EXPR_START)
  800. {
  801. if (pc->type == CT_SQUARE_OPEN)
  802. {
  803. handle_oc_message_send(pc);
  804. }
  805. if (pc->type == CT_CARET)
  806. {
  807. handle_oc_block_literal(pc);
  808. }
  809. }
  810. if (pc->type == CT_OC_PROPERTY)
  811. {
  812. handle_oc_property_decl(pc);
  813. }
  814. }
  815. /* C# stuff */
  816. if (cpd.lang_flags & LANG_CS)
  817. {
  818. /* '[assembly: xxx]' stuff */
  819. if ((pc->flags & PCF_EXPR_START) &&
  820. (pc->type == CT_SQUARE_OPEN))
  821. {
  822. handle_cs_square_stmt(pc);
  823. }
  824. if ((next->type == CT_BRACE_OPEN) &&
  825. (next->parent_type == CT_NONE) &&
  826. ((pc->type == CT_SQUARE_CLOSE) ||
  827. (pc->type == CT_ANGLE_CLOSE) ||
  828. (pc->type == CT_WORD)))
  829. {
  830. handle_cs_property(next);
  831. }
  832. if ((pc->type == CT_SQUARE_CLOSE) &&
  833. (next->type == CT_WORD))
  834. {
  835. handle_cs_array_type(pc);
  836. }
  837. if ((((pc->type == CT_LAMBDA) || (pc->type == CT_DELEGATE))) && (next->type == CT_BRACE_OPEN))
  838. {
  839. set_paren_parent(next, pc->type);
  840. }
  841. if ((pc->type == CT_WHEN) && (pc->next->type != CT_SPAREN_OPEN))
  842. {
  843. set_chunk_type(pc, CT_WORD);
  844. }
  845. }
  846. if (pc->type == CT_NEW)
  847. {
  848. chunk_t *ts = NULL;
  849. tmp = next;
  850. if (tmp->type == CT_TSQUARE)
  851. {
  852. ts = tmp;
  853. tmp = chunk_get_next_ncnl(tmp);
  854. }
  855. if (tmp && (tmp->type == CT_BRACE_OPEN))
  856. {
  857. set_paren_parent(tmp, pc->type);
  858. if (ts)
  859. {
  860. ts->parent_type = pc->type;
  861. }
  862. }
  863. }
  864. /* C++11 Lambda stuff */
  865. if ((cpd.lang_flags & LANG_CPP) &&
  866. ((pc->type == CT_SQUARE_OPEN) || (pc->type == CT_TSQUARE)))
  867. {
  868. handle_cpp_lambda(pc);
  869. }
  870. /* FIXME: which language does this apply to? */
  871. if ((pc->type == CT_ASSIGN) && (next->type == CT_SQUARE_OPEN))
  872. {
  873. set_paren_parent(next, CT_ASSIGN);
  874. /* Mark one-liner assignment */
  875. tmp = next;
  876. while ((tmp = chunk_get_next_nc(tmp)) != NULL)
  877. {
  878. if (chunk_is_newline(tmp))
  879. {
  880. break;
  881. }
  882. if ((tmp->type == CT_SQUARE_CLOSE) && (next->level == tmp->level))
  883. {
  884. chunk_flags_set(tmp, PCF_ONE_LINER);
  885. chunk_flags_set(next, PCF_ONE_LINER);
  886. break;
  887. }
  888. }
  889. }
  890. if (pc->type == CT_ASSERT)
  891. {
  892. handle_java_assert(pc);
  893. }
  894. if (pc->type == CT_ANNOTATION)
  895. {
  896. tmp = chunk_get_next_ncnl(pc);
  897. if (chunk_is_paren_open(tmp))
  898. {
  899. set_paren_parent(tmp, CT_ANNOTATION);
  900. }
  901. }
  902. /* A [] in C# and D only follows a type */
  903. if ((pc->type == CT_TSQUARE) &&
  904. (cpd.lang_flags & (LANG_D | LANG_CS | LANG_VALA)))
  905. {
  906. if (prev->type == CT_WORD)
  907. {
  908. set_chunk_type(prev, CT_TYPE);
  909. }
  910. if (next->type == CT_WORD)
  911. {
  912. chunk_flags_set(next, PCF_VAR_1ST_DEF);
  913. }
  914. }
  915. if ((pc->type == CT_SQL_EXEC) ||
  916. (pc->type == CT_SQL_BEGIN) ||
  917. (pc->type == CT_SQL_END))
  918. {
  919. mark_exec_sql(pc);
  920. }
  921. if (pc->type == CT_PROTO_WRAP)
  922. {
  923. handle_proto_wrap(pc);
  924. }
  925. /* Handle the typedef */
  926. if (pc->type == CT_TYPEDEF)
  927. {
  928. fix_typedef(pc);
  929. }
  930. if ((pc->type == CT_ENUM) ||
  931. (pc->type == CT_STRUCT) ||
  932. (pc->type == CT_UNION))
  933. {
  934. if (prev->type != CT_TYPEDEF)
  935. {
  936. fix_enum_struct_union(pc);
  937. }
  938. }
  939. if (pc->type == CT_EXTERN)
  940. {
  941. if (chunk_is_paren_open(next))
  942. {
  943. tmp = flag_parens(next, 0, CT_NONE, CT_EXTERN, true);
  944. if (tmp && (tmp->type == CT_BRACE_OPEN))
  945. {
  946. set_paren_parent(tmp, CT_EXTERN);
  947. }
  948. }
  949. else
  950. {
  951. /* next likely is a string (see tokenize_cleanup.cpp) */
  952. set_chunk_parent(next, CT_EXTERN);
  953. tmp = chunk_get_next_ncnl(next);
  954. if (tmp && (tmp->type == CT_BRACE_OPEN))
  955. {
  956. set_paren_parent(tmp, CT_EXTERN);
  957. }
  958. }
  959. }
  960. if (pc->type == CT_TEMPLATE)
  961. {
  962. if (cpd.lang_flags & LANG_D)
  963. {
  964. handle_d_template(pc);
  965. }
  966. else
  967. {
  968. handle_cpp_template(pc);
  969. }
  970. }
  971. if ((pc->type == CT_WORD) &&
  972. (next->type == CT_ANGLE_OPEN) &&
  973. (next->parent_type == CT_TEMPLATE))
  974. {
  975. mark_template_func(pc, next);
  976. }
  977. if ((pc->type == CT_SQUARE_CLOSE) &&
  978. (next->type == CT_PAREN_OPEN))
  979. {
  980. flag_parens(next, 0, CT_FPAREN_OPEN, CT_NONE, false);
  981. }
  982. if (pc->type == CT_TYPE_CAST)
  983. {
  984. fix_type_cast(pc);
  985. }
  986. if ((pc->parent_type == CT_ASSIGN) &&
  987. ((pc->type == CT_BRACE_OPEN) ||
  988. (pc->type == CT_SQUARE_OPEN)))
  989. {
  990. /* Mark everything in here as in assign */
  991. flag_parens(pc, PCF_IN_ARRAY_ASSIGN, pc->type, CT_NONE, false);
  992. }
  993. if (pc->type == CT_D_TEMPLATE)
  994. {
  995. set_paren_parent(next, pc->type);
  996. }
  997. /**
  998. * A word before an open paren is a function call or definition.
  999. * CT_WORD => CT_FUNC_CALL or CT_FUNC_DEF
  1000. */
  1001. if (next->type == CT_PAREN_OPEN)
  1002. {
  1003. tmp = chunk_get_next_ncnl(next);
  1004. if ((cpd.lang_flags & LANG_OC) && chunk_is_token(tmp, CT_CARET))
  1005. {
  1006. handle_oc_block_type(tmp);
  1007. // This is the case where a block literal is passed as the first argument of a C-style method invocation.
  1008. if ((tmp->type == CT_OC_BLOCK_CARET) && (pc->type == CT_WORD))
  1009. {
  1010. set_chunk_type(pc, CT_FUNC_CALL);
  1011. }
  1012. }
  1013. else if ((pc->type == CT_WORD) || (pc->type == CT_OPERATOR_VAL))
  1014. {
  1015. set_chunk_type(pc, CT_FUNCTION);
  1016. }
  1017. else if (pc->type == CT_TYPE)
  1018. {
  1019. /**
  1020. * If we are on a type, then we are either on a C++ style cast, a
  1021. * function or we are on a function type.
  1022. * The only way to tell for sure is to find the close paren and see
  1023. * if it is followed by an open paren.
  1024. * "int(5.6)"
  1025. * "int()"
  1026. * "int(foo)(void)"
  1027. *
  1028. * FIXME: this check can be done better...
  1029. */
  1030. tmp = chunk_get_next_type(next, CT_PAREN_CLOSE, next->level);
  1031. tmp = chunk_get_next(tmp);
  1032. if ((tmp != NULL) && (tmp->type == CT_PAREN_OPEN))
  1033. {
  1034. /* we have "TYPE(...)(" */
  1035. set_chunk_type(pc, CT_FUNCTION);
  1036. }
  1037. else
  1038. {
  1039. if ((pc->parent_type == CT_NONE) &&
  1040. ((pc->flags & PCF_IN_TYPEDEF) == 0))
  1041. {
  1042. tmp = chunk_get_next_ncnl(next);
  1043. if ((tmp != NULL) && (tmp->type == CT_PAREN_CLOSE))
  1044. {
  1045. /* we have TYPE() */
  1046. set_chunk_type(pc, CT_FUNCTION);
  1047. }
  1048. else
  1049. {
  1050. /* we have TYPE(...) */
  1051. set_chunk_type(pc, CT_CPP_CAST);
  1052. set_paren_parent(next, CT_CPP_CAST);
  1053. }
  1054. }
  1055. }
  1056. }
  1057. else if (pc->type == CT_ATTRIBUTE)
  1058. {
  1059. flag_parens(next, 0, CT_FPAREN_OPEN, CT_ATTRIBUTE, false);
  1060. }
  1061. }
  1062. if (cpd.lang_flags & LANG_PAWN)
  1063. {
  1064. if ((pc->type == CT_FUNCTION) && (pc->brace_level > 0))
  1065. {
  1066. set_chunk_type(pc, CT_FUNC_CALL);
  1067. }
  1068. if ((pc->type == CT_STATE) &&
  1069. (next->type == CT_PAREN_OPEN))
  1070. {
  1071. set_paren_parent(next, pc->type);
  1072. }
  1073. }
  1074. else
  1075. {
  1076. if ((pc->type == CT_FUNCTION) &&
  1077. ((pc->parent_type == CT_OC_BLOCK_EXPR) || !is_oc_block(pc)))
  1078. {
  1079. mark_function(pc);
  1080. }
  1081. }
  1082. /* Detect C99 member stuff */
  1083. if ((pc->type == CT_MEMBER) &&
  1084. ((prev->type == CT_COMMA) ||
  1085. (prev->type == CT_BRACE_OPEN)))
  1086. {
  1087. set_chunk_type(pc, CT_C99_MEMBER);
  1088. set_chunk_parent(next, CT_C99_MEMBER);
  1089. }
  1090. /* Mark function parens and braces */
  1091. if ((pc->type == CT_FUNC_DEF) ||
  1092. (pc->type == CT_FUNC_CALL) ||
  1093. (pc->type == CT_FUNC_CALL_USER) ||
  1094. (pc->type == CT_FUNC_PROTO))
  1095. {
  1096. tmp = next;
  1097. if (tmp->type == CT_SQUARE_OPEN)
  1098. {
  1099. tmp = set_paren_parent(tmp, pc->type);
  1100. }
  1101. else if ((tmp->type == CT_TSQUARE) ||
  1102. (tmp->parent_type == CT_OPERATOR))
  1103. {
  1104. tmp = chunk_get_next_ncnl(tmp);
  1105. }
  1106. if (tmp != NULL)
  1107. {
  1108. if (chunk_is_paren_open(tmp))
  1109. {
  1110. tmp = flag_parens(tmp, 0, CT_FPAREN_OPEN, pc->type, false);
  1111. if (tmp != NULL)
  1112. {
  1113. if (tmp->type == CT_BRACE_OPEN)
  1114. {
  1115. if ((tmp->parent_type != CT_DOUBLE_BRACE) &&
  1116. ((pc->flags & PCF_IN_CONST_ARGS) == 0))
  1117. {
  1118. set_paren_parent(tmp, pc->type);
  1119. }
  1120. }
  1121. else if (chunk_is_semicolon(tmp) && (pc->type == CT_FUNC_PROTO))
  1122. {
  1123. set_chunk_parent(tmp, pc->type);
  1124. }
  1125. }
  1126. }
  1127. }
  1128. }
  1129. /* Mark the parameters in catch() */
  1130. if ((pc->type == CT_CATCH) && (next->type == CT_SPAREN_OPEN))
  1131. {
  1132. fix_fcn_def_params(next);
  1133. }
  1134. if ((pc->type == CT_THROW) && (prev->type == CT_FPAREN_CLOSE))
  1135. {
  1136. set_chunk_parent(pc, prev->parent_type);
  1137. if (next->type == CT_PAREN_OPEN)
  1138. {
  1139. set_paren_parent(next, CT_THROW);
  1140. }
  1141. }
  1142. /* Mark the braces in: "for_each_entry(xxx) { }" */
  1143. if ((pc->type == CT_BRACE_OPEN) &&
  1144. (pc->parent_type != CT_DOUBLE_BRACE) &&
  1145. (prev->type == CT_FPAREN_CLOSE) &&
  1146. ((prev->parent_type == CT_FUNC_CALL) ||
  1147. (prev->parent_type == CT_FUNC_CALL_USER)) &&
  1148. ((pc->flags & PCF_IN_CONST_ARGS) == 0))
  1149. {
  1150. set_paren_parent(pc, CT_FUNC_CALL);
  1151. }
  1152. /* Check for a close paren followed by an open paren, which means that
  1153. * we are on a function type declaration (C/C++ only?).
  1154. * Note that typedefs are already taken care of.
  1155. */
  1156. if (((pc->flags & (PCF_IN_TYPEDEF | PCF_IN_TEMPLATE)) == 0) &&
  1157. (pc->parent_type != CT_CPP_CAST) &&
  1158. (pc->parent_type != CT_C_CAST) &&
  1159. ((pc->flags & PCF_IN_PREPROC) == 0) &&
  1160. (!is_oc_block(pc)) &&
  1161. (pc->parent_type != CT_OC_MSG_DECL) &&
  1162. (pc->parent_type != CT_OC_MSG_SPEC) &&
  1163. chunk_is_str(pc, ")", 1) &&
  1164. chunk_is_str(next, "(", 1))
  1165. {
  1166. if (cpd.lang_flags & LANG_D)
  1167. {
  1168. flag_parens(next, 0, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
  1169. }
  1170. else
  1171. {
  1172. mark_function_type(pc);
  1173. }
  1174. }
  1175. if (((pc->type == CT_CLASS) ||
  1176. (pc->type == CT_STRUCT)) &&
  1177. (pc->level == pc->brace_level))
  1178. {
  1179. if ((pc->type != CT_STRUCT) || ((cpd.lang_flags & LANG_C) == 0))
  1180. {
  1181. mark_class_ctor(pc);
  1182. }
  1183. }
  1184. if (pc->type == CT_OC_CLASS)
  1185. {
  1186. handle_oc_class(pc);
  1187. }
  1188. if (pc->type == CT_NAMESPACE)
  1189. {
  1190. mark_namespace(pc);
  1191. }
  1192. /*TODO: Check for stuff that can only occur at the start of an statement */
  1193. if ((cpd.lang_flags & LANG_D) == 0)
  1194. {
  1195. /**
  1196. * Check a paren pair to see if it is a cast.
  1197. * Note that SPAREN and FPAREN have already been marked.
  1198. */
  1199. if ((pc->type == CT_PAREN_OPEN) &&
  1200. ((pc->parent_type == CT_NONE) ||
  1201. (pc->parent_type == CT_OC_MSG) ||
  1202. (pc->parent_type == CT_OC_BLOCK_EXPR)) &&
  1203. ((next->type == CT_WORD) ||
  1204. (next->type == CT_TYPE) ||
  1205. (next->type == CT_STRUCT) ||
  1206. (next->type == CT_QUALIFIER) ||
  1207. (next->type == CT_MEMBER) ||
  1208. (next->type == CT_DC_MEMBER) ||
  1209. (next->type == CT_ENUM) ||
  1210. (next->type == CT_UNION)) &&
  1211. (prev->type != CT_SIZEOF) &&
  1212. (prev->parent_type != CT_OPERATOR) &&
  1213. ((pc->flags & PCF_IN_TYPEDEF) == 0) &&
  1214. ((pc->flags & PCF_IN_FCN_DEF) == 0)) // issue # 222
  1215. {
  1216. fix_casts(pc);
  1217. }
  1218. }
  1219. /* Check for stuff that can only occur at the start of an expression */
  1220. if (pc->flags & PCF_EXPR_START)
  1221. {
  1222. /* Change STAR, MINUS, and PLUS in the easy cases */
  1223. if (pc->type == CT_STAR)
  1224. {
  1225. // issue #596
  1226. // [0x100062020:IN_SPAREN,IN_FOR,STMT_START,EXPR_START,PUNCTUATOR]
  1227. // prev->type is CT_COLON ==> CT_DEREF
  1228. if (prev->type == CT_ANGLE_CLOSE)
  1229. {
  1230. set_chunk_type(pc, CT_PTR_TYPE);
  1231. }
  1232. else if (prev->type == CT_COLON)
  1233. {
  1234. set_chunk_type(pc, CT_DEREF);
  1235. }
  1236. else
  1237. {
  1238. set_chunk_type(pc, CT_DEREF);
  1239. }
  1240. }
  1241. if ((cpd.lang_flags & LANG_CPP) && (pc->type == CT_CARET) && (prev->type == CT_ANGLE_CLOSE))
  1242. {
  1243. set_chunk_type(pc, CT_PTR_TYPE);
  1244. }
  1245. if (pc->type == CT_MINUS)
  1246. {
  1247. set_chunk_type(pc, CT_NEG);
  1248. }
  1249. if (pc->type == CT_PLUS)
  1250. {
  1251. set_chunk_type(pc, CT_POS);
  1252. }
  1253. if (pc->type == CT_INCDEC_AFTER)
  1254. {
  1255. set_chunk_type(pc, CT_INCDEC_BEFORE);
  1256. //fprintf(stderr, "%s: %d> changed INCDEC_AFTER to INCDEC_BEFORE\n", __func__, pc->orig_line);
  1257. }
  1258. if (pc->type == CT_AMP)
  1259. {
  1260. //fprintf(stderr, "Changed AMP to ADDR on line %d\n", pc->orig_line);
  1261. set_chunk_type(pc, CT_ADDR);
  1262. }
  1263. if (pc->type == CT_CARET)
  1264. {
  1265. if (cpd.lang_flags & LANG_OC)
  1266. {
  1267. /* This is likely the start of a block literal */
  1268. handle_oc_block_literal(pc);
  1269. }
  1270. }
  1271. }
  1272. /* Detect a variable definition that starts with struct/enum/union/class */
  1273. if (((pc->flags & PCF_IN_TYPEDEF) == 0) &&
  1274. (prev->parent_type != CT_CPP_CAST) &&
  1275. ((prev->flags & PCF_IN_FCN_DEF) == 0) &&
  1276. ((pc->type == CT_STRUCT) ||
  1277. (pc->type == CT_UNION) ||
  1278. (pc->type == CT_CLASS) ||
  1279. (pc->type == CT_ENUM)))
  1280. {
  1281. tmp = skip_dc_member(next);
  1282. if (tmp && ((tmp->type == CT_TYPE) || (tmp->type == CT_WORD)))
  1283. {
  1284. set_chunk_parent(tmp, pc->type);
  1285. set_chunk_type(tmp, CT_TYPE);
  1286. tmp = chunk_get_next_ncnl(tmp);
  1287. }
  1288. if ((tmp != NULL) && (tmp->type == CT_BRACE_OPEN))
  1289. {
  1290. tmp = chunk_skip_to_match(tmp);
  1291. tmp = chunk_get_next_ncnl(tmp);
  1292. }
  1293. if ((tmp != NULL) && (chunk_is_ptr_operator(tmp) || (tmp->type == CT_WORD)))
  1294. {
  1295. mark_variable_definition(tmp);
  1296. }
  1297. }
  1298. /**
  1299. * Change the paren pair after a function/macrofunc.
  1300. * CT_PAREN_OPEN => CT_FPAREN_OPEN
  1301. */
  1302. if (pc->type == CT_MACRO_FUNC)
  1303. {
  1304. flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_MACRO_FUNC, false);
  1305. }
  1306. if ((pc->type == CT_MACRO_OPEN) ||
  1307. (pc->type == CT_MACRO_ELSE) ||
  1308. (pc->type == CT_MACRO_CLOSE))
  1309. {
  1310. if (next->type == CT_PAREN_OPEN)
  1311. {
  1312. flag_parens(next, 0, CT_FPAREN_OPEN, pc->type, false);
  1313. }
  1314. }
  1315. if ((pc->type == CT_DELETE) && (next->type == CT_TSQUARE))
  1316. {
  1317. set_chunk_parent(next, CT_DELETE);
  1318. }
  1319. /* Change CT_STAR to CT_PTR_TYPE or CT_ARITH or CT_DEREF */
  1320. if (pc->type == CT_STAR || ((cpd.lang_flags & LANG_CPP) && (pc->type == CT_CARET)))
  1321. {
  1322. if (chunk_is_paren_close(next) || (next->type == CT_COMMA))
  1323. {
  1324. set_chunk_type(pc, CT_PTR_TYPE);
  1325. }
  1326. else if ((cpd.lang_flags & LANG_OC) && (next->type == CT_STAR))
  1327. {
  1328. /* Change pointer-to-pointer types in OC_MSG_DECLs
  1329. * from ARITH <===> DEREF to PTR_TYPE <===> PTR_TYPE */
  1330. set_chunk_type(pc, CT_PTR_TYPE);
  1331. set_chunk_parent(pc, prev->parent_type);
  1332. set_chunk_type(next, CT_PTR_TYPE);
  1333. set_chunk_parent(next, pc->parent_type);
  1334. }
  1335. else if ((pc->type == CT_STAR) && ((prev->type == CT_SIZEOF) || (prev->type == CT_DELETE)))
  1336. {
  1337. set_chunk_type(pc, CT_DEREF);
  1338. }
  1339. else if (((prev->type == CT_WORD) && chunk_ends_type(prev)) ||
  1340. (prev->type == CT_DC_MEMBER) || (prev->type == CT_PTR_TYPE))
  1341. {
  1342. set_chunk_type(pc, CT_PTR_TYPE);
  1343. }
  1344. else if ((next->type == CT_SQUARE_OPEN) &&
  1345. !(cpd.lang_flags & LANG_OC)) // issue # 408
  1346. {
  1347. set_chunk_type(pc, CT_PTR_TYPE);
  1348. }
  1349. else if (pc->type == CT_STAR)
  1350. {
  1351. /* most PCF_PUNCTUATOR chunks except a paren close would make this
  1352. * a deref. A paren close may end a cast or may be part of a macro fcn.
  1353. */
  1354. if (prev->type == CT_TYPE)
  1355. {
  1356. set_chunk_type(pc, CT_PTR_TYPE);
  1357. }
  1358. else
  1359. {
  1360. set_chunk_type(pc,
  1361. ((prev->flags & PCF_PUNCTUATOR) &&
  1362. (!chunk_is_paren_close(prev) ||
  1363. (prev->parent_type == CT_MACRO_FUNC)) &&
  1364. (prev->type != CT_SQUARE_CLOSE) &&
  1365. (prev->type != CT_DC_MEMBER)) ? CT_DEREF : CT_ARITH);
  1366. }
  1367. }
  1368. }
  1369. if (pc->type == CT_AMP)
  1370. {
  1371. if (prev->type == CT_DELETE)
  1372. {
  1373. set_chunk_type(pc, CT_ADDR);
  1374. }
  1375. else if (prev->type == CT_TYPE)
  1376. {
  1377. set_chunk_type(pc, CT_BYREF);
  1378. }
  1379. else if ((next->type == CT_FPAREN_CLOSE) ||
  1380. (next->type == CT_COMMA))
  1381. {
  1382. // fix the bug #654
  1383. // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &)));
  1384. set_chunk_type(pc, CT_BYREF);
  1385. }
  1386. else
  1387. {
  1388. set_chunk_type(pc, CT_ARITH);
  1389. if (prev->type == CT_WORD)
  1390. {
  1391. tmp = chunk_get_prev_ncnl(prev);
  1392. if ((tmp != NULL) &&
  1393. (chunk_is_semicolon(tmp) ||
  1394. (tmp->type == CT_BRACE_OPEN) ||
  1395. (tmp->type == CT_QUALIFIER)))
  1396. {
  1397. set_chunk_type(prev, CT_TYPE);
  1398. set_chunk_type(pc, CT_ADDR);
  1399. chunk_flags_set(next, PCF_VAR_1ST);
  1400. }
  1401. }
  1402. }
  1403. }
  1404. if ((pc->type == CT_MINUS) ||
  1405. (pc->type == CT_PLUS))
  1406. {
  1407. if ((prev->type == CT_POS) || (prev->type == CT_NEG))
  1408. {
  1409. set_chunk_type(pc, (pc->type == CT_MINUS) ? CT_NEG : CT_POS);
  1410. }
  1411. else if (prev->type == CT_OC_CLASS)
  1412. {
  1413. set_chunk_type(pc, (pc->type == CT_MINUS) ? CT_NEG : CT_POS);
  1414. }
  1415. else
  1416. {
  1417. set_chunk_type(pc, CT_ARITH);
  1418. }
  1419. }
  1420. /**
  1421. * Bug # 634
  1422. * Check for extern "C" NSString* i;
  1423. * NSString is a type
  1424. * change CT_WORD => CT_TYPE for pc
  1425. * change CT_STAR => CT_PTR_TYPE for pc-next
  1426. */
  1427. if (pc->type == CT_WORD) // here NSString
  1428. {
  1429. if (pc->next != NULL) // here *
  1430. {
  1431. if (pc->next->type == CT_STAR) // here *
  1432. {
  1433. if (pc->prev != NULL)
  1434. {
  1435. if (pc->prev->type == CT_STRING)
  1436. {
  1437. if (unc_text::compare(pc->prev->text(), "\"C\"") == 0)
  1438. {
  1439. if (pc->prev->prev->type == CT_EXTERN)
  1440. {
  1441. // change CT_WORD => CT_TYPE
  1442. set_chunk_type(pc, CT_TYPE);
  1443. // change CT_STAR => CT_PTR_TYPE
  1444. set_chunk_type(pc->next, CT_PTR_TYPE);
  1445. }
  1446. }
  1447. }
  1448. }
  1449. // Issue #322 STDMETHOD(GetValues)(BSTR bsName, REFDATA** pData);
  1450. if ((pc->next->next) && (pc->next->next->type == CT_STAR))
  1451. {
  1452. // change CT_STAR => CT_PTR_TYPE
  1453. set_chunk_type(pc->next, CT_PTR_TYPE);
  1454. set_chunk_type(pc->next->next, CT_PTR_TYPE);
  1455. }
  1456. // Issue #222 whatever3 *(func_ptr)( whatever4 *foo2, ...
  1457. if ((pc->next->next) &&
  1458. (pc->next->next->type == CT_WORD) &&
  1459. (pc->flags & PCF_IN_FCN_DEF))
  1460. {
  1461. set_chunk_type(pc->next, CT_PTR_TYPE);
  1462. }
  1463. }
  1464. }
  1465. }
  1466. /**
  1467. * Bug # 634
  1468. * Check for __attribute__((visibility ("default"))) NSString* i;
  1469. * NSString is a type
  1470. * change CT_WORD => CT_TYPE for pc
  1471. * change CT_STAR => CT_PTR_TYPE for pc-next
  1472. */
  1473. if (pc->type == CT_WORD) // here NSString
  1474. {
  1475. if (pc->next != NULL) // here *
  1476. {
  1477. if (pc->next->type == CT_STAR) // here *
  1478. {
  1479. tmp = pc;
  1480. while ((tmp != NULL))
  1481. {
  1482. if (tmp->type == CT_ATTRIBUTE)
  1483. {
  1484. LOG_FMT(LGUY, "ATTRIBUTE found %s:%s\n",
  1485. get_token_name(tmp->type), tmp->text());
  1486. LOG_FMT(LGUY, "for token %s:%s\n", get_token_name(pc->type), pc->text());
  1487. // change CT_WORD => CT_TYPE
  1488. set_chunk_type(pc, CT_TYPE);
  1489. // change CT_STAR => CT_PTR_TYPE
  1490. set_chunk_type(pc->next, CT_PTR_TYPE);
  1491. }
  1492. if (tmp->flags & PCF_STMT_START)
  1493. {
  1494. // we are at beginnig of the line
  1495. break;
  1496. }
  1497. tmp = chunk_get_prev(tmp);
  1498. }
  1499. }
  1500. }
  1501. }
  1502. } // do_symbol_check
  1503. static void check_double_brace_init(chunk_t *bo1)
  1504. {
  1505. LOG_FUNC_ENTRY();
  1506. LOG_FMT(LJDBI, "%s: %zu:%zu", __func__, bo1->orig_line, bo1->orig_col);
  1507. chunk_t *pc = chunk_get_prev_ncnl(bo1);
  1508. if (chunk_is_paren_close(pc))
  1509. {
  1510. chunk_t *bo2 = chunk_get_next(bo1);
  1511. if (chunk_is_token(bo2, CT_BRACE_OPEN))
  1512. {
  1513. /* found a potential double brace */
  1514. chunk_t *bc2 = chunk_skip_to_match(bo2);
  1515. chunk_t *bc1 = chunk_get_next(bc2);
  1516. if (chunk_is_token(bc1, CT_BRACE_CLOSE))
  1517. {
  1518. LOG_FMT(LJDBI, " - end %zu:%zu\n", bc2->orig_line, bc2->orig_col);
  1519. /* delete bo2 and bc1 */
  1520. bo1->str += bo2->str;
  1521. bo1->orig_col_end = bo2->orig_col_end;
  1522. chunk_del(bo2);
  1523. set_chunk_parent(bo1, CT_DOUBLE_BRACE);
  1524. bc2->str += bc1->str;
  1525. bc2->orig_col_end = bc1->orig_col_end;
  1526. chunk_del(bc1);
  1527. set_chunk_parent(bc2, CT_DOUBLE_BRACE);
  1528. return;
  1529. }
  1530. }
  1531. }
  1532. LOG_FMT(LJDBI, " - no\n");
  1533. }
  1534. void fix_symbols(void)
  1535. {
  1536. LOG_FUNC_ENTRY();
  1537. chunk_t *pc;
  1538. chunk_t dummy;
  1539. cpd.unc_stage = US_FIX_SYMBOLS;
  1540. mark_define_expressions();
  1541. bool is_java = (cpd.lang_flags & LANG_JAVA) != 0; // forcing value to bool
  1542. for (pc = chunk_get_head(); pc != NULL; pc = chunk_get_next_ncnl(pc))
  1543. {
  1544. if ((pc->type == CT_FUNC_WRAP) ||
  1545. (pc->type == CT_TYPE_WRAP))
  1546. {
  1547. handle_wrap(pc);
  1548. }
  1549. if (pc->type == CT_ASSIGN)
  1550. {
  1551. mark_lvalue(pc);
  1552. }
  1553. if (is_java && (pc->type == CT_BRACE_OPEN))
  1554. {
  1555. check_double_brace_init(pc);
  1556. }
  1557. }
  1558. pc = chunk_get_head();
  1559. if (chunk_is_newline(pc) || chunk_is_comment(pc))
  1560. {
  1561. pc = chunk_get_next_ncnl(pc);
  1562. }
  1563. while (pc != NULL)
  1564. {
  1565. chunk_t *prev = chunk_get_prev_ncnl(pc, CNAV_PREPROC);
  1566. if (prev == NULL)
  1567. {
  1568. prev = &dummy;
  1569. }
  1570. chunk_t *next = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  1571. if (next == NULL)
  1572. {
  1573. next = &dummy;
  1574. }
  1575. do_symbol_check(prev, pc, next);
  1576. pc = chunk_get_next_ncnl(pc);
  1577. }
  1578. pawn_add_virtual_semicolons();
  1579. process_returns();
  1580. /**
  1581. * 2nd pass - handle variable definitions
  1582. * REVISIT: We need function params marked to do this (?)
  1583. */
  1584. pc = chunk_get_head();
  1585. int square_level = -1;
  1586. while (pc != NULL)
  1587. {
  1588. /* Can't have a variable definition inside [ ] */
  1589. if (square_level < 0)
  1590. {
  1591. if (pc->type == CT_SQUARE_OPEN)
  1592. {
  1593. square_level = pc->level;
  1594. }
  1595. }
  1596. else
  1597. {
  1598. if (pc->level <= (size_t)square_level)
  1599. {
  1600. square_level = -1;
  1601. }
  1602. }
  1603. /**
  1604. * A variable definition is possible after at the start of a statement
  1605. * that starts with: QUALIFIER, TYPE, or WORD
  1606. */
  1607. if ((square_level < 0) &&
  1608. (pc->flags & PCF_STMT_START) &&
  1609. ((pc->type == CT_QUALIFIER) ||
  1610. (pc->type == CT_TYPE) ||
  1611. (pc->type == CT_TYPENAME) ||
  1612. (pc->type == CT_WORD)) &&
  1613. (pc->parent_type != CT_ENUM) &&
  1614. ((pc->flags & PCF_IN_ENUM) == 0))
  1615. {
  1616. pc = fix_var_def(pc);
  1617. }
  1618. else
  1619. {
  1620. pc = chunk_get_next_ncnl(pc);
  1621. }
  1622. }
  1623. } // fix_symbols
  1624. static void mark_lvalue(chunk_t *pc)
  1625. {
  1626. LOG_FUNC_ENTRY();
  1627. chunk_t *prev;
  1628. if (pc->flags & PCF_IN_PREPROC)
  1629. {
  1630. return;
  1631. }
  1632. for (prev = chunk_get_prev_ncnl(pc);
  1633. prev != NULL;
  1634. prev = chunk_get_prev_ncnl(prev))
  1635. {
  1636. if ((prev->level < pc->level) ||
  1637. (prev->type == CT_ASSIGN) ||
  1638. (prev->type == CT_COMMA) ||
  1639. (prev->type == CT_BOOL) ||
  1640. chunk_is_semicolon(prev) ||
  1641. chunk_is_str(prev, "(", 1) ||
  1642. chunk_is_str(prev, "{", 1) ||
  1643. chunk_is_str(prev, "[", 1) ||
  1644. (prev->flags & PCF_IN_PREPROC))
  1645. {
  1646. break;
  1647. }
  1648. chunk_flags_set(prev, PCF_LVALUE);
  1649. if ((prev->level == pc->level) && chunk_is_str(prev, "&", 1))
  1650. {
  1651. make_type(prev);
  1652. }
  1653. }
  1654. }
  1655. static void mark_function_return_type(chunk_t *fname, chunk_t *start, c_token_t parent_type)
  1656. {
  1657. LOG_FUNC_ENTRY();
  1658. chunk_t *pc = start;
  1659. if (pc)
  1660. {
  1661. /* Step backwards from pc and mark the parent of the return type */
  1662. LOG_FMT(LFCNR, "%s: (backwards) return type for '%s' @ %zu:%zu",
  1663. __func__, fname->text(), fname->orig_line, fname->orig_col);
  1664. chunk_t *first = pc;
  1665. while (pc)
  1666. {
  1667. if ((!chunk_is_type(pc) &&
  1668. (pc->type != CT_OPERATOR) &&
  1669. (pc->type != CT_WORD) &&
  1670. (pc->type != CT_ADDR)) ||
  1671. (pc->flags & PCF_IN_PREPROC))
  1672. {
  1673. break;
  1674. }
  1675. if (!chunk_is_ptr_operator(pc))
  1676. {
  1677. first = pc;
  1678. }
  1679. pc = chunk_get_prev_ncnl(pc);
  1680. }
  1681. pc = first;
  1682. while (pc)
  1683. {
  1684. LOG_FMT(LFCNR, " [%s|%s]", pc->text(), get_token_name(pc->type));
  1685. if (parent_type != CT_NONE)
  1686. {
  1687. set_chunk_parent(pc, parent_type);
  1688. }
  1689. make_type(pc);
  1690. if (pc == start)
  1691. {
  1692. break;
  1693. }
  1694. pc = chunk_get_next_ncnl(pc);
  1695. }
  1696. LOG_FMT(LFCNR, "\n");
  1697. }
  1698. } // mark_function_return_type
  1699. static bool mark_function_type(chunk_t *pc)
  1700. {
  1701. LOG_FUNC_ENTRY();
  1702. LOG_FMT(LFTYPE, "%s: [%s] %s @ %zu:%zu\n",
  1703. __func__, get_token_name(pc->type), pc->text(),
  1704. pc->orig_line, pc->orig_col);
  1705. size_t star_count = 0;
  1706. size_t word_count = 0;
  1707. chunk_t *ptrcnk = NULL;
  1708. chunk_t *tmp;
  1709. chunk_t *apo;
  1710. chunk_t *apc;
  1711. chunk_t *aft;
  1712. bool anon = false;
  1713. c_token_t pt, ptp;
  1714. /* Scan backwards across the name, which can only be a word and single star */
  1715. chunk_t *varcnk = chunk_get_prev_ncnl(pc);
  1716. if (!chunk_is_word(varcnk))
  1717. {
  1718. if ((cpd.lang_flags & LANG_OC) && chunk_is_str(varcnk, "^", 1) &&
  1719. chunk_is_paren_open(chunk_get_prev_ncnl(varcnk)))
  1720. {
  1721. /* anonymous ObjC block type -- RTYPE (^)(ARGS) */
  1722. anon = true;
  1723. }
  1724. else
  1725. {
  1726. LOG_FMT(LFTYPE, "%s: not a word '%s' [%s] @ %zu:%zu\n",
  1727. __func__, varcnk->text(), get_token_name(varcnk->type),
  1728. varcnk->orig_line, varcnk->orig_col);
  1729. goto nogo_exit;
  1730. }
  1731. }
  1732. apo = chunk_get_next_ncnl(pc);
  1733. apc = chunk_skip_to_match(apo);
  1734. if (!chunk_is_paren_open(apo) || ((apc = chunk_skip_to_match(apo)) == NULL))
  1735. {
  1736. LOG_FMT(LFTYPE, "%s: not followed by parens\n", __func__);
  1737. goto nogo_exit;
  1738. }
  1739. aft = chunk_get_next_ncnl(apc);
  1740. if (chunk_is_token(aft, CT_BRACE_OPEN))
  1741. {
  1742. pt = CT_FUNC_DEF;
  1743. }
  1744. else if (chunk_is_token(aft, CT_SEMICOLON) ||
  1745. chunk_is_token(aft, CT_ASSIGN))
  1746. {
  1747. pt = CT_FUNC_PROTO;
  1748. }
  1749. else
  1750. {
  1751. LOG_FMT(LFTYPE, "%s: not followed by '{' or ';'\n", __func__);
  1752. goto nogo_exit;
  1753. }
  1754. ptp = (pc->flags & PCF_IN_TYPEDEF) ? CT_FUNC_TYPE : CT_FUNC_VAR;
  1755. tmp = pc;
  1756. while ((tmp = chunk_get_prev_ncnl(tmp)) != NULL)
  1757. {
  1758. LOG_FMT(LFTYPE, " -- [%s] %s on line %zu, col %zu",
  1759. get_token_name(tmp->type), tmp->text(),
  1760. tmp->orig_line, tmp->orig_col);
  1761. if (chunk_is_star(tmp) || chunk_is_token(tmp, CT_PTR_TYPE) ||
  1762. chunk_is_token(tmp, CT_CARET))
  1763. {
  1764. star_count++;
  1765. ptrcnk = tmp;
  1766. LOG_FMT(LFTYPE, " -- PTR_TYPE\n");
  1767. }
  1768. else if (chunk_is_word(tmp) ||
  1769. (tmp->type == CT_WORD) ||
  1770. (tmp->type == CT_TYPE))
  1771. {
  1772. word_count++;
  1773. LOG_FMT(LFTYPE, " -- TYPE(%s)\n", tmp->text());
  1774. }
  1775. else if (tmp->type == CT_DC_MEMBER)
  1776. {
  1777. word_count = 0;
  1778. LOG_FMT(LFTYPE, " -- :: reset word_count\n");
  1779. }
  1780. else if (chunk_is_str(tmp, "(", 1))
  1781. {
  1782. LOG_FMT(LFTYPE, " -- open paren (break)\n");
  1783. break;
  1784. }
  1785. else
  1786. {
  1787. LOG_FMT(LFTYPE, " -- unexpected token [%s] %s on line %zu, col %zu\n",
  1788. get_token_name(tmp->type), tmp->text(),
  1789. tmp->orig_line, tmp->orig_col);
  1790. goto nogo_exit;
  1791. }
  1792. }
  1793. if ((star_count > 1) ||
  1794. (word_count > 1) ||
  1795. ((star_count + word_count) == 0))
  1796. {
  1797. LOG_FMT(LFTYPE, "%s: bad counts word:%zu, star:%zu\n", __func__,
  1798. word_count, star_count);
  1799. goto nogo_exit;
  1800. }
  1801. /* make sure what appears before the first open paren can be a return type */
  1802. if (!chunk_ends_type(chunk_get_prev_ncnl(tmp)))
  1803. {
  1804. goto nogo_exit;
  1805. }
  1806. if (ptrcnk)
  1807. {
  1808. set_chunk_type(ptrcnk, CT_PTR_TYPE);
  1809. }
  1810. if (!anon)
  1811. {
  1812. if (pc->flags & PCF_IN_TYPEDEF)
  1813. {
  1814. set_chunk_type(varcnk, CT_TYPE);
  1815. }
  1816. else
  1817. {
  1818. set_chunk_type(varcnk, CT_FUNC_VAR);
  1819. chunk_flags_set(varcnk, PCF_VAR_1ST_DEF);
  1820. }
  1821. }
  1822. set_chunk_type(pc, CT_TPAREN_CLOSE);
  1823. set_chunk_parent(pc, ptp);
  1824. set_chunk_type(apo, CT_FPAREN_OPEN);
  1825. set_chunk_parent(apo, pt);
  1826. set_chunk_type(apc, CT_FPAREN_CLOSE);
  1827. set_chunk_parent(apc, pt);
  1828. fix_fcn_def_params(apo);
  1829. if (chunk_is_semicolon(aft))
  1830. {
  1831. set_chunk_parent(aft, (aft->flags & PCF_IN_TYPEDEF) ? CT_TYPEDEF : CT_FUNC_VAR);
  1832. }
  1833. else if (chunk_is_token(aft, CT_BRACE_OPEN))
  1834. {
  1835. flag_parens(aft, 0, CT_NONE, pt, false);
  1836. }
  1837. /* Step backwards to the previous open paren and mark everything a
  1838. */
  1839. tmp = pc;
  1840. while ((tmp = chunk_get_prev_ncnl(tmp)) != NULL)
  1841. {
  1842. LOG_FMT(LFTYPE, " ++ [%s] %s on line %zu, col %zu\n",
  1843. get_token_name(tmp->type), tmp->text(),
  1844. tmp->orig_line, tmp->orig_col);
  1845. if (*tmp->str.c_str() == '(')
  1846. {
  1847. if ((pc->flags & PCF_IN_TYPEDEF) == 0)
  1848. {
  1849. chunk_flags_set(tmp, PCF_VAR_1ST_DEF);
  1850. }
  1851. set_chunk_type(tmp, CT_TPAREN_OPEN);
  1852. set_chunk_parent(tmp, ptp);
  1853. tmp = chunk_get_prev_ncnl(tmp);
  1854. if (tmp != NULL)
  1855. {
  1856. if ((tmp->type == CT_FUNCTION) ||
  1857. (tmp->type == CT_FUNC_CALL) ||
  1858. (tmp->type == CT_FUNC_CALL_USER) ||
  1859. (tmp->type == CT_FUNC_DEF) ||
  1860. (tmp->type == CT_FUNC_PROTO))
  1861. {
  1862. set_chunk_type(tmp, CT_TYPE);
  1863. chunk_flags_clr(tmp, PCF_VAR_1ST_DEF);
  1864. }
  1865. }
  1866. mark_function_return_type(varcnk, tmp, ptp);
  1867. break;
  1868. }
  1869. }
  1870. return(true);
  1871. nogo_exit:
  1872. tmp = chunk_get_next_ncnl(pc);
  1873. if (chunk_is_paren_open(tmp))
  1874. {
  1875. LOG_FMT(LFTYPE, "%s:%d setting FUNC_CALL on %zu:%zu\n",
  1876. __func__, __LINE__, tmp->orig_line, tmp->orig_col);
  1877. flag_parens(tmp, 0, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
  1878. }
  1879. return(false);
  1880. } // mark_function_type
  1881. static void process_returns(void)
  1882. {
  1883. LOG_FUNC_ENTRY();
  1884. chunk_t *pc;
  1885. pc = chunk_get_head();
  1886. while (pc != NULL)
  1887. {
  1888. if ((pc->type != CT_RETURN) || (pc->flags & PCF_IN_PREPROC))
  1889. {
  1890. pc = chunk_get_next_type(pc, CT_RETURN, -1);
  1891. continue;
  1892. }
  1893. pc = process_return(pc);
  1894. }
  1895. }
  1896. static chunk_t *process_return(chunk_t *pc)
  1897. {
  1898. LOG_FUNC_ENTRY();
  1899. chunk_t *next;
  1900. chunk_t *temp;
  1901. chunk_t *semi;
  1902. chunk_t *cpar;
  1903. chunk_t chunk;
  1904. /* grab next and bail if it is a semicolon */
  1905. next = chunk_get_next_ncnl(pc);
  1906. if ((next == NULL) || chunk_is_semicolon(next))
  1907. {
  1908. return(next);
  1909. }
  1910. if (cpd.settings[UO_nl_return_expr].a != AV_IGNORE)
  1911. {
  1912. newline_iarf(pc, cpd.settings[UO_nl_return_expr].a);
  1913. }
  1914. if (next->type == CT_PAREN_OPEN)
  1915. {
  1916. /* See if the return is fully paren'd */
  1917. cpar = chunk_get_next_type(next, CT_PAREN_CLOSE, next->level);
  1918. semi = chunk_get_next_ncnl(cpar);
  1919. if (chunk_is_semicolon(semi))
  1920. {
  1921. if (cpd.settings[UO_mod_paren_on_return].a == AV_REMOVE)
  1922. {
  1923. LOG_FMT(LRETURN, "%s: removing parens on line %zu\n",
  1924. __func__, pc->orig_line);
  1925. /* lower the level of everything */
  1926. for (temp = next; temp != cpar; temp = chunk_get_next(temp))
  1927. {
  1928. temp->level--;
  1929. }
  1930. /* delete the parens */
  1931. chunk_del(next);
  1932. chunk_del(cpar);
  1933. /* back up the semicolon */
  1934. semi->column--;
  1935. semi->orig_col--;
  1936. semi->orig_col_end--;
  1937. }
  1938. else
  1939. {
  1940. LOG_FMT(LRETURN, "%s: keeping parens on line %zu\n",
  1941. __func__, pc->orig_line);
  1942. /* mark & keep them */
  1943. set_chunk_parent(next, CT_RETURN);
  1944. set_chunk_parent(cpar, CT_RETURN);
  1945. }
  1946. return(semi);
  1947. }
  1948. }
  1949. /* We don't have a fully paren'd return. Should we add some? */
  1950. if ((cpd.settings[UO_mod_paren_on_return].a & AV_ADD) == 0)
  1951. {
  1952. return(next);
  1953. }
  1954. /* find the next semicolon on the same level */
  1955. semi = next;
  1956. while ((semi = chunk_get_next(semi)) != NULL)
  1957. {
  1958. if ((chunk_is_semicolon(semi) && (pc->level == semi->level)) ||
  1959. (semi->level < pc->level))
  1960. {
  1961. break;
  1962. }
  1963. }
  1964. if (chunk_is_semicolon(semi) && (pc->level == semi->level))
  1965. {
  1966. /* add the parens */
  1967. chunk.type = CT_PAREN_OPEN;
  1968. chunk.str = "(";
  1969. chunk.level = pc->level;
  1970. chunk.brace_level = pc->brace_level;
  1971. chunk.orig_line = pc->orig_line;
  1972. chunk.parent_type = CT_RETURN;
  1973. chunk.flags = pc->flags & PCF_COPY_FLAGS;
  1974. chunk_add_before(&chunk, next);
  1975. chunk.type = CT_PAREN_CLOSE;
  1976. chunk.str = ")";
  1977. chunk.orig_line = semi->orig_line;
  1978. cpar = chunk_add_before(&chunk, semi);
  1979. LOG_FMT(LRETURN, "%s: added parens on line %zu\n",
  1980. __func__, pc->orig_line);
  1981. for (temp = next; temp != cpar; temp = chunk_get_next(temp))
  1982. {
  1983. temp->level++;
  1984. }
  1985. }
  1986. return(semi);
  1987. } // process_return
  1988. static bool is_ucase_str(const char *str, size_t len)
  1989. {
  1990. while (len-- > 0)
  1991. {
  1992. if (unc_toupper(*str) != *str)
  1993. {
  1994. return(false);
  1995. }
  1996. str++;
  1997. }
  1998. return(true);
  1999. }
  2000. static bool is_oc_block(chunk_t *pc)
  2001. {
  2002. return((pc != NULL) &&
  2003. ((pc->parent_type == CT_OC_BLOCK_TYPE) ||
  2004. (pc->parent_type == CT_OC_BLOCK_EXPR) ||
  2005. (pc->parent_type == CT_OC_BLOCK_ARG) ||
  2006. (pc->parent_type == CT_OC_BLOCK) ||
  2007. (pc->type == CT_OC_BLOCK_CARET) ||
  2008. (pc->next && pc->next->type == CT_OC_BLOCK_CARET) ||
  2009. (pc->prev && pc->prev->type == CT_OC_BLOCK_CARET)));
  2010. }
  2011. static void fix_casts(chunk_t *start)
  2012. {
  2013. LOG_FUNC_ENTRY();
  2014. chunk_t *pc;
  2015. chunk_t *prev;
  2016. chunk_t *first;
  2017. chunk_t *after;
  2018. chunk_t *last = NULL;
  2019. chunk_t *paren_close;
  2020. const char *verb = "likely";
  2021. const char *detail = "";
  2022. size_t count = 0;
  2023. int word_count = 0;
  2024. bool nope;
  2025. bool doubtful_cast = false;
  2026. LOG_FMT(LCASTS, "%s:line %zu, col %zu:", __func__, start->orig_line, start->orig_col);
  2027. prev = chunk_get_prev_ncnl(start);
  2028. if ((prev != NULL) && (prev->type == CT_PP_DEFINED))
  2029. {
  2030. LOG_FMT(LCASTS, " -- not a cast - after defined\n");
  2031. return;
  2032. }
  2033. /* Make sure there is only WORD, TYPE, and '*' or '^' before the close paren */
  2034. pc = chunk_get_next_ncnl(start);
  2035. first = pc;
  2036. while ((pc != NULL) && (chunk_is_type(pc) ||
  2037. (pc->type == CT_WORD) ||
  2038. (pc->type == CT_QUALIFIER) ||
  2039. (pc->type == CT_DC_MEMBER) ||
  2040. (pc->type == CT_STAR) ||
  2041. (pc->type == CT_CARET) ||
  2042. (pc->type == CT_TSQUARE) ||
  2043. (pc->type == CT_AMP)))
  2044. {
  2045. LOG_FMT(LCASTS, " [%s]", get_token_name(pc->type));
  2046. if (pc->type == CT_WORD)
  2047. {
  2048. word_count++;
  2049. }
  2050. else if (pc->type == CT_DC_MEMBER)
  2051. {
  2052. word_count--;
  2053. }
  2054. last = pc;
  2055. pc = chunk_get_next_ncnl(pc);
  2056. count++;
  2057. }
  2058. if ((pc == NULL) || (pc->type != CT_PAREN_CLOSE) || (prev->type == CT_OC_CLASS))
  2059. {
  2060. LOG_FMT(LCASTS, " -- not a cast, hit [%s]\n",
  2061. pc == NULL ? "NULL" : get_token_name(pc->type));
  2062. return;
  2063. }
  2064. if (word_count > 1)
  2065. {
  2066. LOG_FMT(LCASTS, " -- too many words: %d\n", word_count);
  2067. return;
  2068. }
  2069. paren_close = pc;
  2070. /* If last is a type or star/caret, we have a cast for sure */
  2071. if ((last->type == CT_STAR) ||
  2072. (last->type == CT_CARET) ||
  2073. (last->type == CT_PTR_TYPE) ||
  2074. (last->type == CT_TYPE))
  2075. {
  2076. verb = "for sure";
  2077. }
  2078. else if (count == 1)
  2079. {
  2080. /**
  2081. * We are on a potential cast of the form "(word)".
  2082. * We don't know if the word is a type. So lets guess based on some
  2083. * simple rules:
  2084. * - if all caps, likely a type
  2085. * - if it ends in _t, likely a type
  2086. * - if it's objective-c and the type is id, likely valid
  2087. */
  2088. verb = "guessed";
  2089. if ((last->len() > 3) &&
  2090. (last->str[last->len() - 2] == '_') &&
  2091. (last->str[last->len() - 1] == 't'))
  2092. {
  2093. detail = " -- '_t'";
  2094. }
  2095. else if (is_ucase_str(last->text(), last->len()))
  2096. {
  2097. detail = " -- upper case";
  2098. }
  2099. else if ((cpd.lang_flags & LANG_OC) && chunk_is_str(last, "id", 2))
  2100. {
  2101. detail = " -- Objective-C id";
  2102. }
  2103. else
  2104. {
  2105. /* If we can't tell for sure whether this is a cast, decide against it */
  2106. detail = " -- mixed case";
  2107. doubtful_cast = true;
  2108. }
  2109. /**
  2110. * If the next item is a * or &, the next item after that can't be a
  2111. * number or string.
  2112. *
  2113. * If the next item is a +, the next item has to be a number.
  2114. *
  2115. * If the next item is a -, the next item can't be a string.
  2116. *
  2117. * For this to be a cast, the close paren must be followed by:
  2118. * - constant (number or string)
  2119. * - paren open
  2120. * - word
  2121. *
  2122. * Find the next non-open paren item.
  2123. */
  2124. pc = chunk_get_next_ncnl(paren_close);
  2125. after = pc;
  2126. do
  2127. {
  2128. after = chunk_get_next_ncnl(after);
  2129. } while ((after != NULL) && (after->type == CT_PAREN_OPEN));
  2130. if (after == NULL)
  2131. {
  2132. LOG_FMT(LCASTS, " -- not a cast - hit NULL\n");
  2133. return;
  2134. }
  2135. nope = false;
  2136. if (chunk_is_ptr_operator(pc))
  2137. {
  2138. /* star (*) and addr (&) are ambiguous */
  2139. if ((after->type == CT_NUMBER_FP) ||
  2140. (after->type == CT_NUMBER) ||
  2141. (after->type == CT_STRING) ||
  2142. doubtful_cast)
  2143. {
  2144. nope = true;
  2145. }
  2146. }
  2147. else if (pc->type == CT_MINUS)
  2148. {
  2149. /* (UINT8)-1 or (foo)-1 or (FOO)-'a' */
  2150. if ((after->type == CT_STRING) || doubtful_cast)
  2151. {
  2152. nope = true;
  2153. }
  2154. }
  2155. else if (pc->type == CT_PLUS)
  2156. {
  2157. /* (UINT8)+1 or (foo)+1 */
  2158. if (((after->type != CT_NUMBER) &&
  2159. (after->type != CT_NUMBER_FP)) || doubtful_cast)
  2160. {
  2161. nope = true;
  2162. }
  2163. }
  2164. else if ((pc->type != CT_NUMBER_FP) &&
  2165. (pc->type != CT_NUMBER) &&
  2166. (pc->type != CT_WORD) &&
  2167. (pc->type != CT_THIS) &&
  2168. (pc->type != CT_TYPE) &&
  2169. (pc->type != CT_PAREN_OPEN) &&
  2170. (pc->type != CT_STRING) &&
  2171. (pc->type != CT_SIZEOF) &&
  2172. (pc->type != CT_FUNC_CALL) &&
  2173. (pc->type != CT_FUNC_CALL_USER) &&
  2174. (pc->type != CT_FUNCTION) &&
  2175. (pc->type != CT_BRACE_OPEN) &&
  2176. (!((pc->type == CT_SQUARE_OPEN) && (cpd.lang_flags & LANG_OC))))
  2177. {
  2178. LOG_FMT(LCASTS, " -- not a cast - followed by '%s' %s\n",
  2179. pc->text(), get_token_name(pc->type));
  2180. return;
  2181. }
  2182. if (nope)
  2183. {
  2184. LOG_FMT(LCASTS, " -- not a cast - '%s' followed by %s\n",
  2185. pc->text(), get_token_name(after->type));
  2186. return;
  2187. }
  2188. }
  2189. /* if the 'cast' is followed by a semicolon, comma or close paren, it isn't */
  2190. pc = chunk_get_next_ncnl(paren_close);
  2191. if (chunk_is_semicolon(pc) || chunk_is_token(pc, CT_COMMA) || chunk_is_paren_close(pc))
  2192. {
  2193. LOG_FMT(LCASTS, " -- not a cast - followed by %s\n", get_token_name(pc->type));
  2194. return;
  2195. }
  2196. set_chunk_parent(start, CT_C_CAST);
  2197. set_chunk_parent(paren_close, CT_C_CAST);
  2198. LOG_FMT(LCASTS, " -- %s c-cast: (", verb);
  2199. for (pc = first; pc != paren_close; pc = chunk_get_next_ncnl(pc))
  2200. {
  2201. set_chunk_parent(pc, CT_C_CAST);
  2202. make_type(pc);
  2203. LOG_FMT(LCASTS, " %s", pc->text());
  2204. }
  2205. LOG_FMT(LCASTS, " )%s\n", detail);
  2206. /* Mark the next item as an expression start */
  2207. pc = chunk_get_next_ncnl(paren_close);
  2208. if (pc != NULL)
  2209. {
  2210. chunk_flags_set(pc, PCF_EXPR_START);
  2211. if (chunk_is_opening_brace(pc))
  2212. {
  2213. set_paren_parent(pc, start->parent_type);
  2214. }
  2215. }
  2216. } // fix_casts
  2217. static void fix_type_cast(chunk_t *start)
  2218. {
  2219. LOG_FUNC_ENTRY();
  2220. chunk_t *pc;
  2221. pc = chunk_get_next_ncnl(start);
  2222. if ((pc == NULL) || (pc->type != CT_ANGLE_OPEN))
  2223. {
  2224. return;
  2225. }
  2226. while (((pc = chunk_get_next_ncnl(pc)) != NULL) &&
  2227. (pc->level >= start->level))
  2228. {
  2229. if ((pc->level == start->level) && (pc->type == CT_ANGLE_CLOSE))
  2230. {
  2231. pc = chunk_get_next_ncnl(pc);
  2232. if (chunk_is_str(pc, "(", 1))
  2233. {
  2234. set_paren_parent(pc, CT_TYPE_CAST);
  2235. }
  2236. return;
  2237. }
  2238. make_type(pc);
  2239. }
  2240. }
  2241. static void fix_enum_struct_union(chunk_t *pc)
  2242. {
  2243. LOG_FUNC_ENTRY();
  2244. chunk_t *next;
  2245. chunk_t *prev = NULL;
  2246. size_t flags = PCF_VAR_1ST_DEF;
  2247. size_t in_fcn_paren = pc->flags & PCF_IN_FCN_DEF;
  2248. /* Make sure this wasn't a cast */
  2249. if (pc->parent_type == CT_C_CAST)
  2250. {
  2251. return;
  2252. }
  2253. /* the next item is either a type or open brace */
  2254. next = chunk_get_next_ncnl(pc);
  2255. if (next && (next->type == CT_ENUM_CLASS))
  2256. {
  2257. next = chunk_get_next_ncnl(next);
  2258. }
  2259. if (next && (next->type == CT_TYPE))
  2260. {
  2261. set_chunk_parent(next, pc->type);
  2262. prev = next;
  2263. next = chunk_get_next_ncnl(next);
  2264. /* next up is either a colon, open brace, or open paren (pawn) */
  2265. if (!next)
  2266. {
  2267. return;
  2268. }
  2269. else if ((cpd.lang_flags & LANG_PAWN) &&
  2270. (next->type == CT_PAREN_OPEN))
  2271. {
  2272. next = set_paren_parent(next, CT_ENUM);
  2273. }
  2274. else if ((pc->type == CT_ENUM) && (next->type == CT_COLON))
  2275. {
  2276. /* enum TYPE : INT_TYPE { */
  2277. next = chunk_get_next_ncnl(next);
  2278. if (next)
  2279. {
  2280. make_type(next);
  2281. next = chunk_get_next_ncnl(next);
  2282. }
  2283. }
  2284. }
  2285. if (next && (next->type == CT_BRACE_OPEN))
  2286. {
  2287. flag_parens(next, (pc->type == CT_ENUM) ? PCF_IN_ENUM : PCF_IN_STRUCT,
  2288. CT_NONE, CT_NONE, false);
  2289. if ((pc->type == CT_UNION) || (pc->type == CT_STRUCT))
  2290. {
  2291. mark_struct_union_body(next);
  2292. }
  2293. /* Skip to the closing brace */
  2294. set_chunk_parent(next, pc->type);
  2295. next = chunk_get_next_type(next, CT_BRACE_CLOSE, pc->level);
  2296. flags |= PCF_VAR_INLINE;
  2297. if (next != NULL)
  2298. {
  2299. set_chunk_parent(next, pc->type);
  2300. next = chunk_get_next_ncnl(next);
  2301. }
  2302. prev = NULL;
  2303. }
  2304. /* reset var name parent type */
  2305. else if (next && prev)
  2306. {
  2307. set_chunk_parent(prev, CT_NONE);
  2308. }
  2309. if ((next == NULL) || (next->type == CT_PAREN_CLOSE))
  2310. {
  2311. return;
  2312. }
  2313. if (!chunk_is_semicolon(next))
  2314. {
  2315. /* Pawn does not require a semicolon after an enum */
  2316. if (cpd.lang_flags & LANG_PAWN)
  2317. {
  2318. return;
  2319. }
  2320. /* D does not require a semicolon after an enum, but we add one to make
  2321. * other code happy.
  2322. */
  2323. if (cpd.lang_flags & LANG_D)
  2324. {
  2325. next = pawn_add_vsemi_after(chunk_get_prev_ncnl(next));
  2326. }
  2327. }
  2328. /* We are either pointing to a ';' or a variable */
  2329. while ((next != NULL) && !chunk_is_semicolon(next) &&
  2330. (next->type != CT_ASSIGN) &&
  2331. ((in_fcn_paren ^ (next->flags & PCF_IN_FCN_DEF)) == 0))
  2332. {
  2333. if (next->level == pc->level)
  2334. {
  2335. if (next->type == CT_WORD)
  2336. {
  2337. chunk_flags_set(next, flags);
  2338. flags &= ~PCF_VAR_1ST; /* clear the first flag for the next items */
  2339. }
  2340. if (next->type == CT_STAR || ((cpd.lang_flags & LANG_CPP) && (next->type == CT_CARET)))
  2341. {
  2342. set_chunk_type(next, CT_PTR_TYPE);
  2343. }
  2344. /* If we hit a comma in a function param, we are done */
  2345. if (((next->type == CT_COMMA) ||
  2346. (next->type == CT_FPAREN_CLOSE)) &&
  2347. (next->flags & (PCF_IN_FCN_DEF | PCF_IN_FCN_CALL)))
  2348. {
  2349. return;
  2350. }
  2351. }
  2352. next = chunk_get_next_ncnl(next);
  2353. }
  2354. if (next && !prev && (next->type == CT_SEMICOLON))
  2355. {
  2356. set_chunk_parent(next, pc->type);
  2357. }
  2358. } // fix_enum_struct_union
  2359. static void fix_typedef(chunk_t *start)
  2360. {
  2361. LOG_FUNC_ENTRY();
  2362. if (start == NULL)
  2363. {
  2364. return;
  2365. }
  2366. LOG_FMT(LTYPEDEF, "%s: typedef @ %zu:%zu\n", __func__, start->orig_line, start->orig_col);
  2367. chunk_t *the_type = NULL;
  2368. chunk_t *open_paren;
  2369. chunk_t *last_op = NULL;
  2370. /* Mark everything in the typedef and scan for ")(", which makes it a
  2371. * function type
  2372. */
  2373. chunk_t *next = start;
  2374. while (((next = chunk_get_next_ncnl(next, CNAV_PREPROC)) != NULL) &&
  2375. (next->level >= start->level))
  2376. {
  2377. chunk_flags_set(next, PCF_IN_TYPEDEF);
  2378. if (start->level == next->level)
  2379. {
  2380. if (chunk_is_semicolon(next))
  2381. {
  2382. set_chunk_parent(next, CT_TYPEDEF);
  2383. break;
  2384. }
  2385. if (next->type == CT_ATTRIBUTE)
  2386. {
  2387. break;
  2388. }
  2389. if ((cpd.lang_flags & LANG_D) && (next->type == CT_ASSIGN))
  2390. {
  2391. set_chunk_parent(next, CT_TYPEDEF);
  2392. break;
  2393. }
  2394. make_type(next);
  2395. if (next->type == CT_TYPE)
  2396. {
  2397. the_type = next;
  2398. }
  2399. chunk_flags_clr(next, PCF_VAR_1ST_DEF);
  2400. if (*next->str.c_str() == '(')
  2401. {
  2402. last_op = next;
  2403. }
  2404. }
  2405. }
  2406. /* avoid interpreting typedef NS_ENUM (NSInteger, MyEnum) as a function def */
  2407. if (last_op && !((cpd.lang_flags & LANG_OC) &&
  2408. (last_op->parent_type == CT_ENUM)))
  2409. {
  2410. flag_parens(last_op, 0, CT_FPAREN_OPEN, CT_TYPEDEF, false);
  2411. fix_fcn_def_params(last_op);
  2412. open_paren = NULL;
  2413. the_type = chunk_get_prev_ncnl(last_op, CNAV_PREPROC);
  2414. if (chunk_is_paren_close(the_type))
  2415. {
  2416. open_paren = chunk_skip_to_match_rev(the_type);
  2417. mark_function_type(the_type);
  2418. the_type = chunk_get_prev_ncnl(the_type, CNAV_PREPROC);
  2419. }
  2420. else
  2421. {
  2422. /* must be: "typedef <return type>func(params);" */
  2423. set_chunk_type(the_type, CT_FUNC_TYPE);
  2424. }
  2425. set_chunk_parent(the_type, CT_TYPEDEF);
  2426. LOG_FMT(LTYPEDEF, "%s: fcn typedef [%s] on line %zu\n",
  2427. __func__, the_type->text(), the_type->orig_line);
  2428. /* If we are aligning on the open paren, grab that instead */
  2429. if (open_paren && (cpd.settings[UO_align_typedef_func].u == 1))
  2430. {
  2431. the_type = open_paren;
  2432. }
  2433. if (cpd.settings[UO_align_typedef_func].u != 0)
  2434. {
  2435. LOG_FMT(LTYPEDEF, "%s: -- align anchor on [%s] @ %zu:%zu\n",
  2436. __func__, the_type->text(), the_type->orig_line, the_type->orig_col);
  2437. chunk_flags_set(the_type, PCF_ANCHOR);
  2438. }
  2439. /* already did everything we need to do */
  2440. return;
  2441. }
  2442. /**
  2443. * Skip over enum/struct/union stuff, as we know it isn't a return type
  2444. * for a function type
  2445. */
  2446. next = chunk_get_next_ncnl(start, CNAV_PREPROC);
  2447. if (next == NULL)
  2448. {
  2449. return;
  2450. }
  2451. if ((next->type != CT_ENUM) &&
  2452. (next->type != CT_STRUCT) &&
  2453. (next->type != CT_UNION))
  2454. {
  2455. if (the_type != NULL)
  2456. {
  2457. /* We have just a regular typedef */
  2458. LOG_FMT(LTYPEDEF, "%s: regular typedef [%s] on line %zu\n",
  2459. __func__, the_type->text(), the_type->orig_line);
  2460. chunk_flags_set(the_type, PCF_ANCHOR);
  2461. }
  2462. return;
  2463. }
  2464. /* We have a struct/union/enum type, set the parent */
  2465. c_token_t tag = next->type;
  2466. /* the next item should be either a type or { */
  2467. next = chunk_get_next_ncnl(next, CNAV_PREPROC);
  2468. if (next == NULL)
  2469. {
  2470. return;
  2471. }
  2472. if (next->type == CT_TYPE)
  2473. {
  2474. next = chunk_get_next_ncnl(next, CNAV_PREPROC);
  2475. }
  2476. if (next == NULL)
  2477. {
  2478. return;
  2479. }
  2480. if (next->type == CT_BRACE_OPEN)
  2481. {
  2482. set_chunk_parent(next, tag);
  2483. /* Skip to the closing brace */
  2484. next = chunk_get_next_type(next, CT_BRACE_CLOSE, next->level, CNAV_PREPROC);
  2485. if (next != NULL)
  2486. {
  2487. set_chunk_parent(next, tag);
  2488. }
  2489. }
  2490. if (the_type != NULL)
  2491. {
  2492. LOG_FMT(LTYPEDEF, "%s: %s typedef [%s] on line %zu\n",
  2493. __func__, get_token_name(tag), the_type->text(), the_type->orig_line);
  2494. chunk_flags_set(the_type, PCF_ANCHOR);
  2495. }
  2496. } // fix_typedef
  2497. static bool cs_top_is_question(ChunkStack &cs, size_t level)
  2498. {
  2499. chunk_t *pc = cs.Empty() ? NULL : cs.Top()->m_pc;
  2500. return(pc && (pc->type == CT_QUESTION) && (pc->level == level));
  2501. }
  2502. void combine_labels(void)
  2503. {
  2504. LOG_FUNC_ENTRY();
  2505. chunk_t *cur;
  2506. chunk_t *prev;
  2507. chunk_t *next;
  2508. chunk_t *tmp;
  2509. bool hit_case = false;
  2510. bool hit_class = false;
  2511. cpd.unc_stage = US_COMBINE_LABELS;
  2512. // need a stack to handle nesting inside of OC messages, which reset the scope
  2513. ChunkStack cs;
  2514. prev = chunk_get_head();
  2515. cur = chunk_get_next_nc(prev);
  2516. next = chunk_get_next_nc(cur);
  2517. /* unlikely that the file will start with a label... */
  2518. while (next != NULL)
  2519. {
  2520. #ifdef DEBUG
  2521. LOG_FMT(LGUY, "(%d) ", __LINE__);
  2522. #endif
  2523. if (cur->type == CT_NEWLINE)
  2524. {
  2525. LOG_FMT(LGUY, "%s: %zu:%zu CT_NEWLINE\n", __func__, cur->orig_line, cur->orig_col);
  2526. }
  2527. else if (cur->type == CT_VBRACE_OPEN)
  2528. {
  2529. LOG_FMT(LGUY, "%s: %zu:%zu CT_VBRACE_OPEN\n", __func__, cur->orig_line, cur->orig_col);
  2530. }
  2531. else if (cur->type == CT_VBRACE_CLOSE)
  2532. {
  2533. LOG_FMT(LGUY, "%s: %zu:%zu CT_VBRACE_CLOSE\n", __func__, cur->orig_line, cur->orig_col);
  2534. }
  2535. else
  2536. {
  2537. LOG_FMT(LGUY, "%s: %zu:%zu %s\n", __func__, cur->orig_line, cur->orig_col, cur->text());
  2538. }
  2539. if (!(next->flags & PCF_IN_OC_MSG) && /* filter OC case of [self class] msg send */
  2540. ((next->type == CT_CLASS) ||
  2541. (next->type == CT_OC_CLASS) ||
  2542. (next->type == CT_TEMPLATE)))
  2543. {
  2544. hit_class = true;
  2545. }
  2546. if (chunk_is_semicolon(next) || (next->type == CT_BRACE_OPEN))
  2547. {
  2548. hit_class = false;
  2549. }
  2550. if (prev->type == CT_SQUARE_OPEN && prev->parent_type == CT_OC_MSG)
  2551. {
  2552. cs.Push_Back(prev);
  2553. }
  2554. else if (next->type == CT_SQUARE_CLOSE && next->parent_type == CT_OC_MSG)
  2555. {
  2556. /* pop until we hit '[' */
  2557. while (!cs.Empty())
  2558. {
  2559. chunk_t *t2 = cs.Top()->m_pc;
  2560. cs.Pop_Back();
  2561. if (t2->type == CT_SQUARE_OPEN)
  2562. {
  2563. break;
  2564. }
  2565. }
  2566. }
  2567. if (next->type == CT_QUESTION)
  2568. {
  2569. cs.Push_Back(next);
  2570. }
  2571. else if (next->type == CT_CASE)
  2572. {
  2573. if (cur->type == CT_GOTO)
  2574. {
  2575. /* handle "goto case x;" */
  2576. set_chunk_type(next, CT_QUALIFIER);
  2577. }
  2578. else
  2579. {
  2580. hit_case = true;
  2581. }
  2582. }
  2583. else if ((next->type == CT_COLON) ||
  2584. ((next->type == CT_OC_COLON) && cs_top_is_question(cs, next->level)))
  2585. {
  2586. if (cur->type == CT_DEFAULT)
  2587. {
  2588. set_chunk_type(cur, CT_CASE);
  2589. hit_case = true;
  2590. }
  2591. if (cs_top_is_question(cs, next->level))
  2592. {
  2593. set_chunk_type(next, CT_COND_COLON);
  2594. cs.Pop_Back();
  2595. }
  2596. else if (hit_case)
  2597. {
  2598. hit_case = false;
  2599. set_chunk_type(next, CT_CASE_COLON);
  2600. tmp = chunk_get_next_ncnl(next);
  2601. if ((tmp != NULL) && (tmp->type == CT_BRACE_OPEN))
  2602. {
  2603. set_chunk_parent(tmp, CT_CASE);
  2604. tmp = chunk_get_next_type(tmp, CT_BRACE_CLOSE, tmp->level);
  2605. if (tmp != NULL)
  2606. {
  2607. set_chunk_parent(tmp, CT_CASE);
  2608. }
  2609. }
  2610. }
  2611. else
  2612. {
  2613. chunk_t *nextprev = chunk_get_prev_ncnl(next);
  2614. if (cpd.lang_flags & LANG_PAWN)
  2615. {
  2616. if ((cur->type == CT_WORD) ||
  2617. (cur->type == CT_BRACE_CLOSE))
  2618. {
  2619. c_token_t new_type = CT_TAG;
  2620. tmp = chunk_get_next_nc(next);
  2621. if (chunk_is_newline(prev) && chunk_is_newline(tmp))
  2622. {
  2623. new_type = CT_LABEL;
  2624. set_chunk_type(next, CT_LABEL_COLON);
  2625. }
  2626. else
  2627. {
  2628. set_chunk_type(next, CT_TAG_COLON);
  2629. }
  2630. if (cur->type == CT_WORD)
  2631. {
  2632. set_chunk_type(cur, new_type);
  2633. }
  2634. }
  2635. }
  2636. else if (next->flags & PCF_IN_ARRAY_ASSIGN)
  2637. {
  2638. set_chunk_type(next, CT_D_ARRAY_COLON);
  2639. }
  2640. else if (next->flags & PCF_IN_FOR)
  2641. {
  2642. set_chunk_type(next, CT_FOR_COLON);
  2643. }
  2644. else if (next->flags & PCF_OC_BOXED)
  2645. {
  2646. set_chunk_type(next, CT_OC_DICT_COLON);
  2647. }
  2648. else if (cur->type == CT_WORD)
  2649. {
  2650. tmp = chunk_get_next_nc(next, CNAV_PREPROC);
  2651. #ifdef DEBUG
  2652. LOG_FMT(LGUY, "(%d) ", __LINE__);
  2653. #endif
  2654. LOG_FMT(LGUY, "%s: %zu:%zu, tmp=%s\n",
  2655. __func__, tmp->orig_line, tmp->orig_col, (tmp->type == CT_NEWLINE) ? "<NL>" : tmp->text());
  2656. log_pcf_flags(LGUY, tmp->flags);
  2657. if (next->flags & PCF_IN_FCN_CALL)
  2658. {
  2659. /* Must be a macro thingy, assume some sort of label */
  2660. set_chunk_type(next, CT_LABEL_COLON);
  2661. }
  2662. else if ((tmp == NULL) ||
  2663. ((tmp->type != CT_NUMBER) &&
  2664. (tmp->type != CT_SIZEOF) &&
  2665. !(tmp->flags & (PCF_IN_STRUCT | PCF_IN_CLASS))) ||
  2666. (tmp->type == CT_NEWLINE)
  2667. )
  2668. {
  2669. /* the CT_SIZEOF isn't great - test 31720 happens to use a sizeof expr,
  2670. * but this really should be able to handle any constant expr */
  2671. set_chunk_type(cur, CT_LABEL);
  2672. set_chunk_type(next, CT_LABEL_COLON);
  2673. }
  2674. else if (next->flags & (PCF_IN_STRUCT | PCF_IN_CLASS | PCF_IN_TYPEDEF))
  2675. {
  2676. set_chunk_type(next, CT_BIT_COLON);
  2677. tmp = chunk_get_next(next);
  2678. while ((tmp = chunk_get_next(tmp)) != NULL)
  2679. {
  2680. if (tmp->type == CT_SEMICOLON)
  2681. {
  2682. break;
  2683. }
  2684. if (tmp->type == CT_COLON)
  2685. {
  2686. set_chunk_type(tmp, CT_BIT_COLON);
  2687. }
  2688. }
  2689. }
  2690. }
  2691. else if (nextprev->type == CT_FPAREN_CLOSE)
  2692. {
  2693. /* it's a class colon */
  2694. set_chunk_type(next, CT_CLASS_COLON);
  2695. }
  2696. else if (next->level > next->brace_level)
  2697. {
  2698. /* ignore it, as it is inside a paren */
  2699. }
  2700. else if (cur->type == CT_TYPE)
  2701. {
  2702. set_chunk_type(next, CT_BIT_COLON);
  2703. }
  2704. else if ((cur->type == CT_ENUM) ||
  2705. (cur->type == CT_PRIVATE) ||
  2706. (cur->type == CT_QUALIFIER) ||
  2707. (cur->parent_type == CT_ALIGN))
  2708. {
  2709. /* ignore it - bit field, align or public/private, etc */
  2710. }
  2711. else if ((cur->type == CT_ANGLE_CLOSE) || hit_class)
  2712. {
  2713. /* ignore it - template thingy */
  2714. }
  2715. else if (cur->parent_type == CT_SQL_EXEC)
  2716. {
  2717. /* ignore it - SQL variable name */
  2718. }
  2719. else if (next->parent_type == CT_ASSERT)
  2720. {
  2721. /* ignore it - Java assert thing */
  2722. }
  2723. else
  2724. {
  2725. tmp = chunk_get_next_ncnl(next);
  2726. if ((tmp != NULL) && ((tmp->type == CT_BASE) ||
  2727. (tmp->type == CT_THIS)))
  2728. {
  2729. /* ignore it, as it is a C# base thingy */
  2730. }
  2731. else
  2732. {
  2733. LOG_FMT(LWARN, "%s:%zu unexpected colon in col %zu n-parent=%s c-parent=%s l=%zu bl=%zu\n",
  2734. cpd.filename, next->orig_line, next->orig_col,
  2735. get_token_name(next->parent_type),
  2736. get_token_name(cur->parent_type),
  2737. next->level, next->brace_level);
  2738. cpd.error_count++;
  2739. }
  2740. }
  2741. }
  2742. }
  2743. prev = cur;
  2744. cur = next;
  2745. next = chunk_get_next_nc(cur);
  2746. }
  2747. } // combine_labels
  2748. static void mark_variable_stack(ChunkStack &cs, log_sev_t sev)
  2749. {
  2750. UNUSED(sev);
  2751. LOG_FUNC_ENTRY();
  2752. /* throw out the last word and mark the rest */
  2753. chunk_t *var_name = cs.Pop_Back();
  2754. if (var_name && (var_name->prev->type == CT_DC_MEMBER))
  2755. {
  2756. cs.Push_Back(var_name);
  2757. }
  2758. if (var_name != NULL)
  2759. {
  2760. LOG_FMT(LFCNP, "%s: parameter on line %zu :",
  2761. __func__, var_name->orig_line);
  2762. size_t word_cnt = 0;
  2763. chunk_t *word_type;
  2764. while ((word_type = cs.Pop_Back()) != NULL)
  2765. {
  2766. if ((word_type->type == CT_WORD) || (word_type->type == CT_TYPE))
  2767. {
  2768. LOG_FMT(LFCNP, " <%s>", word_type->text());
  2769. set_chunk_type(word_type, CT_TYPE);
  2770. chunk_flags_set(word_type, PCF_VAR_TYPE);
  2771. }
  2772. word_cnt++;
  2773. }
  2774. if (var_name->type == CT_WORD)
  2775. {
  2776. if (word_cnt)
  2777. {
  2778. LOG_FMT(LFCNP, " [%s]\n", var_name->text());
  2779. chunk_flags_set(var_name, PCF_VAR_DEF);
  2780. }
  2781. else
  2782. {
  2783. LOG_FMT(LFCNP, " <%s>\n", var_name->text());
  2784. set_chunk_type(var_name, CT_TYPE);
  2785. chunk_flags_set(var_name, PCF_VAR_TYPE);
  2786. }
  2787. }
  2788. }
  2789. } // mark_variable_stack
  2790. static void fix_fcn_def_params(chunk_t *start)
  2791. {
  2792. LOG_FUNC_ENTRY();
  2793. if (start == NULL)
  2794. {
  2795. return;
  2796. }
  2797. LOG_FMT(LFCNP, "%s: %s [%s] on line %zu, level %zu\n",
  2798. __func__, start->text(), get_token_name(start->type), start->orig_line, start->level);
  2799. while ((start != NULL) && !chunk_is_paren_open(start))
  2800. {
  2801. start = chunk_get_next_ncnl(start);
  2802. }
  2803. if (start == NULL)// Coverity CID 76003, 1100782
  2804. {
  2805. return;
  2806. }
  2807. assert((start->len() == 1) && (start->str[0] == '('));
  2808. ChunkStack cs;
  2809. size_t level = start->level + 1;
  2810. chunk_t *pc = start;
  2811. while ((pc = chunk_get_next_ncnl(pc)) != NULL)
  2812. {
  2813. if (((start->len() == 1) && (start->str[0] == ')')) ||
  2814. (pc->level < level))
  2815. {
  2816. LOG_FMT(LFCNP, "%s: bailed on %s on line %zu\n",
  2817. __func__, pc->text(), pc->orig_line);
  2818. break;
  2819. }
  2820. LOG_FMT(LFCNP, "%s: %s %s on line %zu, level %zu\n",
  2821. __func__, (pc->level > level) ? "skipping" : "looking at",
  2822. pc->text(), pc->orig_line, pc->level);
  2823. if (pc->level > level)
  2824. {
  2825. continue;
  2826. }
  2827. if (chunk_is_star(pc) || chunk_is_msref(pc))
  2828. {
  2829. set_chunk_type(pc, CT_PTR_TYPE);
  2830. cs.Push_Back(pc);
  2831. }
  2832. else if ((pc->type == CT_AMP) ||
  2833. ((cpd.lang_flags & LANG_CPP) && chunk_is_str(pc, "&&", 2)))
  2834. {
  2835. set_chunk_type(pc, CT_BYREF);
  2836. cs.Push_Back(pc);
  2837. }
  2838. else if (pc->type == CT_TYPE_WRAP)
  2839. {
  2840. cs.Push_Back(pc);
  2841. }
  2842. else if ((pc->type == CT_WORD) || (pc->type == CT_TYPE))
  2843. {
  2844. cs.Push_Back(pc);
  2845. }
  2846. else if ((pc->type == CT_COMMA) || (pc->type == CT_ASSIGN))
  2847. {
  2848. mark_variable_stack(cs, LFCNP);
  2849. if (pc->type == CT_ASSIGN)
  2850. {
  2851. /* Mark assignment for default param spacing */
  2852. set_chunk_parent(pc, CT_FUNC_PROTO);
  2853. }
  2854. }
  2855. }
  2856. mark_variable_stack(cs, LFCNP);
  2857. } // fix_fcn_def_params
  2858. static chunk_t *skip_to_next_statement(chunk_t *pc)
  2859. {
  2860. while ((pc != NULL) && !chunk_is_semicolon(pc) &&
  2861. (pc->type != CT_BRACE_OPEN) &&
  2862. (pc->type != CT_BRACE_CLOSE))
  2863. {
  2864. pc = chunk_get_next_ncnl(pc);
  2865. }
  2866. return(pc);
  2867. }
  2868. static chunk_t *fix_var_def(chunk_t *start)
  2869. {
  2870. LOG_FUNC_ENTRY();
  2871. chunk_t *pc = start;
  2872. chunk_t *end;
  2873. chunk_t *tmp_pc;
  2874. ChunkStack cs;
  2875. int idx;
  2876. int ref_idx;
  2877. LOG_FMT(LFVD, "%s: start[%zu:%zu]", __func__, pc->orig_line, pc->orig_col);
  2878. /* Scan for words and types and stars oh my! */
  2879. while ((pc != NULL) &&
  2880. ((pc->type == CT_TYPE) ||
  2881. (pc->type == CT_WORD) ||
  2882. (pc->type == CT_QUALIFIER) ||
  2883. (pc->type == CT_TYPENAME) ||
  2884. (pc->type == CT_DC_MEMBER) ||
  2885. (pc->type == CT_MEMBER) ||
  2886. chunk_is_ptr_operator(pc)))
  2887. {
  2888. LOG_FMT(LFVD, " %s[%s]", pc->text(), get_token_name(pc->type));
  2889. cs.Push_Back(pc);
  2890. pc = chunk_get_next_ncnl(pc);
  2891. /* Skip templates and attributes */
  2892. pc = skip_template_next(pc);
  2893. pc = skip_attribute_next(pc);
  2894. if (cpd.lang_flags & LANG_JAVA)
  2895. {
  2896. pc = skip_tsquare_next(pc);
  2897. }
  2898. }
  2899. end = pc;
  2900. LOG_FMT(LFVD, " end=[%s]\n", (end != NULL) ? get_token_name(end->type) : "NULL");
  2901. if (end == NULL)
  2902. {
  2903. return(NULL);
  2904. }
  2905. /* Function defs are handled elsewhere */
  2906. if ((cs.Len() <= 1) ||
  2907. (end->type == CT_FUNC_DEF) ||
  2908. (end->type == CT_FUNC_PROTO) ||
  2909. (end->type == CT_FUNC_CLASS_DEF) ||
  2910. (end->type == CT_FUNC_CLASS_PROTO) ||
  2911. (end->type == CT_OPERATOR))
  2912. {
  2913. return(skip_to_next_statement(end));
  2914. }
  2915. /* ref_idx points to the alignable part of the var def */
  2916. ref_idx = cs.Len() - 1;
  2917. /* Check for the '::' stuff: "char *Engine::name" */
  2918. if ((cs.Len() >= 3) &&
  2919. ((cs.Get(cs.Len() - 2)->m_pc->type == CT_MEMBER) ||
  2920. (cs.Get(cs.Len() - 2)->m_pc->type == CT_DC_MEMBER)))
  2921. {
  2922. idx = cs.Len() - 2;
  2923. while (idx > 0)
  2924. {
  2925. tmp_pc = cs.Get(idx)->m_pc;
  2926. if ((tmp_pc->type != CT_DC_MEMBER) &&
  2927. (tmp_pc->type != CT_MEMBER))
  2928. {
  2929. break;
  2930. }
  2931. idx--;
  2932. tmp_pc = cs.Get(idx)->m_pc;
  2933. if ((tmp_pc->type != CT_WORD) &&
  2934. (tmp_pc->type != CT_TYPE))
  2935. {
  2936. break;
  2937. }
  2938. make_type(tmp_pc);
  2939. idx--;
  2940. }
  2941. ref_idx = idx + 1;
  2942. }
  2943. tmp_pc = cs.Get(ref_idx)->m_pc;
  2944. LOG_FMT(LFVD, " ref_idx(%d) => %s\n", ref_idx, tmp_pc->text());
  2945. /* No type part found! */
  2946. if (ref_idx <= 0)
  2947. {
  2948. return(skip_to_next_statement(end));
  2949. }
  2950. LOG_FMT(LFVD2, "%s:%zu TYPE : ", __func__, start->orig_line);
  2951. for (size_t idxForCs = 0; idxForCs < cs.Len() - 1; idxForCs++)
  2952. {
  2953. tmp_pc = cs.Get(idxForCs)->m_pc;
  2954. make_type(tmp_pc);
  2955. chunk_flags_set(tmp_pc, PCF_VAR_TYPE);
  2956. LOG_FMT(LFVD2, " %s[%s]", tmp_pc->text(), get_token_name(tmp_pc->type));
  2957. }
  2958. LOG_FMT(LFVD2, "\n");
  2959. /**
  2960. * OK we have two or more items, mark types up to the end.
  2961. */
  2962. mark_variable_definition(cs.Get(cs.Len() - 1)->m_pc);
  2963. if (end->type == CT_COMMA)
  2964. {
  2965. return(chunk_get_next_ncnl(end));
  2966. }
  2967. return(skip_to_next_statement(end));
  2968. } // fix_var_def
  2969. static chunk_t *skip_expression(chunk_t *start)
  2970. {
  2971. chunk_t *pc = start;
  2972. while ((pc != NULL) && (pc->level >= start->level))
  2973. {
  2974. if ((pc->level == start->level) &&
  2975. (chunk_is_semicolon(pc) || (pc->type == CT_COMMA)))
  2976. {
  2977. return(pc);
  2978. }
  2979. pc = chunk_get_next_ncnl(pc);
  2980. }
  2981. return(pc);
  2982. }
  2983. /**
  2984. * help function for mark_variable_definition...
  2985. */
  2986. bool go_on(chunk_t *pc, chunk_t *start)
  2987. {
  2988. if ((pc == NULL) ||
  2989. (pc->level != start->level))
  2990. {
  2991. return(false);
  2992. }
  2993. if (pc->flags & PCF_IN_FOR)
  2994. {
  2995. return((!chunk_is_semicolon(pc)) && (!(pc->type == CT_COLON)));
  2996. }
  2997. else
  2998. {
  2999. return(!chunk_is_semicolon(pc));
  3000. }
  3001. } // go_on
  3002. static chunk_t *mark_variable_definition(chunk_t *start)
  3003. {
  3004. LOG_FUNC_ENTRY();
  3005. if (start == NULL)
  3006. {
  3007. return(NULL);
  3008. }
  3009. chunk_t *pc = start;
  3010. size_t flags = PCF_VAR_1ST_DEF;
  3011. LOG_FMT(LVARDEF, "%s: line %zu, col %zu '%s' type %s\n",
  3012. __func__, pc->orig_line, pc->orig_col, pc->text(),
  3013. get_token_name(pc->type));
  3014. pc = start;
  3015. // issue #596
  3016. while (go_on(pc, start))
  3017. {
  3018. if ((pc->type == CT_WORD) || (pc->type == CT_FUNC_CTOR_VAR))
  3019. {
  3020. UINT64 flg = pc->flags;
  3021. if ((pc->flags & PCF_IN_ENUM) == 0)
  3022. {
  3023. chunk_flags_set(pc, flags);
  3024. }
  3025. flags &= ~PCF_VAR_1ST;
  3026. LOG_FMT(LVARDEF, "%s:%zu marked '%s'[%s] in col %zu flags: %#" PRIx64 " -> %#" PRIx64 "\n",
  3027. __func__, pc->orig_line, pc->text(),
  3028. get_token_name(pc->type), pc->orig_col, flg, pc->flags);
  3029. }
  3030. else if (chunk_is_star(pc) || chunk_is_msref(pc))
  3031. {
  3032. set_chunk_type(pc, CT_PTR_TYPE);
  3033. }
  3034. else if (chunk_is_addr(pc))
  3035. {
  3036. set_chunk_type(pc, CT_BYREF);
  3037. }
  3038. else if ((pc->type == CT_SQUARE_OPEN) || (pc->type == CT_ASSIGN))
  3039. {
  3040. pc = skip_expression(pc);
  3041. continue;
  3042. }
  3043. pc = chunk_get_next_ncnl(pc);
  3044. }
  3045. return(pc);
  3046. } // mark_variable_definition
  3047. static bool can_be_full_param(chunk_t *start, chunk_t *end)
  3048. {
  3049. LOG_FUNC_ENTRY();
  3050. LOG_FMT(LFPARAM, "%s:", __func__);
  3051. int word_cnt = 0;
  3052. size_t type_count = 0;
  3053. chunk_t *pc;
  3054. for (pc = start; pc != end; pc = chunk_get_next_ncnl(pc, CNAV_PREPROC))
  3055. {
  3056. LOG_FMT(LFPARAM, " [%s]", pc->text());
  3057. if ((pc->type == CT_QUALIFIER) ||
  3058. (pc->type == CT_STRUCT) ||
  3059. (pc->type == CT_ENUM) ||
  3060. (pc->type == CT_UNION) ||
  3061. (pc->type == CT_TYPENAME))
  3062. {
  3063. LOG_FMT(LFPARAM, " <== %s! (yes)\n", get_token_name(pc->type));
  3064. return(true);
  3065. }
  3066. if ((pc->type == CT_WORD) ||
  3067. (pc->type == CT_TYPE))
  3068. {
  3069. word_cnt++;
  3070. if (pc->type == CT_TYPE)
  3071. {
  3072. type_count++;
  3073. }
  3074. }
  3075. else if ((pc->type == CT_MEMBER) ||
  3076. (pc->type == CT_DC_MEMBER))
  3077. {
  3078. if (word_cnt > 0)
  3079. {
  3080. word_cnt--;
  3081. }
  3082. }
  3083. else if ((pc != start) && chunk_is_ptr_operator(pc))
  3084. {
  3085. /* chunk is OK */
  3086. }
  3087. else if (pc->type == CT_ASSIGN)
  3088. {
  3089. /* chunk is OK (default values) */
  3090. break;
  3091. }
  3092. else if (pc->type == CT_ANGLE_OPEN)
  3093. {
  3094. LOG_FMT(LFPARAM, " <== template\n");
  3095. return(true);
  3096. }
  3097. else if (pc->type == CT_ELLIPSIS)
  3098. {
  3099. LOG_FMT(LFPARAM, " <== elipses\n");
  3100. return(true);
  3101. }
  3102. else if ((word_cnt == 0) && (pc->type == CT_PAREN_OPEN))
  3103. {
  3104. /* Check for old-school func proto param '(type)' */
  3105. chunk_t *tmp1 = chunk_skip_to_match(pc, CNAV_PREPROC);
  3106. chunk_t *tmp2 = chunk_get_next_ncnl(tmp1, CNAV_PREPROC);
  3107. if (chunk_is_token(tmp2, CT_COMMA) || chunk_is_paren_close(tmp2))
  3108. {
  3109. do
  3110. {
  3111. pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  3112. LOG_FMT(LFPARAM, " [%s]", pc->text());
  3113. } while (pc != tmp1);
  3114. /* reset some vars to allow [] after parens */
  3115. word_cnt = 1;
  3116. type_count = 1;
  3117. }
  3118. else
  3119. {
  3120. LOG_FMT(LFPARAM, " <== [%s] not fcn type!\n", get_token_name(pc->type));
  3121. return(false);
  3122. }
  3123. }
  3124. else if (((word_cnt == 1) || ((size_t)word_cnt == type_count)) &&
  3125. (pc->type == CT_PAREN_OPEN))
  3126. {
  3127. /* Check for func proto param 'void (*name)' or 'void (*name)(params)' */
  3128. chunk_t *tmp1 = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  3129. chunk_t *tmp2 = chunk_get_next_ncnl(tmp1, CNAV_PREPROC);
  3130. chunk_t *tmp3 = chunk_get_next_ncnl(tmp2, CNAV_PREPROC);
  3131. if (!chunk_is_str(tmp3, ")", 1) ||
  3132. !chunk_is_str(tmp1, "*", 1) ||
  3133. (tmp2->type != CT_WORD))
  3134. {
  3135. LOG_FMT(LFPARAM, " <== [%s] not fcn type!\n", get_token_name(pc->type));
  3136. return(false);
  3137. }
  3138. LOG_FMT(LFPARAM, " <skip fcn type>");
  3139. tmp1 = chunk_get_next_ncnl(tmp3, CNAV_PREPROC);
  3140. tmp2 = chunk_get_next_ncnl(tmp1, CNAV_PREPROC); /* \todo where is tmp2 used? */
  3141. if (chunk_is_str(tmp1, "(", 1))
  3142. {
  3143. tmp3 = chunk_skip_to_match(tmp1, CNAV_PREPROC);
  3144. }
  3145. pc = tmp3;
  3146. /* reset some vars to allow [] after parens */
  3147. word_cnt = 1;
  3148. type_count = 1;
  3149. }
  3150. else if (pc->type == CT_TSQUARE)
  3151. {
  3152. /* ignore it */
  3153. }
  3154. else if ((word_cnt == 1) && (pc->type == CT_SQUARE_OPEN))
  3155. {
  3156. /* skip over any array stuff */
  3157. pc = chunk_skip_to_match(pc, CNAV_PREPROC);
  3158. }
  3159. else if ((word_cnt == 2) && (pc->type == CT_SQUARE_OPEN))
  3160. {
  3161. /* Bug #671: is it such as: bool foo[FOO_MAX] */
  3162. pc = chunk_skip_to_match(pc, CNAV_PREPROC);
  3163. }
  3164. else if ((word_cnt == 1) && (cpd.lang_flags & LANG_CPP) &&
  3165. chunk_is_str(pc, "&&", 2))
  3166. {
  3167. /* ignore possible 'move' operator */
  3168. }
  3169. else
  3170. {
  3171. LOG_FMT(LFPARAM, " <== [%s] no way! tc=%zu wc=%d\n",
  3172. get_token_name(pc->type), type_count, word_cnt);
  3173. return(false);
  3174. }
  3175. }
  3176. chunk_t *last = chunk_get_prev_ncnl(pc);
  3177. if (chunk_is_ptr_operator(last))
  3178. {
  3179. LOG_FMT(LFPARAM, " <== [%s] sure!\n", get_token_name(pc->type));
  3180. return(true);
  3181. }
  3182. bool ret = ((word_cnt >= 2) ||
  3183. ((word_cnt == 1) && (type_count == 1)));
  3184. LOG_FMT(LFPARAM, " <== [%s] %s!\n",
  3185. get_token_name(pc->type), ret ? "Yup" : "Unlikely");
  3186. return(ret);
  3187. } // can_be_full_param
  3188. static void mark_function(chunk_t *pc)
  3189. {
  3190. LOG_FUNC_ENTRY();
  3191. chunk_t *prev = chunk_get_prev_ncnlnp(pc);
  3192. chunk_t *next = chunk_get_next_ncnlnp(pc);
  3193. if (next == NULL)
  3194. {
  3195. return;
  3196. }
  3197. chunk_t *tmp;
  3198. chunk_t *semi = NULL;
  3199. chunk_t *paren_open;
  3200. chunk_t *paren_close;
  3201. /* Find out what is before the operator */
  3202. if (pc->parent_type == CT_OPERATOR)
  3203. {
  3204. chunk_t *pc_op = chunk_get_prev_type(pc, CT_OPERATOR, pc->level);
  3205. if ((pc_op != NULL) && (pc_op->flags & PCF_EXPR_START))
  3206. {
  3207. set_chunk_type(pc, CT_FUNC_CALL);
  3208. }
  3209. if (cpd.lang_flags & LANG_CPP)
  3210. {
  3211. tmp = pc;
  3212. while ((tmp = chunk_get_prev_ncnl(tmp)) != NULL)
  3213. {
  3214. if ((tmp->type == CT_BRACE_CLOSE) ||
  3215. (tmp->type == CT_BRACE_OPEN) || // Issue 575
  3216. (tmp->type == CT_SEMICOLON))
  3217. {
  3218. break;
  3219. }
  3220. if (chunk_is_paren_open(tmp))
  3221. {
  3222. set_chunk_type(pc, CT_FUNC_CALL);
  3223. break;
  3224. }
  3225. if (tmp->type == CT_ASSIGN)
  3226. {
  3227. set_chunk_type(pc, CT_FUNC_CALL);
  3228. break;
  3229. }
  3230. if (tmp->type == CT_TEMPLATE)
  3231. {
  3232. set_chunk_type(pc, CT_FUNC_DEF);
  3233. break;
  3234. }
  3235. if (tmp->type == CT_BRACE_OPEN)
  3236. {
  3237. if (tmp->parent_type == CT_FUNC_DEF)
  3238. {
  3239. set_chunk_type(pc, CT_FUNC_CALL);
  3240. }
  3241. if ((tmp->parent_type == CT_CLASS) ||
  3242. (tmp->parent_type == CT_STRUCT))
  3243. {
  3244. set_chunk_type(pc, CT_FUNC_DEF);
  3245. }
  3246. break;
  3247. }
  3248. }
  3249. if ((tmp != NULL) && (pc->type != CT_FUNC_CALL))
  3250. {
  3251. /* Mark the return type */
  3252. while ((tmp = chunk_get_next_ncnl(tmp)) != pc)
  3253. {
  3254. make_type(tmp);
  3255. }
  3256. }
  3257. }
  3258. }
  3259. if (chunk_is_ptr_operator(next))
  3260. {
  3261. next = chunk_get_next_ncnlnp(next);
  3262. if (next == NULL)
  3263. {
  3264. return;
  3265. }
  3266. }
  3267. #ifdef DEBUG
  3268. LOG_FMT(LFCN, "\n(%d) ", __LINE__);
  3269. #endif
  3270. LOG_FMT(LFCN, "%s: orig_line=%zu] %s[%s] - parent=%s level=%zu/%zu, next=%s[%s] - level=%zu\n",
  3271. __func__, pc->orig_line, pc->text(),
  3272. get_token_name(pc->type), get_token_name(pc->parent_type),
  3273. pc->level, pc->brace_level,
  3274. next->text(), get_token_name(next->type), next->level);
  3275. if (pc->flags & PCF_IN_CONST_ARGS)
  3276. {
  3277. set_chunk_type(pc, CT_FUNC_CTOR_VAR);
  3278. #ifdef DEBUG
  3279. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3280. #endif
  3281. LOG_FMT(LFCN, " 1) Marked [%s] as FUNC_CTOR_VAR on line %zu col %zu\n",
  3282. pc->text(), pc->orig_line, pc->orig_col);
  3283. next = skip_template_next(next);
  3284. if (next == NULL)
  3285. {
  3286. return;
  3287. }
  3288. flag_parens(next, 0, CT_FPAREN_OPEN, pc->type, true);
  3289. return;
  3290. }
  3291. /* Skip over any template and attribute madness */
  3292. next = skip_template_next(next);
  3293. if (next == NULL)
  3294. {
  3295. return;
  3296. }
  3297. next = skip_attribute_next(next);
  3298. if (next == NULL)
  3299. {
  3300. return;
  3301. }
  3302. /* Find the open and close paren */
  3303. paren_open = chunk_get_next_str(pc, "(", 1, pc->level);
  3304. paren_close = chunk_get_next_str(paren_open, ")", 1, pc->level);
  3305. if ((paren_open == NULL) || (paren_close == NULL))
  3306. {
  3307. #ifdef DEBUG
  3308. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3309. #endif
  3310. LOG_FMT(LFCN, "No parens found for [%s] on line %zu col %zu\n",
  3311. pc->text(), pc->orig_line, pc->orig_col);
  3312. return;
  3313. }
  3314. /**
  3315. * This part detects either chained function calls or a function ptr definition.
  3316. * MYTYPE (*func)(void);
  3317. * mWriter( "class Clst_"c )( somestr.getText() )( " : Cluster {"c ).newline;
  3318. *
  3319. * For it to be a function variable def, there must be a '*' followed by a
  3320. * single word.
  3321. *
  3322. * Otherwise, it must be chained function calls.
  3323. */
  3324. tmp = chunk_get_next_ncnl(paren_close);
  3325. if (chunk_is_str(tmp, "(", 1))
  3326. {
  3327. chunk_t *tmp1, *tmp2, *tmp3;
  3328. /* skip over any leading class/namespace in: "T(F::*A)();" */
  3329. tmp1 = chunk_get_next_ncnl(next);
  3330. while (tmp1)
  3331. {
  3332. tmp2 = chunk_get_next_ncnl(tmp1);
  3333. if (!chunk_is_word(tmp1) || !chunk_is_token(tmp2, CT_DC_MEMBER))
  3334. {
  3335. break;
  3336. }
  3337. tmp1 = chunk_get_next_ncnl(tmp2);
  3338. }
  3339. tmp2 = chunk_get_next_ncnl(tmp1);
  3340. if (chunk_is_str(tmp2, ")", 1))
  3341. {
  3342. tmp3 = tmp2;
  3343. tmp2 = NULL;
  3344. }
  3345. else
  3346. {
  3347. tmp3 = chunk_get_next_ncnl(tmp2);
  3348. }
  3349. if (chunk_is_str(tmp3, ")", 1) &&
  3350. (chunk_is_star(tmp1) || chunk_is_msref(tmp1) ||
  3351. ((cpd.lang_flags & LANG_OC) && chunk_is_token(tmp1, CT_CARET)))
  3352. &&
  3353. ((tmp2 == NULL) || (tmp2->type == CT_WORD)))
  3354. {
  3355. if (tmp2)
  3356. {
  3357. #ifdef DEBUG
  3358. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3359. #endif
  3360. LOG_FMT(LFCN, "%s: [%zu/%zu] function variable [%s], changing [%s] into a type\n",
  3361. __func__, pc->orig_line, pc->orig_col, tmp2->text(), pc->text());
  3362. set_chunk_type(tmp2, CT_FUNC_VAR);
  3363. flag_parens(paren_open, 0, CT_PAREN_OPEN, CT_FUNC_VAR, false);
  3364. #ifdef DEBUG
  3365. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3366. #endif
  3367. LOG_FMT(LFCN, "%s: paren open @ %zu:%zu\n",
  3368. __func__, paren_open->orig_line, paren_open->orig_col);
  3369. }
  3370. else
  3371. {
  3372. #ifdef DEBUG
  3373. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3374. #endif
  3375. LOG_FMT(LFCN, "%s: [%zu/%zu] function type, changing [%s] into a type\n",
  3376. __func__, pc->orig_line, pc->orig_col, pc->text());
  3377. if (tmp2)
  3378. {
  3379. set_chunk_type(tmp2, CT_FUNC_TYPE);
  3380. }
  3381. flag_parens(paren_open, 0, CT_PAREN_OPEN, CT_FUNC_TYPE, false);
  3382. }
  3383. set_chunk_type(pc, CT_TYPE);
  3384. set_chunk_type(tmp1, CT_PTR_TYPE);
  3385. chunk_flags_clr(pc, PCF_VAR_1ST_DEF);
  3386. if (tmp2 != NULL)
  3387. {
  3388. chunk_flags_set(tmp2, PCF_VAR_1ST_DEF);
  3389. }
  3390. flag_parens(tmp, 0, CT_FPAREN_OPEN, CT_FUNC_PROTO, false);
  3391. fix_fcn_def_params(tmp);
  3392. return;
  3393. }
  3394. #ifdef DEBUG
  3395. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3396. #endif
  3397. LOG_FMT(LFCN, "%s: chained function calls? [%zu.%zu] [%s]\n",
  3398. __func__, pc->orig_line, pc->orig_col, pc->text());
  3399. }
  3400. /* Assume it is a function call if not already labeled */
  3401. if (pc->type == CT_FUNCTION)
  3402. {
  3403. #ifdef DEBUG
  3404. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3405. #endif
  3406. LOG_FMT(LFCN, "%s: examine [%zu.%zu] [%s], type %s\n",
  3407. __func__, pc->orig_line, pc->orig_col, pc->text(), get_token_name(pc->type));
  3408. // look for an assigment. Issue 575
  3409. chunk_t *temp = chunk_get_next_type(pc, CT_ASSIGN, pc->level);
  3410. if (temp != NULL)
  3411. {
  3412. LOG_FMT(LFCN, "%s: assigment found [%zu.%zu] [%s]\n",
  3413. __func__, temp->orig_line, temp->orig_col, temp->text());
  3414. set_chunk_type(pc, CT_FUNC_CALL);
  3415. }
  3416. else
  3417. {
  3418. set_chunk_type(pc, (pc->parent_type == CT_OPERATOR) ? CT_FUNC_DEF : CT_FUNC_CALL);
  3419. }
  3420. }
  3421. /* Check for C++ function def */
  3422. if ((pc->type == CT_FUNC_CLASS_DEF) ||
  3423. ((prev != NULL) && ((prev->type == CT_DC_MEMBER) ||
  3424. (prev->type == CT_INV))))
  3425. {
  3426. chunk_t *destr = NULL;
  3427. if (prev->type == CT_INV)
  3428. {
  3429. /* TODO: do we care that this is the destructor? */
  3430. set_chunk_type(prev, CT_DESTRUCTOR);
  3431. set_chunk_type(pc, CT_FUNC_CLASS_DEF);
  3432. set_chunk_parent(pc, CT_DESTRUCTOR);
  3433. destr = prev;
  3434. prev = chunk_get_prev_ncnlnp(prev);
  3435. }
  3436. if ((prev != NULL) && (prev->type == CT_DC_MEMBER))
  3437. {
  3438. prev = chunk_get_prev_ncnlnp(prev);
  3439. // LOG_FMT(LSYS, "%s: prev1 = %s (%s)\n", __func__,
  3440. // get_token_name(prev->type), prev->text());
  3441. prev = skip_template_prev(prev);
  3442. prev = skip_attribute_prev(prev);
  3443. // LOG_FMT(LSYS, "%s: prev2 = %s [%d](%s) pc = %s [%d](%s)\n", __func__,
  3444. // get_token_name(prev->type), prev->len, prev->text(),
  3445. // get_token_name(pc->type), pc->len, pc->text());
  3446. if ((prev != NULL) && ((prev->type == CT_WORD) || (prev->type == CT_TYPE)))
  3447. {
  3448. if (pc->str.equals(prev->str))
  3449. {
  3450. set_chunk_type(pc, CT_FUNC_CLASS_DEF);
  3451. #ifdef DEBUG
  3452. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3453. #endif
  3454. LOG_FMT(LFCN, "(%d) %zu:%zu - FOUND %sSTRUCTOR for %s[%s]\n", __LINE__,
  3455. prev->orig_line, prev->orig_col,
  3456. (destr != NULL) ? "DE" : "CON",
  3457. prev->text(), get_token_name(prev->type));
  3458. mark_cpp_constructor(pc);
  3459. return;
  3460. }
  3461. else
  3462. {
  3463. /* Point to the item previous to the class name */
  3464. prev = chunk_get_prev_ncnlnp(prev);
  3465. }
  3466. }
  3467. }
  3468. }
  3469. /* Determine if this is a function call or a function def/proto
  3470. * We check for level==1 to allow the case that a function prototype is
  3471. * wrapped in a macro: "MACRO(void foo(void));"
  3472. */
  3473. if ((pc->type == CT_FUNC_CALL) &&
  3474. ((pc->level == pc->brace_level) || (pc->level == 1)) &&
  3475. ((pc->flags & PCF_IN_ARRAY_ASSIGN) == 0))
  3476. {
  3477. bool isa_def = false;
  3478. bool hit_star = false;
  3479. #ifdef DEBUG
  3480. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3481. #endif
  3482. LOG_FMT(LFCN, " Checking func call: prev=%s", (prev == NULL) ? "<null>" : get_token_name(prev->type));
  3483. // if (!chunk_ends_type(prev))
  3484. // {
  3485. // goto bad_ret_type;
  3486. // }
  3487. /**
  3488. * REVISIT:
  3489. * a function def can only occur at brace level, but not inside an
  3490. * assignment, structure, enum, or union.
  3491. * The close paren must be followed by an open brace, with an optional
  3492. * qualifier (const) in between.
  3493. * There can be all sorts of template stuff and/or '[]' in the type.
  3494. * This hack mostly checks that.
  3495. *
  3496. * Examples:
  3497. * foo->bar(maid); -- fcn call
  3498. * FOO * bar(); -- fcn proto or class variable
  3499. * FOO foo(); -- fcn proto or class variable
  3500. * FOO foo(1); -- class variable
  3501. * a = FOO * bar(); -- fcn call
  3502. * a.y = foo() * bar(); -- fcn call
  3503. * static const char * const fizz(); -- fcn def
  3504. */
  3505. while (prev != NULL)
  3506. {
  3507. if (prev->flags & PCF_IN_PREPROC)
  3508. {
  3509. prev = chunk_get_prev_ncnlnp(prev);
  3510. continue;
  3511. }
  3512. /* Some code slips an attribute between the type and function */
  3513. if ((prev->type == CT_FPAREN_CLOSE) &&
  3514. (prev->parent_type == CT_ATTRIBUTE))
  3515. {
  3516. prev = skip_attribute_prev(prev);
  3517. continue;
  3518. }
  3519. /* skip const(TYPE) */
  3520. if ((prev->type == CT_PAREN_CLOSE) &&
  3521. (prev->parent_type == CT_D_CAST))
  3522. {
  3523. #ifdef DEBUG
  3524. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3525. #endif
  3526. LOG_FMT(LFCN, " --> For sure a prototype or definition\n");
  3527. isa_def = true;
  3528. break;
  3529. }
  3530. /** Skip the word/type before the '.' or '::' */
  3531. if ((prev->type == CT_DC_MEMBER) ||
  3532. (prev->type == CT_MEMBER))
  3533. {
  3534. prev = chunk_get_prev_ncnlnp(prev);
  3535. if ((prev == NULL) ||
  3536. ((prev->type != CT_WORD) &&
  3537. (prev->type != CT_TYPE) &&
  3538. (prev->type != CT_THIS)))
  3539. {
  3540. #ifdef DEBUG
  3541. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3542. #endif
  3543. LOG_FMT(LFCN, " --? Skipped MEMBER and landed on %s\n",
  3544. (prev == NULL) ? "<null>" : get_token_name(prev->type));
  3545. set_chunk_type(pc, CT_FUNC_CALL);
  3546. isa_def = false;
  3547. break;
  3548. }
  3549. LOG_FMT(LFCN, " <skip %s>", prev->text());
  3550. prev = chunk_get_prev_ncnlnp(prev);
  3551. continue;
  3552. }
  3553. /* If we are on a TYPE or WORD, then we must be on a proto or def */
  3554. if ((prev->type == CT_TYPE) ||
  3555. (prev->type == CT_WORD))
  3556. {
  3557. if (!hit_star)
  3558. {
  3559. #ifdef DEBUG
  3560. LOG_FMT(LFCN, "\n(%d) ", __LINE__);
  3561. #endif
  3562. LOG_FMT(LFCN, " --> For sure a prototype or definition\n");
  3563. isa_def = true;
  3564. break;
  3565. }
  3566. #ifdef DEBUG
  3567. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3568. #endif
  3569. LOG_FMT(LFCN, " --> maybe a proto/def\n");
  3570. isa_def = true;
  3571. }
  3572. if (chunk_is_ptr_operator(prev))
  3573. {
  3574. hit_star = true;
  3575. }
  3576. if ((prev->type != CT_OPERATOR) &&
  3577. (prev->type != CT_TSQUARE) &&
  3578. (prev->type != CT_ANGLE_CLOSE) &&
  3579. (prev->type != CT_QUALIFIER) &&
  3580. (prev->type != CT_TYPE) &&
  3581. (prev->type != CT_WORD) &&
  3582. !chunk_is_ptr_operator(prev))
  3583. {
  3584. #ifdef DEBUG
  3585. LOG_FMT(LFCN, "\n(%d) ", __LINE__);
  3586. #endif
  3587. LOG_FMT(LFCN, " --> Stopping on %s [%s]\n",
  3588. prev->text(), get_token_name(prev->type));
  3589. /* certain tokens are unlikely to precede a proto or def */
  3590. if ((prev->type == CT_ARITH) ||
  3591. (prev->type == CT_ASSIGN) ||
  3592. (prev->type == CT_COMMA) ||
  3593. (prev->type == CT_STRING) ||
  3594. (prev->type == CT_STRING_MULTI) ||
  3595. (prev->type == CT_NUMBER) ||
  3596. (prev->type == CT_NUMBER_FP))
  3597. {
  3598. isa_def = false;
  3599. }
  3600. break;
  3601. }
  3602. /* Skip over template and attribute stuff */
  3603. if (prev->type == CT_ANGLE_CLOSE)
  3604. {
  3605. prev = skip_template_prev(prev);
  3606. }
  3607. else
  3608. {
  3609. prev = chunk_get_prev_ncnlnp(prev);
  3610. }
  3611. }
  3612. //LOG_FMT(LFCN, " -- stopped on %s [%s]\n",
  3613. // prev->text(), get_token_name(prev->type));
  3614. if (isa_def && (prev != NULL) &&
  3615. ((chunk_is_paren_close(prev) && (prev->parent_type != CT_D_CAST)) ||
  3616. (prev->type == CT_ASSIGN) ||
  3617. (prev->type == CT_RETURN)))
  3618. {
  3619. #ifdef DEBUG
  3620. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3621. #endif
  3622. LOG_FMT(LFCN, " -- overriding DEF due to %s [%s]\n",
  3623. prev->text(), get_token_name(prev->type));
  3624. isa_def = false;
  3625. }
  3626. if (isa_def)
  3627. {
  3628. set_chunk_type(pc, CT_FUNC_DEF);
  3629. #ifdef DEBUG
  3630. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3631. #endif
  3632. LOG_FMT(LFCN, "%s: '%s' is FCN_DEF:", __func__, pc->text());
  3633. if (prev == NULL)
  3634. {
  3635. prev = chunk_get_head();
  3636. }
  3637. for (tmp = prev; tmp != pc; tmp = chunk_get_next_ncnl(tmp))
  3638. {
  3639. LOG_FMT(LFCN, " %s[%s]",
  3640. tmp->text(), get_token_name(tmp->type));
  3641. make_type(tmp);
  3642. }
  3643. LOG_FMT(LFCN, "\n");
  3644. }
  3645. }
  3646. if (pc->type != CT_FUNC_DEF)
  3647. {
  3648. #ifdef DEBUG
  3649. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3650. #endif
  3651. LOG_FMT(LFCN, " Detected %s '%s' on line %zu col %zu\n",
  3652. get_token_name(pc->type),
  3653. pc->text(), pc->orig_line, pc->orig_col);
  3654. tmp = flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
  3655. if (tmp && (tmp->type == CT_BRACE_OPEN) && (tmp->parent_type != CT_DOUBLE_BRACE))
  3656. {
  3657. set_paren_parent(tmp, pc->type);
  3658. }
  3659. return;
  3660. }
  3661. /* We have a function definition or prototype
  3662. * Look for a semicolon or a brace open after the close paren to figure
  3663. * out whether this is a prototype or definition
  3664. */
  3665. /* See if this is a prototype or implementation */
  3666. /* FIXME: this doesn't take the old K&R parameter definitions into account */
  3667. /* Scan tokens until we hit a brace open (def) or semicolon (proto) */
  3668. tmp = paren_close;
  3669. while ((tmp = chunk_get_next_ncnl(tmp)) != NULL)
  3670. {
  3671. /* Only care about brace or semi on the same level */
  3672. if (tmp->level < pc->level)
  3673. {
  3674. /* No semicolon - guess that it is a prototype */
  3675. set_chunk_type(pc, CT_FUNC_PROTO);
  3676. break;
  3677. }
  3678. else if (tmp->level == pc->level)
  3679. {
  3680. if (tmp->type == CT_BRACE_OPEN)
  3681. {
  3682. /* its a function def for sure */
  3683. break;
  3684. }
  3685. else if (chunk_is_semicolon(tmp))
  3686. {
  3687. /* Set the parent for the semi for later */
  3688. semi = tmp;
  3689. set_chunk_type(pc, CT_FUNC_PROTO);
  3690. #ifdef DEBUG
  3691. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3692. #endif
  3693. LOG_FMT(LFCN, " 2) Marked [%s] as FUNC_PROTO on line %zu col %zu\n",
  3694. pc->text(), pc->orig_line, pc->orig_col);
  3695. break;
  3696. }
  3697. else if (pc->type == CT_COMMA)
  3698. {
  3699. set_chunk_type(pc, CT_FUNC_CTOR_VAR);
  3700. #ifdef DEBUG
  3701. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3702. #endif
  3703. LOG_FMT(LFCN, " 2) Marked [%s] as FUNC_CTOR_VAR on line %zu col %zu\n",
  3704. pc->text(), pc->orig_line, pc->orig_col);
  3705. break;
  3706. }
  3707. }
  3708. }
  3709. /**
  3710. * C++ syntax is wacky. We need to check to see if a prototype is really a
  3711. * variable definition with parameters passed into the constructor.
  3712. * Unfortunately, the only mostly reliable way to do so is to guess that
  3713. * it is a constructor variable if inside a function body and scan the
  3714. * 'parameter list' for items that are not allowed in a prototype.
  3715. * We search backwards and checking the parent of the containing open braces.
  3716. * If the parent is a class or namespace, then it probably is a prototype.
  3717. */
  3718. if ((cpd.lang_flags & LANG_CPP) &&
  3719. (pc->type == CT_FUNC_PROTO) &&
  3720. (pc->parent_type != CT_OPERATOR))
  3721. {
  3722. #ifdef DEBUG
  3723. LOG_FMT(LFPARAM, "(%d) ", __LINE__);
  3724. #endif
  3725. LOG_FMT(LFPARAM, "%s :: checking '%s' for constructor variable %s %s\n",
  3726. __func__, pc->text(),
  3727. get_token_name(paren_open->type),
  3728. get_token_name(paren_close->type));
  3729. /* Scan the parameters looking for:
  3730. * - constant strings
  3731. * - numbers
  3732. * - non-type fields
  3733. * - function calls
  3734. */
  3735. chunk_t *ref = chunk_get_next_ncnl(paren_open);
  3736. chunk_t *tmp2;
  3737. bool is_param = true;
  3738. tmp = ref;
  3739. while (tmp != paren_close)
  3740. {
  3741. tmp2 = chunk_get_next_ncnl(tmp);
  3742. if ((tmp->type == CT_COMMA) && (tmp->level == (paren_open->level + 1)))
  3743. {
  3744. if (!can_be_full_param(ref, tmp))
  3745. {
  3746. is_param = false;
  3747. break;
  3748. }
  3749. ref = tmp2;
  3750. }
  3751. tmp = tmp2;
  3752. }
  3753. if (is_param && (ref != tmp))
  3754. {
  3755. if (!can_be_full_param(ref, tmp))
  3756. {
  3757. is_param = false;
  3758. }
  3759. }
  3760. if (!is_param)
  3761. {
  3762. set_chunk_type(pc, CT_FUNC_CTOR_VAR);
  3763. #ifdef DEBUG
  3764. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3765. #endif
  3766. LOG_FMT(LFCN, " 3) Marked [%s] as FUNC_CTOR_VAR on line %zu col %zu\n",
  3767. pc->text(), pc->orig_line, pc->orig_col);
  3768. }
  3769. else if (pc->brace_level > 0)
  3770. {
  3771. chunk_t *br_open = chunk_get_prev_type(pc, CT_BRACE_OPEN, pc->brace_level - 1);
  3772. if ((br_open != NULL) &&
  3773. (br_open->parent_type != CT_EXTERN) &&
  3774. (br_open->parent_type != CT_NAMESPACE))
  3775. {
  3776. /* Do a check to see if the level is right */
  3777. prev = chunk_get_prev_ncnl(pc);
  3778. if (!chunk_is_str(prev, "*", 1) && !chunk_is_str(prev, "&", 1))
  3779. {
  3780. chunk_t *p_op = chunk_get_prev_type(pc, CT_BRACE_OPEN, pc->brace_level - 1);
  3781. if ((p_op != NULL) &&
  3782. (p_op->parent_type != CT_CLASS) &&
  3783. (p_op->parent_type != CT_STRUCT) &&
  3784. (p_op->parent_type != CT_NAMESPACE))
  3785. {
  3786. set_chunk_type(pc, CT_FUNC_CTOR_VAR);
  3787. #ifdef DEBUG
  3788. LOG_FMT(LFCN, "(%d) ", __LINE__);
  3789. #endif
  3790. LOG_FMT(LFCN, " 4) Marked [%s] as FUNC_CTOR_VAR on line %zu col %zu\n",
  3791. pc->text(), pc->orig_line, pc->orig_col);
  3792. }
  3793. }
  3794. }
  3795. }
  3796. }
  3797. if (semi != NULL)
  3798. {
  3799. set_chunk_parent(semi, pc->type);
  3800. }
  3801. flag_parens(paren_open, PCF_IN_FCN_DEF, CT_FPAREN_OPEN, pc->type, false);
  3802. if (pc->type == CT_FUNC_CTOR_VAR)
  3803. {
  3804. chunk_flags_set(pc, PCF_VAR_1ST_DEF);
  3805. return;
  3806. }
  3807. if (next->type == CT_TSQUARE)
  3808. {
  3809. next = chunk_get_next_ncnl(next);
  3810. if (next == NULL)
  3811. {
  3812. return;
  3813. }
  3814. }
  3815. /* Mark parameters and return type */
  3816. fix_fcn_def_params(next);
  3817. mark_function_return_type(pc, chunk_get_prev_ncnl(pc), pc->type);
  3818. /* Find the brace pair and set the parent */
  3819. if (pc->type == CT_FUNC_DEF)
  3820. {
  3821. tmp = chunk_get_next_ncnl(paren_close);
  3822. while ((tmp != NULL) &&
  3823. (tmp->type != CT_BRACE_OPEN))
  3824. {
  3825. //LOG_FMT(LSYS, "%s: set parent to FUNC_DEF on line %d: [%s]\n", __func__, tmp->orig_line, tmp->text());
  3826. set_chunk_parent(tmp, CT_FUNC_DEF);
  3827. if (!chunk_is_semicolon(tmp))
  3828. {
  3829. chunk_flags_set(tmp, PCF_OLD_FCN_PARAMS);
  3830. }
  3831. tmp = chunk_get_next_ncnl(tmp);
  3832. }
  3833. if ((tmp != NULL) && (tmp->type == CT_BRACE_OPEN))
  3834. {
  3835. set_chunk_parent(tmp, CT_FUNC_DEF);
  3836. tmp = chunk_skip_to_match(tmp);
  3837. if (tmp != NULL)
  3838. {
  3839. set_chunk_parent(tmp, CT_FUNC_DEF);
  3840. }
  3841. }
  3842. }
  3843. } // mark_function
  3844. static void mark_cpp_constructor(chunk_t *pc)
  3845. {
  3846. LOG_FUNC_ENTRY();
  3847. chunk_t *paren_open;
  3848. chunk_t *tmp;
  3849. chunk_t *after;
  3850. chunk_t *var;
  3851. bool is_destr = false;
  3852. tmp = chunk_get_prev_ncnl(pc);
  3853. if ((tmp->type == CT_INV) || (tmp->type == CT_DESTRUCTOR))
  3854. {
  3855. set_chunk_type(tmp, CT_DESTRUCTOR);
  3856. set_chunk_parent(pc, CT_DESTRUCTOR);
  3857. is_destr = true;
  3858. }
  3859. LOG_FMT(LFTOR, "(%d) %zu:%zu FOUND %sSTRUCTOR for %s[%s] prev=%s[%s]",
  3860. __LINE__, pc->orig_line, pc->orig_col,
  3861. is_destr ? "DE" : "CON",
  3862. pc->text(), get_token_name(pc->type),
  3863. tmp->text(), get_token_name(tmp->type));
  3864. paren_open = skip_template_next(chunk_get_next_ncnl(pc));
  3865. if (!chunk_is_str(paren_open, "(", 1))
  3866. {
  3867. LOG_FMT(LWARN, "%s:%zu Expected '(', got: [%s]\n",
  3868. cpd.filename, paren_open->orig_line,
  3869. paren_open->text());
  3870. return;
  3871. }
  3872. /* Mark parameters */
  3873. fix_fcn_def_params(paren_open);
  3874. after = flag_parens(paren_open, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CLASS_PROTO, false);
  3875. LOG_FMT(LFTOR, "[%s]\n", after->text());
  3876. /* Scan until the brace open, mark everything */
  3877. tmp = paren_open;
  3878. bool hit_colon = false;
  3879. while ((tmp != NULL) && (tmp->type != CT_BRACE_OPEN) &&
  3880. !chunk_is_semicolon(tmp))
  3881. {
  3882. chunk_flags_set(tmp, PCF_IN_CONST_ARGS);
  3883. tmp = chunk_get_next_ncnl(tmp);
  3884. if (chunk_is_str(tmp, ":", 1) && (tmp->level == paren_open->level))
  3885. {
  3886. set_chunk_type(tmp, CT_CONSTR_COLON);
  3887. hit_colon = true;
  3888. }
  3889. if (hit_colon &&
  3890. (chunk_is_paren_open(tmp) ||
  3891. chunk_is_opening_brace(tmp)) &&
  3892. (tmp->level == paren_open->level))
  3893. {
  3894. var = skip_template_prev(chunk_get_prev_ncnl(tmp));
  3895. if ((var->type == CT_TYPE) || (var->type == CT_WORD))
  3896. {
  3897. set_chunk_type(var, CT_FUNC_CTOR_VAR);
  3898. flag_parens(tmp, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CTOR_VAR, false);
  3899. }
  3900. }
  3901. }
  3902. if (tmp != NULL)
  3903. {
  3904. if (tmp->type == CT_BRACE_OPEN)
  3905. {
  3906. set_paren_parent(paren_open, CT_FUNC_CLASS_DEF);
  3907. set_paren_parent(tmp, CT_FUNC_CLASS_DEF);
  3908. }
  3909. else
  3910. {
  3911. set_chunk_parent(tmp, CT_FUNC_CLASS_PROTO);
  3912. set_chunk_type(pc, CT_FUNC_CLASS_PROTO);
  3913. LOG_FMT(LFCN, " 2) Marked [%s] as FUNC_CLASS_PROTO on line %zu col %zu\n",
  3914. pc->text(), pc->orig_line, pc->orig_col);
  3915. }
  3916. }
  3917. } // mark_cpp_constructor
  3918. static void mark_class_ctor(chunk_t *start)
  3919. {
  3920. LOG_FUNC_ENTRY();
  3921. chunk_t *pclass = chunk_get_next_ncnl(start, CNAV_PREPROC);
  3922. if ((pclass == NULL) ||
  3923. ((pclass->type != CT_TYPE) &&
  3924. (pclass->type != CT_WORD)))
  3925. {
  3926. return;
  3927. }
  3928. chunk_t *next = chunk_get_next_ncnl(pclass, CNAV_PREPROC);
  3929. while ((next != NULL) &&
  3930. ((next->type == CT_TYPE) ||
  3931. (next->type == CT_WORD) ||
  3932. (next->type == CT_DC_MEMBER)))
  3933. {
  3934. pclass = next;
  3935. next = chunk_get_next_ncnl(next, CNAV_PREPROC);
  3936. }
  3937. chunk_t *pc = chunk_get_next_ncnl(pclass, CNAV_PREPROC);
  3938. size_t level = pclass->brace_level + 1;
  3939. if (pc == NULL)
  3940. {
  3941. LOG_FMT(LFTOR, "%s: Called on %s on line %zu. Bailed on NULL\n",
  3942. __func__, pclass->text(), pclass->orig_line);
  3943. return;
  3944. }
  3945. /* Add the class name */
  3946. ChunkStack cs;
  3947. cs.Push_Back(pclass);
  3948. LOG_FMT(LFTOR, "%s: Called on %s on line %zu (next='%s')\n",
  3949. __func__, pclass->text(), pclass->orig_line, pc->text());
  3950. /* detect D template class: "class foo(x) { ... }" */
  3951. if (next != NULL) // Coverity CID 76004
  3952. {
  3953. if ((cpd.lang_flags & LANG_D) && (next->type == CT_PAREN_OPEN))
  3954. {
  3955. set_chunk_parent(next, CT_TEMPLATE);
  3956. next = get_d_template_types(cs, next);
  3957. if (next && (next->type == CT_PAREN_CLOSE))
  3958. {
  3959. set_chunk_parent(next, CT_TEMPLATE);
  3960. }
  3961. }
  3962. }
  3963. /* Find the open brace, abort on semicolon */
  3964. size_t flags = 0;
  3965. while ((pc != NULL) && (pc->type != CT_BRACE_OPEN))
  3966. {
  3967. LOG_FMT(LFTOR, " [%s]", pc->text());
  3968. if (chunk_is_str(pc, ":", 1))
  3969. {
  3970. set_chunk_type(pc, CT_CLASS_COLON);
  3971. flags |= PCF_IN_CLASS_BASE;
  3972. LOG_FMT(LFTOR, "%s: class colon on line %zu\n",
  3973. __func__, pc->orig_line);
  3974. }
  3975. if (chunk_is_semicolon(pc))
  3976. {
  3977. LOG_FMT(LFTOR, "%s: bailed on semicolon on line %zu\n",
  3978. __func__, pc->orig_line);
  3979. return;
  3980. }
  3981. chunk_flags_set(pc, flags);
  3982. pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  3983. }
  3984. if (pc == NULL)
  3985. {
  3986. LOG_FMT(LFTOR, "%s: bailed on NULL\n", __func__);
  3987. return;
  3988. }
  3989. set_paren_parent(pc, start->type);
  3990. pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  3991. while (pc != NULL)
  3992. {
  3993. chunk_flags_set(pc, PCF_IN_CLASS);
  3994. if ((pc->brace_level > level) ||
  3995. (pc->level > pc->brace_level) ||
  3996. (pc->flags & PCF_IN_PREPROC))
  3997. {
  3998. pc = chunk_get_next_ncnl(pc);
  3999. continue;
  4000. }
  4001. if ((pc->type == CT_BRACE_CLOSE) && (pc->brace_level < level))
  4002. {
  4003. LOG_FMT(LFTOR, "%s: %zu] Hit brace close\n", __func__, pc->orig_line);
  4004. pc = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  4005. if (pc && (pc->type == CT_SEMICOLON))
  4006. {
  4007. set_chunk_parent(pc, start->type);
  4008. }
  4009. return;
  4010. }
  4011. next = chunk_get_next_ncnl(pc, CNAV_PREPROC);
  4012. if (chunkstack_match(cs, pc))
  4013. {
  4014. if ((next != NULL) && (next->len() == 1) && (next->str[0] == '('))
  4015. {
  4016. set_chunk_type(pc, CT_FUNC_CLASS_DEF);
  4017. LOG_FMT(LFTOR, "(%d) %zu] Marked CTor/DTor %s\n", __LINE__, pc->orig_line, pc->text());
  4018. mark_cpp_constructor(pc);
  4019. }
  4020. else
  4021. {
  4022. make_type(pc);
  4023. }
  4024. }
  4025. pc = next;
  4026. }
  4027. } // mark_class_ctor
  4028. static void mark_namespace(chunk_t *pns)
  4029. {
  4030. LOG_FUNC_ENTRY();
  4031. chunk_t *br_close;
  4032. bool is_using = false;
  4033. chunk_t *pc = chunk_get_prev_ncnl(pns);
  4034. if (chunk_is_token(pc, CT_USING))
  4035. {
  4036. is_using = true;
  4037. set_chunk_parent(pns, CT_USING);
  4038. }
  4039. pc = chunk_get_next_ncnl(pns);
  4040. while (pc != NULL)
  4041. {
  4042. set_chunk_parent(pc, CT_NAMESPACE);
  4043. if (pc->type != CT_BRACE_OPEN)
  4044. {
  4045. if (pc->type == CT_SEMICOLON)
  4046. {
  4047. if (is_using)
  4048. {
  4049. set_chunk_parent(pc, CT_USING);
  4050. }
  4051. return;
  4052. }
  4053. pc = chunk_get_next_ncnl(pc);
  4054. continue;
  4055. }
  4056. if ((cpd.settings[UO_indent_namespace_limit].u > 0) &&
  4057. ((br_close = chunk_skip_to_match(pc)) != NULL))
  4058. {
  4059. // br_close->orig_line is always >= pc->orig_line;
  4060. size_t diff = br_close->orig_line - pc->orig_line;
  4061. if (diff > cpd.settings[UO_indent_namespace_limit].u)
  4062. {
  4063. chunk_flags_set(pc, PCF_LONG_BLOCK);
  4064. chunk_flags_set(br_close, PCF_LONG_BLOCK);
  4065. }
  4066. }
  4067. flag_parens(pc, PCF_IN_NAMESPACE, CT_NONE, CT_NAMESPACE, false);
  4068. return;
  4069. }
  4070. } // mark_namespace
  4071. static chunk_t *skip_align(chunk_t *start)
  4072. {
  4073. chunk_t *pc = start;
  4074. if (pc->type == CT_ALIGN)
  4075. {
  4076. pc = chunk_get_next_ncnl(pc);
  4077. if (pc->type == CT_PAREN_OPEN)
  4078. {
  4079. pc = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level);
  4080. pc = chunk_get_next_ncnl(pc);
  4081. if (pc->type == CT_COLON)
  4082. {
  4083. pc = chunk_get_next_ncnl(pc);
  4084. }
  4085. }
  4086. }
  4087. return(pc);
  4088. }
  4089. static void mark_struct_union_body(chunk_t *start)
  4090. {
  4091. LOG_FUNC_ENTRY();
  4092. chunk_t *pc = start;
  4093. while ((pc != NULL) &&
  4094. (pc->level >= start->level) &&
  4095. !((pc->level == start->level) && (pc->type == CT_BRACE_CLOSE)))
  4096. {
  4097. // LOG_FMT(LSYS, "%s: %d:%d %s:%s\n", __func__, pc->orig_line, pc->orig_col,
  4098. // pc->text(), get_token_name(pc->parent_type));
  4099. if ((pc->type == CT_BRACE_OPEN) ||
  4100. (pc->type == CT_BRACE_CLOSE) ||
  4101. (pc->type == CT_SEMICOLON))
  4102. {
  4103. pc = chunk_get_next_ncnl(pc);
  4104. if (pc == NULL)
  4105. {
  4106. break;
  4107. }
  4108. }
  4109. if (pc->type == CT_ALIGN)
  4110. {
  4111. pc = skip_align(pc); // "align(x)" or "align(x):"
  4112. if (pc == NULL)
  4113. {
  4114. break;
  4115. }
  4116. }
  4117. else
  4118. {
  4119. pc = fix_var_def(pc);
  4120. if (pc == NULL)
  4121. {
  4122. break;
  4123. }
  4124. }
  4125. }
  4126. }
  4127. void mark_comments(void)
  4128. {
  4129. LOG_FUNC_ENTRY();
  4130. cpd.unc_stage = US_MARK_COMMENTS;
  4131. bool prev_nl = true;
  4132. chunk_t *cur = chunk_get_head();
  4133. while (cur != NULL)
  4134. {
  4135. chunk_t *next = chunk_get_next_nvb(cur);
  4136. bool next_nl = (next == NULL) || chunk_is_newline(next);
  4137. if (chunk_is_comment(cur))
  4138. {
  4139. if (next_nl && prev_nl)
  4140. {
  4141. set_chunk_parent(cur, CT_COMMENT_WHOLE);
  4142. }
  4143. else if (next_nl)
  4144. {
  4145. set_chunk_parent(cur, CT_COMMENT_END);
  4146. }
  4147. else if (prev_nl)
  4148. {
  4149. set_chunk_parent(cur, CT_COMMENT_START);
  4150. }
  4151. else
  4152. {
  4153. set_chunk_parent(cur, CT_COMMENT_EMBED);
  4154. }
  4155. }
  4156. prev_nl = chunk_is_newline(cur);
  4157. cur = next;
  4158. }
  4159. }
  4160. static void mark_define_expressions(void)
  4161. {
  4162. LOG_FUNC_ENTRY();
  4163. bool in_define = false;
  4164. bool first = true;
  4165. chunk_t *pc = chunk_get_head();
  4166. chunk_t *prev = pc;
  4167. while (pc != NULL)
  4168. {
  4169. if (!in_define)
  4170. {
  4171. if ((pc->type == CT_PP_DEFINE) ||
  4172. (pc->type == CT_PP_IF) ||
  4173. (pc->type == CT_PP_ELSE))
  4174. {
  4175. in_define = true;
  4176. first = true;
  4177. }
  4178. }
  4179. else
  4180. {
  4181. if (((pc->flags & PCF_IN_PREPROC) == 0) || (pc->type == CT_PREPROC))
  4182. {
  4183. in_define = false;
  4184. }
  4185. else
  4186. {
  4187. if ((pc->type != CT_MACRO) &&
  4188. (first ||
  4189. (prev->type == CT_PAREN_OPEN) ||
  4190. (prev->type == CT_ARITH) ||
  4191. (prev->type == CT_CARET) ||
  4192. (prev->type == CT_ASSIGN) ||
  4193. (prev->type == CT_COMPARE) ||
  4194. (prev->type == CT_RETURN) ||
  4195. (prev->type == CT_GOTO) ||
  4196. (prev->type == CT_CONTINUE) ||
  4197. (prev->type == CT_FPAREN_OPEN) ||
  4198. (prev->type == CT_SPAREN_OPEN) ||
  4199. (prev->type == CT_BRACE_OPEN) ||
  4200. chunk_is_semicolon(prev) ||
  4201. (prev->type == CT_COMMA) ||
  4202. (prev->type == CT_COLON) ||
  4203. (prev->type == CT_QUESTION)))
  4204. {
  4205. chunk_flags_set(pc, PCF_EXPR_START);
  4206. first = false;
  4207. }
  4208. }
  4209. }
  4210. prev = pc;
  4211. pc = chunk_get_next(pc);
  4212. }
  4213. } // mark_define_expressions
  4214. static void handle_cpp_template(chunk_t *pc)
  4215. {
  4216. LOG_FUNC_ENTRY();
  4217. chunk_t *tmp = chunk_get_next_ncnl(pc);
  4218. if (tmp->type != CT_ANGLE_OPEN)
  4219. {
  4220. return;
  4221. }
  4222. set_chunk_parent(tmp, CT_TEMPLATE);
  4223. size_t level = tmp->level;
  4224. while ((tmp = chunk_get_next(tmp)) != NULL)
  4225. {
  4226. if ((tmp->type == CT_CLASS) ||
  4227. (tmp->type == CT_STRUCT))
  4228. {
  4229. set_chunk_type(tmp, CT_TYPE);
  4230. }
  4231. else if ((tmp->type == CT_ANGLE_CLOSE) && (tmp->level == level))
  4232. {
  4233. set_chunk_parent(tmp, CT_TEMPLATE);
  4234. break;
  4235. }
  4236. }
  4237. if (tmp != NULL)
  4238. {
  4239. tmp = chunk_get_next_ncnl(tmp);
  4240. if ((tmp != NULL) &&
  4241. ((tmp->type == CT_CLASS) || (tmp->type == CT_STRUCT)))
  4242. {
  4243. set_chunk_parent(tmp, CT_TEMPLATE);
  4244. /* REVISIT: This may be a bit risky - might need to track the { }; */
  4245. tmp = chunk_get_next_type(tmp, CT_SEMICOLON, tmp->level);
  4246. if (tmp != NULL)
  4247. {
  4248. set_chunk_parent(tmp, CT_TEMPLATE);
  4249. }
  4250. }
  4251. }
  4252. } // handle_cpp_template
  4253. static void handle_cpp_lambda(chunk_t *sq_o)
  4254. {
  4255. LOG_FUNC_ENTRY();
  4256. chunk_t *ret = NULL;
  4257. chunk_t *sq_c = sq_o; /* assuming '[]' */
  4258. if (sq_o->type == CT_SQUARE_OPEN)
  4259. {
  4260. /* make sure there is a ']' */
  4261. sq_c = chunk_skip_to_match(sq_o);
  4262. if (!sq_c)
  4263. {
  4264. return;
  4265. }
  4266. }
  4267. /* Make sure a '(' is next */
  4268. chunk_t *pa_o = chunk_get_next_ncnl(sq_c);
  4269. if (!pa_o || (pa_o->type != CT_PAREN_OPEN))
  4270. {
  4271. return;
  4272. }
  4273. /* and now find the ')' */
  4274. chunk_t *pa_c = chunk_skip_to_match(pa_o);
  4275. if (!pa_c)
  4276. {
  4277. return;
  4278. }
  4279. /* Check if keyword 'mutable' is before '->' */
  4280. chunk_t *br_o = chunk_get_next_ncnl(pa_c);
  4281. if (chunk_is_str(br_o, "mutable", 7))
  4282. {
  4283. br_o = chunk_get_next_ncnl(br_o);
  4284. }
  4285. /* Make sure a '{' or '->' is next */
  4286. if (chunk_is_str(br_o, "->", 2))
  4287. {
  4288. ret = br_o;
  4289. /* REVISIT: really should check the stuff we are skipping */
  4290. br_o = chunk_get_next_type(br_o, CT_BRACE_OPEN, br_o->level);
  4291. }
  4292. if (!br_o || (br_o->type != CT_BRACE_OPEN))
  4293. {
  4294. return;
  4295. }
  4296. /* and now find the '}' */
  4297. chunk_t *br_c = chunk_skip_to_match(br_o);
  4298. if (!br_c)
  4299. {
  4300. return;
  4301. }
  4302. /* This looks like a lambda expression */
  4303. if (sq_o->type == CT_TSQUARE)
  4304. {
  4305. /* split into two chunks */
  4306. chunk_t nc;
  4307. nc = *sq_o;
  4308. set_chunk_type(sq_o, CT_SQUARE_OPEN);
  4309. sq_o->str.resize(1);
  4310. // bug # 664
  4311. // The original orig_col of CT_SQUARE_CLOSE is stored at orig_col_end of CT_TSQUARE.
  4312. // CT_SQUARE_CLOSE orig_col and orig_col_end values are calculate from orig_col_end of CT_TSQUARE.
  4313. nc.orig_col = sq_o->orig_col_end - 1;
  4314. nc.column = (int)nc.orig_col;
  4315. nc.orig_col_end = sq_o->orig_col_end;
  4316. sq_o->orig_col_end = sq_o->orig_col + 1;
  4317. nc.type = CT_SQUARE_CLOSE;
  4318. nc.str.pop_front();
  4319. sq_c = chunk_add_after(&nc, sq_o);
  4320. }
  4321. set_chunk_parent(sq_o, CT_CPP_LAMBDA);
  4322. set_chunk_parent(sq_c, CT_CPP_LAMBDA);
  4323. set_chunk_type(pa_o, CT_FPAREN_OPEN);
  4324. set_chunk_parent(pa_o, CT_CPP_LAMBDA);
  4325. set_chunk_type(pa_c, CT_FPAREN_CLOSE);
  4326. set_chunk_parent(pa_c, CT_CPP_LAMBDA);
  4327. set_chunk_parent(br_o, CT_CPP_LAMBDA);
  4328. set_chunk_parent(br_c, CT_CPP_LAMBDA);
  4329. if (ret)
  4330. {
  4331. set_chunk_type(ret, CT_CPP_LAMBDA_RET);
  4332. ret = chunk_get_next_ncnl(ret);
  4333. while (ret != br_o)
  4334. {
  4335. make_type(ret);
  4336. ret = chunk_get_next_ncnl(ret);
  4337. }
  4338. }
  4339. fix_fcn_def_params(pa_o);
  4340. } // handle_cpp_lambda
  4341. static chunk_t *get_d_template_types(ChunkStack &cs, chunk_t *open_paren)
  4342. {
  4343. LOG_FUNC_ENTRY();
  4344. chunk_t *tmp = open_paren;
  4345. bool maybe_type = true;
  4346. while (((tmp = chunk_get_next_ncnl(tmp)) != NULL) &&
  4347. (tmp->level > open_paren->level))
  4348. {
  4349. if ((tmp->type == CT_TYPE) || (tmp->type == CT_WORD))
  4350. {
  4351. if (maybe_type)
  4352. {
  4353. make_type(tmp);
  4354. cs.Push_Back(tmp);
  4355. }
  4356. maybe_type = false;
  4357. }
  4358. else if (tmp->type == CT_COMMA)
  4359. {
  4360. maybe_type = true;
  4361. }
  4362. }
  4363. return(tmp);
  4364. }
  4365. static bool chunkstack_match(ChunkStack &cs, chunk_t *pc)
  4366. {
  4367. for (size_t idx = 0; idx < cs.Len(); idx++)
  4368. {
  4369. chunk_t *tmp = cs.GetChunk(idx);
  4370. if (pc->str.equals(tmp->str))
  4371. {
  4372. return(true);
  4373. }
  4374. }
  4375. return(false);
  4376. }
  4377. static void handle_d_template(chunk_t *pc)
  4378. {
  4379. LOG_FUNC_ENTRY();
  4380. chunk_t *name = chunk_get_next_ncnl(pc);
  4381. chunk_t *po = chunk_get_next_ncnl(name);
  4382. //if (!name || ((name->type != CT_WORD) && (name->type != CT_WORD))) Coverity CID 76000 Same on both sides, 2016-03-16
  4383. if (!name || (name->type != CT_WORD))
  4384. {
  4385. /* TODO: log an error, expected NAME */
  4386. return;
  4387. }
  4388. if (!po || (po->type != CT_PAREN_OPEN))
  4389. {
  4390. /* TODO: log an error, expected '(' */
  4391. return;
  4392. }
  4393. set_chunk_type(name, CT_TYPE);
  4394. set_chunk_parent(name, CT_TEMPLATE);
  4395. set_chunk_parent(po, CT_TEMPLATE);
  4396. ChunkStack cs;
  4397. chunk_t *tmp = get_d_template_types(cs, po);
  4398. if (!tmp || (tmp->type != CT_PAREN_CLOSE))
  4399. {
  4400. /* TODO: log an error, expected ')' */
  4401. return;
  4402. }
  4403. set_chunk_parent(tmp, CT_TEMPLATE);
  4404. tmp = chunk_get_next_ncnl(tmp);
  4405. if (tmp->type != CT_BRACE_OPEN)
  4406. {
  4407. /* TODO: log an error, expected '{' */
  4408. return;
  4409. }
  4410. set_chunk_parent(tmp, CT_TEMPLATE);
  4411. po = tmp;
  4412. tmp = po;
  4413. while (((tmp = chunk_get_next_ncnl(tmp)) != NULL) &&
  4414. (tmp->level > po->level))
  4415. {
  4416. if ((tmp->type == CT_WORD) && chunkstack_match(cs, tmp))
  4417. {
  4418. set_chunk_type(tmp, CT_TYPE);
  4419. }
  4420. }
  4421. if (tmp->type != CT_BRACE_CLOSE)
  4422. {
  4423. /* TODO: log an error, expected '}' */
  4424. }
  4425. set_chunk_parent(tmp, CT_TEMPLATE);
  4426. } // handle_d_template
  4427. static void mark_template_func(chunk_t *pc, chunk_t *pc_next)
  4428. {
  4429. LOG_FUNC_ENTRY();
  4430. /* We know angle_close must be there... */
  4431. chunk_t *angle_close = chunk_get_next_type(pc_next, CT_ANGLE_CLOSE, pc->level);
  4432. chunk_t *after = chunk_get_next_ncnl(angle_close);
  4433. if (after != NULL)
  4434. {
  4435. if (chunk_is_str(after, "(", 1))
  4436. {
  4437. if (angle_close->flags & PCF_IN_FCN_CALL)
  4438. {
  4439. LOG_FMT(LTEMPFUNC, "%s: marking '%s' in line %zu as a FUNC_CALL\n",
  4440. __func__, pc->text(), pc->orig_line);
  4441. set_chunk_type(pc, CT_FUNC_CALL);
  4442. flag_parens(after, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_FUNC_CALL, false);
  4443. }
  4444. else
  4445. {
  4446. /* Might be a function def. Must check what is before the template:
  4447. * Func call:
  4448. * BTree.Insert(std::pair<int, double>(*it, double(*it) + 1.0));
  4449. * a = Test<int>(j);
  4450. * std::pair<int, double>(*it, double(*it) + 1.0));
  4451. */
  4452. LOG_FMT(LTEMPFUNC, "%s: marking '%s' in line %zu as a FUNC_CALL 2\n",
  4453. __func__, pc->text(), pc->orig_line);
  4454. // its a function!!!
  4455. set_chunk_type(pc, CT_FUNC_CALL);
  4456. mark_function(pc);
  4457. }
  4458. }
  4459. else if (after->type == CT_WORD)
  4460. {
  4461. // its a type!
  4462. set_chunk_type(pc, CT_TYPE);
  4463. chunk_flags_set(pc, PCF_VAR_TYPE);
  4464. chunk_flags_set(after, PCF_VAR_DEF);
  4465. }
  4466. }
  4467. }
  4468. static void mark_exec_sql(chunk_t *pc)
  4469. {
  4470. LOG_FUNC_ENTRY();
  4471. chunk_t *tmp;
  4472. /* Change CT_WORD to CT_SQL_WORD */
  4473. for (tmp = chunk_get_next(pc); tmp != NULL; tmp = chunk_get_next(tmp))
  4474. {
  4475. set_chunk_parent(tmp, pc->type);
  4476. if (tmp->type == CT_WORD)
  4477. {
  4478. set_chunk_type(tmp, CT_SQL_WORD);
  4479. }
  4480. if (tmp->type == CT_SEMICOLON)
  4481. {
  4482. break;
  4483. }
  4484. }
  4485. if ((pc->type != CT_SQL_BEGIN) ||
  4486. (tmp == NULL) || (tmp->type != CT_SEMICOLON))
  4487. {
  4488. return;
  4489. }
  4490. for (tmp = chunk_get_next(tmp);
  4491. (tmp != NULL) && (tmp->type != CT_SQL_END);
  4492. tmp = chunk_get_next(tmp))
  4493. {
  4494. tmp->level++;
  4495. }
  4496. }
  4497. chunk_t *skip_template_next(chunk_t *ang_open)
  4498. {
  4499. if ((ang_open != NULL) && (ang_open->type == CT_ANGLE_OPEN))
  4500. {
  4501. chunk_t *pc = chunk_get_next_type(ang_open, CT_ANGLE_CLOSE, ang_open->level);
  4502. return(chunk_get_next_ncnl(pc));
  4503. }
  4504. return(ang_open);
  4505. }
  4506. chunk_t *skip_template_prev(chunk_t *ang_close)
  4507. {
  4508. if ((ang_close != NULL) && (ang_close->type == CT_ANGLE_CLOSE))
  4509. {
  4510. chunk_t *pc = chunk_get_prev_type(ang_close, CT_ANGLE_OPEN, ang_close->level);
  4511. return(chunk_get_prev_ncnl(pc));
  4512. }
  4513. return(ang_close);
  4514. }
  4515. chunk_t *skip_tsquare_next(chunk_t *ary_def)
  4516. {
  4517. if (ary_def && ((ary_def->type == CT_SQUARE_OPEN) ||
  4518. (ary_def->type == CT_TSQUARE)))
  4519. {
  4520. return(chunk_get_next_nisq(ary_def));
  4521. }
  4522. return(ary_def);
  4523. }
  4524. chunk_t *skip_attribute_next(chunk_t *attr)
  4525. {
  4526. if ((attr != NULL) && (attr->type == CT_ATTRIBUTE))
  4527. {
  4528. chunk_t *pc = chunk_get_next(attr);
  4529. if ((pc != NULL) && (pc->type == CT_FPAREN_OPEN))
  4530. {
  4531. pc = chunk_get_next_type(attr, CT_FPAREN_CLOSE, attr->level);
  4532. return(chunk_get_next_ncnl(pc));
  4533. }
  4534. return(pc);
  4535. }
  4536. return(attr);
  4537. }
  4538. chunk_t *skip_attribute_prev(chunk_t *fp_close)
  4539. {
  4540. if ((fp_close != NULL) &&
  4541. (fp_close->type == CT_FPAREN_CLOSE) &&
  4542. (fp_close->parent_type == CT_ATTRIBUTE))
  4543. {
  4544. chunk_t *pc = chunk_get_prev_type(fp_close, CT_ATTRIBUTE, fp_close->level);
  4545. return(chunk_get_prev_ncnl(pc));
  4546. }
  4547. return(fp_close);
  4548. }
  4549. static void handle_oc_class(chunk_t *pc)
  4550. {
  4551. LOG_FUNC_ENTRY();
  4552. chunk_t *tmp;
  4553. bool hit_scope = false;
  4554. bool passed_name = false; // Did we pass the name of the class and now there can be only protocols, not generics
  4555. int generic_level = 0; // level of depth of generic
  4556. PLBfound do_pl = NO_PROTOCOL_FOUND;
  4557. LOG_FMT(LOCCLASS, "%s: start [%s] [%s] line %zu\n",
  4558. __func__, pc->text(), get_token_name(pc->parent_type), pc->orig_line);
  4559. if (pc->parent_type == CT_OC_PROTOCOL)
  4560. {
  4561. tmp = chunk_get_next_ncnl(pc);
  4562. if (chunk_is_semicolon(tmp))
  4563. {
  4564. set_chunk_parent(tmp, pc->parent_type);
  4565. LOG_FMT(LOCCLASS, "%s: bail on semicolon\n", __func__);
  4566. return;
  4567. }
  4568. }
  4569. tmp = pc;
  4570. while ((tmp = chunk_get_next_nnl(tmp)) != NULL)
  4571. {
  4572. LOG_FMT(LOCCLASS, "%s: %zu [%s]\n",
  4573. __func__, tmp->orig_line, tmp->text());
  4574. if (tmp->type == CT_OC_END)
  4575. {
  4576. break;
  4577. }
  4578. if (tmp->type == CT_PAREN_OPEN)
  4579. {
  4580. passed_name = true;
  4581. }
  4582. if (chunk_is_str(tmp, "<", 1))
  4583. {
  4584. set_chunk_type(tmp, CT_ANGLE_OPEN);
  4585. if (passed_name)
  4586. {
  4587. set_chunk_parent(tmp, CT_OC_PROTO_LIST);
  4588. }
  4589. else
  4590. {
  4591. set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
  4592. generic_level++;
  4593. }
  4594. do_pl = FOUND_ANGLE_OPEN;
  4595. }
  4596. if (chunk_is_str(tmp, ">", 1))
  4597. {
  4598. set_chunk_type(tmp, CT_ANGLE_CLOSE);
  4599. if (passed_name)
  4600. {
  4601. set_chunk_parent(tmp, CT_OC_PROTO_LIST);
  4602. do_pl = FOUND_ANGLE_CLOSE;
  4603. }
  4604. else
  4605. {
  4606. set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
  4607. generic_level--;
  4608. if (generic_level == 0)
  4609. {
  4610. do_pl = FOUND_ANGLE_CLOSE;
  4611. }
  4612. }
  4613. }
  4614. if (chunk_is_str(tmp, ">>", 2))
  4615. {
  4616. set_chunk_type(tmp, CT_ANGLE_CLOSE);
  4617. set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
  4618. split_off_angle_close(tmp);
  4619. generic_level -= 1;
  4620. if (generic_level == 0)
  4621. {
  4622. do_pl = FOUND_ANGLE_CLOSE;
  4623. }
  4624. }
  4625. if (tmp->type == CT_BRACE_OPEN)
  4626. {
  4627. do_pl = FOUND_ANGLE_CLOSE;
  4628. set_chunk_parent(tmp, CT_OC_CLASS);
  4629. tmp = chunk_get_next_type(tmp, CT_BRACE_CLOSE, tmp->level);
  4630. if (tmp != NULL)
  4631. {
  4632. set_chunk_parent(tmp, CT_OC_CLASS);
  4633. }
  4634. }
  4635. else if (tmp->type == CT_COLON)
  4636. {
  4637. if (do_pl != FOUND_ANGLE_OPEN)
  4638. {
  4639. passed_name = true;
  4640. }
  4641. set_chunk_type(tmp, hit_scope ? CT_OC_COLON : CT_CLASS_COLON);
  4642. if (tmp->type == CT_CLASS_COLON)
  4643. {
  4644. set_chunk_parent(tmp, CT_OC_CLASS);
  4645. }
  4646. }
  4647. else if (chunk_is_str(tmp, "-", 1) || chunk_is_str(tmp, "+", 1))
  4648. {
  4649. do_pl = FOUND_ANGLE_CLOSE;
  4650. if (chunk_is_newline(chunk_get_prev(tmp)))
  4651. {
  4652. set_chunk_type(tmp, CT_OC_SCOPE);
  4653. chunk_flags_set(tmp, PCF_STMT_START);
  4654. hit_scope = true;
  4655. }
  4656. }
  4657. if (do_pl == FOUND_ANGLE_OPEN)
  4658. {
  4659. if (passed_name)
  4660. {
  4661. set_chunk_parent(tmp, CT_OC_PROTO_LIST);
  4662. }
  4663. else
  4664. {
  4665. set_chunk_parent(tmp, CT_OC_GENERIC_SPEC);
  4666. }
  4667. }
  4668. }
  4669. if ((tmp != NULL) && (tmp->type == CT_BRACE_OPEN))
  4670. {
  4671. tmp = chunk_get_next_type(tmp, CT_BRACE_CLOSE, tmp->level);
  4672. if (tmp != NULL)
  4673. {
  4674. set_chunk_parent(tmp, CT_OC_CLASS);
  4675. }
  4676. }
  4677. } // handle_oc_class
  4678. static void handle_oc_block_literal(chunk_t *pc)
  4679. {
  4680. LOG_FUNC_ENTRY();
  4681. chunk_t *prev = chunk_get_prev_ncnl(pc);
  4682. chunk_t *next = chunk_get_next_ncnl(pc);
  4683. if (!pc || !prev || !next)
  4684. {
  4685. return; /* let's be paranoid */
  4686. }
  4687. /* block literal: '^ RTYPE ( ARGS ) { }'
  4688. * RTYPE and ARGS are optional
  4689. */
  4690. LOG_FMT(LOCBLK, "%s: block literal @ %zu:%zu\n", __func__, pc->orig_line, pc->orig_col);
  4691. chunk_t *apo = NULL; /* arg paren open */
  4692. chunk_t *bbo = NULL; /* block brace open */
  4693. chunk_t *bbc; /* block brace close */
  4694. LOG_FMT(LOCBLK, "%s: + scan", __func__);
  4695. chunk_t *tmp;
  4696. for (tmp = next; tmp; tmp = chunk_get_next_ncnl(tmp))
  4697. {
  4698. LOG_FMT(LOCBLK, " %s", tmp->text());
  4699. if ((tmp->level < pc->level) || (tmp->type == CT_SEMICOLON))
  4700. {
  4701. LOG_FMT(LOCBLK, "[DONE]");
  4702. break;
  4703. }
  4704. if (tmp->level == pc->level)
  4705. {
  4706. if (chunk_is_paren_open(tmp))
  4707. {
  4708. apo = tmp;
  4709. LOG_FMT(LOCBLK, "[PAREN]");
  4710. }
  4711. if (tmp->type == CT_BRACE_OPEN)
  4712. {
  4713. LOG_FMT(LOCBLK, "[BRACE]");
  4714. bbo = tmp;
  4715. break;
  4716. }
  4717. }
  4718. }
  4719. /* make sure we have braces */
  4720. bbc = chunk_skip_to_match(bbo);
  4721. if (!bbo || !bbc)
  4722. {
  4723. LOG_FMT(LOCBLK, " -- no braces found\n");
  4724. return;
  4725. }
  4726. LOG_FMT(LOCBLK, "\n");
  4727. /* we are on a block literal for sure */
  4728. set_chunk_type(pc, CT_OC_BLOCK_CARET);
  4729. set_chunk_parent(pc, CT_OC_BLOCK_EXPR);
  4730. /* handle the optional args */
  4731. chunk_t *lbp; /* last before paren - end of return type, if any */
  4732. if (apo)
  4733. {
  4734. chunk_t *apc = chunk_skip_to_match(apo); /* arg paren close */
  4735. if (chunk_is_paren_close(apc))
  4736. {
  4737. LOG_FMT(LOCBLK, " -- marking parens @ %zu:%zu and %zu:%zu\n",
  4738. apo->orig_line, apo->orig_col, apc->orig_line, apc->orig_col);
  4739. flag_parens(apo, PCF_OC_ATYPE, CT_FPAREN_OPEN, CT_OC_BLOCK_EXPR, true);
  4740. fix_fcn_def_params(apo);
  4741. }
  4742. lbp = chunk_get_prev_ncnl(apo);
  4743. }
  4744. else
  4745. {
  4746. lbp = chunk_get_prev_ncnl(bbo);
  4747. }
  4748. /* mark the return type, if any */
  4749. while (lbp != pc)
  4750. {
  4751. LOG_FMT(LOCBLK, " -- lbp %s[%s]\n", lbp->text(), get_token_name(lbp->type));
  4752. make_type(lbp);
  4753. chunk_flags_set(lbp, PCF_OC_RTYPE);
  4754. set_chunk_parent(lbp, CT_OC_BLOCK_EXPR);
  4755. lbp = chunk_get_prev_ncnl(lbp);
  4756. }
  4757. /* mark the braces */
  4758. set_chunk_parent(bbo, CT_OC_BLOCK_EXPR);
  4759. set_chunk_parent(bbc, CT_OC_BLOCK_EXPR);
  4760. } // handle_oc_block_literal
  4761. static void handle_oc_block_type(chunk_t *pc)
  4762. {
  4763. LOG_FUNC_ENTRY();
  4764. if (!pc)
  4765. {
  4766. return;
  4767. }
  4768. if (pc->flags & PCF_IN_TYPEDEF)
  4769. {
  4770. LOG_FMT(LOCBLK, "%s: skip block type @ %zu:%zu -- in typedef\n",
  4771. __func__, pc->orig_line, pc->orig_col);
  4772. return;
  4773. }
  4774. /* make sure we have '( ^' */
  4775. chunk_t *tpo = chunk_get_prev_ncnl(pc); /* type paren open */
  4776. if (chunk_is_paren_open(tpo))
  4777. {
  4778. /* block type: 'RTYPE (^LABEL)(ARGS)'
  4779. * LABEL is optional.
  4780. */
  4781. chunk_t *tpc = chunk_skip_to_match(tpo); /* type close paren (after '^') */
  4782. chunk_t *nam = chunk_get_prev_ncnl(tpc); /* name (if any) or '^' */
  4783. chunk_t *apo = chunk_get_next_ncnl(tpc); /* arg open paren */
  4784. chunk_t *apc = chunk_skip_to_match(apo); /* arg close paren */
  4785. // If this is a block literal instead of a block type, 'nam' will actually
  4786. // be the closing bracket of the block.
  4787. // We run into this situation if a block literal is enclosed in parentheses.
  4788. if (chunk_is_closing_brace(nam))
  4789. {
  4790. return(handle_oc_block_literal(pc));
  4791. }
  4792. if (chunk_is_paren_close(apc))
  4793. {
  4794. chunk_t *aft = chunk_get_next_ncnl(apc);
  4795. c_token_t pt;
  4796. if (chunk_is_str(nam, "^", 1))
  4797. {
  4798. set_chunk_type(nam, CT_PTR_TYPE);
  4799. pt = CT_FUNC_TYPE;
  4800. }
  4801. else if (chunk_is_token(aft, CT_ASSIGN) || chunk_is_token(aft, CT_SEMICOLON))
  4802. {
  4803. set_chunk_type(nam, CT_FUNC_VAR);
  4804. pt = CT_FUNC_VAR;
  4805. }
  4806. else
  4807. {
  4808. set_chunk_type(nam, CT_FUNC_TYPE);
  4809. pt = CT_FUNC_TYPE;
  4810. }
  4811. LOG_FMT(LOCBLK, "%s: block type @ %zu:%zu (%s)[%s]\n",
  4812. __func__, pc->orig_line, pc->orig_col, nam->text(), get_token_name(nam->type));
  4813. set_chunk_type(pc, CT_PTR_TYPE);
  4814. set_chunk_parent(pc, pt); //CT_OC_BLOCK_TYPE;
  4815. set_chunk_type(tpo, CT_TPAREN_OPEN);
  4816. set_chunk_parent(tpo, pt); //CT_OC_BLOCK_TYPE;
  4817. set_chunk_type(tpc, CT_TPAREN_CLOSE);
  4818. set_chunk_parent(tpc, pt); //CT_OC_BLOCK_TYPE;
  4819. set_chunk_type(apo, CT_FPAREN_OPEN);
  4820. set_chunk_parent(apo, CT_FUNC_PROTO);
  4821. set_chunk_type(apc, CT_FPAREN_CLOSE);
  4822. set_chunk_parent(apc, CT_FUNC_PROTO);
  4823. fix_fcn_def_params(apo);
  4824. mark_function_return_type(nam, chunk_get_prev_ncnl(tpo), pt);
  4825. }
  4826. }
  4827. } // handle_oc_block_type
  4828. static chunk_t *handle_oc_md_type(chunk_t *paren_open, c_token_t ptype, UINT64 flags, bool &did_it)
  4829. {
  4830. chunk_t *paren_close;
  4831. if (!chunk_is_paren_open(paren_open) ||
  4832. ((paren_close = chunk_skip_to_match(paren_open)) == NULL))
  4833. {
  4834. did_it = false;
  4835. return(paren_open);
  4836. }
  4837. did_it = true;
  4838. set_chunk_parent(paren_open, ptype);
  4839. chunk_flags_set(paren_open, flags);
  4840. set_chunk_parent(paren_close, ptype);
  4841. chunk_flags_set(paren_close, flags);
  4842. for (chunk_t *cur = chunk_get_next_ncnl(paren_open);
  4843. cur != paren_close;
  4844. cur = chunk_get_next_ncnl(cur))
  4845. {
  4846. LOG_FMT(LOCMSGD, " <%s|%s>", cur->text(), get_token_name(cur->type));
  4847. chunk_flags_set(cur, flags);
  4848. make_type(cur);
  4849. }
  4850. /* returning the chunk after the paren close */
  4851. return(chunk_get_next_ncnl(paren_close));
  4852. }
  4853. static void handle_oc_message_decl(chunk_t *pc)
  4854. {
  4855. LOG_FUNC_ENTRY();
  4856. bool did_it;
  4857. //bool in_paren = false;
  4858. //int paren_cnt = 0;
  4859. //int arg_cnt = 0;
  4860. /* Figure out if this is a spec or decl */
  4861. chunk_t *tmp = pc;
  4862. while ((tmp = chunk_get_next(tmp)) != NULL)
  4863. {
  4864. if (tmp->level < pc->level)
  4865. {
  4866. /* should not happen */
  4867. return;
  4868. }
  4869. if ((tmp->type == CT_SEMICOLON) ||
  4870. (tmp->type == CT_BRACE_OPEN))
  4871. {
  4872. break;
  4873. }
  4874. }
  4875. if (tmp == NULL)
  4876. {
  4877. return;
  4878. }
  4879. c_token_t pt = (tmp->type == CT_SEMICOLON) ? CT_OC_MSG_SPEC : CT_OC_MSG_DECL;
  4880. set_chunk_type(pc, CT_OC_SCOPE);
  4881. set_chunk_parent(pc, pt);
  4882. LOG_FMT(LOCMSGD, "%s: %s @ %zu:%zu -", __func__, get_token_name(pt), pc->orig_line, pc->orig_col);
  4883. /* format: -(TYPE) NAME [: (TYPE)NAME */
  4884. /* handle the return type */
  4885. tmp = handle_oc_md_type(chunk_get_next_ncnl(pc), pt, PCF_OC_RTYPE, did_it);
  4886. if (!did_it)
  4887. {
  4888. LOG_FMT(LOCMSGD, " -- missing type parens\n");
  4889. return;
  4890. }
  4891. /* expect the method name/label */
  4892. if (!chunk_is_token(tmp, CT_WORD))
  4893. {
  4894. LOG_FMT(LOCMSGD, " -- missing method name\n");
  4895. return;
  4896. }
  4897. chunk_t *label = tmp;
  4898. set_chunk_type(tmp, pt);
  4899. set_chunk_parent(tmp, pt);
  4900. pc = chunk_get_next_ncnl(tmp);
  4901. LOG_FMT(LOCMSGD, " [%s]%s", pc->text(), get_token_name(pc->type));
  4902. /* if we have a colon next, we have args */
  4903. if ((pc->type == CT_COLON) || (pc->type == CT_OC_COLON))
  4904. {
  4905. pc = label;
  4906. while (true)
  4907. {
  4908. /* skip optional label */
  4909. if (chunk_is_token(pc, CT_WORD) || chunk_is_token(pc, pt))
  4910. {
  4911. set_chunk_parent(pc, pt);
  4912. pc = chunk_get_next_ncnl(pc);
  4913. }
  4914. /* a colon must be next */
  4915. if (!chunk_is_str(pc, ":", 1))
  4916. {
  4917. break;
  4918. }
  4919. set_chunk_type(pc, CT_OC_COLON);
  4920. set_chunk_parent(pc, pt);
  4921. pc = chunk_get_next_ncnl(pc);
  4922. /* next is the type in parens */
  4923. LOG_FMT(LOCMSGD, " (%s)", pc->text());
  4924. tmp = handle_oc_md_type(pc, pt, PCF_OC_ATYPE, did_it);
  4925. if (!did_it)
  4926. {
  4927. LOG_FMT(LWARN, "%s: %zu:%zu expected type\n", __func__, pc->orig_line, pc->orig_col);
  4928. break;
  4929. }
  4930. pc = tmp;
  4931. /* we should now be on the arg name */
  4932. chunk_flags_set(pc, PCF_VAR_DEF);
  4933. LOG_FMT(LOCMSGD, " arg[%s]", pc->text());
  4934. pc = chunk_get_next_ncnl(pc);
  4935. }
  4936. }
  4937. LOG_FMT(LOCMSGD, " end[%s]", pc->text());
  4938. if (chunk_is_token(pc, CT_BRACE_OPEN))
  4939. {
  4940. set_chunk_parent(pc, pt);
  4941. pc = chunk_skip_to_match(pc);
  4942. if (pc)
  4943. {
  4944. set_chunk_parent(pc, pt);
  4945. }
  4946. }
  4947. else if (chunk_is_token(pc, CT_SEMICOLON))
  4948. {
  4949. set_chunk_parent(pc, pt);
  4950. }
  4951. LOG_FMT(LOCMSGD, "\n");
  4952. /* Mark everything */
  4953. // 76020 Structurally dead code, 2016-03-16
  4954. //tmp = pc;
  4955. //while ((tmp = chunk_get_next(tmp)) != NULL)
  4956. //{
  4957. // LOG_FMT(LOCMSGD, " [%s]", tmp->text());
  4958. // if ((tmp->type == CT_SEMICOLON) ||
  4959. // (tmp->type == CT_BRACE_OPEN))
  4960. // {
  4961. // set_chunk_parent(tmp, pt);
  4962. // break;
  4963. // }
  4964. // /* Mark first parens as return type */
  4965. // if ((arg_cnt == 0) &&
  4966. // ((tmp->type == CT_PAREN_OPEN) ||
  4967. // (tmp->type == CT_PAREN_CLOSE)))
  4968. // {
  4969. // set_chunk_parent(tmp, CT_OC_RTYPE);
  4970. // in_paren = (tmp->type == CT_PAREN_OPEN);
  4971. // if (!in_paren)
  4972. // {
  4973. // paren_cnt++;
  4974. // arg_cnt++;
  4975. // }
  4976. // }
  4977. // else if ((tmp->type == CT_PAREN_OPEN) ||
  4978. // (tmp->type == CT_PAREN_CLOSE))
  4979. // {
  4980. // set_chunk_parent(tmp, pt);
  4981. // in_paren = (tmp->type == CT_PAREN_OPEN);
  4982. // if (!in_paren)
  4983. // {
  4984. // paren_cnt++;
  4985. // }
  4986. // }
  4987. // else if (tmp->type == CT_WORD)
  4988. // {
  4989. // if (in_paren)
  4990. // {
  4991. // set_chunk_type(tmp, CT_TYPE);
  4992. // set_chunk_parent(tmp, pt);
  4993. // }
  4994. // else if (paren_cnt == 1)
  4995. // {
  4996. // set_chunk_type(tmp, pt);
  4997. // }
  4998. // else
  4999. // {
  5000. // tmp->flags |= PCF_VAR_DEF;
  5001. // }
  5002. // }
  5003. // else if (tmp->type == CT_COLON)
  5004. // {
  5005. // set_chunk_type(tmp, CT_OC_COLON);
  5006. // set_chunk_parent(tmp, pt);
  5007. // }
  5008. //}
  5009. //if ((tmp != NULL) && (tmp->type == CT_BRACE_OPEN))
  5010. //{
  5011. // tmp = chunk_skip_to_match(tmp);
  5012. // if (tmp)
  5013. // {
  5014. // set_chunk_parent(tmp, pt);
  5015. // }
  5016. //}
  5017. //LOG_FMT(LOCMSGD, "\n");
  5018. } // handle_oc_message_decl
  5019. static void handle_oc_message_send(chunk_t *os)
  5020. {
  5021. LOG_FUNC_ENTRY();
  5022. chunk_t *cs = chunk_get_next(os);
  5023. while ((cs != NULL) && (cs->level > os->level))
  5024. {
  5025. cs = chunk_get_next(cs);
  5026. }
  5027. if ((cs == NULL) || (cs->type != CT_SQUARE_CLOSE))
  5028. {
  5029. return;
  5030. }
  5031. LOG_FMT(LOCMSG, "%s: line %zu, col %zu\n", __func__, os->orig_line, os->orig_col);
  5032. chunk_t *tmp = chunk_get_next_ncnl(cs);
  5033. if (chunk_is_semicolon(tmp))
  5034. {
  5035. set_chunk_parent(tmp, CT_OC_MSG);
  5036. }
  5037. set_chunk_parent(os, CT_OC_MSG);
  5038. chunk_flags_set(os, PCF_IN_OC_MSG);
  5039. set_chunk_parent(cs, CT_OC_MSG);
  5040. chunk_flags_set(cs, PCF_IN_OC_MSG);
  5041. /* expect a word first thing or [...] */
  5042. tmp = chunk_get_next_ncnl(os);
  5043. if ((tmp->type == CT_SQUARE_OPEN) || (tmp->type == CT_PAREN_OPEN))
  5044. {
  5045. tmp = chunk_skip_to_match(tmp);
  5046. }
  5047. else if ((tmp->type != CT_WORD) && (tmp->type != CT_TYPE) && (tmp->type != CT_STRING))
  5048. {
  5049. LOG_FMT(LOCMSG, "%s: %zu:%zu expected identifier, not '%s' [%s]\n",
  5050. __func__, tmp->orig_line, tmp->orig_col,
  5051. tmp->text(), get_token_name(tmp->type));
  5052. return;
  5053. }
  5054. else
  5055. {
  5056. chunk_t *tt = chunk_get_next_ncnl(tmp);
  5057. if (chunk_is_paren_open(tt))
  5058. {
  5059. set_chunk_type(tmp, CT_FUNC_CALL);
  5060. tmp = chunk_get_prev_ncnl(set_paren_parent(tt, CT_FUNC_CALL));
  5061. }
  5062. else
  5063. {
  5064. set_chunk_type(tmp, CT_OC_MSG_CLASS);
  5065. }
  5066. }
  5067. /* handle '< protocol >' */
  5068. tmp = chunk_get_next_ncnl(tmp);
  5069. if (chunk_is_str(tmp, "<", 1))
  5070. {
  5071. chunk_t *ao = tmp;
  5072. chunk_t *ac = chunk_get_next_str(ao, ">", 1, ao->level);
  5073. if (ac)
  5074. {
  5075. set_chunk_type(ao, CT_ANGLE_OPEN);
  5076. set_chunk_parent(ao, CT_OC_PROTO_LIST);
  5077. set_chunk_type(ac, CT_ANGLE_CLOSE);
  5078. set_chunk_parent(ac, CT_OC_PROTO_LIST);
  5079. for (tmp = chunk_get_next(ao); tmp != ac; tmp = chunk_get_next(tmp))
  5080. {
  5081. tmp->level += 1;
  5082. set_chunk_parent(tmp, CT_OC_PROTO_LIST);
  5083. }
  5084. }
  5085. tmp = chunk_get_next_ncnl(ac);
  5086. }
  5087. /* handle 'object.property' and 'collection[index]' */
  5088. else
  5089. {
  5090. while (tmp)
  5091. {
  5092. if (tmp->type == CT_MEMBER) /* move past [object.prop1.prop2 */
  5093. {
  5094. chunk_t *typ = chunk_get_next_ncnl(tmp);
  5095. if (typ && ((typ->type == CT_WORD) || (typ->type == CT_TYPE)))
  5096. {
  5097. tmp = chunk_get_next_ncnl(typ);
  5098. }
  5099. else
  5100. {
  5101. break;
  5102. }
  5103. }
  5104. else if (tmp->type == CT_SQUARE_OPEN) /* move past [collection[index] */
  5105. {
  5106. chunk_t *tcs = chunk_get_next_ncnl(tmp);
  5107. while (tcs && (tcs->level > tmp->level))
  5108. {
  5109. tcs = chunk_get_next_ncnl(tcs);
  5110. }
  5111. if (tcs && (tcs->type == CT_SQUARE_CLOSE))
  5112. {
  5113. tmp = chunk_get_next_ncnl(tcs);
  5114. }
  5115. else
  5116. {
  5117. break;
  5118. }
  5119. }
  5120. else
  5121. {
  5122. break;
  5123. }
  5124. }
  5125. }
  5126. if (tmp && ((tmp->type == CT_WORD) || (tmp->type == CT_TYPE)))
  5127. {
  5128. set_chunk_type(tmp, CT_OC_MSG_FUNC);
  5129. }
  5130. chunk_t *prev = NULL;
  5131. for (tmp = chunk_get_next(os); tmp != cs; tmp = chunk_get_next(tmp))
  5132. {
  5133. chunk_flags_set(tmp, PCF_IN_OC_MSG);
  5134. if (tmp->level == cs->level + 1)
  5135. {
  5136. if (tmp->type == CT_COLON)
  5137. {
  5138. set_chunk_type(tmp, CT_OC_COLON);
  5139. if ((prev != NULL) && ((prev->type == CT_WORD) || (prev->type == CT_TYPE)))
  5140. {
  5141. /* Might be a named param, check previous block */
  5142. chunk_t *pp = chunk_get_prev(prev);
  5143. if ((pp != NULL) &&
  5144. (pp->type != CT_OC_COLON) &&
  5145. (pp->type != CT_ARITH) &&
  5146. (pp->type != CT_CARET))
  5147. {
  5148. set_chunk_type(prev, CT_OC_MSG_NAME);
  5149. set_chunk_parent(tmp, CT_OC_MSG_NAME);
  5150. }
  5151. }
  5152. }
  5153. }
  5154. prev = tmp;
  5155. }
  5156. } // handle_oc_message_send
  5157. static void handle_oc_property_decl(chunk_t *os)
  5158. {
  5159. if (cpd.settings[UO_mod_sort_oc_properties].b)
  5160. {
  5161. typedef std::vector<chunk_t *> ChunkGroup;
  5162. chunk_t *next = chunk_get_next(os);
  5163. chunk_t *open_paren = NULL;
  5164. std::vector<ChunkGroup> thread_chunks; // atomic/nonatomic
  5165. std::vector<ChunkGroup> readwrite_chunks; // readwrite, readonly
  5166. std::vector<ChunkGroup> ref_chunks; // retain, copy, assign, weak, strong, unsafe_unretained
  5167. std::vector<ChunkGroup> getter_chunks; // getter
  5168. std::vector<ChunkGroup> setter_chunks; // setter
  5169. std::vector<ChunkGroup> nullability_chunks; // nonnull/nullable
  5170. if (next->type == CT_PAREN_OPEN)
  5171. {
  5172. open_paren = next;
  5173. next = chunk_get_next(next);
  5174. // Determine location of the property attributes
  5175. // NOTE: Did not do this in the combine.cpp do_symbol_check as I was not sure
  5176. // what the ramifications of adding a new type for each of the below types would
  5177. // be. It did break some items when I attempted to add them so this is my hack for
  5178. // now.
  5179. while (next != NULL && next->type != CT_PAREN_CLOSE)
  5180. {
  5181. if (next->type == CT_WORD)
  5182. {
  5183. if (chunk_is_str(next, "atomic", 6))
  5184. {
  5185. ChunkGroup chunkGroup;
  5186. chunkGroup.push_back(next);
  5187. thread_chunks.push_back(chunkGroup);
  5188. }
  5189. else if (chunk_is_str(next, "nonatomic", 9))
  5190. {
  5191. ChunkGroup chunkGroup;
  5192. chunkGroup.push_back(next);
  5193. thread_chunks.push_back(chunkGroup);
  5194. }
  5195. else if (chunk_is_str(next, "readonly", 8))
  5196. {
  5197. ChunkGroup chunkGroup;
  5198. chunkGroup.push_back(next);
  5199. readwrite_chunks.push_back(chunkGroup);
  5200. }
  5201. else if (chunk_is_str(next, "readwrite", 9))
  5202. {
  5203. ChunkGroup chunkGroup;
  5204. chunkGroup.push_back(next);
  5205. readwrite_chunks.push_back(chunkGroup);
  5206. }
  5207. else if (chunk_is_str(next, "assign", 6))
  5208. {
  5209. ChunkGroup chunkGroup;
  5210. chunkGroup.push_back(next);
  5211. ref_chunks.push_back(chunkGroup);
  5212. }
  5213. else if (chunk_is_str(next, "retain", 6))
  5214. {
  5215. ChunkGroup chunkGroup;
  5216. chunkGroup.push_back(next);
  5217. ref_chunks.push_back(chunkGroup);
  5218. }
  5219. else if (chunk_is_str(next, "copy", 4))
  5220. {
  5221. ChunkGroup chunkGroup;
  5222. chunkGroup.push_back(next);
  5223. ref_chunks.push_back(chunkGroup);
  5224. }
  5225. else if (chunk_is_str(next, "strong", 6))
  5226. {
  5227. ChunkGroup chunkGroup;
  5228. chunkGroup.push_back(next);
  5229. ref_chunks.push_back(chunkGroup);
  5230. }
  5231. else if (chunk_is_str(next, "weak", 4))
  5232. {
  5233. ChunkGroup chunkGroup;
  5234. chunkGroup.push_back(next);
  5235. ref_chunks.push_back(chunkGroup);
  5236. }
  5237. else if (chunk_is_str(next, "unsafe_unretained", 17))
  5238. {
  5239. ChunkGroup chunkGroup;
  5240. chunkGroup.push_back(next);
  5241. ref_chunks.push_back(chunkGroup);
  5242. }
  5243. else if (chunk_is_str(next, "getter", 6))
  5244. {
  5245. ChunkGroup chunkGroup;
  5246. do
  5247. {
  5248. chunkGroup.push_back(next);
  5249. next = chunk_get_next(next);
  5250. } while (next && next->type != CT_COMMA && next->type != CT_PAREN_CLOSE);
  5251. next = next->prev;
  5252. getter_chunks.push_back(chunkGroup);
  5253. }
  5254. else if (chunk_is_str(next, "setter", 6))
  5255. {
  5256. ChunkGroup chunkGroup;
  5257. do
  5258. {
  5259. chunkGroup.push_back(next);
  5260. next = chunk_get_next(next);
  5261. } while (next && next->type != CT_COMMA && next->type != CT_PAREN_CLOSE);
  5262. next = next->prev;
  5263. setter_chunks.push_back(chunkGroup);
  5264. }
  5265. else if (chunk_is_str(next, "nullable", 8))
  5266. {
  5267. ChunkGroup chunkGroup;
  5268. chunkGroup.push_back(next);
  5269. nullability_chunks.push_back(chunkGroup);
  5270. }
  5271. else if (chunk_is_str(next, "nonnull", 7))
  5272. {
  5273. ChunkGroup chunkGroup;
  5274. chunkGroup.push_back(next);
  5275. nullability_chunks.push_back(chunkGroup);
  5276. }
  5277. }
  5278. next = chunk_get_next(next);
  5279. }
  5280. int thread_w = cpd.settings[UO_mod_sort_oc_property_thread_safe_weight].n;
  5281. int readwrite_w = cpd.settings[UO_mod_sort_oc_property_readwrite_weight].n;
  5282. int ref_w = cpd.settings[UO_mod_sort_oc_property_reference_weight].n;
  5283. int getter_w = cpd.settings[UO_mod_sort_oc_property_getter_weight].n;
  5284. int setter_w = cpd.settings[UO_mod_sort_oc_property_setter_weight].n;
  5285. int nullability_w = cpd.settings[UO_mod_sort_oc_property_nullability_weight].n;
  5286. std::multimap<int, std::vector<ChunkGroup> > sorted_chunk_map;
  5287. sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(thread_w, thread_chunks));
  5288. sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(readwrite_w, readwrite_chunks));
  5289. sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(ref_w, ref_chunks));
  5290. sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(getter_w, getter_chunks));
  5291. sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(setter_w, setter_chunks));
  5292. sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(nullability_w, nullability_chunks));
  5293. chunk_t *curr_chunk = open_paren;
  5294. for (multimap<int, std::vector<ChunkGroup> >::reverse_iterator it = sorted_chunk_map.rbegin(); it != sorted_chunk_map.rend(); ++it)
  5295. {
  5296. std::vector<ChunkGroup> chunk_groups = (*it).second;
  5297. for (std::vector<int>::size_type i = 0; i < chunk_groups.size(); i++)
  5298. {
  5299. ChunkGroup chunk_group = chunk_groups[i];
  5300. for (std::vector<int>::size_type j = 0; j < chunk_group.size(); j++)
  5301. {
  5302. chunk_t *chunk = chunk_group[j];
  5303. chunk->orig_prev_sp = 0;
  5304. if (chunk != curr_chunk)
  5305. {
  5306. chunk_move_after(chunk, curr_chunk);
  5307. curr_chunk = chunk;
  5308. }
  5309. else
  5310. {
  5311. curr_chunk = chunk_get_next(curr_chunk);
  5312. }
  5313. }
  5314. /* add the parens */
  5315. chunk_t endchunk;
  5316. endchunk.type = CT_COMMA;
  5317. endchunk.str = ", ";
  5318. endchunk.level = curr_chunk->level;
  5319. endchunk.brace_level = curr_chunk->brace_level;
  5320. endchunk.orig_line = curr_chunk->orig_line;
  5321. endchunk.column = (int)curr_chunk->orig_col_end + 1;
  5322. endchunk.parent_type = curr_chunk->parent_type;
  5323. endchunk.flags = curr_chunk->flags & PCF_COPY_FLAGS;
  5324. chunk_add_after(&endchunk, curr_chunk);
  5325. curr_chunk = curr_chunk->next;
  5326. }
  5327. }
  5328. // Remove the extra comma's that we did not move
  5329. while (curr_chunk && curr_chunk->type != CT_PAREN_CLOSE)
  5330. {
  5331. chunk_t *rm_chunk = curr_chunk;
  5332. curr_chunk = chunk_get_next(curr_chunk);
  5333. chunk_del(rm_chunk);
  5334. }
  5335. }
  5336. }
  5337. chunk_t *tmp = chunk_get_next_ncnl(os);
  5338. if (chunk_is_paren_open(tmp))
  5339. {
  5340. tmp = chunk_get_next_ncnl(chunk_skip_to_match(tmp));
  5341. }
  5342. fix_var_def(tmp);
  5343. } // handle_oc_property_decl
  5344. static void handle_cs_square_stmt(chunk_t *os)
  5345. {
  5346. LOG_FUNC_ENTRY();
  5347. chunk_t *cs = chunk_get_next(os);
  5348. while ((cs != NULL) && (cs->level > os->level))
  5349. {
  5350. cs = chunk_get_next(cs);
  5351. }
  5352. if ((cs == NULL) || (cs->type != CT_SQUARE_CLOSE))
  5353. {
  5354. return;
  5355. }
  5356. set_chunk_parent(os, CT_CS_SQ_STMT);
  5357. set_chunk_parent(cs, CT_CS_SQ_STMT);
  5358. chunk_t *tmp;
  5359. for (tmp = chunk_get_next(os); tmp != cs; tmp = chunk_get_next(tmp))
  5360. {
  5361. set_chunk_parent(tmp, CT_CS_SQ_STMT);
  5362. if (tmp->type == CT_COLON)
  5363. {
  5364. set_chunk_type(tmp, CT_CS_SQ_COLON);
  5365. }
  5366. }
  5367. tmp = chunk_get_next_ncnl(cs);
  5368. if (tmp != NULL)
  5369. {
  5370. chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START);
  5371. }
  5372. }
  5373. static void handle_cs_property(chunk_t *bro)
  5374. {
  5375. LOG_FUNC_ENTRY();
  5376. set_paren_parent(bro, CT_CS_PROPERTY);
  5377. bool did_prop = false;
  5378. chunk_t *pc = bro;
  5379. while ((pc = chunk_get_prev_ncnl(pc)) != NULL)
  5380. {
  5381. if (pc->level == bro->level)
  5382. {
  5383. if (!did_prop && ((pc->type == CT_WORD) || (pc->type == CT_THIS)))
  5384. {
  5385. set_chunk_type(pc, CT_CS_PROPERTY);
  5386. did_prop = true;
  5387. }
  5388. else
  5389. {
  5390. set_chunk_parent(pc, CT_CS_PROPERTY);
  5391. make_type(pc);
  5392. }
  5393. if (pc->flags & PCF_STMT_START)
  5394. {
  5395. break;
  5396. }
  5397. }
  5398. }
  5399. }
  5400. static void handle_cs_array_type(chunk_t *pc)
  5401. {
  5402. chunk_t *prev;
  5403. for (prev = chunk_get_prev(pc);
  5404. prev && (prev->type == CT_COMMA);
  5405. prev = chunk_get_prev(prev))
  5406. {
  5407. /* empty */
  5408. }
  5409. if (prev && (prev->type == CT_SQUARE_OPEN))
  5410. {
  5411. while (pc != prev)
  5412. {
  5413. pc->parent_type = CT_TYPE;
  5414. pc = chunk_get_prev(pc);
  5415. }
  5416. prev->parent_type = CT_TYPE;
  5417. }
  5418. }
  5419. void remove_extra_returns(void)
  5420. {
  5421. LOG_FUNC_ENTRY();
  5422. chunk_t *pc = chunk_get_head();
  5423. while (pc != NULL)
  5424. {
  5425. if ((pc->type == CT_RETURN) && ((pc->flags & PCF_IN_PREPROC) == 0))
  5426. {
  5427. chunk_t *semi = chunk_get_next_ncnl(pc);
  5428. chunk_t *cl_br = chunk_get_next_ncnl(semi);
  5429. if ((semi != NULL) && (semi->type == CT_SEMICOLON) &&
  5430. (cl_br != NULL) && (cl_br->type == CT_BRACE_CLOSE) &&
  5431. ((cl_br->parent_type == CT_FUNC_DEF) ||
  5432. (cl_br->parent_type == CT_FUNC_CLASS_DEF)))
  5433. {
  5434. LOG_FMT(LRMRETURN, "Removed 'return;' on line %zu\n", pc->orig_line);
  5435. chunk_del(pc);
  5436. chunk_del(semi);
  5437. pc = cl_br;
  5438. }
  5439. }
  5440. pc = chunk_get_next(pc);
  5441. }
  5442. }
  5443. static void handle_wrap(chunk_t *pc)
  5444. {
  5445. LOG_FUNC_ENTRY();
  5446. chunk_t *opp = chunk_get_next(pc);
  5447. chunk_t *name = chunk_get_next(opp);
  5448. chunk_t *clp = chunk_get_next(name);
  5449. argval_t pav = (pc->type == CT_FUNC_WRAP) ?
  5450. cpd.settings[UO_sp_func_call_paren].a :
  5451. cpd.settings[UO_sp_cpp_cast_paren].a;
  5452. argval_t av = (pc->type == CT_FUNC_WRAP) ?
  5453. cpd.settings[UO_sp_inside_fparen].a :
  5454. cpd.settings[UO_sp_inside_paren_cast].a;
  5455. if ((clp != NULL) &&
  5456. (opp->type == CT_PAREN_OPEN) &&
  5457. ((name->type == CT_WORD) || (name->type == CT_TYPE)) &&
  5458. (clp->type == CT_PAREN_CLOSE))
  5459. {
  5460. const char *psp = (pav & AV_ADD) ? " " : "";
  5461. const char *fsp = (av & AV_ADD) ? " " : "";
  5462. pc->str.append(psp);
  5463. pc->str.append("(");
  5464. pc->str.append(fsp);
  5465. pc->str.append(name->str);
  5466. pc->str.append(fsp);
  5467. pc->str.append(")");
  5468. set_chunk_type(pc, (pc->type == CT_FUNC_WRAP) ? CT_FUNCTION : CT_TYPE);
  5469. pc->orig_col_end = pc->orig_col + pc->len();
  5470. chunk_del(opp);
  5471. chunk_del(name);
  5472. chunk_del(clp);
  5473. }
  5474. }
  5475. static void handle_proto_wrap(chunk_t *pc)
  5476. {
  5477. LOG_FUNC_ENTRY();
  5478. chunk_t *opp = chunk_get_next_ncnl(pc);
  5479. chunk_t *name = chunk_get_next_ncnl(opp);
  5480. chunk_t *tmp = chunk_get_next_ncnl(chunk_get_next_ncnl(name));
  5481. chunk_t *clp = chunk_skip_to_match(opp);
  5482. chunk_t *cma = chunk_get_next_ncnl(clp);
  5483. if (!opp || !name || !clp || !cma || !tmp ||
  5484. ((name->type != CT_WORD) && (name->type != CT_TYPE)) ||
  5485. (opp->type != CT_PAREN_OPEN))
  5486. {
  5487. return;
  5488. }
  5489. if (cma->type == CT_SEMICOLON)
  5490. {
  5491. set_chunk_type(pc, CT_FUNC_PROTO);
  5492. }
  5493. else if (cma->type == CT_BRACE_OPEN)
  5494. {
  5495. set_chunk_type(pc, CT_FUNC_DEF);
  5496. }
  5497. else
  5498. {
  5499. return;
  5500. }
  5501. set_chunk_parent(opp, pc->type);
  5502. set_chunk_parent(clp, pc->type);
  5503. set_chunk_parent(tmp, CT_PROTO_WRAP);
  5504. if (tmp->type == CT_PAREN_OPEN)
  5505. {
  5506. fix_fcn_def_params(tmp);
  5507. }
  5508. else
  5509. {
  5510. fix_fcn_def_params(opp);
  5511. set_chunk_type(name, CT_WORD);
  5512. }
  5513. tmp = chunk_skip_to_match(tmp);
  5514. if (tmp)
  5515. {
  5516. set_chunk_parent(tmp, CT_PROTO_WRAP);
  5517. }
  5518. /* Mark return type (TODO: move to own function) */
  5519. tmp = pc;
  5520. while ((tmp = chunk_get_prev_ncnl(tmp)) != NULL)
  5521. {
  5522. if (!chunk_is_type(tmp) &&
  5523. (tmp->type != CT_OPERATOR) &&
  5524. (tmp->type != CT_WORD) &&
  5525. (tmp->type != CT_ADDR))
  5526. {
  5527. break;
  5528. }
  5529. set_chunk_parent(tmp, pc->type);
  5530. make_type(tmp);
  5531. }
  5532. } // handle_proto_wrap
  5533. /**
  5534. * Java assert statements are: "assert EXP1 [: EXP2] ;"
  5535. * Mark the parent of the colon and semicolon
  5536. */
  5537. static void handle_java_assert(chunk_t *pc)
  5538. {
  5539. LOG_FUNC_ENTRY();
  5540. bool did_colon = false;
  5541. chunk_t *tmp = pc;
  5542. while ((tmp = chunk_get_next(tmp)) != NULL)
  5543. {
  5544. if (tmp->level == pc->level)
  5545. {
  5546. if (!did_colon && (tmp->type == CT_COLON))
  5547. {
  5548. did_colon = true;
  5549. set_chunk_parent(tmp, pc->type);
  5550. }
  5551. if (tmp->type == CT_SEMICOLON)
  5552. {
  5553. set_chunk_parent(tmp, pc->type);
  5554. break;
  5555. }
  5556. }
  5557. }
  5558. }