void NonConstParameterCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Parm = Result.Nodes.getNodeAs<ParmVarDecl>("Parm")) { if (const DeclContext *D = Parm->getParentFunctionOrMethod()) { if (const auto *M = dyn_cast<CXXMethodDecl>(D)) { if (M->isVirtual() || M->size_overridden_methods() != 0) return; } } addParm(Parm); } else if (const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("Ctor")) { for (const auto *Parm : Ctor->parameters()) addParm(Parm); for (const auto *Init : Ctor->inits()) markCanNotBeConst(Init->getInit(), true); } else if (const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("Ref")) { setReferenced(Ref); } else if (const auto *S = Result.Nodes.getNodeAs<Stmt>("Mark")) { if (const auto *B = dyn_cast<BinaryOperator>(S)) { if (B->isAssignmentOp()) markCanNotBeConst(B, false); } else if (const auto *CE = dyn_cast<CallExpr>(S)) { // Typically, if a parameter is const then it is fine to make the data // const. But sometimes the data is written even though the parameter // is const. Mark all data passed by address to the function. for (const auto *Arg : CE->arguments()) { markCanNotBeConst(Arg->IgnoreParenCasts(), true); } // Data passed by nonconst reference should not be made const. if (const FunctionDecl *FD = CE->getDirectCallee()) { unsigned ArgNr = 0U; for (const auto *Par : FD->parameters()) { if (ArgNr >= CE->getNumArgs()) break; const Expr *Arg = CE->getArg(ArgNr++); // Is this a non constant reference parameter? const Type *ParType = Par->getType().getTypePtr(); if (!ParType->isReferenceType() || Par->getType().isConstQualified()) continue; markCanNotBeConst(Arg->IgnoreParenCasts(), false); } } } else if (const auto *CE = dyn_cast<CXXConstructExpr>(S)) { for (const auto *Arg : CE->arguments()) { markCanNotBeConst(Arg->IgnoreParenCasts(), true); } } else if (const auto *R = dyn_cast<ReturnStmt>(S)) { markCanNotBeConst(R->getRetValue(), true); } else if (const auto *U = dyn_cast<UnaryOperator>(S)) { markCanNotBeConst(U, true); } } else if (const auto *VD = Result.Nodes.getNodeAs<VarDecl>("Mark")) { const QualType T = VD->getType(); if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) || T->isArrayType()) markCanNotBeConst(VD->getInit(), true); } }
void VariableSerializer::writeOverflow(void* ptr, bool isObject /* = false */) { bool wasRef = m_referenced; setReferenced(false); switch (m_type) { case PrintR: if (!m_objClass.empty()) { m_buf->append(m_objClass); m_buf->append(" Object\n"); } else { m_buf->append("Array\n"); } m_buf->append(" *RECURSION*"); break; case VarExport: throw NestingLevelTooDeepException(); case VarDump: case DebugDump: case DebuggerDump: indent(); m_buf->append("*RECURSION*\n"); break; case DebuggerSerialize: if (m_maxLevelDebugger > 0 && m_levelDebugger > m_maxLevelDebugger) { // Not recursion, just cut short of print m_buf->append("s:12:\"...(omitted)\";", 20); break; } // fall through case Serialize: case APCSerialize: { ASSERT(m_arrayIds); PointerCounterMap::const_iterator iter = m_arrayIds->find(ptr); ASSERT(iter != m_arrayIds->end()); int id = iter->second; if (isObject) { m_buf->append("r:"); m_buf->append(id); m_buf->append(';'); } else if (wasRef) { m_buf->append("R:"); m_buf->append(id); m_buf->append(';'); } else { m_buf->append("N;"); } } break; case JSON: raise_warning("json_encode(): recursion detected"); m_buf->append("null"); break; default: ASSERT(false); break; } }
void VariableSerializer::write(CVarRef v, bool isArrayKey /* = false */) { if (!isArrayKey && v.isObject()) { write(v.toObject()); return; } setReferenced(v.isReferenced()); setRefCount(v.getRefCount()); v.serialize(this, isArrayKey); }
void VariableSerializer::writeOverflow(void* ptr, bool isObject /* = false */) { bool wasRef = m_referenced; setReferenced(false); switch (m_type) { case PrintR: *m_out << "*RECURSION*"; break; case VarExport: throw NestingLevelTooDeepException(); case VarDump: case DebugDump: indent(); *m_out << "*RECURSION*\n"; break; case Serialize: { map<void*, int>::const_iterator iter = m_arrayIds.find(ptr); ASSERT(iter != m_arrayIds.end()); int id = iter->second; if (isObject) { *m_out << "r:" << id << ";"; } else if (wasRef) { *m_out << "R:" << id << ";"; } else { *m_out << "N;"; } } break; case JSON: *m_out << "null"; break; default: ASSERT(false); break; } }