PageRenderTime 147ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 2ms

/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

Large files files are truncated, but you can click here to view the full file

  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

Large files files are truncated, but you can click here to view the full file