bool DeclReferencer::VisitCXXConstructExpr(const clang::CXXConstructExpr *E) { auto ConstructedType = E->getType(); if (!ConstructedType.isNull()) Reference(ConstructedType.getTypePtr()); return Reference(E->getConstructor()); }
bool DeclReferencer::VisitCXXDeleteExpr(const clang::CXXDeleteExpr *E) { auto DestroyedType = E->getDestroyedType(); if (!DestroyedType.isNull()) Reference(DestroyedType.getTypePtr()); return Reference(E->getOperatorDelete()); }
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); }
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(); }
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; }
/* 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; }