diff --git a/doc/README.modern_cpp.md b/doc/README.modern_cpp.md index 3f13ae5618..aae134d3f1 100644 --- a/doc/README.modern_cpp.md +++ b/doc/README.modern_cpp.md @@ -23,3 +23,5 @@ Only ones mentioned in this document could be used, but as necessities appears, - [strongly-typed enum](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf) - [atomic types and operations](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html) - [static_assert](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html) +- [decltype](https://en.cppreference.com/w/cpp/language/decltype) +- [std::is_convertible](https://en.cppreference.com/w/cpp/types/is_convertible) diff --git a/src/dsql/AggNodes.cpp b/src/dsql/AggNodes.cpp index d6dbc2fc87..1ab513f2c2 100644 --- a/src/dsql/AggNodes.cpp +++ b/src/dsql/AggNodes.cpp @@ -151,8 +151,8 @@ bool AggNode::dsqlAggregateFinder(AggregateFinder& visitor) NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - visitor.visit(i->getExpr()); + for (auto i : holder.refs) + visitor.visit(*i); localDeepestLevel = visitor.deepestLevel; } @@ -183,8 +183,8 @@ bool AggNode::dsqlAggregateFinder(AggregateFinder& visitor) NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - aggregate |= visitor.visit(i->getExpr()); + for (auto i : holder.refs) + aggregate |= visitor.visit(*i); } return aggregate; @@ -201,8 +201,8 @@ bool AggNode::dsqlAggregate2Finder(Aggregate2Finder& visitor) NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - found |= fieldFinder.visit(i->getExpr()); + for (auto i : holder.refs) + found |= fieldFinder.visit(*i); if (!fieldFinder.getField()) { @@ -248,14 +248,14 @@ bool AggNode::dsqlInvalidReferenceFinder(InvalidReferenceFinder& visitor) NodeRefsHolder holder(visitor.dsqlScratch->getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) + for (auto i : holder.refs) { // If there's another aggregate with the same scope_level or // an higher one then it's a invalid aggregate, because // aggregate-functions from the same context can't // be part of each other. if (Aggregate2Finder::find(visitor.dsqlScratch->getPool(), visitor.context->ctx_scope_level, - FIELD_MATCH_TYPE_EQUAL, false, i->getExpr())) + FIELD_MATCH_TYPE_EQUAL, false, *i)) { // Nested aggregate functions are not allowed ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << @@ -287,8 +287,11 @@ ValueExprNode* AggNode::dsqlFieldRemapper(FieldRemapper& visitor) NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - i->remap(visitor); + for (auto i : holder.refs) + { + if (*i) + *i = (*i)->dsqlFieldRemapper(visitor); + } return this; } @@ -326,7 +329,7 @@ void AggNode::genBlr(DsqlCompilerScratch* dsqlScratch) unsigned count = 0; - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) + for (auto i : holder.refs) { if (*i) ++count; @@ -335,10 +338,10 @@ void AggNode::genBlr(DsqlCompilerScratch* dsqlScratch) dsqlScratch->appendUChar(UCHAR(count)); } - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) + for (auto i : holder.refs) { if (*i) - GEN_expr(dsqlScratch, i->getExpr()); + GEN_expr(dsqlScratch, *i); } } diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index 36af4b92cc..aa7984ac55 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -185,35 +185,6 @@ static void setParameterInfo(dsql_par* parameter, const dsql_ctx* context); //-------------------- -void NodeRef::pass2(thread_db* tdbb, CompilerScratch* csb) -{ - internalPass2(tdbb, csb); - - ExprNode* node = getExpr(); - - // Bind values of invariant nodes to top-level RSE (if present) - if (node && (node->nodFlags & ExprNode::FLAG_INVARIANT)) - { - if (csb->csb_current_nodes.hasData()) - { - RseNode* topRseNode = nodeAs(csb->csb_current_nodes[0]); - fb_assert(topRseNode); - - if (!topRseNode->rse_invariants) - { - topRseNode->rse_invariants = - FB_NEW_POOL(*tdbb->getDefaultPool()) VarInvariantArray(*tdbb->getDefaultPool()); - } - - topRseNode->rse_invariants->add(node->impureOffset); - } - } -} - - -//-------------------- - - void Printable::print(NodePrinter& printer) const { NodePrinter subPrinter(printer.getIndent() + 1); @@ -267,9 +238,9 @@ bool ExprNode::dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other const auto* j = otherHolder.refs.begin(); - for (const auto& i : thisHolder.refs) + for (const auto i : thisHolder.refs) { - if (!i != !*j || !PASS1_node_match(dsqlScratch, i.getExpr(), j->getExpr(), ignoreMapCast)) + if (!*i != !**j || !PASS1_node_match(dsqlScratch, *i, **j, ignoreMapCast)) return false; ++j; @@ -295,12 +266,12 @@ bool ExprNode::sameAs(CompilerScratch* csb, const ExprNode* other, bool ignoreSt const auto* j = otherHolder.refs.begin(); - for (const auto& i : thisHolder.refs) + for (const auto i : thisHolder.refs) { - if (!i && !*j) + if (!*i && !**j) continue; - if (!i || !*j || !i.getExpr()->sameAs(csb, j->getExpr(), ignoreStreams)) + if (!*i || !**j || !(*i)->sameAs(csb, **j, ignoreStreams)) return false; ++j; @@ -314,9 +285,9 @@ bool ExprNode::possiblyUnknown(OptimizerBlk* opt) NodeRefsHolder holder(opt->getPool()); getChildren(holder, false); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) + for (auto i : holder.refs) { - if (*i && i->getExpr()->possiblyUnknown(opt)) + if (*i && (*i)->possiblyUnknown(opt)) return true; } @@ -328,9 +299,9 @@ bool ExprNode::unmappable(CompilerScratch* csb, const MapNode* mapNode, StreamTy NodeRefsHolder holder(csb->csb_pool); getChildren(holder, false); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) + for (auto i : holder.refs) { - if (*i && !i->getExpr()->unmappable(csb, mapNode, shellStream)) + if (*i && !(*i)->unmappable(csb, mapNode, shellStream)) return false; } @@ -342,10 +313,10 @@ void ExprNode::collectStreams(CompilerScratch* csb, SortedStreamList& streamList NodeRefsHolder holder(csb->csb_pool); getChildren(holder, false); - for (const NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) + for (auto i : holder.refs) { if (*i) - i->getExpr()->collectStreams(csb, streamList); + (*i)->collectStreams(csb, streamList); } } @@ -355,9 +326,9 @@ bool ExprNode::computable(CompilerScratch* csb, StreamType stream, NodeRefsHolder holder(csb->csb_pool); getChildren(holder, false); - for (auto& i : holder.refs) + for (auto i : holder.refs) { - if (i && !i.getExpr()->computable(csb, stream, allowOnlyCurrentStream)) + if (*i && !(*i)->computable(csb, stream, allowOnlyCurrentStream)) return false; } @@ -369,10 +340,10 @@ void ExprNode::findDependentFromStreams(const OptimizerRetrieval* optRet, Sorted NodeRefsHolder holder(optRet->getPool()); getChildren(holder, false); - for (auto& i : holder.refs) + for (auto i : holder.refs) { - if (i) - i.getExpr()->findDependentFromStreams(optRet, streamList); + if (*i) + (*i)->findDependentFromStreams(optRet, streamList); } } @@ -381,10 +352,10 @@ ExprNode* ExprNode::pass1(thread_db* tdbb, CompilerScratch* csb) NodeRefsHolder holder(csb->csb_pool); getChildren(holder, false); - for (auto& i : holder.refs) + for (auto i : holder.refs) { - if (i) - i.pass1(tdbb, csb); + if (*i) + doPass1(tdbb, csb, i); } return this; @@ -395,10 +366,32 @@ ExprNode* ExprNode::pass2(thread_db* tdbb, CompilerScratch* csb) NodeRefsHolder holder(csb->csb_pool); getChildren(holder, false); - for (auto& i : holder.refs) + for (auto i : holder.refs) { - if (i) - i.pass2(tdbb, csb); + if (!*i) + continue; + + doPass2(tdbb, csb, i); + + ExprNode* node = *i; + + // Bind values of invariant nodes to top-level RSE (if present) + if (node && (node->nodFlags & ExprNode::FLAG_INVARIANT)) + { + if (csb->csb_current_nodes.hasData()) + { + RseNode* topRseNode = nodeAs(csb->csb_current_nodes[0]); + fb_assert(topRseNode); + + if (!topRseNode->rse_invariants) + { + topRseNode->rse_invariants = + FB_NEW_POOL(*tdbb->getDefaultPool()) VarInvariantArray(*tdbb->getDefaultPool()); + } + + topRseNode->rse_invariants->add(node->impureOffset); + } + } } return this; @@ -9051,8 +9044,8 @@ bool OverNode::dsqlAggregateFinder(AggregateFinder& visitor) NodeRefsHolder holder(visitor.getPool()); aggExpr->getChildren(holder, true); - for (auto& child : holder.refs) - aggregate |= visitor.visit(child.getExpr()); + for (auto child : holder.refs) + aggregate |= visitor.visit(*child); } else aggregate |= visitor.visit(aggExpr); @@ -9114,10 +9107,10 @@ ValueExprNode* OverNode::dsqlFieldRemapper(FieldRemapper& visitor) NodeRefsHolder holder(visitor.getPool()); aggNode->getChildren(holder, true); - for (auto& child : holder.refs) + for (auto child : holder.refs) { if (Aggregate2Finder::find(visitor.getPool(), visitor.context->ctx_scope_level, FIELD_MATCH_TYPE_EQUAL, - true, child.getExpr())) + true, *child)) { ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << Arg::Gds(isc_dsql_agg_nested_err)); @@ -9137,8 +9130,11 @@ ValueExprNode* OverNode::dsqlFieldRemapper(FieldRemapper& visitor) NodeRefsHolder holder(visitor.getPool()); aggNode->getChildren(holder, true); - for (auto& child : holder.refs) - child.remap(visitor); + for (auto child : holder.refs) + { + if (*child) + *child = (*child)->dsqlFieldRemapper(visitor); + } doDsqlFieldRemapper(visitor, window); } diff --git a/src/dsql/Nodes.h b/src/dsql/Nodes.h index 330a480527..255953724b 100644 --- a/src/dsql/Nodes.h +++ b/src/dsql/Nodes.h @@ -395,64 +395,6 @@ template static bool nodeIs(const NestConst& } -// Stores a reference to a specialized ExprNode. -// This class and NodeRefImpl exists for nodes to replace themselves (eg. pass1) in a type-safe way. -class NodeRef -{ -public: - NodeRef() - : ptr(NULL) - { - } - - template - explicit NodeRef(const NestConst& node) - : ptr(NULL) - { - static_assert(std::is_base_of::value, "T must be derived from ExprNode"); - - T** aPtr = const_cast (node.getAddress()); - ptr = reinterpret_cast (aPtr); - - fb_assert(ptr); - } - - bool operator !() const - { - return !getExpr(); - } - - operator bool() const - { - return getExpr() != NULL; - } - - ExprNode* getExpr() - { - return *ptr; - } - - const ExprNode* getExpr() const - { - return *ptr; - } - - void remap(FieldRemapper& visitor); - - void pass1(thread_db* tdbb, CompilerScratch* csb) - { - DmlNode::doPass1(tdbb, csb, ptr); - } - - void pass2(thread_db* tdbb, CompilerScratch* csb); - -protected: - void internalPass2(thread_db* tdbb, CompilerScratch* csb); - -private: - ExprNode** ptr; -}; - class NodeRefsHolder : public Firebird::PermanentStorage { public: @@ -462,18 +404,41 @@ public: { } - ~NodeRefsHolder() - { - } - - template void add(const NestConst& node) { - refs.add(NodeRef(node)); + static_assert(std::is_base_of::value, "T must be derived from ExprNode"); + + static_assert( + std::is_convertible< + decltype(const_cast(node.getObject())->pass1( + (thread_db*) nullptr, (CompilerScratch*) nullptr)), + decltype(const_cast(node.getObject())) + >::value, + "pass1 problem"); + + static_assert( + std::is_convertible< + decltype(const_cast(node.getObject())->pass2( + (thread_db*) nullptr, (CompilerScratch*) nullptr)), + decltype(const_cast(node.getObject())) + >::value, + "pass2 problem"); + + static_assert( + std::is_convertible< + decltype(const_cast(node.getObject())->dsqlFieldRemapper(*(FieldRemapper*) nullptr)), + decltype(const_cast(node.getObject())) + >::value, + "dsqlFieldRemapper problem"); + + T** ptr = const_cast (node.getAddress()); + fb_assert(ptr); + + refs.add(reinterpret_cast(ptr)); } public: - Firebird::HalfStaticArray refs; + Firebird::HalfStaticArray refs; }; @@ -600,8 +565,8 @@ public: NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - ret |= visitor.visit(i->getExpr()); + for (auto i : holder.refs) + ret |= visitor.visit(*i); return ret; } @@ -613,8 +578,8 @@ public: NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - ret |= visitor.visit(i->getExpr()); + for (auto i : holder.refs) + ret |= visitor.visit(*i); return ret; } @@ -626,8 +591,8 @@ public: NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - ret |= visitor.visit(i->getExpr()); + for (auto i : holder.refs) + ret |= visitor.visit(*i); return ret; } @@ -639,8 +604,8 @@ public: NodeRefsHolder holder(visitor.dsqlScratch->getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - ret |= visitor.visit(i->getExpr()); + for (auto i : holder.refs) + ret |= visitor.visit(*i); return ret; } @@ -652,8 +617,8 @@ public: NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - ret |= visitor.visit(i->getExpr()); + for (auto i : holder.refs) + ret |= visitor.visit(*i); return ret; } @@ -663,8 +628,11 @@ public: NodeRefsHolder holder(visitor.getPool()); getChildren(holder, true); - for (NodeRef* i = holder.refs.begin(); i != holder.refs.end(); ++i) - i->remap(visitor); + for (auto i : holder.refs) + { + if (*i) + *i = (*i)->dsqlFieldRemapper(visitor); + } return this; } @@ -730,18 +698,6 @@ public: }; -inline void NodeRef::remap(FieldRemapper& visitor) -{ - if (*ptr) - *ptr = (*ptr)->dsqlFieldRemapper(visitor); -} - -inline void NodeRef::internalPass2(thread_db* tdbb, CompilerScratch* csb) -{ - ExprNode::doPass2(tdbb, csb, ptr); -} - - class BoolExprNode : public ExprNode { public: diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index c22a734d5b..28a2ccba5c 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -9435,7 +9435,7 @@ static void dsqlSetParameterName(DsqlCompilerScratch* dsqlScratch, ExprNode* exp exprNode->getChildren(holder, true); for (auto ref : holder.refs) - dsqlSetParameterName(dsqlScratch, ref.getExpr(), fld_node, relation); + dsqlSetParameterName(dsqlScratch, *ref, fld_node, relation); break; }