summaryrefslogtreecommitdiffstats
path: root/debian/uncrustify-trinity/uncrustify-trinity-0.74.0/src/tokenize_cleanup.cpp
diff options
context:
space:
mode:
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.cpp1756
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;
- }
-}