Example #1
0
bool DeclReferencer::VisitCXXConstructExpr(const clang::CXXConstructExpr *E)
{
    auto ConstructedType = E->getType();
    if (!ConstructedType.isNull())
        Reference(ConstructedType.getTypePtr());
    return Reference(E->getConstructor());
}
Example #2
0
bool DeclReferencer::VisitCXXDeleteExpr(const clang::CXXDeleteExpr *E)
{
    auto DestroyedType = E->getDestroyedType();
    if (!DestroyedType.isNull())
        Reference(DestroyedType.getTypePtr());

    return Reference(E->getOperatorDelete());
}
Example #3
0
void freeModel(_md)
{
	size_t predNum, funcNum, axNum, taskNum,
		   factNum, restrNum, typeNum, srcNum, errNum;

	freeServData(modelPtr);

	/* Predicates */
	forVect(predNum, preds_m)
		freeFunc(getPredPtr(predNum));
	
	/* Functions */
	forVect(funcNum, funcs_m)
		freeFunc(getFuncPtr(funcNum));
		
	/* Axioms */
	forVect(axNum, axioms_m)
		freeAxiom(getAxPtr(axNum));

	/* Tasks */
	forVect(taskNum, taskPtrs_m)
		freeTask(getTaskPtr(taskNum));

	/* Temp Facts */
	forVect(factNum, tmpFacts_m)
		freeFact(ptr(Fact, tmpFacts_m) + factNum);

	/* Restrictions */
	forVect(restrNum, restrs_m)
		freeRestriction(getRestrPtr(restrNum));

	/* DataTypes */
	forVect(typeNum, types_m)
		freeDataType(getTypePtr(typeNum));

	/* Sources */
	forVect(srcNum, modelPtr->sources)
		freeSource(ptr(Source, modelPtr->sources) + srcNum);
	
	/* Errors */
	forVect(errNum, modelPtr->errors)
		freeError(ptr(Error, modelPtr->errors) + errNum);

	/* Vectors */
	freeVect(preds_m);
	freeVect(funcs_m);
	freeVect(axioms_m);
	freeVect(taskPtrs_m);
	freeVect(tmpFacts_m)
	freeVect(restrs_m); 
	freeVect(types_m);
	freeVect(modelPtr->errors);
	freeVect(modelPtr->sources);
}
Example #4
0
void initModel(_md)
{
	/* initialize vectors */
	initVect(preds_m,		Pred);
	initVect(funcs_m,		Func);
	initVect(axioms_m,		Axiom);
	initVect(taskPtrs_m,	Task*);
	initVect(tmpFacts_m,	Fact);
	initVect(restrs_m,		Restriction);
	initVect(types_m,		DataType);

	/* create standart datatypes */
	addDataType("Boolean",	modelPtr);
	addDataType("Integer",	modelPtr);
	addDataType("Real",		modelPtr);
	
	/* CONST_TRUE, CONST_FALSE */
	//~ DataType* boolPtr = ptr(DataType, types_m) + DT_BOOL;
	DataType* boolPtr = getTypePtr(DT_BOOL);
	addBack(boolPtr->constNames, char*, getDynamicStr("True"));
	addBack(boolPtr->constNames, char*, getDynamicStr("False"));
	
	/* create arithmetic fuctions */
	size_t funcNum;
	DataTypeId paramTypes[] = {DT_INT, DT_INT};
	
	for (funcNum = 0; funcNum < ARITHMETIC_FUNCTION_COUNT; ++funcNum)
	{	
		Func func = createFunc(	(char*)ARITH_FUNCTION_NAMES[funcNum],
								ARITH_FUNCTION_PAR_COUNTS[funcNum],
								paramTypes, DT_REAL);
		addFunc(func, modelPtr);
	}
	
	/* create arithmetic relations */
	size_t predNum;
	
	for (predNum = 0; predNum < ARITHMETIC_RELATIONS_COUNT; ++predNum)
	{	
		Pred pred = createFunc(	(char*)ARITH_RELATION_NAMES[predNum],
								ARITH_RELATION_PAR_COUNTS[predNum],
								paramTypes, DT_BOOL);
		addPred(pred, modelPtr);
	}
	
	/* other initialization */
	initVect(modelPtr->errors, Error);
	initVect(modelPtr->sources, Source);
	modelPtr->currSrcPtr = NULL;
	modelPtr->totalFactCt = 0;
	modelPtr->debugStream = modelPtr->errorStream = NULL;
}
void OpDeleteExprHandler::run(const clang::ast_matchers::MatchFinder::MatchResult& result) {
  const clang::CallExpr* deleteExpr = result.Nodes.getNodeAs<clang::CallExpr>("deleteStmt");
  const clang::FunctionDecl* funDecl = result.Nodes.getNodeAs<clang::FunctionDecl>("fun");
  if (nullptr == deleteExpr) {
    llvm::errs() << "Couldn't convert MatcherResult to CallExpr!\n";
    return;
  }

  clang::SourceLocation startLoc = deleteExpr->getArg(0)->getLocStart();
  clang::SourceLocation endLoc = deleteExpr->getArg(0)->getLocEnd();

  const clang::Expr* pointerExpr = deleteExpr->getArg(0)->IgnoreCasts();

  auto deletedType = pointerExpr->getType();
  auto ptr = deletedType.getTypePtr();
  if (!ptr->isInstantiationDependentType() && !ptr->hasUnnamedOrLocalType()) {
    handleSpecializedType(pointerExpr->getType(), startLoc.getRawEncoding(), CONVERT_TO_POINTEE);
  }

  if (!processingLocation(startLoc)) return;

  MacroAdder deleteLoggerMacro(funDecl->getNameInfo().getName().getAsString() == "operator delete[]"
                                   ? "TYPEGRIND_LOG_OP_DELETE_ARRAY"
                                   : "TYPEGRIND_LOG_OP_DELETE",
                               startLoc, endLoc, mRewriter);

  // 2nd and 3rd paramter: name of the type.
  addTypeInformationParameters(deleteLoggerMacro, deletedType, startLoc.getRawEncoding(),
                               CONVERT_TO_POINTEE);

  // last parameter: the pointer expression
  // parenthesis around it, for multiple template parameters
  deleteLoggerMacro.startBuffer() << "(";
  deleteLoggerMacro.endBuffer() << ")";

  deleteLoggerMacro.commitAroundLocations();
}
Example #6
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);
    }
void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) {
  auto TL = *Result.Nodes.getNodeAs<TypeLoc>("tl");
  SourceLocation Loc = TL.getBeginLoc();

  if (Loc.isInvalid() || Loc.isMacroID())
    return;

  // Look through qualification.
  if (auto QualLoc = TL.getAs<QualifiedTypeLoc>())
    TL = QualLoc.getUnqualifiedLoc();

  auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();
  if (!BuiltinLoc)
    return;

  Token Tok = getTokenAtLoc(Loc, Result, *IdentTable);
  // Ensure the location actually points to one of the builting integral type
  // names we're interested in. Otherwise, we might be getting this match from
  // implicit code (e.g. an implicit assignment operator of a class containing
  // an array of non-POD types).
  if (!Tok.isOneOf(tok::kw_short, tok::kw_long, tok::kw_unsigned,
                   tok::kw_signed))
    return;

  bool IsSigned;
  unsigned Width;
  const TargetInfo &TargetInfo = Result.Context->getTargetInfo();

  // Look for uses of short, long, long long and their unsigned versions.
  switch (BuiltinLoc.getTypePtr()->getKind()) {
  case BuiltinType::Short:
    Width = TargetInfo.getShortWidth();
    IsSigned = true;
    break;
  case BuiltinType::Long:
    Width = TargetInfo.getLongWidth();
    IsSigned = true;
    break;
  case BuiltinType::LongLong:
    Width = TargetInfo.getLongLongWidth();
    IsSigned = true;
    break;
  case BuiltinType::UShort:
    Width = TargetInfo.getShortWidth();
    IsSigned = false;
    break;
  case BuiltinType::ULong:
    Width = TargetInfo.getLongWidth();
    IsSigned = false;
    break;
  case BuiltinType::ULongLong:
    Width = TargetInfo.getLongLongWidth();
    IsSigned = false;
    break;
  default:
    return;
  }

  // We allow "unsigned short port" as that's reasonably common and required by
  // the sockets API.
  const StringRef Port = "unsigned short port";
  const char *Data = Result.SourceManager->getCharacterData(Loc);
  if (!std::strncmp(Data, Port.data(), Port.size()) &&
      !isIdentifierBody(Data[Port.size()]))
    return;

  std::string Replacement =
      ((IsSigned ? SignedTypePrefix : UnsignedTypePrefix) + Twine(Width) +
       TypeSuffix)
          .str();

  // We don't add a fix-it as changing the type can easily break code,
  // e.g. when a function requires a 'long' argument on all platforms.
  // QualTypes are printed with implicit quotes.
  diag(Loc, "consider replacing %0 with '%1'") << BuiltinLoc.getType()
                                               << Replacement;
}
Example #8
0
/* Returns pointer to base type symbol of the subrange symbol
 *
 * Parameters:
 * 		s: subrange symbol
 *
 * Return: a pointer to the type symbol
 */
Symbol * getSubrangeBaseTypeSym(Symbol *sr) {
	if (!sr) return NULL;
	if (getType(sr) != SUBRANGE_T) return NULL;
	return getTypePtr(sr)->Subrange->baseTypeSym;
}