Ejemplo n.º 1
0
 std::string Property::getAsStringOrDefaultVal(const std::string& defaultVal) const
 {
   if (getAsString().length() > 0)
   {
     return getAsString();
   }
   return defaultVal;
 }
Ejemplo n.º 2
0
void InfoControl::audioStreamChanged(){
	bool exist = false;
	int row = audioStream.getActiveItem(exist);
	if(exist){
		auto stream = actualMediaFile->getMediaInfo().getAudioStreams()[row];
		audioCodec << getAsString(stream, "", MediaFile::AudioStream::CODEC);
		audioBitrate << getAsString(stream, "", MediaFile::AudioStream::BITRATE);
		samplerate << getAsString(stream, "", MediaFile::AudioStream::SAMPLERATE);
		channels << getAsString(stream, "", MediaFile::AudioStream::CHANNELS);
	}
}
Ejemplo n.º 3
0
/*!
 * \brief This method creates a MockDataSet
 * \return Returns a mocked DataSet that has the required behavior for unittests
 */
te::da::MockDataSet* createMockDataSet()
{
  te::da::MockDataSet* mockDataSet(new te::da::MockDataSet());

  EXPECT_CALL(*mockDataSet, moveNext()).WillRepeatedly(::testing::Return(true));
  EXPECT_CALL(*mockDataSet, getAsString(::testing::An<const std::string&>(),::testing::_)).WillRepeatedly(::testing::Return(""));
  EXPECT_CALL(*mockDataSet, getAsString(::testing::An<std::size_t>(),::testing::_)).WillRepeatedly(::testing::Return(""));
  EXPECT_CALL(*mockDataSet, isNull(std::string())).WillRepeatedly(::testing::Return(false));
  EXPECT_CALL(*mockDataSet, getNumProperties()).WillRepeatedly(::testing::Return(0));
  EXPECT_CALL(*mockDataSet, moveFirst()).WillRepeatedly(::testing::Return(true));

  return mockDataSet;
}
Ejemplo n.º 4
0
bool HTTPRequest::send() {
    // CREATE HTTP REQUEST
    std::string request = getAsString();
    std::copy(request.begin(), request.end(), std::back_inserter(out_buffer));

    // HINTS FOR SOCKET
    struct addrinfo hints;
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = 0;

    // SECURE CONNECTION?
    std::string port = "80";
    if(is_secure) {
        port = "443";
    }

    int r = uv_getaddrinfo(loop, &resolver_req, httpreq_on_resolved, host.c_str(), port.c_str(), &hints);
    if(r) {
        printf("ERROR: cannot resolve addres: %s\n", uv_err_name(uv_last_error(loop)));
        return false;
    }
    return true;
}
Ejemplo n.º 5
0
    void changeListenerCallback (ChangeBroadcaster* source) override
    {
        if (ColourSelector* cs = dynamic_cast<ColourSelector*> (source))
            editor.applyNewValue (getAsString (cs->getCurrentColour(), true));

        repaint();
    }
Ejemplo n.º 6
0
 double Property::getAsDoubleOrDefaultVal(double defaultVal) const
 {
   if (getAsString().length() > 0)
   {
     return getAsDouble();
   }
   return defaultVal;
 }
Ejemplo n.º 7
0
 bool Property::getAsBoolOrDefault(bool defaultVal) const
 {
   if (getAsString().length() > 0)
   {
     return getAsBool();
   }
   return defaultVal;
 }
Ejemplo n.º 8
0
 int Property::getAsIntOrDefaultVal(int defaultVal) const
 {
   if (getAsString().length() > 0)
   {
     return getAsInt();
   }
   return defaultVal;
 }
Ejemplo n.º 9
0
bool LuaFileFormat::write(Project * project, const std::string & filename){
	std::ofstream file(filename.c_str());
	if (!file) {
		error_code = EFFE_IO_ERROR;
		return false;
	}
	file << getAsString(project);
	file.close();
	return true;
}
void MemsetZeroLengthCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("decl");

  // Note, this is:
  // void *memset(void *buffer, int fill_char, size_t byte_count);
  // Arg1 is fill_char, Arg2 is byte_count.
  const Expr *Arg1 = Call->getArg(1);
  const Expr *Arg2 = Call->getArg(2);

  // Return if `byte_count` is not zero at compile time.
  llvm::APSInt Value1, Value2;
  if (Arg2->isValueDependent() ||
      !Arg2->EvaluateAsInt(Value2, *Result.Context) || Value2 != 0)
    return;

  // Return if `fill_char` is known to be zero or negative at compile
  // time. In these cases, swapping the args would be a nop, or
  // introduce a definite bug. The code is likely correct.
  if (!Arg1->isValueDependent() &&
      Arg1->EvaluateAsInt(Value1, *Result.Context) &&
      (Value1 == 0 || Value1.isNegative()))
    return;

  // `byte_count` is known to be zero at compile time, and `fill_char` is
  // either not known or known to be a positive integer. Emit a warning
  // and fix-its to swap the arguments.
  auto D = diag(Call->getLocStart(),
                "memset of size zero, potentially swapped arguments");
  SourceRange LHSRange = Arg1->getSourceRange();
  SourceRange RHSRange = Arg2->getSourceRange();
  StringRef RHSString = getAsString(Result, RHSRange);
  StringRef LHSString = getAsString(Result, LHSRange);
  if (LHSString.empty() || RHSString.empty())
    return;

  D << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(LHSRange),
                                    RHSString)
    << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(RHSRange),
                                    LHSString);
}
Ejemplo n.º 11
0
// get string representation (for %n and %N), foff is for multi-line formatting offset, -1 = no line breaks
// if del is true, then the returned QoreString * should be deleted, if false, then it must not be
// the ExceptionSink is only needed for QoreObject where a method may be executed
// use the QoreNodeAsStringHelper class (defined in QoreStringNode.h) instead of using this function directly
QoreString* QoreValueList::getAsString(bool &del, int foff, ExceptionSink* xsink) const {
   if (!priv->length && foff != FMT_YAML_SHORT) {
      del = false;
      return &EmptyListString;
   }

   TempString rv(new QoreString);
   if (getAsString(*(*rv), foff, xsink))
      return 0;

   del = true;
   return rv.release();
}
Ejemplo n.º 12
0
void InfoControl::videoStreamChanged(){
	bool exist = false;
	int row = videoStream.getActiveItem(exist);
	if(exist){
		auto stream = actualMediaFile->getMediaInfo().getVideoStreams()[row];
		videoCodec << getAsString(stream, "", MediaFile::VideoStream::CODEC);
		colorSpace << getAsString(stream, "", MediaFile::VideoStream::COLORSPACE);
		resolution << (getAsString(stream, "", MediaFile::VideoStream::RESX) + "x" +
				getAsString(stream, "", MediaFile::VideoStream::RESY));
		fps << getAsString(stream, "", MediaFile::VideoStream::FPS);
		tbr << getAsString(stream, "", MediaFile::VideoStream::TBR);
		tbn << getAsString(stream, "", MediaFile::VideoStream::TBN);
		tbc << getAsString(stream, "", MediaFile::VideoStream::TBC);
		if(stream.isDefault()){
			extra << DEFAULT_STREAM;
		}else{
			extra << std::string();
		}
	}
}
Ejemplo n.º 13
0
IntVec IntVec::append(const IntVec& rhs){
  IntVec new_vec(getAsString());

  //base case
  if(!rhs.first){return new_vec;}

  Node* current = rhs.first;
  new_vec.last->next = new Node;
  new_vec.last = new_vec.last->next;
  new_vec.last->i = current->i;
  while(current->next){
    current = current->next;
    new_vec.last->next = new Node;
    new_vec.last = new_vec.last->next;
    new_vec.last->i = current->i;
  }

  return new_vec;
}
Ejemplo n.º 14
0
 double Property::getAsDouble() const
 {
   return stringutil::StringToDouble(getAsString());
 }
Ejemplo n.º 15
0
 bool Property::getAsBool() const
 {
   return stringutil::StringToBool(getAsString());
 }
Ejemplo n.º 16
0
    void OpNewExprHandler::run(const clang::ast_matchers::MatchFinder::MatchResult &result)
    {
        const clang::ExplicitCastExpr* castExpr = result.Nodes.getNodeAs<clang::ExplicitCastExpr>("castExpr");
        const clang::CallExpr* newExpr = result.Nodes.getNodeAs<clang::CallExpr>("newStmt");
        if (nullptr == castExpr)
        {
            llvm::errs() << "Couldn't convert MatcherResult to ExplicitCastExpr!\n";
            return;
        }
        if (nullptr == newExpr)
        {
            llvm::errs() << "Couldn't convert MatcherResult to CallExpr!\n";
            return;
        }
        // Skipping substituted template types
        auto srcType = castExpr->getTypeInfoAsWritten()->getTypeLoc();
        auto ptr = srcType.getType().getTypePtr()->getAs<clang::SubstTemplateTypeParmType>();
        if (ptr) {
            // This is an automatic template specialization.
            // TODO: add additional checks that this condition is good! TBH I have no idea why it works, I should read more CLANG apidocs :)
            // I mean:
            // * partial template specialization
            // * why isn't a specialized template a substitution? (or maybe it's in the standard?)
            return;
        }

        std::string macroStart = "TYPEGRIND_LOG_OP_NEW";
        macroStart += "(";

        // 1st paramter: name of the type.
        // Currently it is the concrete name if we can place it in the source without generating a template specialization
        // otherwise it's based on typeid, so we are missing a demangle function ...

        auto allocatedType = castExpr->getType()->getPointeeType();
        if (allocatedType.getTypePtr()->isTemplateTypeParmType()) {
            // TODO: somehow add compiler specific demangle ...
            // We could generate a (manual) specialization for this function, but for now, this is enough
            // Let's just use type_info::name(), and demangle it somehow runtime...
            // or maybe create an initialization code dumping the mangled names for all affected specializations? (the ones skipped by the previous return)
            macroStart += "typeid(" + allocatedType.getAsString() + ").name()";
        } else {
            macroStart += "\"" + allocatedType.getAsString() + "\""; // + (int)allocatedType.getTypePtr()->getAsTagDecl();
        }
        macroStart += ", ";

        // 2nd parameter: source location. At least this is easy
        auto& sm = result.Context->getSourceManager();
        auto ploc = sm.getPresumedLoc(newExpr->getLocEnd());
        macroStart += "\"";
        macroStart += ploc.getFilename();
        macroStart += ":";
        macroStart += std::to_string(ploc.getLine());
        macroStart += "\", ";

        // 3rd parameter: the new call. It's the expression itself

        clang::SourceLocation startLoc = newExpr->getLocStart();
        mRewriter->InsertText(startLoc, macroStart);

        // 4th parameter: sizeof type
        std::string macroEnd;
        macroEnd += ", ";
        macroEnd += "sizeof(";
        macroEnd += allocatedType.getAsString();
        macroEnd += ")";


        // 5th argument: size, which is the first argument to the call
        // TODO: extract it to a variable!
        macroEnd += ", ";
        llvm::raw_string_ostream os(macroEnd);
        newExpr->getArg(0)->printPretty(os, nullptr, clang::PrintingPolicy(result.Context->getPrintingPolicy()));
        os.flush();

        // end added function call
        macroEnd += ")";

        clang::SourceLocation endLoc = newExpr->getLocEnd();
        mRewriter->InsertTextAfterToken(endLoc, macroEnd);
    }
Ejemplo n.º 17
0
// if del is true, then the returned QoreString*  should be deleted, if false, then it must not be
QoreString* CallReferenceCallNode::getAsString(bool& del, int foff, ExceptionSink* xsink) const {
   del = true;
   QoreString* rv = new QoreString;
   getAsString(*rv, foff, xsink);
   return rv;
}
Ejemplo n.º 18
0
const std::string JSONArray::getAsString(const int index,
                                         const std::string& defaultValue) const {
  const JSONString* jsString = getAsString(index);
  return (jsString == NULL) ? defaultValue : jsString->value();
}
Ejemplo n.º 19
0
Variable* getAsVariable(types::InternalType* _pIT)
{
    Variable* pOut = NULL;

    switch (_pIT->getType())
    {
        case types::InternalType::ScilabDouble :
        {
            return getAsDouble(_pIT);
        }
        case types::InternalType::ScilabString :
        {
            return getAsString(_pIT);
        }
        case types::InternalType::ScilabBool :
        {
            return getAsBoolean(_pIT);
        }
        case types::InternalType::ScilabSparse :
        {
            return getAsSparse(_pIT);
        }
        case types::InternalType::ScilabSparseBool :
        {
            //return getAsSparseBool(_pIT);
            return NULL;
        }
        case types::InternalType::ScilabHandle :
        {
            return getAsHandle(_pIT);
        }
        case types::InternalType::ScilabUserType :
        {
            return getAsPointer(_pIT);
        }
        case types::InternalType::ScilabList :
        {
            return getAsList(_pIT);
        }
        case types::InternalType::ScilabMList :
        {
            return getAsMList(_pIT);
        }
        case types::InternalType::ScilabTList :
        {
            return getAsTList(_pIT);
        }
        case types::InternalType::ScilabPolynom :
        {
            //return getAsPolynom(_pIT);
            return NULL;
        }
        case types::InternalType::ScilabStruct :
        {
            //return getAsStruct(_pIT);
            return NULL;
        }
        default:
        {
            return NULL;
        }
    }

    return NULL;
}
Ejemplo n.º 20
0
// if del is true, then the returned QoreString * should be deleted, if false, then it must not be
QoreString *RegexTransNode::getAsString(bool &del, int foff, ExceptionSink *xsink) const {
   del = true;
   QoreString *rv = new QoreString;
   getAsString(*rv, foff, xsink);
   return rv;
}
Ejemplo n.º 21
0
/**
 * \a obj is an expression to a type of an QObject (or pointer to) that is the sender or the receiver
 * \a method is an expression like SIGNAL(....)  or SLOT(....)
 *
 * This function try to find the matching signal or slot declaration, and register its use.
 */
void QtSupport::handleSignalOrSlot(clang::Expr* obj, clang::Expr* method)
{
    if (!obj || !method) return;
    obj = obj->IgnoreImpCasts();
    method = method->IgnoreImpCasts();
    auto objType = obj->getType().getTypePtrOrNull();
    if (!objType) return;

    const clang::CXXRecordDecl* objClass = objType->getPointeeCXXRecordDecl();
    if (!objClass) {
        // It can be a non-pointer if called like:  foo.connect(....);
        objClass = objType->getAsCXXRecordDecl();
        if (!objClass) return;
    }

    const clang::StringLiteral *methodLiteral = clang::dyn_cast<clang::StringLiteral>(method);
    if (!methodLiteral) {
        // try qFlagLocation
        clang::CallExpr *flagLoc = clang::dyn_cast<clang::CallExpr>(method);

        if (!flagLoc || flagLoc->getNumArgs() != 1 || !flagLoc->getDirectCallee()
            || flagLoc->getDirectCallee()->getName() != "qFlagLocation") return;


        methodLiteral = clang::dyn_cast<clang::StringLiteral>(flagLoc->getArg(0)->IgnoreImpCasts());
        if (!methodLiteral) return;
    }
    if (methodLiteral->getCharByteWidth() != 1) return;


    auto signature = methodLiteral->getString().trim();
    if (signature.size() < 4)
        return;

    if (signature.find('\0') != signature.npos) {
        signature = signature.substr(0, signature.find('\0')).trim();
    }

    auto lParenPos = signature.find('(');
    auto rParenPos = signature.find(')');
    if (rParenPos == std::string::npos || rParenPos < lParenPos || lParenPos < 2)
        return;

    llvm::StringRef methodName = signature.slice(1 , lParenPos).trim();

    // Try to find the method which match this name in the given class or bases.
    auto candidates = lookUpCandidates(objClass, methodName);

    clang::LangOptions lo;
    lo.CPlusPlus = true;
    lo.Bool = true;
    clang::PrintingPolicy policy(lo);
    policy.SuppressScope = true;

    auto argPos = lParenPos + 1;
    unsigned int arg = 0;
    while (argPos < signature.size() && !candidates.empty()) {

        // Find next comma to extract the next argument
        auto searchPos = argPos;
        while (searchPos < signature.size() && signature[searchPos] != ','
                && signature[searchPos] != ')') {
            if (signature[searchPos] == '<') {
                int depth = 0;
                int templDepth = 0;
                searchPos++;
                while(searchPos < signature.size() && depth >= 0 && templDepth >= 0) {
                    switch (signature[searchPos]) {
                        case '(': case '[': case '{': depth++; break;
                        case ')': case ']': case '}': depth--; break;
                        case '>': if (depth == 0) templDepth--; break;
                        case '<': if (depth == 0) templDepth++; break;
                    }
                    ++searchPos;
                }
                continue;
            }
            ++searchPos;
        }

        if (searchPos == signature.size())
            return;

        llvm::StringRef argument = signature.substr(argPos, searchPos - argPos).trim();
        // Skip the const at the beginning

        if (argument.startswith("const ") && argument.endswith("&"))
            argument = argument.slice(6, argument.size()-1).trim();

        argPos = searchPos + 1;

        if (argument.empty() && signature[searchPos] == ')' && arg == 0)
            break; //No arguments


        //Now go over the candidates and prune the impossible ones.
        auto it = candidates.begin();
        while (it != candidates.end()) {
            if ((*it)->getNumParams() < arg + 1) {
                // Not enough argument
                it = candidates.erase(it);
                continue;
            }

            auto type = (*it)->getParamDecl(arg)->getType();

            // remove const or const &
            if (type->isReferenceType() && type.getNonReferenceType().isConstQualified())
                type = type.getNonReferenceType();
            type.removeLocalConst();

            auto typeString_ = type.getAsString(policy);

            auto typeString = llvm::StringRef(typeString_).trim();

            // Now compare the two string without mathcin spaces,
            auto sigIt = argument.begin();
            auto parIt = typeString.begin();
            while (sigIt != argument.end() && parIt != typeString.end()) {
                if (*sigIt == *parIt) {
                    ++sigIt;
                    ++parIt;
                } else if (*sigIt == ' ') {
                    ++sigIt;
                } else if (*parIt == ' ') {
                    ++parIt;
                } else if (*sigIt == 'n' && llvm::StringRef(sigIt, 9).startswith("nsigned ")) {
                    // skip unsigned
                    sigIt += 8;
                } else if (*parIt == 'n' && llvm::StringRef(parIt, 9).startswith("nsigned ")) {
                    // skip unsigned
                    parIt += 8;
                } else {
                    break;
                }
            }

            if (sigIt != argument.end() || parIt != typeString.end()) {
                // Did not match.
                it = candidates.erase(it);
                continue;
            }

            ++it;
        }

        arg++;
        if (signature[searchPos] == ')')
            break;
    }

    if (argPos != signature.size())
        return;


    // Remove candidates that needs more argument
    candidates.erase(std::remove_if(candidates.begin(), candidates.end(), [=](clang::CXXMethodDecl *it) {
            return it->getMinRequiredArguments() > arg &&
                !(it->getNumParams() == arg+1 && it->getParamDecl(arg)->getType().getAsString(policy) == "QPrivateSignal");
        }), candidates.end());

    if (candidates.empty())
        return;

    auto used = candidates.front();



    clang::SourceRange range = methodLiteral->getSourceRange();
    if (methodLiteral->getNumConcatenated() >= 2) {
        auto &sm = annotator.getSourceMgr();
        // Goes two level up in the macro expension:  First level is the # expansion,  Second level is SIGNAL macro
        auto r = sm.getImmediateExpansionRange(methodLiteral->getStrTokenLoc(1));
#if CLANG_VERSION_MAJOR < 7
        range = { sm.getImmediateExpansionRange(r.first).first, sm.getImmediateExpansionRange(r.second).second };
#else
        range = { sm.getImmediateExpansionRange(r.getBegin()).getBegin(), sm.getImmediateExpansionRange(r.getEnd()).getEnd() };
#endif

        // now remove the SIGNAL or SLOT macro from the range.
        auto skip = clang::Lexer::MeasureTokenLength(range.getBegin(), sm, annotator.getLangOpts());
        range.setBegin(range.getBegin().getLocWithOffset(skip+1));
        // remove the ')' while we are on it
        range.setEnd(range.getEnd().getLocWithOffset(-1));

    }

    annotator.registerUse(used, range, Annotator::Call, currentContext, Annotator::Use_Address);
}
Ejemplo n.º 22
0
//-------------------------------------------------------------
void Value::fromBlob (
		ValueType type,
		const Byte *blob
	)
{
	int i;

	// Set type
	setType( type );

	if (blob==NULL)
		return;

	switch( type_m ) {
		case VT_Int:
			getAsInt() = *(int *) blob;
			break;

		case VT_IntList:
		{
			int len = *(int *) blob;
			int *data = ((int *) blob) + 1;

			IntList &ilist = getAsIntList();
			ilist.resize( len );

			for(i = 0; i < len; ++i)
				ilist[ i ] = *data++;

			break;
		}

		case VT_Double:
			getAsDouble() = *(double *) blob;
			break;

		case VT_Date:
			getAsDate() = *(double *) blob;
			break;

		case VT_DoubleList:
		{
			int len = *(int *) blob;
			double *data = (double *) (((int *) blob) + 1);

			DoubleList &dlist = getAsDoubleList();
			dlist.resize( len );

			for(i = 0; i < len; ++i)
				dlist[ i ] = *data++;

			break;
		}


		case VT_DateList:
		{
			int len = *(int *) blob;
			double *data = (double *) (((int *) blob) + 1);

			DoubleList &dlist = getAsDateList();
			dlist.resize( len );

			for(i = 0; i < len; ++i)
				dlist[ i ] = *data++;

			break;
		}

		case VT_String:
			getAsString() = (Byte *) blob;
			break;

		case VT_StringList:
		{
			int len = *(int *) blob;
			Byte *data = (Byte *) (((int *) blob) + 1);

			StringList &slist = getAsStringList();
			slist.resize( len );

			for(i = 0; i < len; ++i) {
				slist[ i ] = data;
				data += strlen( data ) + 1;
			}

			break;
		}

		case VT_Uid:
			getAsUid().fromMemory( (Byte *) blob );
			break;

		case VT_UidList:
		{
			int len = *(int *) blob;
			Byte *data = (Byte *) (((int *) blob) + 1);

			UidList &slist = getAsUidList();
			slist.resize( len );

			for(i = 0; i < len; ++i) {
				slist[ i ].fromMemory( data );
				data += Signature::length_scm;
			}

			break;
		}

		case VT_Reference:
			getAsReference().fromString( (Byte *) blob );
			break;

		case VT_ReferenceList:
		{
			int len = *(int *) blob;
			Byte *data = (Byte *) (((int *) blob) + 1);

			ReferenceList &reflist = getAsReferenceList();
			reflist.resize( len );

			for(i = 0; i < len; ++i) {
				reflist[ i ].fromString( data );
				data += strlen( data ) + 1;
			}

			break;
		}

		case VT_StringMap:
		{
			int len = *(int *) blob;
			Byte *data = (Byte *) (((int *) blob) + 1);
			Byte *kdata;

			StringMap &smap = getAsStringMap();
			smap.clear();

			for(i = 0; i < len; ++i) {
				
				kdata = data;
				data += strlen( data ) + 1;
				smap[kdata] =  data;
				data += strlen( data ) + 1;
			}

			break;
		}

	}
}
Ejemplo n.º 23
0
 int Property::getAsInt() const
 {
   return stringutil::StringToInt(getAsString());
 };
Ejemplo n.º 24
0
void getQuery(char* destination) {
	getAsString(ENTER_A_QUERY_IMAGE_OR_TO_TERMINATE, destination);
}
Ejemplo n.º 25
0
// get string representation (for %n and %N), foff is for multi-line formatting offset, -1 = no line breaks
// if del is true, then the returned QoreString*  should be deleted, if false, then it must not be
// the ExceptionSink is only needed for QoreObject where a method may be executed
// use the QoreNodeAsStringHelper class (defined in QoreStringNode.h) instead of using this function directly
QoreString* DateTimeNode::getAsString(bool& del, int foff, ExceptionSink* xsink) const {
   del = true;
   QoreString* str = new QoreString;
   getAsString(*str, foff, xsink);
   return str;
}
Ejemplo n.º 26
0
    void sliderValueChanged (Slider*)
    {
        editor.applyNewValue (isFloat ? getAsString ((double) slider.getValue(), editor.wasHex)
                                      : getAsString ((int64)  slider.getValue(), editor.wasHex));

    }
Ejemplo n.º 27
0
// if del is true, then the returned QoreString * should be deleted, if false, then it must not be
QoreString *SelfVarrefNode::getAsString(bool &del, int foff, ExceptionSink *xsink) const {
   del = true;
   QoreString *rv = new QoreString();
   getAsString(*rv, foff, xsink);
   return rv;
}
void NonConstReferences::check(const MatchFinder::MatchResult &Result) {
  const auto *Parameter = Result.Nodes.getNodeAs<ParmVarDecl>("param");
  const auto *Function =
      dyn_cast_or_null<FunctionDecl>(Parameter->getParentFunctionOrMethod());

  if (Function == nullptr || Function->isImplicit())
    return;

  if (!Function->isCanonicalDecl())
    return;

  if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
    // Don't warn on implementations of an interface using references.
    if (Method->begin_overridden_methods() != Method->end_overridden_methods())
      return;
    // Don't warn on lambdas, as they frequently have to conform to the
    // interface defined elsewhere.
    if (Method->getParent()->isLambda())
      return;
  }

  auto ReferencedType = *Result.Nodes.getNodeAs<QualType>("referenced_type");
  // Don't warn on function references, they shouldn't be constant.
  if (ReferencedType->isFunctionProtoType())
    return;

  // Don't warn on dependent types in templates.
  if (ReferencedType->isDependentType())
    return;

  if (Function->isOverloadedOperator()) {
    switch (Function->getOverloadedOperator()) {
      case clang::OO_LessLess:
      case clang::OO_PlusPlus:
      case clang::OO_MinusMinus:
      case clang::OO_PlusEqual:
      case clang::OO_MinusEqual:
      case clang::OO_StarEqual:
      case clang::OO_SlashEqual:
      case clang::OO_PercentEqual:
      case clang::OO_LessLessEqual:
      case clang::OO_GreaterGreaterEqual:
      case clang::OO_PipeEqual:
      case clang::OO_CaretEqual:
      case clang::OO_AmpEqual:
        // Don't warn on the first parameter of operator<<(Stream&, ...),
        // operator++, operator-- and operation+assignment operators.
        if (Function->getParamDecl(0) == Parameter)
          return;
        break;
      case clang::OO_GreaterGreater: {
        auto isNonConstRef = [](clang::QualType T) {
          return T->isReferenceType() &&
                 !T.getNonReferenceType().isConstQualified();
        };
        // Don't warn on parameters of stream extractors:
        //   Stream& operator>>(Stream&, Value&);
        // Both parameters should be non-const references by convention.
        if (isNonConstRef(Function->getParamDecl(0)->getType()) &&
            (Function->getNumParams() < 2 || // E.g. member operator>>.
             isNonConstRef(Function->getParamDecl(1)->getType())) &&
            isNonConstRef(Function->getReturnType()))
          return;
        break;
      }
      default:
        break;
    }
  }

  // Some functions use references to comply with established standards.
  if (Function->getDeclName().isIdentifier() && Function->getName() == "swap")
    return;

  // iostream parameters are typically passed by non-const reference.
  if (StringRef(ReferencedType.getAsString()).endswith("stream"))
    return;

  diag(Parameter->getLocation(),
       "non-const reference parameter '%0', make it const or use a pointer")
      << Parameter->getName();
}