diff options
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/combine.cpp')
-rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/combine.cpp | 4044 |
1 files changed, 0 insertions, 4044 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/combine.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/combine.cpp deleted file mode 100644 index a033be49..00000000 --- a/debian/uncrustify-trinity/uncrustify-trinity-0.78.1/src/combine.cpp +++ /dev/null @@ -1,4044 +0,0 @@ -/** - * @file combine.cpp - * Labels the chunks as needed. - * - * @author Ben Gardner - * @author Guy Maurel - * @license GPL v2+ - */ - -#include "combine.h" - -#include "combine_fix_mark.h" -#include "combine_skip.h" -#include "combine_tools.h" -#include "EnumStructUnionParser.h" -#include "flag_braced_init_list.h" -#include "flag_parens.h" -#include "lang_pawn.h" -#include "mark_question_colon.h" -#include "newlines.h" -#include "prototypes.h" -#include "tokenize_cleanup.h" -#include "unc_tools.h" - -#include <limits> - -constexpr static auto LCURRENT = LCOMBINE; - -using namespace std; -using namespace uncrustify; - - -/** - * Mark the parens and colons in: - * asm volatile ( "xx" : "xx" (l), "yy"(h) : ... ); - * - * @param pc the CT_ASM item - */ -static void flag_asm(Chunk *pc); - - -/** - * Combines two tokens into {{ and }} if inside parens and nothing is between - * either pair. - */ -static void check_double_brace_init(Chunk *bo1); - - -static void process_returns_and_throws(); - - -/** - * Processes a 'return' or 'throw' statement, labeling the parens and marking - * the parent. May remove or add parens around the return/throw statement. - * - * @param pc Pointer to the return or throw chunk - */ -static Chunk *process_return_or_throw(Chunk *pc); - - -/** - * Process an ObjC 'class' - * pc is the chunk after '@implementation' or '@interface' or '@protocol'. - * Change colons, etc. Processes stuff until '@end'. - * Skips anything in braces. - */ -static void handle_oc_class(Chunk *pc); - - -/** - * Mark Objective-C blocks (aka lambdas or closures) - * The syntax and usage is exactly like C function pointers - * but instead of an asterisk they have a caret as pointer symbol. - * Although it may look expensive this functions is only triggered - * on appearance of an OC_BLOCK_CARET for LANG_OC. - * repeat(10, ^{ putc('0'+d); }); - * typedef void (^workBlk_t)(void); - * - * @param pc points to the '^' - */ -static void handle_oc_block_literal(Chunk *pc); - - -/** - * Mark Objective-C block types. - * The syntax and usage is exactly like C function pointers - * but instead of an asterisk they have a caret as pointer symbol. - * typedef void (^workBlk_t)(void); - * const char * (^workVar)(void); - * -(void)Foo:(void(^)())blk { } - * - * This is triggered when the sequence '(' '^' is found. - * - * @param pc points to the '^' - */ -static void handle_oc_block_type(Chunk *pc); - - -/** - * Process an ObjC message spec/dec - * - * Specs: - * -(void) foo ARGS; - * - * Declaration: - * -(void) foo ARGS { } - * - * LABEL : (ARGTYPE) ARGNAME - * - * ARGS is ': (ARGTYPE) ARGNAME [MOREARGS...]' - * MOREARGS is ' [ LABEL] : (ARGTYPE) ARGNAME ' - * -(void) foo: (int) arg: { } - * -(void) foo: (int) arg: { } - * -(void) insertObject:(id)anObject atIndex:(int)index - */ -static void handle_oc_message_decl(Chunk *pc); - - -/** - * Process an ObjC message send statement: - * [ class func: val1 name2: val2 name3: val3] ; // named params - * [ class func: val1 : val2 : val3] ; // unnamed params - * [ class <proto> self method ] ; // with protocol - * [[NSMutableString alloc] initWithString: @"" ] // class from msg - * [func(a,b,c) lastObject ] // class from func - * - * Mainly find the matching ']' and ';' and mark the colons. - * - * @param pc points to the open square '[' - */ -static void handle_oc_message_send(Chunk *pc); - - -//! Process @Property values and re-arrange them if necessary -static void handle_oc_property_decl(Chunk *pc); - -//! Process @available annotation -static void handle_oc_available(Chunk *pc); - -/** - * Process a type that is enclosed in parens in message declarations. - * TODO: handle block types, which get special formatting - * - * @param pc points to the open paren - * - * @return the chunk after the type - */ -static Chunk *handle_oc_md_type(Chunk *paren_open, E_Token ptype, PcfFlags flags, bool &did_it); - -/** - * Process an C# [] thingy: - * [assembly: xxx] - * [AttributeUsage()] - * [@X] - * - * Set the next chunk to a statement start after the close ']' - * - * @param pc points to the open square '[' - */ -static void handle_cs_square_stmt(Chunk *pc); - - -/** - * We are on a brace open that is preceded by a word or square close. - * Set the brace parent to CT_CS_PROPERTY and find the first item in the - * property and set its parent, too. - */ -static void handle_cs_property(Chunk *pc); - - -/** - * We hit a ']' followed by a WORD. This may be a multidimensional array type. - * Example: int[,,] x; - * If there is nothing but commas between the open and close, then mark it. - */ -static void handle_cs_array_type(Chunk *pc); - - -/** - * We are on the C++ 'template' keyword. - * What follows should be the following: - * - * template <class identifier> function_declaration; - * template <typename identifier> function_declaration; - * template <class identifier> class class_declaration; - * template <typename identifier> class class_declaration; - * - * Change the 'class' inside the <> to CT_TYPE. - * Set the parent to the class after the <> to CT_TEMPLATE. - * Set the parent of the semicolon to CT_TEMPLATE. - */ -static void handle_cpp_template(Chunk *pc); - - -/** - * Verify and then mark C++ lambda expressions. - * The expected format is '[...](...){...}' or '[...](...) -> type {...}' - * sq_o is '[' CT_SQUARE_OPEN or '[]' CT_TSQUARE - * Split the '[]' so we can control the space - */ -static void handle_cpp_lambda(Chunk *pc); - - -/** - * We are on the D 'template' keyword. - * What follows should be the following: - * - * template NAME ( TYPELIST ) { BODY } - * - * Set the parent of NAME to template, change NAME to CT_TYPE. - * Set the parent of the parens and braces to CT_TEMPLATE. - * Scan the body for each type in TYPELIST and change the type to CT_TYPE. - */ -static void handle_d_template(Chunk *pc); - - -/** - * A func wrap chunk and what follows should be treated as a function name. - * Create new text for the chunk and call it a CT_FUNCTION. - * - * A type wrap chunk and what follows should be treated as a simple type. - * Create new text for the chunk and call it a CT_TYPE. - */ -static void handle_wrap(Chunk *pc); - - -/** - * A proto wrap chunk and what follows should be treated as a function proto. - * - * RETTYPE PROTO_WRAP( NAME, PARAMS ); or RETTYPE PROTO_WRAP( NAME, (PARAMS) ); - * RETTYPE gets changed with make_type(). - * PROTO_WRAP is marked as CT_FUNC_PROTO or CT_FUNC_DEF. - * NAME is marked as CT_WORD. - * PARAMS is all marked as prototype parameters. - */ -static void handle_proto_wrap(Chunk *pc); - - -static bool is_oc_block(Chunk *pc); - - -/** - * Java assert statements are: "assert EXP1 [: EXP2] ;" - * Mark the parent of the colon and semicolon - */ -static void handle_java_assert(Chunk *pc); - - -static void flag_asm(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - - Chunk *tmp = pc->GetNextNcNnl(E_Scope::PREPROC); - - if (tmp->IsNot(CT_QUALIFIER)) - { - return; - } - Chunk *po = tmp->GetNextNcNnl(E_Scope::PREPROC); - - if (!po->IsParenOpen()) - { - return; - } - Chunk *end = po->GetClosingParen(E_Scope::PREPROC); - - if (end->IsNullChunk()) - { - return; - } - po->SetParentType(CT_ASM); - end->SetParentType(CT_ASM); - - for ( tmp = po->GetNextNcNnl(E_Scope::PREPROC); - tmp->IsNotNullChunk() - && tmp != end; - tmp = tmp->GetNextNcNnl(E_Scope::PREPROC)) - { - if (tmp->Is(CT_COLON)) - { - tmp->SetType(CT_ASM_COLON); - } - else if (tmp->Is(CT_DC_MEMBER)) - { - // if there is a string on both sides, then this is two ASM_COLONs - if ( tmp->GetNextNcNnl(E_Scope::PREPROC)->Is(CT_STRING) - && tmp->GetPrevNcNnlNi(E_Scope::PREPROC)->Is(CT_STRING)) // Issue #2279 - { - Chunk nc; - - nc = *tmp; - - tmp->Str().resize(1); - tmp->SetOrigColEnd(tmp->GetOrigCol() + 1); - tmp->SetType(CT_ASM_COLON); - - nc.SetType(tmp->GetType()); - nc.Str().pop_front(); - nc.SetOrigCol(nc.GetOrigCol() + 1); - nc.SetColumn(nc.GetColumn() + 1); - nc.CopyAndAddAfter(tmp); - } - } - } - - tmp = end->GetNextNcNnl(E_Scope::PREPROC); - - if (tmp->IsNullChunk()) - { - return; - } - - if (tmp->Is(CT_SEMICOLON)) - { - tmp->SetParentType(CT_ASM); - } -} // flag_asm - - -void do_symbol_check(Chunk *prev, Chunk *pc, Chunk *next) -{ - LOG_FUNC_ENTRY(); - LOG_FMT(LFCNR, "%s(%d): prev is '%s' %s\n", - __func__, __LINE__, - prev->Text(), get_token_name(prev->GetType())); - log_pcf_flags(LFCNR, prev->GetFlags()); - LOG_FMT(LFCNR, "%s(%d): pc is '%s' %s\n", - __func__, __LINE__, - pc->Text(), get_token_name(pc->GetType())); - log_pcf_flags(LFCNR, pc->GetFlags()); - LOG_FMT(LFCNR, "%s(%d): next is '%s' %s\n", - __func__, __LINE__, - next->Text(), get_token_name(next->GetType())); - log_pcf_flags(LFCNR, next->GetFlags()); - - if ( pc->Is(CT_NOEXCEPT) // Issue #3284 - && next->Is(CT_ASSIGN)) // skip over noexcept - { - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - pc = next; - next = pc->GetNext(); - } - - // separate the uses of CT_ASSIGN sign '=' - // into CT_ASSIGN_DEFAULT_ARG, CT_ASSIGN_FUNC_PROTO - if ( pc->Is(CT_ASSIGN) - && pc->GetParentType() == CT_FUNC_PROTO - && ( pc->TestFlags(PCF_IN_FCN_DEF) // Issue #2236 - || pc->TestFlags(PCF_IN_CONST_ARGS))) - { - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - log_pcf_flags(LFCNR, pc->GetFlags()); - pc->SetType(CT_ASSIGN_DEFAULT_ARG); - return; - } - - if ( ( prev->Is(CT_FPAREN_CLOSE) - || ( ( prev->IsString("const") - || prev->IsString("override")) - && prev->GetPrev()->Is(CT_FPAREN_CLOSE))) - && pc->Is(CT_ASSIGN) - && ( next->Is(CT_DEFAULT) - || next->Is(CT_DELETE) - || next->IsString("0"))) - { - pc->SetType(CT_ASSIGN_FUNC_PROTO); - return; // cpp 30031 - } - - if (pc->Is(CT_OC_AT)) - { - if ( next->Is(CT_PAREN_OPEN) - || next->Is(CT_BRACE_OPEN) - || next->Is(CT_SQUARE_OPEN)) - { - flag_parens(next, PCF_OC_BOXED, next->GetType(), CT_OC_AT, false); - } - else - { - next->SetParentType(CT_OC_AT); - return; // objective-c_50095 - } - } - - // D stuff - if ( language_is_set(LANG_D) - && pc->Is(CT_QUALIFIER) - && pc->IsString("const") - && next->Is(CT_PAREN_OPEN)) - { - pc->SetType(CT_D_CAST); - set_paren_parent(next, pc->GetType()); - return; // d_40061 - } - - if ( next->Is(CT_PAREN_OPEN) - && ( pc->Is(CT_D_CAST) - || pc->Is(CT_DELEGATE) - || pc->Is(CT_ALIGN))) - { - // mark the parenthesis parent - Chunk *tmp = set_paren_parent(next, pc->GetType()); - - // For a D cast - convert the next item - if ( pc->Is(CT_D_CAST) - && tmp->IsNotNullChunk()) - { - if (tmp->Is(CT_STAR)) - { - tmp->SetType(CT_DEREF); - return; // d_40006 - } - else if (tmp->Is(CT_AMP)) - { - tmp->SetType(CT_ADDR); - return; // d_40060 - } - else if (tmp->Is(CT_MINUS)) - { - tmp->SetType(CT_NEG); - return; // d_40060 - } - else if (tmp->Is(CT_PLUS)) - { - tmp->SetType(CT_POS); - return; // d_40060 - } - } - - /* - * For a delegate, mark previous words as types and the item after the - * close paren as a variable def - */ - if (pc->Is(CT_DELEGATE)) - { - if (tmp->IsNotNullChunk()) - { - tmp->SetParentType(CT_DELEGATE); - - if (tmp->GetLevel() == tmp->GetBraceLevel()) - { - tmp->SetFlagBits(PCF_VAR_1ST_DEF); - } - } - - for (tmp = pc->GetPrevNcNnlNi(); tmp->IsNotNullChunk(); tmp = tmp->GetPrevNcNnlNi()) // Issue #2279 - { - if ( tmp->IsSemicolon() - || tmp->Is(CT_BRACE_OPEN) - || tmp->Is(CT_VBRACE_OPEN)) - { - break; - } - make_type(tmp); - } - - return; // c-sharp_10160 - } - - if ( pc->Is(CT_ALIGN) - && tmp->IsNotNullChunk()) - { - if (tmp->Is(CT_BRACE_OPEN)) - { - set_paren_parent(tmp, pc->GetType()); - return; // d_40024 - } - else if (tmp->Is(CT_COLON)) - { - tmp->SetParentType(pc->GetType()); - return; // d_40024 - } - } - } // paren open + cast/align/delegate - - if (pc->Is(CT_INVARIANT)) - { - if (next->Is(CT_PAREN_OPEN)) - { - next->SetParentType(pc->GetType()); - Chunk *tmp = next->GetNext(); - - while (tmp->IsNotNullChunk()) - { - if (tmp->Is(CT_PAREN_CLOSE)) - { - tmp->SetParentType(pc->GetType()); - break; - } - make_type(tmp); - tmp = tmp->GetNext(); - } - return; // d_40100 - } - else - { - pc->SetType(CT_QUALIFIER); - return; - } - } - - if ( prev->Is(CT_BRACE_OPEN) - && prev->GetParentType() != CT_CS_PROPERTY - && ( pc->Is(CT_GETSET) - || pc->Is(CT_GETSET_EMPTY))) - { - flag_parens(prev, PCF_NONE, CT_NONE, CT_GETSET, false); - return; - } - - if (pc->Is(CT_ASM)) - { - flag_asm(pc); - return; - } - - // clang stuff - A new derived type is introduced to C and, by extension, Objective-C, C++, and Objective-C++ - if (language_is_set(LANG_C | LANG_CPP | LANG_OC)) - { - if (pc->Is(CT_CARET)) - { - if ( pc->TestFlags(PCF_EXPR_START) - || pc->TestFlags(PCF_IN_PREPROC)) - { - handle_oc_block_literal(pc); - return; - } - } - } - - // Objective C stuff - if (language_is_set(LANG_OC)) - { - // Check for message declarations - if (pc->TestFlags(PCF_STMT_START)) - { - if ( ( pc->IsString("-") - || pc->IsString("+")) - && next->IsString("(")) - { - handle_oc_message_decl(pc); - return; - } - } - - if ( pc->TestFlags(PCF_EXPR_START) - || pc->TestFlags(PCF_IN_PREPROC)) - { - if (pc->Is(CT_SQUARE_OPEN)) - { - handle_oc_message_send(pc); - - // Only return early if the '[' was determined to be an OC MSG - // Otherwise, it could have been a lambda capture list (ie '[&]') - if (pc->GetParentType() == CT_OC_MSG) - { - return; // objective-c_50003 - } - } - } - - if (pc->Is(CT_OC_PROPERTY)) - { - handle_oc_property_decl(pc); - return; - } - - if (pc->Is(CT_OC_AVAILABLE)) - { - handle_oc_available(pc); - return; - } - } - - // C# and Vala stuff - if (language_is_set(LANG_CS | LANG_VALA)) - { - // '[assembly: xxx]' stuff - if ( language_is_set(LANG_CS) - && pc->TestFlags(PCF_EXPR_START) - && pc->Is(CT_SQUARE_OPEN)) - { - handle_cs_square_stmt(pc); - return; - } - - if ( language_is_set(LANG_CS) - && next->Is(CT_BRACE_OPEN) - && next->GetParentType() == CT_NONE - && ( pc->Is(CT_SQUARE_CLOSE) - || pc->Is(CT_ANGLE_CLOSE) - || pc->Is(CT_WORD))) - { - handle_cs_property(next); - return; - } - - if ( pc->Is(CT_SQUARE_CLOSE) - && next->Is(CT_WORD)) - { - handle_cs_array_type(pc); - return; - } - - if ( ( pc->Is(CT_LAMBDA) - || pc->Is(CT_DELEGATE)) - && next->Is(CT_BRACE_OPEN)) - { - set_paren_parent(next, pc->GetType()); - return; - } - - if ( language_is_set(LANG_CS) - && pc->Is(CT_WHEN) - && pc->GetNext()->IsNotNullChunk() - && pc->GetNext()->IsNot(CT_SPAREN_OPEN)) - { - pc->SetType(CT_WORD); - return; - } - } - - if ( language_is_set(LANG_JAVA) - && pc->Is(CT_LAMBDA) - && next->Is(CT_BRACE_OPEN)) - { - set_paren_parent(next, pc->GetType()); - return; - } - - if (pc->Is(CT_NEW)) - { - Chunk *ts = Chunk::NullChunkPtr; - Chunk *tmp = next; - - if (tmp->Is(CT_TSQUARE)) - { - ts = tmp; - tmp = tmp->GetNextNcNnl(); - } - - if ( tmp->Is(CT_BRACE_OPEN) - || tmp->Is(CT_PAREN_OPEN)) - { - set_paren_parent(tmp, pc->GetType()); - - if (ts->IsNotNullChunk()) - { - ts->SetParentType(pc->GetType()); - } - } - return; - } - - // C++11 Lambda stuff - if ( language_is_set(LANG_CPP) - && ( pc->Is(CT_SQUARE_OPEN) - || pc->Is(CT_TSQUARE))) - { - handle_cpp_lambda(pc); - } - - // FIXME: which language does this apply to? - // Issue #2432 - if (!language_is_set(LANG_OC)) - { - if ( pc->Is(CT_ASSIGN) - && next->Is(CT_SQUARE_OPEN)) - { - set_paren_parent(next, CT_ASSIGN); - - // Mark one-liner assignment - Chunk *tmp = next; - - while ((tmp = tmp->GetNextNc())->IsNotNullChunk()) - { - if (tmp->IsNewline()) - { - break; - } - - if ( tmp->Is(CT_SQUARE_CLOSE) - && next->GetLevel() == tmp->GetLevel()) - { - tmp->SetFlagBits(PCF_ONE_LINER); - next->SetFlagBits(PCF_ONE_LINER); - break; - } - } - return; - } - } - - if (pc->Is(CT_ASSERT)) - { - handle_java_assert(pc); - return; - } - - if (pc->Is(CT_ANNOTATION)) - { - Chunk *tmp = pc->GetNextNcNnl(); - - if (tmp->IsParenOpen()) - { - set_paren_parent(tmp, CT_ANNOTATION); - } - return; - } - - if ( pc->Is(CT_SIZEOF) - && language_is_set(LANG_ALLC)) - { - Chunk *tmp = pc->GetNextNcNnl(); - - if (tmp->Is(CT_ELLIPSIS)) - { - tmp->SetParentType(CT_SIZEOF); - } - return; - } - - if ( pc->Is(CT_DECLTYPE) - && pc->GetParentType() != CT_FUNC_DEF) - { - Chunk *tmp = pc->GetNextNcNnl(); - - if (tmp->IsParenOpen()) - { - // decltype may be followed by a braced-init-list - tmp = set_paren_parent(tmp, CT_DECLTYPE); - - if (tmp->IsBraceOpen() && !pc->TestFlags(PCF_IN_LAMBDA)) - { - tmp = set_paren_parent(tmp, CT_BRACED_INIT_LIST); - - if (tmp->IsNotNullChunk()) - { - tmp->ResetFlagBits(PCF_EXPR_START | PCF_STMT_START); - } - } - else - { - if (tmp->Is(CT_WORD)) - { - tmp->SetFlagBits(PCF_VAR_1ST_DEF); - } - } - } - return; - } - - // A [] in C#, D and Vala only follows a type - if ( pc->Is(CT_TSQUARE) - && language_is_set(LANG_D | LANG_CS | LANG_VALA)) - { - if (prev->Is(CT_WORD)) - { - prev->SetType(CT_TYPE); - } - - if (next->Is(CT_WORD)) - { - next->SetFlagBits(PCF_VAR_1ST_DEF); - } - return; - } - - if ( pc->Is(CT_SQL_EXEC) - || pc->Is(CT_SQL_BEGIN) - || pc->Is(CT_SQL_END)) - { - mark_exec_sql(pc); - return; - } - - if (pc->Is(CT_PROTO_WRAP)) - { - handle_proto_wrap(pc); - return; - } - - // Handle the typedef - if (pc->Is(CT_TYPEDEF)) - { - fix_typedef(pc); - return; - } - - if ( pc->IsClassEnumStructOrUnion() - && prev->IsNot(CT_TYPEDEF)) - { - // Issue #3811 - // Sometimes the enum chunk can exist in a parameter (ie. `void foo(enum EnumType param)`) - // In this case we don't need to run the parser since we are not declaring an enum. - if (pc->IsEnum()) - { - const size_t level = pc->GetLevel(); - Chunk *tmp = pc; - - while (tmp->GetLevel() == level && tmp->IsNotNullChunk()) - { - tmp = tmp->GetNextNcNnl(); - } - - if (tmp->GetLevel() < level) - { - return; - } - } - EnumStructUnionParser parser; - parser.parse(pc); - return; - } - - if (pc->Is(CT_EXTERN)) - { - if (next->IsParenOpen()) - { - Chunk *tmp = flag_parens(next, PCF_NONE, CT_NONE, CT_EXTERN, true); - - if (tmp->Is(CT_BRACE_OPEN)) - { - set_paren_parent(tmp, CT_EXTERN); - } - } - else - { - // next likely is a string (see tokenize_cleanup.cpp) - next->SetParentType(CT_EXTERN); - Chunk *tmp = next->GetNextNcNnl(); - - if (tmp->Is(CT_BRACE_OPEN)) - { - set_paren_parent(tmp, CT_EXTERN); - } - } - return; - } - - if (pc->Is(CT_TEMPLATE)) - { - if (language_is_set(LANG_D)) - { - handle_d_template(pc); - } - else - { - handle_cpp_template(pc); - } - return; - } - - if ( pc->Is(CT_WORD) - && next->Is(CT_ANGLE_OPEN) - && next->GetParentType() == CT_TEMPLATE) - { - mark_template_func(pc, next); - return; - } - - if ( pc->Is(CT_SQUARE_CLOSE) - && next->Is(CT_PAREN_OPEN)) - { - flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_NONE, false); - return; - } - - if (pc->Is(CT_TYPE_CAST)) - { - fix_type_cast(pc); - return; - } - - if ( pc->GetParentType() == CT_ASSIGN - && ( pc->Is(CT_BRACE_OPEN) - || pc->Is(CT_SQUARE_OPEN))) - { - // Mark everything in here as in assign - flag_parens(pc, PCF_IN_ARRAY_ASSIGN, pc->GetType(), CT_NONE, false); - return; - } - - if (pc->Is(CT_D_TEMPLATE)) - { - set_paren_parent(next, pc->GetType()); - return; - } - - /* - * A word before an open paren is a function call or definition. - * CT_WORD => CT_FUNC_CALL or CT_FUNC_DEF - */ - if (next->Is(CT_PAREN_OPEN)) - { - Chunk *tmp = next->GetNextNcNnl(); - - if ( language_is_set(LANG_C | LANG_CPP | LANG_OC) - && tmp->Is(CT_CARET)) - { - handle_oc_block_type(tmp); - - // This is the case where a block literal is passed as the first argument of a C-style method invocation. - if ( ( tmp->Is(CT_OC_BLOCK_CARET) - || tmp->Is(CT_CARET)) - && pc->Is(CT_WORD)) - { - LOG_FMT(LFCN, "%s(%d): (1) SET TO CT_FUNC_CALL: orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - pc->SetType(CT_FUNC_CALL); - } - } - else if ( pc->Is(CT_WORD) - || pc->Is(CT_OPERATOR_VAL)) - { - pc->SetType(CT_FUNCTION); - } - else if (pc->Is(CT_FIXED)) - { - pc->SetType(CT_FUNCTION); - pc->SetParentType(CT_FIXED); - } - else if (pc->Is(CT_TYPE)) - { - /* - * If we are on a type, then we are either on a C++ style cast, an - * array reference, a function or we are on a function type. - * The only way to tell for sure is to find the close paren and see - * if it is followed by an open paren. - * "int(5.6)" - * "int()" - * "int(foo)(void)" - * - * FIXME: this check can be done better... - */ - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - - bool is_byref_array = false; - - if (language_is_set(LANG_CPP)) - { - // If the open paren is followed by an ampersand, an optional word, - // a close parenthesis, and an open square bracket, then it is an - // array being passed by reference, not a cast - tmp = next->GetNextNcNnl(); - - if (tmp->Is(CT_AMP)) - { - auto tmp2 = tmp->GetNextNcNnl(); - - if (tmp2->Is(CT_WORD)) - { - tmp2 = tmp2->GetNextNcNnl(); - } - - if (tmp2->Is(CT_PAREN_CLOSE)) - { - tmp2 = tmp2->GetNextNcNnl(); - - if (tmp2->Is(CT_SQUARE_OPEN)) - { - is_byref_array = true; - tmp->SetType(CT_BYREF); - } - } - } - } - - if (!is_byref_array) - { - tmp = next->GetNextType(CT_PAREN_CLOSE, next->GetLevel()); - - if (tmp->IsNotNullChunk()) - { - tmp = tmp->GetNext(); - - if (tmp->Is(CT_PAREN_OPEN)) - { - pc->SetType(CT_FUNCTION); - } - else - { - if ( pc->GetParentType() == CT_NONE - && !pc->TestFlags(PCF_IN_TYPEDEF)) - { - tmp = next->GetNextNcNnl(); - - if (tmp->Is(CT_PAREN_CLOSE)) - { - // we have TYPE() - pc->SetType(CT_FUNCTION); - } - else - { - // we have TYPE(...) - pc->SetType(CT_CPP_CAST); - set_paren_parent(next, CT_CPP_CAST); - } - } - } - } - } - } - } - - if (language_is_set(LANG_PAWN)) - { - if ( pc->Is(CT_FUNCTION) - && pc->GetBraceLevel() > 0) - { - LOG_FMT(LFCN, "%s(%d): (2) SET TO CT_FUNC_CALL: orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - pc->SetType(CT_FUNC_CALL); - } - - if ( pc->Is(CT_STATE) - && next->Is(CT_PAREN_OPEN)) - { - set_paren_parent(next, pc->GetType()); - } - } - else - { - if ( ( pc->Is(CT_FUNCTION) - || pc->Is(CT_FUNC_DEF)) - && ( (pc->GetParentType() == CT_OC_BLOCK_EXPR) - || !is_oc_block(pc))) - { - mark_function(pc); - } - } - - // Detect C99 member stuff - if ( pc->Is(CT_MEMBER) - && ( prev->Is(CT_COMMA) - || prev->Is(CT_BRACE_OPEN))) - { - pc->SetType(CT_C99_MEMBER); - next->SetParentType(CT_C99_MEMBER); - return; - } - - // Mark function parens and braces - if ( pc->Is(CT_FUNC_DEF) - || pc->Is(CT_FUNC_CALL) - || pc->Is(CT_FUNC_CALL_USER) - || pc->Is(CT_FUNC_PROTO)) - { - Chunk *tmp = next; - - if (tmp->Is(CT_SQUARE_OPEN)) - { - tmp = set_paren_parent(tmp, pc->GetType()); - } - else if ( tmp->Is(CT_TSQUARE) - || tmp->GetParentType() == CT_OPERATOR) - { - tmp = tmp->GetNextNcNnl(); - } - - if (tmp->IsNotNullChunk()) - { - if (tmp->IsParenOpen()) - { - tmp = flag_parens(tmp, PCF_NONE, CT_FPAREN_OPEN, pc->GetType(), false); - - if (tmp->IsNotNullChunk()) - { - if (tmp->Is(CT_BRACE_OPEN)) - { - if ( tmp->GetParentType() != CT_DOUBLE_BRACE - && !pc->TestFlags(PCF_IN_CONST_ARGS)) - { - set_paren_parent(tmp, pc->GetType()); - } - } - else if ( tmp->IsSemicolon() - && pc->Is(CT_FUNC_PROTO)) - { - tmp->SetParentType(pc->GetType()); - } - } - } - } - return; - } - - // Mark the parameters in catch() - if ( pc->Is(CT_CATCH) - && next->Is(CT_SPAREN_OPEN)) - { - fix_fcn_def_params(next); - return; - } - - if ( pc->Is(CT_THROW) - && prev->Is(CT_FPAREN_CLOSE)) - { - pc->SetParentType(prev->GetParentType()); - - if (next->Is(CT_PAREN_OPEN)) - { - set_paren_parent(next, CT_THROW); - } - return; - } - - // Mark the braces in: "for_each_entry(xxx) { }" - if ( pc->Is(CT_BRACE_OPEN) - && pc->GetParentType() != CT_DOUBLE_BRACE - && prev->Is(CT_FPAREN_CLOSE) - && ( prev->GetParentType() == CT_FUNC_CALL - || prev->GetParentType() == CT_FUNC_CALL_USER) - && !pc->TestFlags(PCF_IN_CONST_ARGS)) - { - LOG_FMT(LFCN, "%s(%d): (3) SET TO CT_FUNC_CALL: orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - set_paren_parent(pc, CT_FUNC_CALL); - return; - } - - /* - * Check for a close parenthesis followed by an open parenthesis, - * which means that we are on a function type declaration (C/C++ only?). - * Note that typedefs are already taken care of. - */ - if ( !pc->TestFlags(PCF_IN_TEMPLATE) // Issue #3252 - && pc->GetParentType() != CT_CPP_CAST - && pc->GetParentType() != CT_C_CAST - && !pc->TestFlags(PCF_IN_PREPROC) - && !is_oc_block(pc) - && pc->GetParentType() != CT_OC_MSG_DECL - && pc->GetParentType() != CT_OC_MSG_SPEC - && ( pc->IsString(")") - || pc->Is(CT_FUNC_TYPE)) - && next->IsString("(")) - { - if (language_is_set(LANG_D)) - { - flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_FUNC_CALL, false); - } - else - { - mark_function_type(pc); - } - return; - } - - if (pc->Is(CT_OC_CLASS)) - { - handle_oc_class(pc); - return; - } - // TODO: Check for stuff that can only occur at the start of an statement - - if (!language_is_set(LANG_D)) - { - /* - * Check a parenthesis pair to see if it is a cast. - * Note that SPAREN and FPAREN have already been marked. - */ - if ( pc->Is(CT_PAREN_OPEN) - && ( pc->GetParentType() == CT_NONE - || pc->GetParentType() == CT_OC_MSG - || pc->GetParentType() == CT_OC_BLOCK_EXPR - || pc->GetParentType() == CT_CS_SQ_STMT) // Issue # 1256 - && ( next->Is(CT_WORD) - || next->Is(CT_TYPE) - || next->Is(CT_STRUCT) - || next->Is(CT_QUALIFIER) - || next->Is(CT_MEMBER) - || next->Is(CT_DC_MEMBER) - || next->Is(CT_ENUM) - || next->Is(CT_UNION)) - && prev->IsNot(CT_DECLTYPE) - && prev->IsNot(CT_SIZEOF) - && prev->GetParentType() != CT_SIZEOF - && prev->GetParentType() != CT_OPERATOR - && !pc->TestFlags(PCF_IN_TYPEDEF)) - { - fix_casts(pc); - return; - } - } - - if (language_is_set(LANG_CPP)) - { - Chunk *nnext = next->GetNextNcNnl(); - - // handle parent_type of assigns in special functions (ro5 + pure virtual) - if ( pc->GetFlags().test_any(PCF_IN_STRUCT | PCF_IN_CLASS) - && pc->Is(CT_ASSIGN) - && nnext->Is(CT_SEMICOLON) - && ( next->Is(CT_DEFAULT) - || next->Is(CT_DELETE) - || ( next->Is(CT_NUMBER) - && next->IsString("0")))) - { - const size_t level = pc->GetLevel(); - bool found_status = false; - Chunk *pprev = pc->GetPrev(); - - for ( ; ( pprev->IsNotNullChunk() - && pprev->GetLevel() >= level - && pprev->IsNot(CT_SEMICOLON) - && pprev->IsNot(CT_ACCESS_COLON)) - ; pprev = pprev->GetPrev()) - { - if (pprev->GetLevel() != level) - { - continue; - } - - if (next->Is(CT_NUMBER)) - { - if ( pprev->Is(CT_QUALIFIER) - && pprev->IsString("virtual")) - { - found_status = true; - break; - } - } - else - { - if ( pprev->Is(CT_FUNC_CLASS_PROTO) // ctor/dtor - || pprev->Is(CT_FUNC_PROTO)) // normal function - { - found_status = true; - break; - } - } - } - - if (found_status) - { - pc->SetParentType(pprev->GetType()); - } - } - - if (detect_cpp_braced_init_list(pc, next)) - { - flag_cpp_braced_init_list(pc, next); - } - } - - // Check for stuff that can only occur at the start of an expression - if ( pc->TestFlags(PCF_EXPR_START) - || ( prev->TestFlags(PCF_EXPR_START) - && pc->GetParentType() == CT_OC_AT)) - { - // Change STAR, MINUS, and PLUS in the easy cases - if (pc->Is(CT_STAR)) - { - // issue #596 - // [0x100062020:IN_SPAREN,IN_FOR,STMT_START,EXPR_START,PUNCTUATOR] - // prev->GetType() is CT_COLON ==> CT_DEREF - if (prev->Is(CT_ANGLE_CLOSE)) - { - pc->SetType(CT_PTR_TYPE); - } - else if (prev->Is(CT_COLON)) - { - pc->SetType(CT_DEREF); - } - else - { - pc->SetType(CT_DEREF); - } - } - - if ( language_is_set(LANG_CPP) - && pc->Is(CT_CARET) - && prev->Is(CT_ANGLE_CLOSE)) - { - pc->SetType(CT_PTR_TYPE); - } - - if ( language_is_set(LANG_CS | LANG_VALA) - && pc->Is(CT_QUESTION) - && prev->Is(CT_ANGLE_CLOSE)) - { - pc->SetType(CT_PTR_TYPE); - } - - else if (pc->Is(CT_MINUS)) - { - pc->SetType(CT_NEG); - } - - else if (pc->Is(CT_PLUS)) - { - pc->SetType(CT_POS); - } - - else if (pc->Is(CT_INCDEC_AFTER)) - { - pc->SetType(CT_INCDEC_BEFORE); - } - - else if (pc->Is(CT_AMP)) - { - if (prev->Is(CT_ANGLE_CLOSE)) // Issue #2324 - { - pc->SetType(CT_BYREF); - } - else - { - pc->SetType(CT_ADDR); - } - } - - else if (pc->Is(CT_CARET)) - { - if (language_is_set(LANG_C | LANG_CPP | LANG_OC)) - { - // This is likely the start of a block literal - handle_oc_block_literal(pc); - } - } - } - - /* - * Change the parenthesis pair after a function/macro-function - * CT_PAREN_OPEN => CT_FPAREN_OPEN - */ - if (pc->Is(CT_MACRO_FUNC)) - { - flag_parens(next, PCF_IN_FCN_CALL, CT_FPAREN_OPEN, CT_MACRO_FUNC, false); - } - - if ( pc->Is(CT_MACRO_OPEN) - || pc->Is(CT_MACRO_ELSE) - || pc->Is(CT_MACRO_CLOSE)) - { - if (next->Is(CT_PAREN_OPEN)) - { - flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, pc->GetType(), false); - } - } - - if ( pc->Is(CT_DELETE) - && next->Is(CT_TSQUARE)) - { - next->SetParentType(CT_DELETE); - } - - // Change CT_STAR to CT_PTR_TYPE or CT_ARITH or CT_DEREF - if ( pc->Is(CT_STAR) - || ( language_is_set(LANG_CPP) - && pc->Is(CT_CARET))) - { - if ( next->IsParenClose() - || next->Is(CT_COMMA)) - { - pc->SetType(CT_PTR_TYPE); - } - else if ( language_is_set(LANG_OC) - && next->Is(CT_STAR)) - { - /* - * Change pointer-to-pointer types in OC_MSG_DECLs - * from ARITH <===> DEREF to PTR_TYPE <===> PTR_TYPE - */ - pc->SetType(CT_PTR_TYPE); - pc->SetParentType(prev->GetParentType()); - - next->SetType(CT_PTR_TYPE); - next->SetParentType(pc->GetParentType()); - } - else if ( pc->Is(CT_STAR) - && ( prev->Is(CT_DECLTYPE) - || prev->Is(CT_SIZEOF) - || prev->Is(CT_DELETE) - || pc->GetParentType() == CT_SIZEOF)) - { - pc->SetType(CT_DEREF); - } - else if ( ( prev->Is(CT_WORD) - && chunk_ends_type(prev) - && !prev->TestFlags(PCF_IN_FCN_CTOR) - && !prev->TestFlags(PCF_IN_ARRAY_ASSIGN)) // Issue #3345 - || prev->Is(CT_DC_MEMBER) - || prev->Is(CT_PTR_TYPE)) - { - LOG_FMT(LFCNR, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n ", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); - log_pcf_flags(LFCNR, pc->GetFlags()); - pc->SetType(CT_PTR_TYPE); - } - else if ( next->Is(CT_SQUARE_OPEN) - && !language_is_set(LANG_OC)) // Issue #408 - { - pc->SetType(CT_PTR_TYPE); - } - else if (pc->Is(CT_STAR)) - { - // Add check for CT_DC_MEMBER CT_WORD CT_STAR sequence - // to convert CT_WORD into CT_TYPE - // and CT_STAR into CT_PTR_TYPE - // look for an assign backward, function call, return to distinguish between - // double result = Constants::PI * factor; - // and - // ::some::name * foo; - if ( prev->Is(CT_WORD) - && prev->GetPrev()->Is(CT_DC_MEMBER) - && language_is_set(LANG_CPP)) - { - // Issue 1402 - bool is_multiplication = false; - Chunk *tmp = pc; - - while (tmp->IsNotNullChunk()) - { - if ( tmp->Is(CT_SEMICOLON) - || tmp->GetParentType() == CT_CLASS) - { - break; - } - else if ( tmp->Is(CT_ASSIGN) - || tmp->Is(CT_FUNC_CALL) - || tmp->Is(CT_RETURN)) - { - is_multiplication = true; - break; - } - tmp = tmp->GetPrevNcNnlNi(); // Issue #2279 - } - - if (is_multiplication) - { - // double result = Constants::PI * factor; - pc->SetType(CT_ARITH); - } - else - { - // ::some::name * foo; - prev->SetType(CT_TYPE); - pc->SetType(CT_PTR_TYPE); - } - } - - /* - * A star can have three meanings - * 1. CT_DEREF = pointer dereferencing - * 2. CT_PTR_TYPE = pointer definition - * 3. CT_ARITH = arithmetic multiplication - * - * most PCF_PUNCTUATOR chunks except a paren close would make this - * a deref. A paren close may end a cast or may be part of a macro fcn. - */ - if (prev->Is(CT_TYPE)) - { - pc->SetType(CT_PTR_TYPE); - } - else if ( pc->GetNext()->Is(CT_SEMICOLON) // Issue #2319 - || ( pc->GetNext()->Is(CT_STAR) - && pc->GetNext()->GetNext()->Is(CT_SEMICOLON))) - { - // example: - // using AbstractLinkPtr = AbstractLink*; - // using AbstractLinkPtrPtr = AbstractLink**; - pc->SetType(CT_PTR_TYPE); - } - else if ( ( pc->GetParentType() == CT_FUNC_DEF - && ( next->IsBraceOpen() - || pc->GetNext()->IsStar())) - || next->Is(CT_QUALIFIER)) // Issue #2648 - { - // example: - // auto getComponent(Color *color) -> Component * { - // auto getComponent(Color *color) -> Component ** { - // auto getComponent(Color *color) -> Component * _Nonnull - // only to help the vim command }} - pc->SetType(CT_PTR_TYPE); - } - else if ( pc->GetNext()->Is(CT_SEMICOLON) // Issue #2319 - || ( pc->GetNext()->Is(CT_STAR) - && pc->GetNext()->GetNext()->Is(CT_STAR))) - { - // more pointers are NOT yet possible - fprintf(stderr, "Too many pointers: the maximum level of pointer indirection is 3 (i.e., ***p)\n"); - fprintf(stderr, "at line %zu, column %zu.\n", pc->GetOrigLine(), pc->GetOrigCol()); - fprintf(stderr, "Please make a report.\n"); - log_flush(true); - exit(EX_SOFTWARE); - } - else if ( !prev->TestFlags(PCF_PUNCTUATOR) - || prev->Is(CT_INCDEC_AFTER) - || prev->Is(CT_SQUARE_CLOSE) - || prev->Is(CT_DC_MEMBER)) // Issue 1402 - { - pc->SetType(CT_ARITH); - } - else if ( !prev->IsParenClose() - || prev->Is(CT_SPAREN_CLOSE) - || prev->GetParentType() == CT_MACRO_FUNC) - { - pc->SetType(CT_DEREF); - } - else - { - pc->SetType(CT_ARITH); - } - - if (pc->TestFlags(PCF_IN_TYPEDEF)) // Issue #1255/#633 - { - Chunk *tmp = pc; - - while (tmp->IsNotNullChunk()) - { - if ( tmp->Is(CT_SEMICOLON) - || tmp->Is(CT_BRACE_OPEN) - || tmp->Is(CT_SQUARE_OPEN)) // Issue #3342 - { - break; - } - else if (tmp->Is(CT_TYPEDEF)) - { - pc->SetType(CT_PTR_TYPE); - } - tmp = tmp->GetPrevNcNnlNi(); // Issue #2279 - } - } - } - } - - if (pc->Is(CT_AMP)) - { - Chunk *prevNext = prev->GetNext(); - - if (prev->Is(CT_DELETE)) - { - pc->SetType(CT_ADDR); - } - else if ( prev->Is(CT_TYPE) - || prev->Is(CT_QUALIFIER) - || prevNext->Is(CT_QUALIFIER)) - { - pc->SetType(CT_BYREF); - } - else if ( prev->Is(CT_WORD) // Issue #3204 - && next->Is(CT_OPERATOR)) - { - pc->SetType(CT_BYREF); - } - else if ( next->Is(CT_FPAREN_CLOSE) - || next->Is(CT_COMMA)) - { - // fix the bug #654 - // connect(&mapper, SIGNAL(mapped(QString &)), this, SLOT(onSomeEvent(QString &))); - pc->SetType(CT_BYREF); - } - else if (pc->GetParentType() == CT_USING_ALIAS) - { - // fix the Issue # 1689 - // using reference = value_type &; - pc->GetPrev()->SetType(CT_TYPE); - pc->SetType(CT_BYREF); - } - else - { - // Issue # 1398 - if ( pc->TestFlags(PCF_IN_FCN_DEF) - && prev->Is(CT_WORD) - && pc->Is(CT_AMP) - && next->Is(CT_WORD)) - { - /* - * Change CT_WORD before CT_AMP before CT_WORD to CT_TYPE - */ - prev->SetType(CT_TYPE); - } - else if ( pc->TestFlags(PCF_IN_PREPROC) // Issue #3559 - && prev->IsNot(CT_WORD) // Issue #2205 - && pc->Is(CT_AMP) - && next->Is(CT_WORD) - && !pc->TestFlags(PCF_IN_SPAREN)) - { - pc->SetType(CT_ADDR); - } - else - { - pc->SetType(CT_ARITH); - - if ( prev->Is(CT_WORD) - && next->IsNot(CT_NUMBER)) // Issue #3407 - { - Chunk *tmp = prev->GetPrevNcNnlNi(); // Issue #2279 - - if (tmp->IsNotNullChunk()) - { - if ( tmp->IsSemicolon() - || tmp->Is(CT_BRACE_OPEN) - || tmp->Is(CT_QUALIFIER)) - { - pc->SetType(CT_BYREF); - prev->SetType(CT_TYPE); - - if (!( next->Is(CT_OPERATOR) - || next->Is(CT_TYPE) - || next->Is(CT_DC_MEMBER))) - { - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', set PCF_VAR_1ST\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - next->SetFlagBits(PCF_VAR_1ST); - } - } - else if (tmp->Is(CT_DC_MEMBER)) - { - // see also Issue #3967 - // Issue #2103 & Issue #3865: partial fix - // No easy way to tell between an enum and a type with - // a namespace qualifier. Compromise: if we're in a - // function def or call, assume it's a ref. - Chunk *nextNext = next->GetNext(); - - if ( nextNext->IsNot(CT_DC_MEMBER) - && ( pc->TestFlags(PCF_IN_FCN_CALL) - || pc->TestFlags(PCF_IN_FCN_CTOR) - || pc->TestFlags(PCF_IN_FCN_DEF))) - { - pc->SetType(CT_BYREF); - } - else - { - prev->SetType(CT_TYPE); - } - } - } - } - } - } - } - - if ( pc->Is(CT_MINUS) - || pc->Is(CT_PLUS)) - { - if ( prev->Is(CT_POS) - || prev->Is(CT_NEG) - || prev->Is(CT_ARITH) - || prev->Is(CT_SHIFT)) - { - pc->SetType(pc->Is(CT_MINUS) ? CT_NEG : CT_POS); - } - else if (prev->Is(CT_OC_CLASS)) - { - pc->SetType((pc->Is(CT_MINUS)) ? CT_NEG : CT_POS); - } - else - { - pc->SetType(CT_ARITH); - } - } - - /* - * Bug # 634 - * Check for extern "C" NSString* i; - * NSString is a type - * change CT_WORD => CT_TYPE for pc - * change CT_STAR => CT_PTR_TYPE for pc-next - */ - if (pc->Is(CT_WORD)) // here NSString - { - Chunk *pcNext = pc->GetNext(); - Chunk *pcPrev = pc->GetPrev(); - - if (pcNext->Is(CT_STAR)) // here * - { - // compare text with "C" to find extern "C" instructions - if (pcPrev->Is(CT_STRING)) - { - if (UncText::compare(pcPrev->Text(), "\"C\"") == 0) - { - if (pcPrev->GetPrev()->Is(CT_EXTERN)) - { - pc->SetType(CT_TYPE); // change CT_WORD => CT_TYPE - pcNext->SetType(CT_PTR_TYPE); // change CT_STAR => CT_PTR_TYPE - } - } - } - // Issue #322 STDMETHOD(GetValues)(BSTR bsName, REFDATA** pData); - Chunk *nnext = pcNext->GetNext(); - - if ( nnext->Is(CT_STAR) - && pc->TestFlags(PCF_IN_CONST_ARGS)) - { - // change CT_STAR => CT_PTR_TYPE - pcNext->SetType(CT_PTR_TYPE); - nnext->SetType(CT_PTR_TYPE); - } - - // Issue #222 whatever3 *(func_ptr)( whatever4 *foo2, ... - if ( nnext->Is(CT_WORD) - && pc->TestFlags(PCF_IN_FCN_DEF)) - { - // look for the opening parenthesis - // Issue 1403 - Chunk *tmp = pc->GetPrevType(CT_FPAREN_OPEN, pc->GetLevel() - 1); - - if ( tmp->IsNotNullChunk() - && tmp->GetParentType() != CT_FUNC_CTOR_VAR) - { - pcNext->SetType(CT_PTR_TYPE); - } - } - } - } - - /* - * Bug # 634 - * Check for __attribute__((visibility ("default"))) NSString* i; - * NSString is a type - * change CT_WORD => CT_TYPE for pc - * change CT_STAR => CT_PTR_TYPE for pc-next - */ - if (pc->Is(CT_WORD)) // here NSString - { - Chunk *pcNext = pc->GetNext(); - - if (pcNext->Is(CT_STAR)) // here * - { - Chunk *tmp = pc; - - while (tmp->IsNotNullChunk()) - { - if (tmp->Is(CT_ATTRIBUTE)) - { - LOG_FMT(LFCNR, "%s(%d): ATTRIBUTE found, type is %s, Text() '%s'\n", - __func__, __LINE__, get_token_name(tmp->GetType()), tmp->Text()); - LOG_FMT(LFCNR, "for token, type is %s, Text() '%s'\n", get_token_name(pc->GetType()), pc->Text()); - // change CT_WORD => CT_TYPE - pc->SetType(CT_TYPE); - // change CT_STAR => CT_PTR_TYPE - pcNext->SetType(CT_PTR_TYPE); - } - - if (tmp->TestFlags(PCF_STMT_START)) - { - // we are at beginning of the line - break; - } - tmp = tmp->GetPrev(); - } - } - } - - /* - * Issue # 1689 - * Check for using reference = value_type&; - * is it a Type alias, alias template? - */ - if (pc->Is(CT_USING)) - { - // look for CT_ASSIGN before CT_SEMICOLON at the end of the statement - - bool is_preproc = pc->TestFlags(PCF_IN_PREPROC); - auto const search_assign = [&pc, &is_preproc]() - { - for (Chunk *temp = pc; temp->IsNotNullChunk(); temp = temp->GetNextNcNnl()) - { - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", - __func__, __LINE__, temp->GetOrigLine(), temp->GetOrigCol(), - temp->Text(), get_token_name(temp->GetType())); - - if (temp->Is(CT_ASSIGN)) - { - return(true); - } - - if ( temp->Is(CT_SEMICOLON) - || ( is_preproc - && ( !temp->TestFlags(PCF_IN_PREPROC) - || temp->Is(CT_PREPROC)))) - { - return(false); - } - } - - return(false); - }; - - const bool assign_found = language_is_set(LANG_D) || search_assign(); - - if (assign_found) - { - // it is a Type alias, alias template - for (Chunk *temp = pc; temp->IsNotNullChunk(); temp = temp->GetNextNcNnl()) - { - if (temp->GetParentType() == CT_NONE) - { - temp->SetParentType(CT_USING_ALIAS); - } - - if ( temp->Is(CT_SEMICOLON) - || ( is_preproc - && ( !temp->TestFlags(PCF_IN_PREPROC) - || temp->Is(CT_PREPROC)))) - { - break; - } - } - } - } - - // Issue #548: inline T && someFunc(foo * *p, bar && q) { } - if ( pc->Is(CT_BOOL) - && !pc->TestFlags(PCF_IN_PREPROC) - && pc->IsString("&&") - && chunk_ends_type(pc->GetPrev())) - { - Chunk *tmp = pc->GetPrev(); // Issue #2688 - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", - __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), - tmp->Text(), get_token_name(tmp->GetType())); - log_pcf_flags(LFCNR, tmp->GetFlags()); - // look for a type - - if (tmp->Is(CT_TYPE)) - { - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), - pc->Text(), get_token_name(pc->GetType())); - log_pcf_flags(LFCNR, pc->GetFlags()); - pc->SetType(CT_BYREF); - } - // look next, is there a "assign" before the ";" - Chunk *semi = pc->GetNextType(CT_SEMICOLON, pc->GetLevel()); // Issue #2688 - - if (semi->IsNotNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", - __func__, __LINE__, semi->GetOrigLine(), semi->GetOrigCol(), - semi->Text(), get_token_name(semi->GetType())); - - for (Chunk *test_it = pc; test_it != semi; test_it = test_it->GetNext()) - { - LOG_FMT(LFCNR, "%s(%d): test_it orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", - __func__, __LINE__, test_it->GetOrigLine(), test_it->GetOrigCol(), - test_it->Text(), get_token_name(test_it->GetType())); - - if (test_it->Is(CT_ASSIGN)) - { - // the statement is an assignment - // && is before assign - pc->SetType(CT_BYREF); - break; - } - } - } - } - - // Issue #1704 - if ( pc->Is(CT_INCDEC_AFTER) - && pc->TestFlags(PCF_IN_PREPROC)) - { - Chunk *tmp_2 = pc->GetNext(); - LOG_FMT(LFCNR, "%s(%d): orig line is %zu, orig col is %zu, Text() '%s', type is %s\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), - pc->Text(), get_token_name(pc->GetType())); - log_pcf_flags(LFTYPE, pc->GetFlags()); - - if (tmp_2->Is(CT_WORD)) - { - pc->SetType(CT_INCDEC_BEFORE); - } - } -} // do_symbol_check - - -static void check_double_brace_init(Chunk *bo1) -{ - LOG_FUNC_ENTRY(); - LOG_FMT(LJDBI, "%s(%d): orig line is %zu, orig col is %zu", __func__, __LINE__, bo1->GetOrigLine(), bo1->GetOrigCol()); - Chunk *pc = bo1->GetPrevNcNnlNi(); // Issue #2279 - - if (pc->IsNullChunk()) - { - return; - } - - if (pc->IsParenClose()) - { - Chunk *bo2 = bo1->GetNext(); - - if (bo2->IsNullChunk()) - { - return; - } - - if (bo2->Is(CT_BRACE_OPEN)) - { - // found a potential double brace - Chunk *bc2 = bo2->GetClosingParen(); - - if (bc2->IsNullChunk()) - { - return; - } - Chunk *bc1 = bc2->GetNext(); - - if (bc1->IsNullChunk()) - { - return; - } - - if (bc1->Is(CT_BRACE_CLOSE)) - { - LOG_FMT(LJDBI, " - end, orig line is %zu, orig col is %zu\n", bc2->GetOrigLine(), bc2->GetOrigCol()); - // delete bo2 and bc1 - bo1->Str() += bo2->GetStr(); - bo1->SetOrigColEnd(bo2->GetOrigColEnd()); - Chunk::Delete(bo2); - bo1->SetParentType(CT_DOUBLE_BRACE); - - bc2->Str() += bc1->GetStr(); - bc2->SetOrigColEnd(bc1->GetOrigColEnd()); - Chunk::Delete(bc1); - bc2->SetParentType(CT_DOUBLE_BRACE); - return; - } - } - } - LOG_FMT(LJDBI, " - no\n"); -} // check_double_brace_init - - -void fix_symbols() -{ - LOG_FUNC_ENTRY(); - Chunk *pc; - - cpd.unc_stage = unc_stage_e::FIX_SYMBOLS; - - mark_define_expressions(); - - bool is_cpp = language_is_set(LANG_CPP); - bool is_java = language_is_set(LANG_JAVA); - - for (pc = Chunk::GetHead(); pc->IsNotNullChunk(); pc = pc->GetNextNcNnl()) - { - LOG_FMT(LFCNR, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); - - if ( pc->Is(CT_FUNC_WRAP) - || pc->Is(CT_TYPE_WRAP)) - { - handle_wrap(pc); - } - - if (pc->Is(CT_ASSIGN)) - { - mark_lvalue(pc); - } - // a brace immediately preceded by word in C++11 is an initializer list though it may also - // by a type casting initializer list if the word is really a type; sadly uncrustify knows - // only built-in types and knows nothing of user-defined types - Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279 - - if ( is_cpp - && pc->Is(CT_BRACE_OPEN) - && ( prev->Is(CT_WORD) - || prev->Is(CT_TYPE))) - { - mark_lvalue(pc); - } - - if ( is_java - && pc->Is(CT_BRACE_OPEN)) - { - check_double_brace_init(pc); - } - - if (pc->Is(CT_ATTRIBUTE)) - { - Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC); - - if ( next->IsNotNullChunk() - && next->Is(CT_PAREN_OPEN)) - { - flag_parens(next, PCF_NONE, CT_FPAREN_OPEN, CT_ATTRIBUTE, false); - } - } - } - - pc = Chunk::GetHead(); - - if (pc->IsCommentOrNewline()) - { - pc = pc->GetNextNcNnl(); - } - - while (pc->IsNotNullChunk()) - { - if (pc->Is(CT_IGNORED)) - { - pc = pc->GetNextNcNnl(); - continue; - } - LOG_FMT(LFCNR, "%s(%d): pc orig line %zu, orig col %zu, text '%s', type %s\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text(), get_token_name(pc->GetType())); - Chunk *prev = pc->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #2279 - - if (prev->Is(CT_QUALIFIER)) - { - prev = prev->GetPrevNcNnlNi(E_Scope::PREPROC); // Issue #3513 - } - - if (prev->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): prev is NOT defined\n", __func__, __LINE__); - } - else - { - // Issue #2279 - LOG_FMT(LFCNR, "%s(%d): prev(ni) orig line %zu, orig col %zu, text '%s', type %s\n", - __func__, __LINE__, prev->GetOrigLine(), prev->GetOrigCol(), prev->Text(), get_token_name(prev->GetType())); - } - Chunk *next = pc->GetNextNcNnl(E_Scope::PREPROC); - - if (next->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): next is NOT defined\n", __func__, __LINE__); - } - else - { - // Issue #2279 - LOG_FMT(LFCNR, "%s(%d): next orig line %zu, orig col %zu, text '%s', type %s\n", - __func__, __LINE__, next->GetOrigLine(), next->GetOrigCol(), next->Text(), get_token_name(next->GetType())); - } - LOG_FMT(LFCNR, "%s(%d): do_symbol_check for '%s, %s, %s'\n", - __func__, __LINE__, prev->Text(), pc->Text(), next->Text()); - do_symbol_check(prev, pc, next); - pc = pc->GetNextNcNnl(); - } - pawn_add_virtual_semicolons(); - process_returns_and_throws(); - - /* - * 2nd pass - handle variable definitions - * REVISIT: We need function params marked to do this (?) - */ - pc = Chunk::GetHead(); - int square_level = -1; - - while (pc->IsNotNullChunk()) - { - char copy[1000]; - LOG_FMT(LFCNR, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s, parent type is %s\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()), get_token_name(pc->GetParentType())); - - // Can't have a variable definition inside [ ] - if (square_level < 0) - { - if (pc->Is(CT_SQUARE_OPEN)) - { - square_level = pc->GetLevel(); - } - } - else - { - if (pc->GetLevel() <= static_cast<size_t>(square_level)) - { - square_level = -1; - } - } - - if ( pc->Is(CT_EXTERN) - && language_is_set(LANG_ALLC)) - { - Chunk *next = pc->GetNextNcNnl(); - - if (next->Is(CT_STRING)) - { - Chunk *tmp = next->GetNextNcNnl(); - - while (tmp->IsNotNullChunk()) - { - if ( tmp->Is(CT_TYPE) - || tmp->Is(CT_BRACE_OPEN) - || tmp->Is(CT_ATTRIBUTE)) - { - break; - } - - if (tmp->Is(CT_WORD)) - { - tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START); - log_ruleStart("start statement/ expression", tmp); - break; - } - tmp = tmp->GetNextNcNnl(); - } - } - } - - if ( pc->Is(CT_ATTRIBUTE) - && language_is_set(LANG_ALLC)) - { - Chunk *tmp = skip_attribute_next(pc); - - if (tmp->Is(CT_WORD)) - { - tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START); - log_ruleStart("start statement/ expression", tmp); - } - } - - if ( pc->Is(CT_BRACE_OPEN) // Issue #2332 - && pc->GetParentType() == CT_BRACED_INIT_LIST) - { - LOG_FMT(LFCNR, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', look for CT_BRACE_OPEN\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - pc = pc->GetNextType(CT_BRACE_CLOSE, pc->GetLevel()); - } - /* - * A variable definition is possible after at the start of a statement - * that starts with: DC_MEMBER, QUALIFIER, TYPE, or WORD - */ - // Issue #2279 - // Issue #2478 - LOG_FMT(LFCNR, "%s(%d): pc orig line is %zu, orig col is %zu, Text() is '%s', type is %s, parent type is %s\n ", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->ElidedText(copy), get_token_name(pc->GetType()), get_token_name(pc->GetParentType())); - log_pcf_flags(LFCNR, pc->GetFlags()); - - if ( (square_level < 0) - && pc->TestFlags(PCF_STMT_START) - && ( pc->Is(CT_QUALIFIER) - || pc->Is(CT_TYPE) - || pc->Is(CT_TYPENAME) - || pc->Is(CT_DC_MEMBER) // Issue #2478 - || ( pc->Is(CT_WORD) - && !pc->TestFlags(PCF_IN_CONDITIONAL) // Issue #3558 -// && language_is_set(LANG_CPP) - ) - ) - && pc->GetParentType() != CT_BIT_COLON - && pc->GetParentType() != CT_ENUM_COLON // Issue #4040 - && pc->GetParentType() != CT_ENUM - && !pc->TestFlags(PCF_IN_CLASS_BASE) - && !pc->TestFlags(PCF_IN_ENUM)) - { - pc = fix_variable_definition(pc); - } - else - { - pc = pc->GetNextNcNnl(); - } - } -} // fix_symbols - - -static void process_returns_and_throws() -{ - LOG_FUNC_ENTRY(); - Chunk *pc; - - pc = Chunk::GetHead(); - - while (pc->IsNotNullChunk()) - { - if ( pc->Is(CT_RETURN) - || pc->Is(CT_THROW)) - { - pc = process_return_or_throw(pc); - } - else - { - pc = pc->GetNext(); - } - } -} - - -static Chunk *process_return_or_throw(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - - const char *nl_expr_name; - iarf_e nl_expr_value; - const char *mod_paren_name; - iarf_e mod_paren_value; - - if (pc->Is(CT_RETURN)) - { - nl_expr_name = "nl_return_expr"; - nl_expr_value = options::nl_return_expr(); - mod_paren_name = "mod_paren_on_return"; - mod_paren_value = options::mod_paren_on_return(); - } - else if (pc->Is(CT_THROW)) - { - nl_expr_name = "nl_throw_expr"; - nl_expr_value = options::nl_throw_expr(); - mod_paren_name = "mod_paren_on_throw"; - mod_paren_value = options::mod_paren_on_throw(); - } - else // should never happen - { - return(pc->GetNext()); - } - Chunk *next; - Chunk *temp; - Chunk *semi; - Chunk *cpar; - Chunk chunk; - - // grab next and bail if it is a semicolon - next = pc->PpaGetNextNcNnl(); - - if ( next->IsNullChunk() - || next->IsSemicolon() - || next->Is(CT_NEWLINE)) - { - return(next); - } - log_rule_B(nl_expr_name); - - if ( nl_expr_value != IARF_IGNORE - && !pc->TestFlags(PCF_IN_PREPROC)) - { - newline_iarf(pc, nl_expr_value); - } - - if (next->Is(CT_PAREN_OPEN)) - { - // See if the return/throw is fully paren'd - cpar = next->GetNextType(CT_PAREN_CLOSE, next->GetLevel()); - - if (cpar->IsNullChunk()) - { - return(Chunk::NullChunkPtr); - } - semi = cpar->PpaGetNextNcNnl(); - - if (semi->IsNullChunk()) - { - return(Chunk::NullChunkPtr); - } - - if ( semi->Is(CT_NEWLINE) - || semi->IsSemicolon()) - { - log_rule_B(mod_paren_name); - - if (mod_paren_value == IARF_REMOVE) - { - LOG_FMT(LRETURN, "%s(%d): removing parens on orig line %zu\n", - __func__, __LINE__, pc->GetOrigLine()); - - // lower the level of everything - for (temp = next; temp != cpar; temp = temp->GetNext()) - { - if (temp->GetLevel() == 0) - { - fprintf(stderr, "%s(%d): temp->GetLevel() is ZERO, cannot be decremented, at line %zu, column %zu\n", - __func__, __LINE__, temp->GetOrigLine(), temp->GetOrigCol()); - log_flush(true); - exit(EX_SOFTWARE); - } - temp->SetLevel(temp->GetLevel() - 1); - } - - // delete the parenthesis - Chunk::Delete(next); - Chunk::Delete(cpar); - - // back up following chunks - temp = semi; - - while ( temp->IsNotNullChunk() - && temp->IsNot(CT_NEWLINE)) - { - temp->SetColumn(temp->GetColumn() - 2); - temp->SetOrigCol(temp->GetOrigCol() - 2); - temp->SetOrigColEnd(temp->GetOrigColEnd() - 2); - temp = temp->GetNext(); - } - } - else - { - LOG_FMT(LRETURN, "%s(%d): keeping parens on orig line %zu\n", - __func__, __LINE__, pc->GetOrigLine()); - - // mark & keep them - next->SetParentType(pc->GetType()); - cpar->SetParentType(pc->GetType()); - } - return(semi); - } - } - // We don't have a fully paren'd return/throw. Should we add some? - log_rule_B(mod_paren_name); - - if (!(mod_paren_value & IARF_ADD)) - { - return(next); - } - - // Issue #1917 - // Never add parens to a braced init list; that breaks the code - // return {args...}; // C++11 type elision; okay - // return ({args...}); // ill-formed - if ( language_is_set(LANG_CPP) - && next->Is(CT_BRACE_OPEN) - && next->GetParentType() == CT_BRACED_INIT_LIST) - { - LOG_FMT(LRETURN, "%s(%d): not adding parens around braced initializer" - " on orig line %zd\n", - __func__, __LINE__, pc->GetOrigLine()); - return(next); - } - // find the next semicolon on the same level - semi = next; - - if (pc->TestFlags(PCF_IN_PREPROC)) - { - while ((semi = semi->GetNext())->IsNotNullChunk()) - { - if (!semi->TestFlags(PCF_IN_PREPROC)) - { - break; - } - - if (semi->GetLevel() < pc->GetLevel()) - { - return(semi); - } - - if ( semi->IsSemicolon() - && pc->GetLevel() == semi->GetLevel()) - { - break; - } - } - } - else - { - while ((semi = semi->GetNext())->IsNotNullChunk()) - { - if (semi->GetLevel() < pc->GetLevel()) - { - return(semi); - } - - if ( semi->IsSemicolon() - && pc->GetLevel() == semi->GetLevel()) - { - break; - } - } - } - - if (semi->IsNotNullChunk()) - { - // add the parenthesis - chunk.SetType(CT_PAREN_OPEN); - chunk.SetParentType(pc->GetType()); - chunk.Str() = "("; - chunk.SetLevel(pc->GetLevel()); - chunk.SetPpLevel(pc->GetPpLevel()); - chunk.SetBraceLevel(pc->GetBraceLevel()); - chunk.SetOrigLine(pc->GetOrigLine()); - chunk.SetOrigCol(next->GetOrigCol() - 1); - chunk.SetFlags(pc->GetFlags() & PCF_COPY_FLAGS); - chunk.CopyAndAddBefore(next); - - chunk.SetType(CT_PAREN_CLOSE); - chunk.Str() = ")"; - chunk.SetOrigLine(semi->GetOrigLine()); - chunk.SetOrigCol(semi->GetOrigCol() - 1); - cpar = chunk.CopyAndAddBefore(semi); - - LOG_FMT(LRETURN, "%s(%d): added parens on orig line %zu\n", - __func__, __LINE__, pc->GetOrigLine()); - - for (temp = next; temp != cpar; temp = temp->GetNext()) - { - temp->SetLevel(temp->GetLevel() + 1); - } - } - return(semi); -} // process_return_or_throw - - -static bool is_oc_block(Chunk *pc) -{ - return( pc->GetParentType() == CT_OC_BLOCK_TYPE - || pc->GetParentType() == CT_OC_BLOCK_EXPR - || pc->GetParentType() == CT_OC_BLOCK_ARG - || pc->GetParentType() == CT_OC_BLOCK - || pc->Is(CT_OC_BLOCK_CARET) - || pc->GetNext()->Is(CT_OC_BLOCK_CARET) - || pc->GetPrev()->Is(CT_OC_BLOCK_CARET)); -} - - -void mark_comments() -{ - LOG_FUNC_ENTRY(); - - cpd.unc_stage = unc_stage_e::MARK_COMMENTS; - - bool prev_nl = true; - Chunk *cur = Chunk::GetHead(); - - while (cur->IsNotNullChunk()) - { - Chunk *next = cur->GetNextNvb(); - bool next_nl = next->IsNullChunk() || next->IsNewline(); - - if (cur->IsComment()) - { - if ( next_nl - && prev_nl) - { - cur->SetParentType(CT_COMMENT_WHOLE); - } - else if (next_nl) - { - cur->SetParentType(CT_COMMENT_END); - } - else if (prev_nl) - { - cur->SetParentType(CT_COMMENT_START); - } - else - { - cur->SetParentType(CT_COMMENT_EMBED); - } - } - prev_nl = cur->IsNewline(); - cur = next; - } -} - - -static void handle_cpp_template(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - - Chunk *tmp = pc->GetNextNcNnl(); - - if (tmp->IsNot(CT_ANGLE_OPEN)) - { - return; - } - tmp->SetParentType(CT_TEMPLATE); - - size_t level = tmp->GetLevel(); - - tmp = tmp->GetNext(); - - while (tmp->IsNotNullChunk()) - { - if ( tmp->Is(CT_CLASS) - || tmp->Is(CT_STRUCT)) - { - tmp->SetType(CT_TYPE); - } - else if ( tmp->Is(CT_ANGLE_CLOSE) - && tmp->GetLevel() == level) - { - tmp->SetParentType(CT_TEMPLATE); - break; - } - tmp = tmp->GetNext(); - } - - if (tmp->IsNotNullChunk()) - { - tmp = tmp->GetNextNcNnl(); - - if (tmp->Is(CT_FRIEND)) - { - // Account for a template friend declaration - tmp->SetParentType(CT_TEMPLATE); - - tmp = tmp->GetNextNcNnl(); - } - - if (tmp->IsClassOrStruct()) - { - tmp->SetParentType(CT_TEMPLATE); - - // REVISIT: This may be a bit risky - might need to track the { }; - tmp = tmp->GetNextType(CT_SEMICOLON, tmp->GetLevel()); - - if (tmp->IsNotNullChunk()) - { - tmp->SetParentType(CT_TEMPLATE); - } - } - } -} // handle_cpp_template - - -static void handle_cpp_lambda(Chunk *sq_o) -{ - LOG_FUNC_ENTRY(); - - Chunk *ret = Chunk::NullChunkPtr; - - // abort if type of the previous token is not contained in this whitelist - Chunk *prev = sq_o->GetPrevNcNnlNi(); // Issue #2279 - - if (prev->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): prev is null chunk\n", __func__, __LINE__); - } - - if ( prev->IsNullChunk() - || ( prev->IsNot(CT_ASSIGN) - && prev->IsNot(CT_COMMA) - && prev->IsNot(CT_PAREN_OPEN) // allow Js like self invoking lambda syntax: ([](){})(); - && prev->IsNot(CT_FPAREN_OPEN) - && prev->IsNot(CT_SQUARE_OPEN) - && prev->IsNot(CT_BRACE_OPEN) - && prev->IsNot(CT_SEMICOLON) - && prev->IsNot(CT_RETURN))) - { - LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__); - return; - } - Chunk *sq_c = sq_o; // assuming '[]' - - if (sq_o->Is(CT_SQUARE_OPEN)) - { - // make sure there is a ']' - sq_c = sq_o->GetClosingParen(); - - if (sq_c->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__); - return; - } - } - Chunk *pa_o = sq_c->GetNextNcNnl(); - - // check to see if there is a lambda-specifier in the pa_o chunk; - // assuming chunk is CT_EXECUTION_CONTEXT, ignore lambda-specifier - while (pa_o->Is(CT_EXECUTION_CONTEXT)) - { - // set pa_o to next chunk after this specifier - pa_o = pa_o->GetNextNcNnl(); - } - - if (pa_o->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__); - return; - } - Chunk *pa_c = Chunk::NullChunkPtr; - - // lambda-declarator '( params )' is optional - if (pa_o->Is(CT_PAREN_OPEN)) - { - // and now find the ')' - pa_c = pa_o->GetClosingParen(); - - if (pa_c->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__); - return; - } - } - // Check for 'mutable' keyword: '[]() mutable {}' or []() mutable -> ret {} - Chunk *br_o = pa_c->IsNotNullChunk() ? pa_c->GetNextNcNnl() : pa_o; - - if (br_o->IsString("mutable")) - { - br_o = br_o->GetNextNcNnl(); - } - //TODO: also check for exception and attribute between [] ... {} - - // skip possible arrow syntax: '-> ret' - if (br_o->IsString("->")) - { - ret = br_o; - // REVISIT: really should check the stuff we are skipping - br_o = br_o->GetNextType(CT_BRACE_OPEN, br_o->GetLevel()); - } - - // skip possible CT_NOEXCEPT - if (br_o->Is(CT_NOEXCEPT)) // Issue #3321 - { - ret = br_o; - // REVISIT: really should check the stuff we are skipping - br_o = br_o->GetNextType(CT_BRACE_OPEN, br_o->GetLevel()); - } - - if (br_o->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): br_o is null. Return\n", __func__, __LINE__); - return; - } - - if (br_o->IsNot(CT_BRACE_OPEN)) - { - LOG_FMT(LFCNR, "%s(%d): br_o is '%s'/%s\n", - __func__, __LINE__, - br_o->Text(), get_token_name(br_o->GetType())); - LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__); - return; - } - // and now find the '}' - Chunk *br_c = br_o->GetClosingParen(); - - if (br_c->IsNullChunk()) - { - LOG_FMT(LFCNR, "%s(%d): return\n", __func__, __LINE__); - return; - } - - // This looks like a lambda expression - if (sq_o->Is(CT_TSQUARE)) - { - // split into two chunks - Chunk nc; - - nc = *sq_o; - sq_o->SetType(CT_SQUARE_OPEN); - sq_o->Str().resize(1); - /* - * bug # 664 - * - * The original m_origCol of CT_SQUARE_CLOSE is stored at m_origColEnd - * of CT_TSQUARE. CT_SQUARE_CLOSE m_origCol and m_origColEnd values - * are calculate from m_origColEnd of CT_TSQUARE. - */ - nc.SetOrigCol(sq_o->GetOrigColEnd() - 1); - nc.SetColumn(nc.GetOrigCol()); - nc.SetOrigColEnd(sq_o->GetOrigColEnd()); - sq_o->SetOrigColEnd(sq_o->GetOrigCol() + 1); - - nc.SetType(CT_SQUARE_CLOSE); - nc.Str().pop_front(); - sq_c = nc.CopyAndAddAfter(sq_o); - } - sq_o->SetParentType(CT_CPP_LAMBDA); - sq_c->SetParentType(CT_CPP_LAMBDA); - - if (pa_c->IsNotNullChunk()) - { - pa_o->SetType(CT_LPAREN_OPEN); // Issue #3054 - pa_o->SetParentType(CT_CPP_LAMBDA); - pa_o->SetParent(sq_o); - br_o->SetParent(sq_o); - pa_c->SetType(CT_LPAREN_CLOSE); - pa_c->SetParentType(CT_CPP_LAMBDA); - pa_c->SetParent(sq_o); - br_c->SetParent(sq_o); - } - br_o->SetParentType(CT_CPP_LAMBDA); - br_c->SetParentType(CT_CPP_LAMBDA); - - if (ret->IsNotNullChunk()) - { - ret->SetType(CT_CPP_LAMBDA_RET); - ret = ret->GetNextNcNnl(); - - while (ret != br_o) - { - make_type(ret); - ret = ret->GetNextNcNnl(); - } - } - - if (pa_c->IsNotNullChunk()) - { - fix_fcn_def_params(pa_o); - } - //handle self calling lambda paren - Chunk *call_pa_o = br_c->GetNextNcNnl(); - - if (call_pa_o->Is(CT_PAREN_OPEN)) - { - Chunk *call_pa_c = call_pa_o->GetClosingParen(); - - if (call_pa_c->IsNotNullChunk()) - { - call_pa_o->SetType(CT_FPAREN_OPEN); - call_pa_o->SetParentType(CT_FUNC_CALL); - call_pa_c->SetType(CT_FPAREN_CLOSE); - call_pa_c->SetParentType(CT_FUNC_CALL); - } - } - mark_cpp_lambda(sq_o); -} // handle_cpp_lambda - - -static void handle_d_template(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - - Chunk *name = pc->GetNextNcNnl(); - Chunk *po = name->GetNextNcNnl(); - - if ( name->IsNullChunk() - || name->IsNot(CT_WORD)) - { - // TODO: log an error, expected NAME - return; - } - - if ( po->IsNullChunk() - || po->IsNot(CT_PAREN_OPEN)) - { - // TODO: log an error, expected '(' - return; - } - name->SetType(CT_TYPE); - name->SetParentType(CT_TEMPLATE); - po->SetParentType(CT_TEMPLATE); - - ChunkStack cs; - Chunk *tmp = get_d_template_types(cs, po); - - if ( tmp->IsNullChunk() - || tmp->IsNot(CT_PAREN_CLOSE)) - { - // TODO: log an error, expected ')' - return; - } - tmp->SetParentType(CT_TEMPLATE); - - tmp = tmp->GetNextNcNnl(); - - if (tmp->IsNot(CT_BRACE_OPEN)) - { - // TODO: log an error, expected '{' - return; - } - tmp->SetParentType(CT_TEMPLATE); - po = tmp; - tmp = tmp->GetNextNcNnl(); - - while ( tmp->IsNotNullChunk() - && tmp->GetLevel() > po->GetLevel()) - { - if ( tmp->Is(CT_WORD) - && chunkstack_match(cs, tmp)) - { - tmp->SetType(CT_TYPE); - } - tmp = tmp->GetNextNcNnl(); - } -// if (!tmp->Is(CT_BRACE_CLOSE)) -// { -// // TODO: log an error, expected '}' -// } - tmp->SetParentType(CT_TEMPLATE); -} // handle_d_template - - -Chunk *skip_template_next(Chunk *ang_open) -{ - if (ang_open->Is(CT_ANGLE_OPEN)) - { - Chunk *pc = ang_open->GetNextType(CT_ANGLE_CLOSE, ang_open->GetLevel()); - - if (pc->IsNullChunk()) - { - return(Chunk::NullChunkPtr); - } - return(pc->GetNextNcNnl()); - } - return(ang_open); -} - - -static void handle_oc_class(Chunk *pc) -{ - enum class angle_state_e : unsigned int - { - NONE = 0, - OPEN = 1, // '<' found - CLOSE = 2, // '>' found - }; - - LOG_FUNC_ENTRY(); - Chunk *tmp; - bool hit_scope = false; - bool passed_name = false; // Did we pass the name of the class and now there can be only protocols, not generics - int generic_level = 0; // level of depth of generic - angle_state_e as = angle_state_e::NONE; - - LOG_FMT(LOCCLASS, "%s(%d): start [%s] [%s] line %zu\n", - __func__, __LINE__, pc->Text(), get_token_name(pc->GetParentType()), pc->GetOrigLine()); - - if (pc->GetParentType() == CT_OC_PROTOCOL) - { - tmp = pc->GetNextNcNnl(); - - if (tmp->IsSemicolon()) - { - tmp->SetParentType(pc->GetParentType()); - LOG_FMT(LOCCLASS, "%s(%d): bail on semicolon\n", __func__, __LINE__); - return; - } - } - tmp = pc; - - while ((tmp = tmp->GetNextNnl())->IsNotNullChunk()) - { - LOG_FMT(LOCCLASS, "%s(%d): orig line is %zu, [%s]\n", - __func__, __LINE__, tmp->GetOrigLine(), tmp->Text()); - - if (tmp->Is(CT_OC_END)) - { - break; - } - - if (tmp->Is(CT_PAREN_OPEN)) - { - passed_name = true; - } - - if (tmp->IsString("<")) - { - tmp->SetType(CT_ANGLE_OPEN); - - if (passed_name) - { - tmp->SetParentType(CT_OC_PROTO_LIST); - } - else - { - tmp->SetParentType(CT_OC_GENERIC_SPEC); - generic_level++; - } - as = angle_state_e::OPEN; - } - - if (tmp->IsString(">")) - { - tmp->SetType(CT_ANGLE_CLOSE); - - if (passed_name) - { - tmp->SetParentType(CT_OC_PROTO_LIST); - as = angle_state_e::CLOSE; - } - else - { - tmp->SetParentType(CT_OC_GENERIC_SPEC); - - if (generic_level == 0) - { - fprintf(stderr, "%s(%d): generic_level is ZERO, cannot be decremented, at line %zu, column %zu\n", - __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol()); - log_flush(true); - exit(EX_SOFTWARE); - } - generic_level--; - - if (generic_level == 0) - { - as = angle_state_e::CLOSE; - } - } - } - - if (tmp->IsString(">>")) - { - tmp->SetType(CT_ANGLE_CLOSE); - tmp->SetParentType(CT_OC_GENERIC_SPEC); - split_off_angle_close(tmp); - generic_level -= 1; - - if (generic_level == 0) - { - as = angle_state_e::CLOSE; - } - } - - if ( tmp->Is(CT_BRACE_OPEN) - && tmp->GetParentType() != CT_ASSIGN) - { - as = angle_state_e::CLOSE; - tmp->SetParentType(CT_OC_CLASS); - tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->GetLevel()); - - if ( tmp->IsNotNullChunk() - && tmp->GetParentType() != CT_ASSIGN) - { - tmp->SetParentType(CT_OC_CLASS); - } - } - else if (tmp->Is(CT_COLON)) - { - if (as != angle_state_e::OPEN) - { - passed_name = true; - } - tmp->SetType(hit_scope ? CT_OC_COLON : CT_CLASS_COLON); - - if (tmp->Is(CT_CLASS_COLON)) - { - tmp->SetParentType(CT_OC_CLASS); - } - } - else if ( tmp->IsString("-") - || tmp->IsString("+")) - { - as = angle_state_e::CLOSE; - - if (tmp->GetPrev()->IsNewline()) - { - tmp->SetType(CT_OC_SCOPE); - tmp->SetFlagBits(PCF_STMT_START); - log_ruleStart("start statement", tmp); - hit_scope = true; - } - } - - if (as == angle_state_e::OPEN) - { - if (passed_name) - { - tmp->SetParentType(CT_OC_PROTO_LIST); - } - else - { - tmp->SetParentType(CT_OC_GENERIC_SPEC); - } - } - } - - if (tmp->Is(CT_BRACE_OPEN)) - { - tmp = tmp->GetNextType(CT_BRACE_CLOSE, tmp->GetLevel()); - - if (tmp->IsNotNullChunk()) - { - tmp->SetParentType(CT_OC_CLASS); - } - } -} // handle_oc_class - - -static void handle_oc_block_literal(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - - Chunk *prev = pc->GetPrevNcNnlNi(); // Issue #2279 - Chunk *next = pc->GetNextNcNnl(); - - if ( prev->IsNullChunk() - || next->IsNullChunk()) - { - return; // let's be paranoid - } - /* - * block literal: '^ RTYPE ( ARGS ) { }' - * RTYPE and ARGS are optional - */ - LOG_FMT(LOCBLK, "%s(%d): block literal @ orig line is %zu, orig col is %zu\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); - - Chunk *apo = Chunk::NullChunkPtr; // arg paren open - Chunk *bbo = Chunk::NullChunkPtr; // block brace open - Chunk *bbc; // block brace close - - LOG_FMT(LOCBLK, "%s(%d): + scan", __func__, __LINE__); - Chunk *tmp; - - for (tmp = next; tmp->IsNotNullChunk(); tmp = tmp->GetNextNcNnl()) - { - /* handle '< protocol >' */ - if (tmp->IsString("<")) - { - Chunk *ao = tmp; - Chunk *ac = ao->GetNextString(">", 1, ao->GetLevel()); - - if (ac->IsNotNullChunk()) - { - ao->SetType(CT_ANGLE_OPEN); - ao->SetParentType(CT_OC_PROTO_LIST); - ac->SetType(CT_ANGLE_CLOSE); - ac->SetParentType(CT_OC_PROTO_LIST); - - for (tmp = ao->GetNext(); tmp != ac; tmp = tmp->GetNext()) - { - tmp->SetLevel(tmp->GetLevel() + 1); - tmp->SetParentType(CT_OC_PROTO_LIST); - } - - tmp = ac->GetNextNcNnl(); - } - else - { - tmp = Chunk::NullChunkPtr; - } - } - LOG_FMT(LOCBLK, " '%s'", tmp->Text()); - - if ( tmp->GetLevel() < pc->GetLevel() - || tmp->Is(CT_SEMICOLON)) - { - LOG_FMT(LOCBLK, "[DONE]"); - break; - } - - if (tmp->GetLevel() == pc->GetLevel()) - { - if (tmp->IsParenOpen()) - { - apo = tmp; - LOG_FMT(LOCBLK, "[PAREN]"); - } - - if (tmp->Is(CT_BRACE_OPEN)) - { - LOG_FMT(LOCBLK, "[BRACE]"); - bbo = tmp; - break; - } - } - } - - // make sure we have braces - bbc = bbo->GetClosingParen(); - - if ( bbo->IsNullChunk() - || bbc->IsNullChunk()) - { - LOG_FMT(LOCBLK, " -- no braces found\n"); - return; - } - LOG_FMT(LOCBLK, "\n"); - - // we are on a block literal for sure - pc->SetType(CT_OC_BLOCK_CARET); - pc->SetParentType(CT_OC_BLOCK_EXPR); - - // handle the optional args - Chunk *lbp; // last before paren - end of return type, if any - - if (apo->IsNotNullChunk()) - { - Chunk *apc = apo->GetClosingParen(); // arg parenthesis close - - if (apc->IsParenClose()) - { - LOG_FMT(LOCBLK, " -- marking parens @ apo orig line is %zu, orig col is %zu and apc orig line is %zu, orig col is %zu\n", - apo->GetOrigLine(), apo->GetOrigCol(), apc->GetOrigLine(), apc->GetOrigCol()); - flag_parens(apo, PCF_OC_ATYPE, CT_FPAREN_OPEN, CT_OC_BLOCK_EXPR, true); - fix_fcn_def_params(apo); - } - lbp = apo->GetPrevNcNnlNi(); // Issue #2279 - } - else - { - lbp = bbo->GetPrevNcNnlNi(); // Issue #2279 - } - - // mark the return type, if any - while (lbp != pc) - { - LOG_FMT(LOCBLK, " -- lbp %s[%s]\n", lbp->Text(), get_token_name(lbp->GetType())); - make_type(lbp); - lbp->SetFlagBits(PCF_OC_RTYPE); - lbp->SetParentType(CT_OC_BLOCK_EXPR); - lbp = lbp->GetPrevNcNnlNi(); // Issue #2279 - } - // mark the braces - bbo->SetParentType(CT_OC_BLOCK_EXPR); - bbc->SetParentType(CT_OC_BLOCK_EXPR); - - // mark the OC_BLOCK - for (Chunk *tmp1 = bbo; tmp1 != bbc; tmp1 = tmp1->GetNextNcNnl()) - { - tmp1->SetFlagBits(PCF_OC_IN_BLOCK); - } -} // handle_oc_block_literal - - -static void handle_oc_block_type(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - - if (pc->IsNullChunk()) - { - return; - } - - if (pc->TestFlags(PCF_IN_TYPEDEF)) - { - LOG_FMT(LOCBLK, "%s(%d): skip block type @ orig line is %zu, orig col is %zu, -- in typedef\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); - return; - } - // make sure we have '( ^' - Chunk *tpo = pc->GetPrevNcNnlNi(); // type paren open Issue #2279 - - if (tpo->IsParenOpen()) - { - /* - * block type: 'RTYPE (^LABEL)(ARGS)' - * LABEL is optional. - */ - Chunk *tpc = tpo->GetClosingParen(); // type close paren (after '^') - Chunk *nam = tpc->GetPrevNcNnlNi(); // name (if any) or '^' Issue #2279 - Chunk *apo = tpc->GetNextNcNnl(); // arg open paren - Chunk *apc = apo->GetClosingParen(); // arg close paren - - /* - * If this is a block literal instead of a block type, 'nam' - * will actually be the closing bracket of the block. We run into - * this situation if a block literal is enclosed in parentheses. - */ - if (nam->IsBraceClose()) - { - return(handle_oc_block_literal(pc)); - } - - // Check apo is '(' or else this might be a block literal. Issue 2643. - if (!apo->IsParenOpen()) - { - return(handle_oc_block_literal(pc)); - } - - if (apc->IsParenClose()) - { - Chunk *aft = apc->GetNextNcNnl(); - E_Token pt; - - if (nam->IsString("^")) - { - nam->SetType(CT_PTR_TYPE); - pt = CT_FUNC_TYPE; - } - else if ( aft->Is(CT_ASSIGN) - || aft->Is(CT_SEMICOLON)) - { - nam->SetType(CT_FUNC_VAR); - pt = CT_FUNC_VAR; - } - else - { - nam->SetType(CT_FUNC_TYPE); - pt = CT_FUNC_TYPE; - } - LOG_FMT(LOCBLK, "%s(%d): block type @ orig line is %zu, orig col is %zu, Text() '%s'[%s]\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), nam->Text(), get_token_name(nam->GetType())); - pc->SetType(CT_PTR_TYPE); - pc->SetParentType(pt); //CT_OC_BLOCK_TYPE; - tpo->SetType(CT_TPAREN_OPEN); - tpo->SetParentType(pt); //CT_OC_BLOCK_TYPE; - tpc->SetType(CT_TPAREN_CLOSE); - tpc->SetParentType(pt); //CT_OC_BLOCK_TYPE; - apo->SetType(CT_FPAREN_OPEN); - apo->SetParentType(CT_FUNC_PROTO); - apc->SetType(CT_FPAREN_CLOSE); - apc->SetParentType(CT_FUNC_PROTO); - fix_fcn_def_params(apo); - mark_function_return_type(nam, tpo->GetPrevNcNnlNi(), pt); // Issue #2279 - } - } -} // handle_oc_block_type - - -static Chunk *handle_oc_md_type(Chunk *paren_open, E_Token ptype, PcfFlags flags, bool &did_it) -{ - Chunk *paren_close; - - if ( !paren_open->IsParenOpen() - || ((paren_close = paren_open->GetClosingParen())->IsNullChunk())) - { - did_it = false; - return(paren_open); - } - did_it = true; - - paren_open->SetParentType(ptype); - paren_open->SetFlagBits(flags); - paren_close->SetParentType(ptype); - paren_close->SetFlagBits(flags); - - for (Chunk *cur = paren_open->GetNextNcNnl(); - cur != paren_close; - cur = cur->GetNextNcNnl()) - { - LOG_FMT(LOCMSGD, " <%s|%s>", cur->Text(), get_token_name(cur->GetType())); - cur->SetFlagBits(flags); - make_type(cur); - } - - // returning the chunk after the paren close - return(paren_close->GetNextNcNnl()); -} - - -static void handle_oc_message_decl(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - - bool did_it; - //bool in_paren = false; - //int paren_cnt = 0; - //int arg_cnt = 0; - - // Figure out if this is a spec or decl - Chunk *tmp = pc; - - while ((tmp = tmp->GetNext())->IsNotNullChunk()) - { - if (tmp->GetLevel() < pc->GetLevel()) - { - // should not happen - return; - } - - if ( tmp->Is(CT_SEMICOLON) - || tmp->Is(CT_BRACE_OPEN)) - { - break; - } - } - - if (tmp->IsNullChunk()) - { - return; - } - E_Token pt = tmp->Is(CT_SEMICOLON) ? CT_OC_MSG_SPEC : CT_OC_MSG_DECL; - - pc->SetType(CT_OC_SCOPE); - pc->SetParentType(pt); - - LOG_FMT(LOCMSGD, "%s(%d): %s @ orig line is %zu, orig col is %zu -", - __func__, __LINE__, get_token_name(pt), pc->GetOrigLine(), pc->GetOrigCol()); - - // format: -(TYPE) NAME [: (TYPE)NAME - - // handle the return type - tmp = handle_oc_md_type(pc->GetNextNcNnl(), pt, PCF_OC_RTYPE, did_it); - - if (!did_it) - { - LOG_FMT(LOCMSGD, " -- missing type parens\n"); - return; - } - - // expect the method name/label - if (tmp->IsNot(CT_WORD)) - { - LOG_FMT(LOCMSGD, " -- missing method name\n"); - return; - } // expect the method name/label - - Chunk *label = tmp; - - tmp->SetType(pt); - tmp->SetParentType(pt); - pc = tmp->GetNextNcNnl(); - - LOG_FMT(LOCMSGD, " [%s]%s", pc->Text(), get_token_name(pc->GetType())); - - // if we have a colon next, we have args - if ( pc->Is(CT_COLON) - || pc->Is(CT_OC_COLON)) - { - pc = label; - - while (true) - { - // skip optional label - if ( pc->Is(CT_WORD) - || pc->Is(pt)) - { - pc->SetParentType(pt); - pc = pc->GetNextNcNnl(); - } - - // a colon must be next - if (!pc->IsString(":")) - { - break; - } - pc->SetType(CT_OC_COLON); - pc->SetParentType(pt); - pc = pc->GetNextNcNnl(); - - // next is the type in parens - LOG_FMT(LOCMSGD, " (%s)", pc->Text()); - tmp = handle_oc_md_type(pc, pt, PCF_OC_ATYPE, did_it); - - if (!did_it) - { - LOG_FMT(LWARN, "%s(%d): orig line is %zu, orig col is %zu expected type\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol()); - break; - } - // attributes for a method parameter sit between the parameter type and the parameter name - pc = skip_attribute_next(tmp); - // we should now be on the arg name - pc->SetFlagBits(PCF_VAR_DEF); - LOG_FMT(LOCMSGD, " arg[%s]", pc->Text()); - pc = pc->GetNextNcNnl(); - } - } - LOG_FMT(LOCMSGD, " end[%s]", pc->Text()); - - if (pc->Is(CT_BRACE_OPEN)) - { - pc->SetParentType(pt); - pc = pc->GetClosingParen(); - - if (pc->IsNotNullChunk()) - { - pc->SetParentType(pt); - } - } - else if (pc->Is(CT_SEMICOLON)) - { - pc->SetParentType(pt); - } - LOG_FMT(LOCMSGD, "\n"); -} // handle_oc_message_decl - - -static void handle_oc_message_send(Chunk *os) -{ - LOG_FUNC_ENTRY(); - - Chunk *cs = os->GetNext(); - - while ( cs->IsNotNullChunk() - && cs->GetLevel() > os->GetLevel()) - { - cs = cs->GetNext(); - } - - if ( cs->IsNullChunk() - || cs->IsNot(CT_SQUARE_CLOSE)) - { - return; - } - LOG_FMT(LOCMSG, "%s(%d): orig line is %zu, orig col is %zu\n", - __func__, __LINE__, os->GetOrigLine(), os->GetOrigCol()); - - Chunk *tmp = cs->GetNextNcNnl(); - - if (tmp->IsSemicolon()) - { - tmp->SetParentType(CT_OC_MSG); - } - // expect a word first thing or [...] - tmp = os->GetNextNcNnl(); - - if ( tmp->Is(CT_SQUARE_OPEN) - || tmp->Is(CT_PAREN_OPEN) - || tmp->Is(CT_OC_AT)) - { - Chunk *tt = tmp->GetNextNcNnl(); - - if ( tmp->Is(CT_OC_AT) - && tt->IsNotNullChunk()) - { - if ( tt->Is(CT_PAREN_OPEN) - || tt->Is(CT_BRACE_OPEN) - || tt->Is(CT_SQUARE_OPEN)) - { - tmp = tt; - } - else - { - LOG_FMT(LOCMSG, "%s(%d): tmp orig line is %zu, orig col is %zu, expected identifier, not '%s' [%s]\n", - __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), - tmp->Text(), get_token_name(tmp->GetType())); - return; - } - } - tmp = tmp->GetClosingParen(); - } - else if ( tmp->IsNot(CT_WORD) - && tmp->IsNot(CT_TYPE) - && tmp->IsNot(CT_THIS) - && tmp->IsNot(CT_STAR) - && tmp->IsNot(CT_STRING)) - { - LOG_FMT(LOCMSG, "%s(%d): orig line is %zu, orig col is %zu, expected identifier, not '%s' [%s]\n", - __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), - tmp->Text(), get_token_name(tmp->GetType())); - return; - } - else - { - if (tmp->IsStar()) // Issue #2722 - { - tmp->SetType(CT_PTR_TYPE); - tmp = tmp->GetNextNcNnl(); - } - Chunk *tt = tmp->GetNextNcNnl(); - - if (tt->IsParenOpen()) - { - LOG_FMT(LFCN, "%s(%d): (18) SET TO CT_FUNC_CALL: orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, tmp->GetOrigLine(), tmp->GetOrigCol(), tmp->Text()); - tmp->SetType(CT_FUNC_CALL); - tmp = set_paren_parent(tt, CT_FUNC_CALL)->GetPrevNcNnlNi(); // Issue #2279 - } - else - { - tmp->SetType(CT_OC_MSG_CLASS); - } - } - os->SetParentType(CT_OC_MSG); - os->SetFlagBits(PCF_IN_OC_MSG); - cs->SetParentType(CT_OC_MSG); - cs->SetFlagBits(PCF_IN_OC_MSG); - - // handle '< protocol >' - tmp = tmp->GetNextNcNnl(); - - if (tmp->IsString("<")) - { - Chunk *ao = tmp; - Chunk *ac = ao->GetNextString(">", 1, ao->GetLevel()); - - if (ac->IsNotNullChunk()) - { - ao->SetType(CT_ANGLE_OPEN); - ao->SetParentType(CT_OC_PROTO_LIST); - ac->SetType(CT_ANGLE_CLOSE); - ac->SetParentType(CT_OC_PROTO_LIST); - - for (tmp = ao->GetNext(); tmp != ac; tmp = tmp->GetNext()) - { - tmp->SetLevel(tmp->GetLevel() + 1); - tmp->SetParentType(CT_OC_PROTO_LIST); - } - - tmp = ac->GetNextNcNnl(); - } - else - { - tmp = Chunk::NullChunkPtr; - } - } - // handle 'object.property' and 'collection[index]' - else - { - while (tmp->IsNotNullChunk()) - { - if (tmp->Is(CT_MEMBER)) // move past [object.prop1.prop2 - { - Chunk *typ = tmp->GetNextNcNnl(); - - if ( typ->Is(CT_WORD) - || typ->Is(CT_TYPE)) - { - tmp = typ->GetNextNcNnl(); - } - else - { - break; - } - } - else if (tmp->Is(CT_SQUARE_OPEN)) // move past [collection[index] - { - Chunk *tcs = tmp->GetNextNcNnl(); - - while ( tcs->IsNotNullChunk() - && tcs->GetLevel() > tmp->GetLevel()) - { - tcs = tcs->GetNextNcNnl(); - } - - if (tcs->Is(CT_SQUARE_CLOSE)) - { - tmp = tcs->GetNextNcNnl(); - } - else - { - break; - } - } - else - { - break; - } - } - } - - // [(self.foo.bar) method] - if (tmp->IsParenOpen()) - { - tmp = tmp->GetClosingParen()->GetNextNcNnl(); - } - - if ( tmp->Is(CT_WORD) - || tmp->Is(CT_ACCESS) - || tmp->Is(CT_TYPE)) - { - tmp->SetType(CT_OC_MSG_FUNC); - } - Chunk *prev = Chunk::NullChunkPtr; - - for (tmp = os->GetNext(); tmp != cs; tmp = tmp->GetNext()) - { - tmp->SetFlagBits(PCF_IN_OC_MSG); - - if (tmp->GetLevel() == cs->GetLevel() + 1) - { - if ( tmp->Is(CT_COLON) - || tmp->Is(CT_ACCESS_COLON)) - { - tmp->SetType(CT_OC_COLON); - - if ( prev->Is(CT_WORD) - || prev->Is(CT_ACCESS) - || prev->Is(CT_TYPE)) - { - // Might be a named param, check previous block - Chunk *pp = prev->GetPrev(); - - if ( pp->IsNotNullChunk() - && pp->IsNot(CT_OC_COLON) - && pp->IsNot(CT_ARITH) - && pp->IsNot(CT_SHIFT) - && pp->IsNot(CT_CARET)) - { - prev->SetType(CT_OC_MSG_NAME); - tmp->SetParentType(CT_OC_MSG_NAME); - } - } - } - } - prev = tmp; - } -} // handle_oc_message_send - - -static void handle_oc_available(Chunk *os) -{ - os = os->GetNext(); - - while (os->IsNotNullChunk()) - { - E_Token origType = os->GetType(); - os->SetType(CT_OC_AVAILABLE_VALUE); - - if (origType == CT_PAREN_CLOSE) - { - break; - } - os = os->GetNext(); - } -} - - -static void handle_oc_property_decl(Chunk *os) -{ - log_rule_B("mod_sort_oc_properties"); - - if (options::mod_sort_oc_properties()) - { - typedef std::vector<Chunk *> ChunkGroup; - - Chunk *next = os->GetNext(); - Chunk *open_paren = Chunk::NullChunkPtr; - - std::vector<ChunkGroup> class_chunks; // class - std::vector<ChunkGroup> thread_chunks; // atomic, nonatomic - std::vector<ChunkGroup> readwrite_chunks; // readwrite, readonly - std::vector<ChunkGroup> ref_chunks; // retain, copy, assign, weak, strong, unsafe_unretained - std::vector<ChunkGroup> getter_chunks; // getter - std::vector<ChunkGroup> setter_chunks; // setter - std::vector<ChunkGroup> nullability_chunks; // nonnull, nullable, null_unspecified, null_resettable - std::vector<ChunkGroup> other_chunks; // any words other than above - - if (next->Is(CT_PAREN_OPEN)) - { - open_paren = next; - next = next->GetNext(); - - /* - * Determine location of the property attributes - * NOTE: Did not do this in the combine.cpp do_symbol_check as - * I was not sure what the ramifications of adding a new type - * for each of the below types would be. It did break some items - * when I attempted to add them so this is my hack for now. - */ - while ( next->IsNotNullChunk() - && next->IsNot(CT_PAREN_CLOSE)) - { - if (next->Is(CT_OC_PROPERTY_ATTR)) - { - if ( next->IsString("atomic") - || next->IsString("nonatomic")) - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - thread_chunks.push_back(chunkGroup); - } - else if ( next->IsString("readonly") - || next->IsString("readwrite")) - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - readwrite_chunks.push_back(chunkGroup); - } - else if ( next->IsString("assign") - || next->IsString("retain") - || next->IsString("copy") - || next->IsString("strong") - || next->IsString("weak") - || next->IsString("unsafe_unretained")) - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - ref_chunks.push_back(chunkGroup); - } - else if (next->IsString("getter")) - { - ChunkGroup chunkGroup; - - do - { - chunkGroup.push_back(next); - next = next->GetNext(); - } while ( next->IsNotNullChunk() - && next->IsNot(CT_COMMA) - && next->IsNot(CT_PAREN_CLOSE)); - - next = next->GetPrev(); - - // coverity CID 160946 - if (next->IsNullChunk()) - { - break; - } - getter_chunks.push_back(chunkGroup); - } - else if (next->IsString("setter")) - { - ChunkGroup chunkGroup; - - do - { - chunkGroup.push_back(next); - next = next->GetNext(); - } while ( next->IsNotNullChunk() - && next->IsNot(CT_COMMA) - && next->IsNot(CT_PAREN_CLOSE)); - - if (next->IsNotNullChunk()) - { - next = next->GetPrev(); - } - - if (next->IsNullChunk()) - { - break; - } - setter_chunks.push_back(chunkGroup); - } - else if ( next->IsString("nullable") - || next->IsString("nonnull") - || next->IsString("null_resettable") - || next->IsString("null_unspecified")) - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - nullability_chunks.push_back(chunkGroup); - } - else if (next->IsString("class")) - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - class_chunks.push_back(chunkGroup); - } - else - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - other_chunks.push_back(chunkGroup); - } - } - else if (next->IsWord()) - { - if (next->IsString("class")) - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - class_chunks.push_back(chunkGroup); - } - else - { - ChunkGroup chunkGroup; - chunkGroup.push_back(next); - other_chunks.push_back(chunkGroup); - } - } - next = next->GetNext(); - } - log_rule_B("mod_sort_oc_property_class_weight"); - int class_w = options::mod_sort_oc_property_class_weight(); - log_rule_B("mod_sort_oc_property_thread_safe_weight"); - int thread_w = options::mod_sort_oc_property_thread_safe_weight(); - log_rule_B("mod_sort_oc_property_readwrite_weight"); - int readwrite_w = options::mod_sort_oc_property_readwrite_weight(); - log_rule_B("mod_sort_oc_property_reference_weight"); - int ref_w = options::mod_sort_oc_property_reference_weight(); - log_rule_B("mod_sort_oc_property_getter_weight"); - int getter_w = options::mod_sort_oc_property_getter_weight(); - log_rule_B("mod_sort_oc_property_setter_weight"); - int setter_w = options::mod_sort_oc_property_setter_weight(); - log_rule_B("mod_sort_oc_property_nullability_weight"); - int nullability_w = options::mod_sort_oc_property_nullability_weight(); - - // - std::multimap<int, std::vector<ChunkGroup> > sorted_chunk_map; - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(class_w, class_chunks)); - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(thread_w, thread_chunks)); - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(readwrite_w, readwrite_chunks)); - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(ref_w, ref_chunks)); - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(getter_w, getter_chunks)); - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(setter_w, setter_chunks)); - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(nullability_w, nullability_chunks)); - sorted_chunk_map.insert(pair<int, std::vector<ChunkGroup> >(std::numeric_limits<int>::min(), other_chunks)); - - Chunk *curr_chunk = open_paren; - - for (multimap<int, std::vector<ChunkGroup> >::reverse_iterator it = sorted_chunk_map.rbegin(); it != sorted_chunk_map.rend(); ++it) - { - std::vector<ChunkGroup> chunk_groups = (*it).second; - - for (auto chunk_group : chunk_groups) - { - for (auto chunk : chunk_group) - { - chunk->SetOrigPrevSp(0); - - if (chunk != curr_chunk) - { - chunk->MoveAfter(curr_chunk); - curr_chunk = chunk; - } - else - { - curr_chunk = curr_chunk->GetNext(); - } - } - - // add the parenthesis - Chunk endchunk; - endchunk.SetType(CT_COMMA); - endchunk.SetParentType(curr_chunk->GetParentType()); - endchunk.Str() = ","; - endchunk.SetLevel(curr_chunk->GetLevel()); - endchunk.SetPpLevel(curr_chunk->GetPpLevel()); - endchunk.SetBraceLevel(curr_chunk->GetBraceLevel()); - endchunk.SetOrigLine(curr_chunk->GetOrigLine()); - endchunk.SetOrigCol(curr_chunk->GetOrigCol()); - endchunk.SetColumn(curr_chunk->GetOrigColEnd() + 1); - endchunk.SetFlags(curr_chunk->GetFlags() & PCF_COPY_FLAGS); - endchunk.CopyAndAddAfter(curr_chunk); - curr_chunk = curr_chunk->GetNext(); - } - } - - // Remove the extra comma's that we did not move - while ( curr_chunk->IsNotNullChunk() - && curr_chunk->IsNot(CT_PAREN_CLOSE)) - { - Chunk *rm_chunk = curr_chunk; - curr_chunk = curr_chunk->GetNext(); - Chunk::Delete(rm_chunk); - } - } - } - Chunk *tmp = os->GetNextNcNnl(); - - if (tmp->IsParenOpen()) - { - tmp = tmp->GetClosingParen()->GetNextNcNnl(); - } - fix_variable_definition(tmp); -} // handle_oc_property_decl - - -static void handle_cs_square_stmt(Chunk *os) -{ - LOG_FUNC_ENTRY(); - - Chunk *cs = os->GetNext(); - - while ( cs->IsNotNullChunk() - && cs->GetLevel() > os->GetLevel()) - { - cs = cs->GetNext(); - } - - if ( cs->IsNullChunk() - || cs->IsNot(CT_SQUARE_CLOSE)) - { - return; - } - os->SetParentType(CT_CS_SQ_STMT); - cs->SetParentType(CT_CS_SQ_STMT); - - Chunk *tmp; - - for (tmp = os->GetNext(); tmp != cs; tmp = tmp->GetNext()) - { - tmp->SetParentType(CT_CS_SQ_STMT); - - if (tmp->Is(CT_COLON)) - { - tmp->SetType(CT_CS_SQ_COLON); - } - } - - tmp = cs->GetNextNcNnl(); - - if (tmp->IsNotNullChunk()) - { - tmp->SetFlagBits(PCF_STMT_START | PCF_EXPR_START); - log_ruleStart("start statement/ expression", tmp); - } -} // handle_cs_square_stmt - - -static void handle_cs_property(Chunk *bro) -{ - LOG_FUNC_ENTRY(); - - set_paren_parent(bro, CT_CS_PROPERTY); - - bool did_prop = false; - Chunk *pc = bro; - - while ((pc = pc->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279 - { - if (pc->GetLevel() == bro->GetLevel()) - { - //prevent scanning back past 'new' in expressions like new List<int> {1,2,3} - // Issue # 1620, UNI-24090.cs - if (pc->Is(CT_NEW)) - { - break; - } - - if ( !did_prop - && ( pc->Is(CT_WORD) - || pc->Is(CT_THIS))) - { - pc->SetType(CT_CS_PROPERTY); - did_prop = true; - } - else - { - pc->SetParentType(CT_CS_PROPERTY); - make_type(pc); - } - - if (pc->TestFlags(PCF_STMT_START)) - { - break; - } - } - } -} - - -static void handle_cs_array_type(Chunk *pc) -{ - if (pc->IsNullChunk()) - { - return; - } - Chunk *prev = pc->GetPrev(); - - for ( ; - prev->Is(CT_COMMA); - prev = prev->GetPrev()) - { - // empty - } - - if (prev->Is(CT_SQUARE_OPEN)) - { - while (pc != prev) - { - pc->SetParentType(CT_TYPE); - pc = pc->GetPrev(); - } - prev->SetParentType(CT_TYPE); - } -} - - -static void handle_wrap(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - Chunk *opp = pc->GetNext(); - Chunk *name = opp->GetNext(); - Chunk *clp = name->GetNext(); - - log_rule_B("sp_func_call_paren"); - log_rule_B("sp_cpp_cast_paren"); - iarf_e pav = pc->Is(CT_FUNC_WRAP) ? - options::sp_func_call_paren() : - options::sp_cpp_cast_paren(); - - log_rule_B("sp_inside_fparen"); - log_rule_B("sp_inside_paren_cast"); - iarf_e av = pc->Is(CT_FUNC_WRAP) ? - options::sp_inside_fparen() : - options::sp_inside_paren_cast(); - - if ( clp->Is(CT_PAREN_CLOSE) - && opp->Is(CT_PAREN_OPEN) - && ( name->Is(CT_WORD) - || name->Is(CT_TYPE))) - { - const char *psp = (pav & IARF_ADD) ? " " : ""; - const char *fsp = (av & IARF_ADD) ? " " : ""; - - pc->Str().append(psp); - pc->Str().append("("); - pc->Str().append(fsp); - pc->Str().append(name->GetStr()); - pc->Str().append(fsp); - pc->Str().append(")"); - - pc->SetType(pc->Is(CT_FUNC_WRAP) ? CT_FUNCTION : CT_TYPE); - - pc->SetOrigColEnd(pc->GetOrigCol() + pc->Len()); - - Chunk::Delete(opp); - Chunk::Delete(name); - Chunk::Delete(clp); - } -} // handle_wrap - - -static void handle_proto_wrap(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - Chunk *opp = pc->GetNextNcNnl(); - Chunk *name = opp->GetNextNcNnl(); - Chunk *tmp = name->GetNextNcNnl()->GetNextNcNnl(); - Chunk *clp = opp->GetClosingParen(); - Chunk *cma = clp->GetNextNcNnl(); - - if ( opp->IsNullChunk() - || name->IsNullChunk() - || tmp->IsNullChunk() - || clp->IsNullChunk() - || cma->IsNullChunk() - || ( name->IsNot(CT_WORD) - && name->IsNot(CT_TYPE)) - || opp->IsNot(CT_PAREN_OPEN)) - { - return; - } - - if (cma->Is(CT_SEMICOLON)) - { - pc->SetType(CT_FUNC_PROTO); - } - else if (cma->Is(CT_BRACE_OPEN)) - { - LOG_FMT(LFCN, "%s(%d): (19) SET TO CT_FUNC_DEF: orig line is %zu, orig col is %zu, Text() '%s'\n", - __func__, __LINE__, pc->GetOrigLine(), pc->GetOrigCol(), pc->Text()); - pc->SetType(CT_FUNC_DEF); - } - else - { - return; - } - opp->SetParentType(pc->GetType()); - clp->SetParentType(pc->GetType()); - - tmp->SetParentType(CT_PROTO_WRAP); - - if (tmp->Is(CT_PAREN_OPEN)) - { - fix_fcn_def_params(tmp); - } - else - { - fix_fcn_def_params(opp); - name->SetType(CT_WORD); - } - tmp = tmp->GetClosingParen(); - - if (tmp->IsNotNullChunk()) - { - tmp->SetParentType(CT_PROTO_WRAP); - } - // Mark return type (TODO: move to own function) - tmp = pc; - - while ((tmp = tmp->GetPrevNcNnlNi())->IsNotNullChunk()) // Issue #2279 - { - if ( !tmp->IsTypeDefinition() - && tmp->IsNot(CT_OPERATOR) - && tmp->IsNot(CT_WORD) - && tmp->IsNot(CT_ADDR)) - { - break; - } - tmp->SetParentType(pc->GetType()); - make_type(tmp); - } -} // handle_proto_wrap - - -/** - * Java assert statements are: "assert EXP1 [: EXP2] ;" - * Mark the parent of the colon and semicolon - */ -static void handle_java_assert(Chunk *pc) -{ - LOG_FUNC_ENTRY(); - bool did_colon = false; - Chunk *tmp = pc; - - while ((tmp = tmp->GetNext())->IsNotNullChunk()) - { - if (tmp->GetLevel() == pc->GetLevel()) - { - if ( !did_colon - && tmp->Is(CT_COLON)) - { - did_colon = true; - tmp->SetParentType(pc->GetType()); - } - - if (tmp->Is(CT_SEMICOLON)) - { - tmp->SetParentType(pc->GetType()); - break; - } - } - } -} // handle_java_assert |