diff options
Diffstat (limited to 'debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/tokenize_cleanup.cpp')
-rw-r--r-- | debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/tokenize_cleanup.cpp | 1756 |
1 files changed, 0 insertions, 1756 deletions
diff --git a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/tokenize_cleanup.cpp b/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/tokenize_cleanup.cpp deleted file mode 100644 index 23a87479..00000000 --- a/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/tokenize_cleanup.cpp +++ /dev/null @@ -1,1756 +0,0 @@ -/** - * @file tokenize_cleanup.cpp - * Looks at simple sequences to refine the chunk types. - * Examples: - * - change '[' + ']' into '[]'/ - * - detect "version = 10;" vs "version (xxx) {" - * - * @author Ben Gardner - * @author Guy Maurel 2015, 2021 - * @license GPL v2+ - */ - -#include "tokenize_cleanup.h" - -#include "combine.h" -#include "combine_skip.h" -#include "flag_braced_init_list.h" -#include "flag_decltype.h" -#include "keywords.h" -#include "prototypes.h" -#include "punctuators.h" -#include "space.h" -#include "unc_ctype.h" - - -using namespace uncrustify; - - -/** - * Mark types in a single template argument. - * - * @param start chunk to start check at - * @param end chunk to end check at - */ -static void check_template_arg(chunk_t *start, chunk_t *end); - - -/** - * Mark types in template argument(s). - * - * @param start chunk to start check at - * @param end chunk to end check at - */ -static void check_template_args(chunk_t *start, chunk_t *end); - - -/** - * If there is nothing but CT_WORD and CT_MEMBER, then it's probably a - * template thingy. Otherwise, it's likely a comparison. - * - * @param start chunk to start check at - */ -static void check_template(chunk_t *start, bool in_type_cast); - - -/** - * Convert '>' + '>' into '>>' - * If we only have a single '>', then change it to CT_COMPARE. - * - * @param pc chunk to start at - */ -static chunk_t *handle_double_angle_close(chunk_t *pc); - - -/** - * Marks ObjC specific chunks in propery declaration, by setting - * parent types and chunk types. - */ -static void cleanup_objc_property(chunk_t *start); - - -/** - * Marks ObjC specific chunks in propery declaration (getter/setter attribute) - * Will mark 'test4Setter'and ':' in '@property (setter=test4Setter:, strong) int test4;' as CT_OC_SEL_NAME - */ -static void mark_selectors_in_property_with_open_paren(chunk_t *open_paren); - - -/** - * Marks ObjC specific chunks in propery declaration ( attributes) - * Changes all the CT_WORD and CT_TYPE to CT_OC_PROPERTY_ATTR - */ -static void mark_attributes_in_property_with_open_paren(chunk_t *open_paren); - - -static chunk_t *handle_double_angle_close(chunk_t *pc) -{ - chunk_t *next = chunk_get_next(pc); - - if (next != nullptr) - { - if ( chunk_is_token(pc, CT_ANGLE_CLOSE) - && chunk_is_token(next, CT_ANGLE_CLOSE) - && get_chunk_parent_type(pc) == CT_NONE - && (pc->orig_col_end + 1) == next->orig_col - && get_chunk_parent_type(next) == CT_NONE) - { - pc->str.append('>'); - set_chunk_type(pc, CT_SHIFT); - pc->orig_col_end = next->orig_col_end; - - chunk_t *tmp = chunk_get_next_ncnnl(next); - chunk_del(next); - next = tmp; - } - else - { - // bug #663 - set_chunk_type(pc, CT_COMPARE); - } - } - return(next); -} - - -void split_off_angle_close(chunk_t *pc) -{ - const chunk_tag_t *ct = find_punctuator(pc->text() + 1, cpd.lang_flags); - - if (ct == nullptr) - { - return; - } - chunk_t nc = *pc; - - pc->str.resize(1); - pc->orig_col_end = pc->orig_col + 1; - set_chunk_type(pc, CT_ANGLE_CLOSE); - - set_chunk_type(&nc, ct->type); - nc.str.pop_front(); - nc.orig_col++; - nc.column++; - chunk_add_after(&nc, pc); -} - - -void tokenize_trailing_return_types(void) -{ - // Issue #2330 - // auto max(int a, int b) -> int; - // Issue #2460 - // auto f01() -> bool; - // auto f02() noexcept -> bool; - // auto f03() noexcept(true) -> bool; - // auto f04() noexcept(false) -> bool; - // auto f05() noexcept -> bool = delete; - // auto f06() noexcept(true) -> bool = delete; - // auto f07() noexcept(false) -> bool = delete; - // auto f11() const -> bool; - // auto f12() const noexcept -> bool; - // auto f13() const noexcept(true) -> bool; - // auto f14() const noexcept(false) -> bool; - // auto f15() const noexcept -> bool = delete; - // auto f16() const noexcept(true) -> bool = delete; - // auto f17() const noexcept(false) -> bool = delete; - // auto f21() throw() -> bool; - // auto f22() throw() -> bool = delete; - // auto f23() const throw() -> bool; - // auto f24() const throw() -> bool = delete; - chunk_t *pc; - - for (pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc)) - { - char copy[1000]; - LOG_FMT(LNOTE, "%s(%d): orig_line is %zu, orig_col is %zu, text() is '%s'\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, pc->elided_text(copy)); - - if ( chunk_is_token(pc, CT_MEMBER) - && (strcmp(pc->text(), "->") == 0)) - { - chunk_t *tmp = chunk_get_prev_ncnnl(pc); - chunk_t *tmp_2; - chunk_t *open_paren; - - if (chunk_is_token(tmp, CT_QUALIFIER)) - { - // auto max(int a, int b) const -> int; - // auto f11() const -> bool; - tmp = chunk_get_prev_ncnnl(tmp); - } - else if (chunk_is_token(tmp, CT_NOEXCEPT)) - { - // noexcept is present - tmp_2 = chunk_get_prev_ncnnl(tmp); - - if (chunk_is_token(tmp_2, CT_QUALIFIER)) - { - // auto f12() const noexcept -> bool; - // auto f15() const noexcept -> bool = delete; - tmp = chunk_get_prev_ncnnl(tmp_2); - } - else - { - // auto f02() noexcept -> bool; - // auto f05() noexcept -> bool = delete; - tmp = tmp_2; - } - } - else if (chunk_is_token(tmp, CT_PAREN_CLOSE)) - { - open_paren = chunk_get_prev_type(tmp, CT_PAREN_OPEN, tmp->level); - tmp = chunk_get_prev_ncnnl(open_paren); - - if (chunk_is_token(tmp, CT_NOEXCEPT)) - { - // noexcept is present - tmp_2 = chunk_get_prev_ncnnl(tmp); - - if (chunk_is_token(tmp_2, CT_QUALIFIER)) - { - // auto f13() const noexcept(true) -> bool; - // auto f14() const noexcept(false) -> bool; - // auto f16() const noexcept(true) -> bool = delete; - // auto f17() const noexcept(false) -> bool = delete; - tmp = chunk_get_prev_ncnnl(tmp_2); - } - else - { - // auto f03() noexcept(true) -> bool; - // auto f04() noexcept(false) -> bool; - // auto f06() noexcept(true) -> bool = delete; - // auto f07() noexcept(false) -> bool = delete; - tmp = tmp_2; - } - } - else if (chunk_is_token(tmp, CT_THROW)) - { - // throw is present - tmp_2 = chunk_get_prev_ncnnl(tmp); - - if (chunk_is_token(tmp_2, CT_QUALIFIER)) - { - // auto f23() const throw() -> bool; - // auto f24() const throw() -> bool = delete; - tmp = chunk_get_prev_ncnnl(tmp_2); - } - else - { - // auto f21() throw() -> bool; - // auto f22() throw() -> bool = delete; - tmp = tmp_2; - } - } - else - { - LOG_FMT(LNOTE, "%s(%d): NOT COVERED\n", __func__, __LINE__); - } - } - else - { - LOG_FMT(LNOTE, "%s(%d): NOT COVERED\n", __func__, __LINE__); - } - - if ( chunk_is_token(tmp, CT_FPAREN_CLOSE) - && ( get_chunk_parent_type(tmp) == CT_FUNC_PROTO - || get_chunk_parent_type(tmp) == CT_FUNC_DEF)) - { - set_chunk_type(pc, CT_TRAILING_RET); - LOG_FMT(LNOTE, "%s(%d): set trailing return type for text() is '%s'\n", - __func__, __LINE__, pc->text()); // Issue #3222 - // TODO - // https://en.cppreference.com/w/cpp/language/function - // noptr-declarator ( parameter-list ) cv(optional) ref(optional) except(optional) attr(optional) -> trailing - chunk_t *next = chunk_get_next_ncnnl(pc); - - if (chunk_is_token(next, CT_DECLTYPE)) - { - // TODO - } - else if (chunk_is_token(next, CT_WORD)) - { - set_chunk_type(next, CT_TYPE); // Issue #3222 - next = chunk_get_next_ncnnl(next); - - if ( chunk_is_token(next, CT_ARITH) - && (next->str[0] == '*')) - { - set_chunk_type(next, CT_PTR_TYPE); - } - } - else - { - // TODO - } - } - } - } -} // tokenize_trailing_return_types - - -void tokenize_cleanup(void) -{ - LOG_FUNC_ENTRY(); - - chunk_t *prev = nullptr; - chunk_t *next; - bool in_type_cast = false; - - cpd.unc_stage = unc_stage_e::TOKENIZE_CLEANUP; - - /* - * Since [] is expected to be TSQUARE for the 'operator', we need to make - * this change in the first pass. - */ - chunk_t *pc; - - for (pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc)) - { - if (chunk_is_token(pc, CT_SQUARE_OPEN)) - { - next = chunk_get_next_ncnnl(pc); - - if (chunk_is_token(next, CT_SQUARE_CLOSE)) - { - // Change '[' + ']' into '[]' - set_chunk_type(pc, CT_TSQUARE); - pc->str = "[]"; - /* - * bug #664: The original orig_col_end of CT_SQUARE_CLOSE is - * stored at orig_col_end of CT_TSQUARE. - * pc->orig_col_end += 1; - */ - pc->orig_col_end = next->orig_col_end; - chunk_del(next); - } - } - - if ( chunk_is_token(pc, CT_SEMICOLON) - && pc->flags.test(PCF_IN_PREPROC) - && !chunk_get_next_ncnnl(pc, scope_e::PREPROC)) - { - LOG_FMT(LNOTE, "%s(%d): %s:%zu Detected a macro that ends with a semicolon. Possible failures if used.\n", - __func__, __LINE__, cpd.filename.c_str(), pc->orig_line); - } - } - - // change := to CT_SQL_ASSIGN Issue #527 - for (pc = chunk_get_head(); pc != nullptr; pc = chunk_get_next_ncnnl(pc)) - { - if (chunk_is_token(pc, CT_COLON)) - { - next = chunk_get_next_ncnnl(pc); - - if (chunk_is_token(next, CT_ASSIGN)) - { - // Change ':' + '=' into ':=' - set_chunk_type(pc, CT_SQL_ASSIGN); - pc->str = ":="; - pc->orig_col_end = next->orig_col_end; - chunk_del(next); - } - } - } - - // We can handle everything else in the second pass - pc = chunk_get_head(); - next = chunk_get_next_ncnnl(pc); - - while ( pc != nullptr - && next != nullptr) - { - if ( chunk_is_token(pc, CT_DOT) - && language_is_set(LANG_ALLC)) - { - set_chunk_type(pc, CT_MEMBER); - } - - if ( chunk_is_token(pc, CT_NULLCOND) - && language_is_set(LANG_CS)) - { - set_chunk_type(pc, CT_MEMBER); - } - - // Determine the version stuff (D only) - if (chunk_is_token(pc, CT_D_VERSION)) - { - if (chunk_is_token(next, CT_PAREN_OPEN)) - { - set_chunk_type(pc, CT_D_VERSION_IF); - } - else - { - if (next->type != CT_ASSIGN) - { - LOG_FMT(LERR, "%s(%d): %s:%zu: version: Unexpected token %s\n", - __func__, __LINE__, cpd.filename.c_str(), pc->orig_line, get_token_name(next->type)); - cpd.error_count++; - } - set_chunk_type(pc, CT_WORD); - } - } - - // Determine the scope stuff (D only) - if (chunk_is_token(pc, CT_D_SCOPE)) - { - if (chunk_is_token(next, CT_PAREN_OPEN)) - { - set_chunk_type(pc, CT_D_SCOPE_IF); - } - else - { - set_chunk_type(pc, CT_TYPE); - } - } - - /* - * Change CT_BASE before CT_PAREN_OPEN to CT_WORD. - * public myclass() : base() {} - * -or- - * var x = (T)base.y; - */ - if ( chunk_is_token(pc, CT_BASE) - && ( chunk_is_token(next, CT_PAREN_OPEN) - || chunk_is_token(next, CT_DOT))) - { - set_chunk_type(pc, CT_WORD); - } - - if ( chunk_is_token(pc, CT_ENUM) - && ( chunk_is_token(next, CT_STRUCT) - || chunk_is_token(next, CT_CLASS))) - { - set_chunk_type(next, CT_ENUM_CLASS); - } - chunk_t *next_non_attr = language_is_set(LANG_CPP) ? skip_attribute_next(next) : next; - - /* - * Change CT_WORD after CT_ENUM, CT_UNION, CT_STRUCT, or CT_CLASS to CT_TYPE - * Change CT_WORD before CT_WORD to CT_TYPE - */ - if (chunk_is_token(next_non_attr, CT_WORD)) - { - if ( chunk_is_token(pc, CT_ENUM) - || chunk_is_token(pc, CT_ENUM_CLASS) - || chunk_is_token(pc, CT_UNION) - || chunk_is_token(pc, CT_STRUCT) - || chunk_is_token(pc, CT_CLASS)) - { - set_chunk_type(next_non_attr, CT_TYPE); - } - - if (chunk_is_token(pc, CT_WORD)) - { - set_chunk_type(pc, CT_TYPE); - } - } - - /* - * change extern to qualifier if extern isn't followed by a string or - * an open parenthesis - */ - if (chunk_is_token(pc, CT_EXTERN)) - { - if (chunk_is_token(next, CT_STRING)) - { - // Probably 'extern "C"' - } - else if (chunk_is_token(next, CT_PAREN_OPEN)) - { - // Probably 'extern (C)' - } - else - { - // Something else followed by a open brace - chunk_t *tmp = chunk_get_next_ncnnl(next); - - if ( tmp == nullptr - || tmp->type != CT_BRACE_OPEN) - { - set_chunk_type(pc, CT_QUALIFIER); - } - } - } - - /* - * Change CT_STAR to CT_PTR_TYPE if preceded by - * CT_TYPE, CT_QUALIFIER, or CT_PTR_TYPE - * or by a - * CT_WORD which is preceded by CT_DC_MEMBER: '::aaa *b' - */ - if ( (chunk_is_token(next, CT_STAR)) - || ( language_is_set(LANG_CPP) - && (chunk_is_token(next, CT_CARET))) - || ( language_is_set(LANG_CS) - && (chunk_is_token(next, CT_QUESTION)) - && (strcmp(pc->text(), "null") != 0))) - { - if ( chunk_is_token(pc, CT_TYPE) - || chunk_is_token(pc, CT_QUALIFIER) - || chunk_is_token(pc, CT_PTR_TYPE)) - { - set_chunk_type(next, CT_PTR_TYPE); - } - } - - if ( chunk_is_token(pc, CT_TYPE_CAST) - && chunk_is_token(next, CT_ANGLE_OPEN)) - { - set_chunk_parent(next, CT_TYPE_CAST); - in_type_cast = true; - } - - if (chunk_is_token(pc, CT_DECLTYPE)) - { - flag_cpp_decltype(pc); - } - - // Change angle open/close to CT_COMPARE, if not a template thingy - if ( chunk_is_token(pc, CT_ANGLE_OPEN) - && pc->parent_type != CT_TYPE_CAST) - { - /* - * pretty much all languages except C use <> for something other than - * comparisons. "#include<xxx>" is handled elsewhere. - */ - if (language_is_set(LANG_OC | LANG_CPP | LANG_CS | LANG_JAVA | LANG_VALA)) - { - // bug #663 - check_template(pc, in_type_cast); - } - else - { - // convert CT_ANGLE_OPEN to CT_COMPARE - set_chunk_type(pc, CT_COMPARE); - } - } - - if ( chunk_is_token(pc, CT_ANGLE_CLOSE) - && pc->parent_type != CT_TEMPLATE) - { - if (in_type_cast) - { - in_type_cast = false; - set_chunk_parent(pc, CT_TYPE_CAST); - } - else - { - next = handle_double_angle_close(pc); - } - } - - if (language_is_set(LANG_D)) - { - // Check for the D string concat symbol '~' - if ( chunk_is_token(pc, CT_INV) - && ( chunk_is_token(prev, CT_STRING) - || chunk_is_token(prev, CT_WORD) - || chunk_is_token(next, CT_STRING))) - { - set_chunk_type(pc, CT_CONCAT); - } - - // Check for the D template symbol '!' (word + '!' + word or '(') - if ( chunk_is_token(pc, CT_NOT) - && chunk_is_token(prev, CT_WORD) - && ( chunk_is_token(next, CT_PAREN_OPEN) - || chunk_is_token(next, CT_WORD) - || chunk_is_token(next, CT_TYPE) - || chunk_is_token(next, CT_NUMBER) - || chunk_is_token(next, CT_NUMBER_FP) - || chunk_is_token(next, CT_STRING) - || chunk_is_token(next, CT_STRING_MULTI))) - { - set_chunk_type(pc, CT_D_TEMPLATE); - } - - // handle "version(unittest) { }" vs "unittest { }" - if ( chunk_is_token(pc, CT_UNITTEST) - && chunk_is_token(prev, CT_PAREN_OPEN)) - { - set_chunk_type(pc, CT_WORD); - } - - // handle 'static if' and merge the tokens - if ( chunk_is_token(pc, CT_IF) - && chunk_is_str(prev, "static", 6)) - { - // delete PREV and merge with IF - pc->str.insert(0, ' '); - pc->str.insert(0, prev->str); - pc->orig_col = prev->orig_col; - pc->orig_line = prev->orig_line; - chunk_t *to_be_deleted = prev; - prev = chunk_get_prev_ncnnl(prev); - - if (prev != nullptr) - { - chunk_del(to_be_deleted); - } - } - } - - if (language_is_set(LANG_CPP)) - { - // Change Word before '::' into a type - if ( chunk_is_token(pc, CT_WORD) - && chunk_is_token(next, CT_DC_MEMBER)) - { - prev = chunk_get_prev(pc); - - if (prev == nullptr) // Issue #3010 - { - set_chunk_type(pc, CT_TYPE); - } - else - { - if (chunk_is_token(prev, CT_COLON)) - { - // nothing to do - } - else - { - set_chunk_type(pc, CT_TYPE); - } - } - } - - // Set parent type for 'if constexpr' - if ( chunk_is_token(prev, CT_IF) - && chunk_is_token(pc, CT_QUALIFIER) - && chunk_is_str(pc, "constexpr", 9)) - { - set_chunk_type(pc, CT_CONSTEXPR); - } - } - - // Change get/set to CT_WORD if not followed by a brace open - if ( chunk_is_token(pc, CT_GETSET) - && next->type != CT_BRACE_OPEN) - { - if ( chunk_is_token(next, CT_SEMICOLON) - && ( chunk_is_token(prev, CT_BRACE_CLOSE) - || chunk_is_token(prev, CT_BRACE_OPEN) - || chunk_is_token(prev, CT_SEMICOLON))) - { - set_chunk_type(pc, CT_GETSET_EMPTY); - set_chunk_parent(next, CT_GETSET); - } - else - { - set_chunk_type(pc, CT_WORD); - } - } - - /* - * Interface is only a keyword in MS land if followed by 'class' or 'struct' - * likewise, 'class' may be a member name in Java. - */ - if ( chunk_is_token(pc, CT_CLASS) - && !CharTable::IsKw1(next->str[0])) - { - if ( chunk_is_not_token(next, CT_DC_MEMBER) - && chunk_is_not_token(next, CT_ATTRIBUTE)) // Issue #2570 - { - set_chunk_type(pc, CT_WORD); - } - else if ( chunk_is_token(prev, CT_DC_MEMBER) - || chunk_is_token(prev, CT_TYPE)) - { - set_chunk_type(pc, CT_TYPE); - } - else if (chunk_is_token(next, CT_DC_MEMBER)) - { - chunk_t *next2 = chunk_get_next_nblank(next); - - if ( chunk_is_token(next2, CT_INV) // CT_INV hasn't turned into CT_DESTRUCTOR just yet - || ( chunk_is_token(next2, CT_CLASS) // constructor isn't turned into CT_FUNC* just yet - && !strcmp(pc->text(), next2->text()))) - { - set_chunk_type(pc, CT_TYPE); - } - } - } - - /* - * Change item after operator (>=, ==, etc) to a CT_OPERATOR_VAL - * Usually the next item is part of the operator. - * In a few cases the next few tokens are part of it: - * operator + - common case - * operator >> - need to combine '>' and '>' - * operator () - * operator [] - already converted to TSQUARE - * operator new [] - * operator delete [] - * operator const char * - * operator const B& - * operator std::allocator<U> - * - * In all cases except the last, this will put the entire operator value - * in one chunk. - */ - if (chunk_is_token(pc, CT_OPERATOR)) - { - chunk_t *tmp2 = chunk_get_next(next); - - // Handle special case of () operator -- [] already handled - if (chunk_is_token(next, CT_PAREN_OPEN)) - { - chunk_t *tmp = chunk_get_next(next); - - if (chunk_is_token(tmp, CT_PAREN_CLOSE)) - { - next->str = "()"; - set_chunk_type(next, CT_OPERATOR_VAL); - chunk_del(tmp); - next->orig_col_end += 1; - } - } - else if ( chunk_is_token(next, CT_ANGLE_CLOSE) - && chunk_is_token(tmp2, CT_ANGLE_CLOSE) - && tmp2->orig_col == next->orig_col_end) - { - next->str.append('>'); - next->orig_col_end++; - set_chunk_type(next, CT_OPERATOR_VAL); - chunk_del(tmp2); - } - else if (next->flags.test(PCF_PUNCTUATOR)) - { - set_chunk_type(next, CT_OPERATOR_VAL); - } - else - { - set_chunk_type(next, CT_TYPE); - - /* - * Replace next with a collection of all tokens that are part of - * the type. - */ - tmp2 = next; - chunk_t *tmp; - - while ((tmp = chunk_get_next(tmp2)) != nullptr) - { - if ( tmp->type != CT_WORD - && tmp->type != CT_TYPE - && tmp->type != CT_QUALIFIER - && tmp->type != CT_STAR - && tmp->type != CT_CARET - && tmp->type != CT_AMP - && tmp->type != CT_TSQUARE) - { - break; - } - // Change tmp into a type so that space_needed() works right - make_type(tmp); - size_t num_sp = space_needed(tmp2, tmp); - - while (num_sp-- > 0) - { - next->str.append(" "); - } - next->str.append(tmp->str); - tmp2 = tmp; - } - - while ((tmp2 = chunk_get_next(next)) != tmp) - { - chunk_del(tmp2); - } - set_chunk_type(next, CT_OPERATOR_VAL); - - next->orig_col_end = next->orig_col + next->len(); - } - set_chunk_parent(next, CT_OPERATOR); - - LOG_FMT(LOPERATOR, "%s(%d): %zu:%zu operator '%s'\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, next->text()); - } - - // Change private, public, protected into either a qualifier or label - if (chunk_is_token(pc, CT_ACCESS)) - { - // Handle Qt slots - maybe should just check for a CT_WORD? - if ( chunk_is_str(next, "slots", 5) - || chunk_is_str(next, "Q_SLOTS", 7)) - { - chunk_t *tmp = chunk_get_next(next); - - if (chunk_is_token(tmp, CT_COLON)) - { - next = tmp; - } - } - - if (chunk_is_token(next, CT_COLON)) - { - set_chunk_type(next, CT_ACCESS_COLON); - chunk_t *tmp; - - if ((tmp = chunk_get_next_ncnnl(next)) != nullptr) - { - chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); - } - } - else - { - set_chunk_type(pc, ( chunk_is_str(pc, "signals", 7) - || chunk_is_str(pc, "Q_SIGNALS", 9)) - ? CT_WORD : CT_QUALIFIER); - } - } - - // Look for <newline> 'EXEC' 'SQL' - if ( ( chunk_is_str_case(pc, "EXEC", 4) - && chunk_is_str_case(next, "SQL", 3)) - || ( (*pc->str.c_str() == '$') - && pc->type != CT_SQL_WORD - /* but avoid breaking tokenization for C# 6 interpolated strings. */ - && ( !language_is_set(LANG_CS) - || ( chunk_is_token(pc, CT_STRING) - && (!pc->str.startswith("$\"")) - && (!pc->str.startswith("$@\"")))))) - { - chunk_t *tmp = chunk_get_prev(pc); - - if (chunk_is_newline(tmp)) - { - if (*pc->str.c_str() == '$') - { - set_chunk_type(pc, CT_SQL_EXEC); - - if (pc->len() > 1) - { - // SPLIT OFF '$' - chunk_t nc; - - nc = *pc; - pc->str.resize(1); - pc->orig_col_end = pc->orig_col + 1; - - set_chunk_type(&nc, CT_SQL_WORD); - nc.str.pop_front(); - nc.orig_col++; - nc.column++; - chunk_add_after(&nc, pc); - - next = chunk_get_next(pc); - } - } - tmp = chunk_get_next(next); - - if (chunk_is_str_case(tmp, "BEGIN", 5)) - { - set_chunk_type(pc, CT_SQL_BEGIN); - } - else if (chunk_is_str_case(tmp, "END", 3)) - { - set_chunk_type(pc, CT_SQL_END); - } - else - { - set_chunk_type(pc, CT_SQL_EXEC); - } - - // Change words into CT_SQL_WORD until CT_SEMICOLON - while (tmp != nullptr) - { - if (chunk_is_token(tmp, CT_SEMICOLON)) - { - break; - } - - if ( (tmp->len() > 0) - && ( unc_isalpha(*tmp->str.c_str()) - || (*tmp->str.c_str() == '$'))) - { - set_chunk_type(tmp, CT_SQL_WORD); - } - tmp = chunk_get_next_ncnnl(tmp); - } - } - } - - // handle MS abomination 'for each' - if ( chunk_is_token(pc, CT_FOR) - && chunk_is_str(next, "each", 4) - && (next == chunk_get_next(pc))) - { - // merge the two with a space between - pc->str.append(' '); - pc->str += next->str; - pc->orig_col_end = next->orig_col_end; - chunk_del(next); - next = chunk_get_next_ncnnl(pc); - - // label the 'in' - if (chunk_is_token(next, CT_PAREN_OPEN)) - { - chunk_t *tmp = chunk_get_next_ncnnl(next); - - while ( tmp != nullptr - && tmp->type != CT_PAREN_CLOSE) - { - if (chunk_is_str(tmp, "in", 2)) - { - set_chunk_type(tmp, CT_IN); - break; - } - tmp = chunk_get_next_ncnnl(tmp); - } - } - } - - /* - * ObjectiveC allows keywords to be used as identifiers in some situations - * This is a dirty hack to allow some of the more common situations. - */ - if (language_is_set(LANG_OC)) - { - if ( ( chunk_is_token(pc, CT_IF) - || chunk_is_token(pc, CT_FOR) - || chunk_is_token(pc, CT_WHILE)) - && !chunk_is_token(next, CT_PAREN_OPEN)) - { - set_chunk_type(pc, CT_WORD); - } - - if ( chunk_is_token(pc, CT_DO) - && ( chunk_is_token(prev, CT_MINUS) - || chunk_is_token(next, CT_SQUARE_CLOSE))) - { - set_chunk_type(pc, CT_WORD); - } - - // Fix self keyword back to word when mixing c++/objective-c - if ( chunk_is_token(pc, CT_THIS) - && !strcmp(pc->text(), "self") - && ( chunk_is_token(next, CT_COMMA) - || chunk_is_token(next, CT_PAREN_CLOSE))) - { - set_chunk_type(pc, CT_WORD); - } - - // Fix self keyword back to word when mixing c++/objective-c - if ( chunk_is_token(pc, CT_THIS) - && !strcmp(pc->text(), "self") - && ( chunk_is_token(next, CT_COMMA) - || chunk_is_token(next, CT_PAREN_CLOSE))) - { - set_chunk_type(pc, CT_WORD); - } - } - - // Another hack to clean up more keyword abuse - if ( chunk_is_token(pc, CT_CLASS) - && ( chunk_is_token(prev, CT_DOT) - || chunk_is_token(next, CT_DOT) - || chunk_is_token(prev, CT_MEMBER) // Issue #3031 - || chunk_is_token(next, CT_MEMBER))) - { - set_chunk_type(pc, CT_WORD); - } - - // Detect Objective C class name - if ( chunk_is_token(pc, CT_OC_IMPL) - || chunk_is_token(pc, CT_OC_INTF) - || chunk_is_token(pc, CT_OC_PROTOCOL)) - { - if (next->type != CT_PAREN_OPEN) - { - set_chunk_type(next, CT_OC_CLASS); - } - set_chunk_parent(next, pc->type); - - chunk_t *tmp = chunk_get_next_ncnnl(next); - - if (tmp != nullptr) - { - chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); - } - tmp = chunk_get_next_type(pc, CT_OC_END, pc->level); - - if (tmp != nullptr) - { - set_chunk_parent(tmp, pc->type); - } - } - - if (chunk_is_token(pc, CT_OC_INTF)) - { - chunk_t *tmp = chunk_get_next_ncnnl(pc, scope_e::PREPROC); - - while ( tmp != nullptr - && tmp->type != CT_OC_END) - { - if (get_token_pattern_class(tmp->type) != pattern_class_e::NONE) - { - LOG_FMT(LOBJCWORD, "%s(%d): @interface %zu:%zu change '%s' (%s) to CT_WORD\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, tmp->text(), - get_token_name(tmp->type)); - set_chunk_type(tmp, CT_WORD); - } - tmp = chunk_get_next_ncnnl(tmp, scope_e::PREPROC); - } - } - - /* - * Detect Objective-C categories and class extensions: - * @interface ClassName (CategoryName) - * @implementation ClassName (CategoryName) - * @interface ClassName () - * @implementation ClassName () - */ - if ( ( get_chunk_parent_type(pc) == CT_OC_IMPL - || get_chunk_parent_type(pc) == CT_OC_INTF - || chunk_is_token(pc, CT_OC_CLASS)) - && chunk_is_token(next, CT_PAREN_OPEN)) - { - set_chunk_parent(next, get_chunk_parent_type(pc)); - - chunk_t *tmp = chunk_get_next(next); - - if ( tmp != nullptr - && tmp->next != nullptr) - { - if (chunk_is_token(tmp, CT_PAREN_CLOSE)) - { - //set_chunk_type(tmp, CT_OC_CLASS_EXT); - set_chunk_parent(tmp, get_chunk_parent_type(pc)); - } - else - { - set_chunk_type(tmp, CT_OC_CATEGORY); - set_chunk_parent(tmp, get_chunk_parent_type(pc)); - } - } - tmp = chunk_get_next_type(pc, CT_PAREN_CLOSE, pc->level); - - if (tmp != nullptr) - { - set_chunk_parent(tmp, get_chunk_parent_type(pc)); - } - } - - /* - * Detect Objective C @property: - * @property NSString *stringProperty; - * @property(nonatomic, retain) NSMutableDictionary *shareWith; - */ - if (chunk_is_token(pc, CT_OC_PROPERTY)) - { - if (next->type != CT_PAREN_OPEN) - { - chunk_flags_set(next, PCF_STMT_START | PCF_EXPR_START); - } - else - { - cleanup_objc_property(pc); - } - } - - /* - * Detect Objective C @selector: - * @selector(msgNameWithNoArg) - * @selector(msgNameWith1Arg:) - * @selector(msgNameWith2Args:arg2Name:) - */ - if ( chunk_is_token(pc, CT_OC_SEL) - && chunk_is_token(next, CT_PAREN_OPEN)) - { - set_chunk_parent(next, pc->type); - - chunk_t *tmp = chunk_get_next(next); - - if (tmp != nullptr) - { - set_chunk_type(tmp, CT_OC_SEL_NAME); - set_chunk_parent(tmp, pc->type); - - while ((tmp = chunk_get_next_ncnnl(tmp)) != nullptr) - { - if (chunk_is_token(tmp, CT_PAREN_CLOSE)) - { - set_chunk_parent(tmp, CT_OC_SEL); - break; - } - set_chunk_type(tmp, CT_OC_SEL_NAME); - set_chunk_parent(tmp, pc->type); - } - } - } - - // Handle special preprocessor junk - if (chunk_is_token(pc, CT_PREPROC)) - { - set_chunk_parent(pc, next->type); - } - - // Detect "pragma region" and "pragma endregion" - if ( chunk_is_token(pc, CT_PP_PRAGMA) - && chunk_is_token(next, CT_PREPROC_BODY)) - { - if ( (strncmp(next->str.c_str(), "region", 6) == 0) - || (strncmp(next->str.c_str(), "endregion", 9) == 0)) - // TODO: probably better use strncmp - { - set_chunk_type(pc, (*next->str.c_str() == 'r') ? CT_PP_REGION : CT_PP_ENDREGION); - - set_chunk_parent(prev, pc->type); - } - } - - // Change 'default(' into a sizeof-like statement - if ( language_is_set(LANG_CS) - && chunk_is_token(pc, CT_DEFAULT) - && chunk_is_token(next, CT_PAREN_OPEN)) - { - set_chunk_type(pc, CT_SIZEOF); - } - - if ( chunk_is_token(pc, CT_UNSAFE) - && next->type != CT_BRACE_OPEN) - { - set_chunk_type(pc, CT_QUALIFIER); - } - - if ( ( chunk_is_token(pc, CT_USING) - || ( chunk_is_token(pc, CT_TRY) - && language_is_set(LANG_JAVA))) - && chunk_is_token(next, CT_PAREN_OPEN)) - { - set_chunk_type(pc, CT_USING_STMT); - } - - // Add minimal support for C++0x rvalue references - if ( chunk_is_token(pc, CT_BOOL) - && language_is_set(LANG_CPP) - && chunk_is_str(pc, "&&", 2)) - { - if (chunk_is_token(prev, CT_TYPE)) - { - // Issue # 1002 - if (!pc->flags.test(PCF_IN_TEMPLATE)) - { - set_chunk_type(pc, CT_BYREF); - } - } - } - - /* - * HACK: treat try followed by a colon as a qualifier to handle this: - * A::A(int) try : B() { } catch (...) { } - */ - if ( chunk_is_token(pc, CT_TRY) - && chunk_is_str(pc, "try", 3) - && chunk_is_token(next, CT_COLON)) - { - set_chunk_type(pc, CT_QUALIFIER); - } - - /* - * If Java's 'synchronized' is in a method declaration, it should be - * a qualifier. - */ - if ( language_is_set(LANG_JAVA) - && chunk_is_token(pc, CT_SYNCHRONIZED) - && next->type != CT_PAREN_OPEN) - { - set_chunk_type(pc, CT_QUALIFIER); - } - - // change CT_DC_MEMBER + CT_FOR into CT_DC_MEMBER + CT_FUNC_CALL - if ( chunk_is_token(pc, CT_FOR) - && chunk_is_token(pc->prev, CT_DC_MEMBER)) - { - set_chunk_type(pc, CT_FUNC_CALL); - } - // TODO: determine other stuff here - - prev = pc; - pc = next; - next = chunk_get_next_ncnnl(pc); - } -} // tokenize_cleanup - - -bool invalid_open_angle_template(chunk_t *prev) -{ - if (prev == nullptr) - { - return(false); - } - // A template requires a word/type right before the open angle - return( prev->type != CT_WORD - && prev->type != CT_TYPE - && prev->type != CT_COMMA - && prev->type != CT_QUALIFIER - && prev->type != CT_OPERATOR_VAL - && get_chunk_parent_type(prev) != CT_OPERATOR); -} - - -static void check_template(chunk_t *start, bool in_type_cast) -{ - LOG_FMT(LTEMPL, "%s(%d): orig_line %zu, orig_col %zu:\n", - __func__, __LINE__, start->orig_line, start->orig_col); - - chunk_t *prev = chunk_get_prev_ncnnl(start, scope_e::PREPROC); - - if (prev == nullptr) - { - return; - } - chunk_t *end; - chunk_t *pc; - - if (chunk_is_token(prev, CT_TEMPLATE)) - { - LOG_FMT(LTEMPL, "%s(%d): CT_TEMPLATE:\n", __func__, __LINE__); - - // We have: "template< ... >", which is a template declaration - size_t level = 1; - size_t parens = 0; - - for (pc = chunk_get_next_ncnnl(start, scope_e::PREPROC); - pc != nullptr; - pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC)) - { - LOG_FMT(LTEMPL, "%s(%d): type is %s, level is %zu\n", - __func__, __LINE__, get_token_name(pc->type), level); - - if ( (pc->str[0] == '>') - && (pc->len() > 1)) - { - if (pc->str[1] == '=') // Issue #1462 and #2565 - { - LOG_FMT(LTEMPL, "%s(%d): do not split '%s' at orig_line %zu, orig_col %zu\n", - __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col); - } - else - { - LOG_FMT(LTEMPL, "%s(%d): {split '%s' at orig_line %zu, orig_col %zu}\n", - __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col); - split_off_angle_close(pc); - } - } - - if (chunk_is_token(pc, CT_DECLTYPE)) - { - flag_cpp_decltype(pc); - } - else if (chunk_is_token(pc, CT_PAREN_OPEN)) - { - ++parens; - } - else if (chunk_is_token(pc, CT_PAREN_CLOSE)) - { - --parens; - } - - if (parens == 0) - { - if (chunk_is_str(pc, "<", 1)) - { - level++; - } - else if (chunk_is_str(pc, ">", 1)) - { - if (level == 0) - { - fprintf(stderr, "%s(%d): level is ZERO, cannot be decremented, at line %zu, column %zu\n", - __func__, __LINE__, pc->orig_line, pc->orig_col); - log_flush(true); - exit(EX_SOFTWARE); - } - level--; - - if (level == 0) - { - break; - } - } - } - } - - end = pc; - } - else - { - /* - * We may have something like "a< ... >", which is a template where - * '...' may consist of anything except a semicolon, unbalanced - * parens, or braces (with one exception being braced initializers - * embedded within decltypes). - * - * For example, braces may be encountered as such in the following - * snippet of valid C++ code: - * - * template<typename T, - * typename = enable_if_t<is_same<typename decay<T>::type, - * decltype (make_index_sequence<5> { })>::value>> - * void foo(T &&arg) - * { - * - * } - * - * Finally, if we are inside an 'if' statement and hit a CT_BOOL, - * then it isn't a template. - */ - - if (invalid_open_angle_template(prev)) - { - LOG_FMT(LTEMPL, "%s(%d): - after type %s + ( - Not a template\n", - __func__, __LINE__, get_token_name(prev->type)); - set_chunk_type(start, CT_COMPARE); - return; - } - LOG_FMT(LTEMPL, "%s(%d): - prev->type is %s -\n", - __func__, __LINE__, get_token_name(prev->type)); - - // Scan back and make sure we aren't inside square parenthesis - bool in_if = false; - bool hit_semicolon = false; - pc = start; - - while ((pc = chunk_get_prev_ncnnl(pc, scope_e::PREPROC)) != nullptr) - { - if ( ( chunk_is_token(pc, CT_SEMICOLON) - && hit_semicolon) - || chunk_is_token(pc, CT_SQUARE_CLOSE)) - { - break; - } - - if (chunk_is_token(pc, CT_DECLTYPE)) - { - flag_cpp_decltype(pc); - } - - if (chunk_is_token(pc, CT_BRACE_OPEN)) - { - if ( !pc->flags.test(PCF_IN_DECLTYPE) - || !detect_cpp_braced_init_list(pc->prev, pc)) - { - break; - } - flag_cpp_braced_init_list(pc->prev, pc); - } - - if ( chunk_is_token(pc, CT_BRACE_CLOSE) - && get_chunk_parent_type(pc) != CT_BRACED_INIT_LIST - && !pc->flags.test(PCF_IN_DECLTYPE)) - { - break; - } - - if ( chunk_is_token(pc, CT_SEMICOLON) - && !hit_semicolon) - { - hit_semicolon = true; - } - - if ( ( ( chunk_is_token(pc, CT_IF) - || chunk_is_token(pc, CT_RETURN) - || chunk_is_token(pc, CT_WHILE) - || chunk_is_token(pc, CT_WHILE_OF_DO)) - && !hit_semicolon) - || ( chunk_is_token(pc, CT_FOR) - && hit_semicolon)) - { - in_if = true; - break; - } - } - /* - * Scan forward to the angle close - * If we have a comparison in there, then it can't be a template. - */ - const int max_token_count = 1024; - c_token_t tokens[max_token_count]; - size_t num_tokens = 1; - - tokens[0] = CT_ANGLE_OPEN; - - for (pc = chunk_get_next_ncnnl(start, scope_e::PREPROC); - pc != nullptr; - pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC)) - { - constexpr static auto LCURRENT = LTEMPL; - - LOG_FMT(LTEMPL, "%s(%d): pc->orig_line is %zu, pc->orig_col is %zu, type is %s, num_tokens is %zu\n", - __func__, __LINE__, pc->orig_line, pc->orig_col, get_token_name(pc->type), num_tokens); - - log_rule_B("tok_split_gte"); - - if (chunk_is_token(pc, CT_BRACE_OPEN)) // Issue #2886 - { - // look for the closing brace - chunk_t *A = chunk_skip_to_match(pc); - LOG_FMT(LTEMPL, "%s(%d): A->orig_line is %zu, A->orig_col is %zu, type is %s\n", - __func__, __LINE__, A->orig_line, A->orig_col, get_token_name(A->type)); - pc = chunk_get_next(A); - } - - if ( (tokens[num_tokens - 1] == CT_ANGLE_OPEN) - && (pc->str[0] == '>') - && (pc->len() > 1) - && ( options::tok_split_gte() - || ( ( chunk_is_str(pc, ">>", 2) - || chunk_is_str(pc, ">>>", 3)) - && ( num_tokens >= 2 - || ( num_tokens >= 1 - && in_type_cast))))) - { - LOG_FMT(LTEMPL, "%s(%d): {split '%s' at orig_line %zu, orig_col %zu}\n", - __func__, __LINE__, pc->text(), pc->orig_line, pc->orig_col); - - split_off_angle_close(pc); - } - - if (chunk_is_str(pc, "<", 1)) - { - if ( num_tokens > 0 && (tokens[num_tokens - 1] == CT_PAREN_OPEN) - && invalid_open_angle_template(pc->prev)) - { - set_chunk_type(pc, CT_COMPARE); // Issue #3127 - } - else - { - tokens[num_tokens] = CT_ANGLE_OPEN; - num_tokens++; - } - } - else if (chunk_is_str(pc, ">", 1)) - { - if (num_tokens > 0 && (tokens[num_tokens - 1] == CT_PAREN_OPEN)) - { - handle_double_angle_close(pc); - } - else if (--num_tokens <= 0) - { - break; - } - else if (tokens[num_tokens] != CT_ANGLE_OPEN) - { - break; // unbalanced parentheses - } - } - else if ( in_if - && ( chunk_is_token(pc, CT_BOOL) - || chunk_is_token(pc, CT_COMPARE))) - { - break; - } - else if (chunk_is_token(pc, CT_BRACE_OPEN)) - { - if ( !pc->flags.test(PCF_IN_DECLTYPE) - || !detect_cpp_braced_init_list(pc->prev, pc)) - { - break; - } - auto brace_open = chunk_get_next_ncnnl(pc); - auto brace_close = chunk_skip_to_match(brace_open); - - set_chunk_parent(brace_open, CT_BRACED_INIT_LIST); - set_chunk_parent(brace_close, CT_BRACED_INIT_LIST); - } - else if ( chunk_is_token(pc, CT_BRACE_CLOSE) - && get_chunk_parent_type(pc) != CT_BRACED_INIT_LIST - && !pc->flags.test(PCF_IN_DECLTYPE)) - { - break; - } - else if (chunk_is_token(pc, CT_SEMICOLON)) - { - break; - } - else if (chunk_is_token(pc, CT_PAREN_OPEN)) - { - if (num_tokens >= max_token_count - 1) - { - break; - } - tokens[num_tokens] = CT_PAREN_OPEN; - num_tokens++; - } - else if ( chunk_is_token(pc, CT_QUESTION) // Issue #2949 - && language_is_set(LANG_CPP)) - { - break; - } - else if (chunk_is_token(pc, CT_PAREN_CLOSE)) - { - if (num_tokens == 0) - { - fprintf(stderr, "%s(%d): num_tokens is ZERO, cannot be decremented, at line %zu, column %zu\n", - __func__, __LINE__, pc->orig_line, pc->orig_col); - log_flush(true); - exit(EX_SOFTWARE); - } - num_tokens--; - - if (tokens[num_tokens] != CT_PAREN_OPEN) - { - break; // unbalanced parentheses - } - } - } - - end = pc; - } - - if (chunk_is_token(end, CT_ANGLE_CLOSE)) - { - pc = chunk_get_next_ncnnl(end, scope_e::PREPROC); - - if ( pc == nullptr - || pc->type != CT_NUMBER) - { - LOG_FMT(LTEMPL, "%s(%d): Template detected\n", __func__, __LINE__); - LOG_FMT(LTEMPL, "%s(%d): from orig_line %zu, orig_col %zu\n", - __func__, __LINE__, start->orig_line, start->orig_col); - LOG_FMT(LTEMPL, "%s(%d): to orig_line %zu, orig_col %zu\n", - __func__, __LINE__, end->orig_line, end->orig_col); - set_chunk_parent(start, CT_TEMPLATE); - - check_template_args(start, end); - - set_chunk_parent(end, CT_TEMPLATE); - chunk_flags_set(end, PCF_IN_TEMPLATE); - return; - } - } - LOG_FMT(LTEMPL, "%s(%d): - Not a template: end = %s\n", - __func__, __LINE__, (end != nullptr) ? get_token_name(end->type) : "<null>"); - set_chunk_type(start, CT_COMPARE); -} // check_template - - -static void check_template_arg(chunk_t *start, chunk_t *end) -{ - LOG_FMT(LTEMPL, "%s(%d): Template argument detected\n", __func__, __LINE__); - LOG_FMT(LTEMPL, "%s(%d): from orig_line %zu, orig_col %zu\n", - __func__, __LINE__, start->orig_line, start->orig_col); - LOG_FMT(LTEMPL, "%s(%d): to orig_line %zu, orig_col %zu\n", - __func__, __LINE__, end->orig_line, end->orig_col); - - // Issue #1127 - // MyFoo<mySize * 2> foo1; - // MyFoo<2*mySize * 2> foo1; - // Issue #1346 - // use it as ONE line: - // typename std::enable_if<!std::is_void<T>::value, - // QVector<T> >::type dummy(const std::function<T*(const S&)>& - // pFunc, const QVector<S>& pItems) - // we need two runs - // 1. run to test if expression is numeric - bool expressionIsNumeric = false; - chunk_t *pc = start; - - while (pc != end) - { - chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC); - // a test "if (next == nullptr)" is not necessary - chunk_flags_set(pc, PCF_IN_TEMPLATE); - - if ( chunk_is_token(pc, CT_DECLTYPE) - || chunk_is_token(pc, CT_SIZEOF)) - { - expressionIsNumeric = true; - break; - } - - if (next->type != CT_PAREN_OPEN) - { - if ( chunk_is_token(pc, CT_NUMBER) - || chunk_is_token(pc, CT_ARITH) - || chunk_is_token(pc, CT_SHIFT)) - { - expressionIsNumeric = true; - break; - } - } - pc = next; - } - LOG_FMT(LTEMPL, "%s(%d): expressionIsNumeric is %s\n", - __func__, __LINE__, expressionIsNumeric ? "TRUE" : "FALSE"); - - // 2. run to do the work - if (!expressionIsNumeric) - { - pc = start; - - while (pc != end) - { - chunk_t *next = chunk_get_next_ncnnl(pc, scope_e::PREPROC); - // a test "if (next == nullptr)" is not necessary - chunk_flags_set(pc, PCF_IN_TEMPLATE); - - chunk_t *prev = chunk_get_prev_ncnnl(pc, scope_e::PREPROC); - chunk_t *prev2 = chunk_get_prev_ncnnl(prev, scope_e::PREPROC); - - if ( chunk_is_token(prev, CT_ELLIPSIS) // Issue #3309 - && chunk_is_token(prev2, CT_TYPENAME)) - { - set_chunk_type(pc, CT_PARAMETER_PACK); - } - else - { - make_type(pc); - } - pc = next; - } - } -} // check_template_arg - - -static void check_template_args(chunk_t *start, chunk_t *end) -{ - std::vector<c_token_t> tokens; - - // Scan for commas - chunk_t *pc; - - for (pc = chunk_get_next_ncnnl(start, scope_e::PREPROC); - pc != nullptr && pc != end; - pc = chunk_get_next_ncnnl(pc, scope_e::PREPROC)) - { - switch (pc->type) - { - case CT_COMMA: - - if (tokens.empty()) - { - // Check current argument - check_template_args(start, pc); - start = pc; - } - break; - - case CT_ANGLE_OPEN: - case CT_PAREN_OPEN: - tokens.push_back(pc->type); - break; - - case CT_ANGLE_CLOSE: - - if ( !tokens.empty() - && tokens.back() == CT_ANGLE_OPEN) - { - tokens.pop_back(); - } - break; - - case CT_PAREN_CLOSE: - - if ( !tokens.empty() - && tokens.back() == CT_PAREN_OPEN) - { - tokens.pop_back(); - } - break; - - default: - break; - } - } - - // Check whatever is left - check_template_arg(start, end); -} // check_template_args - - -static void cleanup_objc_property(chunk_t *start) -{ - assert(chunk_is_token(start, CT_OC_PROPERTY)); - - chunk_t *open_paren = chunk_get_next_type(start, CT_PAREN_OPEN, start->level); - - if (open_paren == nullptr) - { - LOG_FMT(LTEMPL, "%s(%d): Property is not followed by openning paren\n", __func__, __LINE__); - return; - } - set_chunk_parent(open_paren, start->type); - - chunk_t *tmp = chunk_get_next_type(start, CT_PAREN_CLOSE, start->level); - - if (tmp != nullptr) - { - set_chunk_parent(tmp, start->type); - tmp = chunk_get_next_ncnnl(tmp); - - if (tmp != nullptr) - { - chunk_flags_set(tmp, PCF_STMT_START | PCF_EXPR_START); - - tmp = chunk_get_next_type(tmp, CT_SEMICOLON, start->level); - - if (tmp != nullptr) - { - set_chunk_parent(tmp, start->type); - } - } - } - mark_selectors_in_property_with_open_paren(open_paren); - mark_attributes_in_property_with_open_paren(open_paren); -} - - -static void mark_selectors_in_property_with_open_paren(chunk_t *open_paren) -{ - assert(chunk_is_token(open_paren, CT_PAREN_OPEN)); - - chunk_t *tmp = open_paren; - - while ( tmp != nullptr - && tmp->type != CT_PAREN_CLOSE) - { - if ( chunk_is_token(tmp, CT_WORD) - && ( chunk_is_str(tmp, "setter", 6) - || chunk_is_str(tmp, "getter", 6))) - { - tmp = tmp->next; - - while ( tmp != nullptr - && tmp->type != CT_COMMA - && tmp->type != CT_PAREN_CLOSE) - { - if ( chunk_is_token(tmp, CT_WORD) - || chunk_is_str(tmp, ":", 1)) - { - set_chunk_type(tmp, CT_OC_SEL_NAME); - } - tmp = tmp->next; - } - } - else - { - tmp = tmp->next; - } - } -} - - -static void mark_attributes_in_property_with_open_paren(chunk_t *open_paren) -{ - assert(chunk_is_token(open_paren, CT_PAREN_OPEN)); - - chunk_t *tmp = open_paren; - - while ( tmp != nullptr - && tmp->type != CT_PAREN_CLOSE) - { - if ( ( chunk_is_token(tmp, CT_COMMA) - || chunk_is_token(tmp, CT_PAREN_OPEN)) - && ( chunk_is_token(tmp->next, CT_WORD) - || chunk_is_token(tmp->next, CT_TYPE))) - { - set_chunk_type(tmp->next, CT_OC_PROPERTY_ATTR); - } - tmp = tmp->next; - } -} |