void MultiwayPathsCoveredCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( switchStmt( hasCondition(allOf( // Match on switch statements that have either a bit-field or // an integer condition. The ordering in 'anyOf()' is // important because the last condition is the most general. anyOf(ignoringImpCasts(memberExpr(hasDeclaration( fieldDecl(isBitField()).bind("bitfield")))), ignoringImpCasts(declRefExpr().bind("non-enum-condition"))), // 'unless()' must be the last match here and must be bound, // otherwise the matcher does not work correctly, because it // will not explicitly ignore enum conditions. unless(ignoringImpCasts( declRefExpr(hasType(enumType())).bind("enum-condition")))))) .bind("switch"), this); // This option is noisy, therefore matching is configurable. if (WarnOnMissingElse) { Finder->addMatcher( ifStmt(allOf(hasParent(ifStmt()), unless(hasElse(anything())))) .bind("else-if"), this); } }
bool BitFieldAggregation::getBitFieldAggregations(TYPECONST Type *type, const EDIType *aEDIType, std::vector<BitFieldAggregation> &bfas, bool returnOnError) { std::vector<BitFieldAggregation> emptyBfas; if(!hasBitFields(type, aEDIType)) { return true; } unsigned typeIndex = 0; unsigned EDITypeIndex = 0; unsigned typeContainedTypes = type->getNumContainedTypes(); unsigned aEDITypeContainedTypes = aEDIType->getNumContainedTypes(); unsigned counter = 1; const EDIType privateEDIType(*aEDIType); aEDIType = &privateEDIType; while(typeIndex < typeContainedTypes) { TYPECONST Type *containedType = type->getContainedType(typeIndex); if(EDITypeIndex >= aEDITypeContainedTypes && typeIndex == typeContainedTypes-1 && TypeUtil::isPaddedType(type)) { break; } BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, EDITypeIndex < aEDITypeContainedTypes); const EDIType containedEDIType = aEDIType->getContainedType(EDITypeIndex); unsigned typeBits = TypeUtil::typeToBits(containedType); if(typeBits > 0 && containedEDIType.isIntegerTy()) { unsigned EDITypeBits = aEDIType->getMember(EDITypeIndex).getSizeInBits(); assert(typeBits >= EDITypeBits); if(typeBits > EDITypeBits) { unsigned lastTypeIndex = typeIndex; unsigned lastEDITypeIndex = EDITypeIndex; while(lastEDITypeIndex+1 < aEDITypeContainedTypes && isBitField(type, aEDIType, lastEDITypeIndex+1)) { // grab all the bitfields following the first one found lastEDITypeIndex++; EDITypeBits += aEDIType->getMember(lastEDITypeIndex).getSizeInBits(); } while(lastTypeIndex+1 < typeContainedTypes && EDITypeBits > typeBits) { // grab all the necessary fields to cover all the bits found in the bitfields lastTypeIndex++; typeBits += TypeUtil::typeToBits(type->getContainedType(lastTypeIndex)); } BitFieldAggregation *bfa = BitFieldAggregation::getBitFieldAggregation(type, aEDIType, returnOnError, typeIndex, EDITypeIndex, lastTypeIndex, lastEDITypeIndex, counter++); BitFieldAggregation_assert_or_return(returnOnError, false, type, aEDIType, bfa != NULL); if(bfa->getSize() > 1) { //we don't care about single-element aggregates bfas.push_back(*bfa); } typeIndex++; EDITypeIndex += bfa->getSize(); continue; } } typeIndex++; EDITypeIndex++; } return true; }
void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus11) return; // FIXME: Bunch of functionality that could be easily added: // + add handling of `push_front` for std::forward_list, std::list // and std::deque. // + add handling of `push` for std::stack, std::queue, std::priority_queue // + add handling of `insert` for stl associative container, but be careful // because this requires special treatment (it could cause performance // regression) // + match for emplace calls that should be replaced with insertion // + match for make_pair calls. auto callPushBack = cxxMemberCallExpr( hasDeclaration(functionDecl(hasName("push_back"))), on(hasType(cxxRecordDecl(hasAnyName(SmallVector<StringRef, 5>( ContainersWithPushBack.begin(), ContainersWithPushBack.end())))))); // We can't replace push_backs of smart pointer because // if emplacement fails (f.e. bad_alloc in vector) we will have leak of // passed pointer because smart pointer won't be constructed // (and destructed) as in push_back case. auto isCtorOfSmartPtr = hasDeclaration(cxxConstructorDecl(ofClass(hasAnyName( SmallVector<StringRef, 5>(SmartPointers.begin(), SmartPointers.end()))))); // Bitfields binds only to consts and emplace_back take it by universal ref. auto bitFieldAsArgument = hasAnyArgument( ignoringImplicit(memberExpr(hasDeclaration(fieldDecl(isBitField()))))); // Initializer list can't be passed to universal reference. auto initializerListAsArgument = hasAnyArgument( ignoringImplicit(cxxConstructExpr(isListInitialization()))); // We could have leak of resource. auto newExprAsArgument = hasAnyArgument(ignoringImplicit(cxxNewExpr())); // We would call another constructor. auto constructingDerived = hasParent(implicitCastExpr(hasCastKind(CastKind::CK_DerivedToBase))); // emplace_back can't access private constructor. auto isPrivateCtor = hasDeclaration(cxxConstructorDecl(isPrivate())); auto hasInitList = has(ignoringImplicit(initListExpr())); // FIXME: Discard 0/NULL (as nullptr), static inline const data members, // overloaded functions and template names. auto soughtConstructExpr = cxxConstructExpr( unless(anyOf(isCtorOfSmartPtr, hasInitList, bitFieldAsArgument, initializerListAsArgument, newExprAsArgument, constructingDerived, isPrivateCtor))) .bind("ctor"); auto hasConstructExpr = has(ignoringImplicit(soughtConstructExpr)); auto ctorAsArgument = materializeTemporaryExpr( anyOf(hasConstructExpr, has(cxxFunctionalCastExpr(hasConstructExpr)))); Finder->addMatcher(cxxMemberCallExpr(callPushBack, has(ctorAsArgument), unless(isInTemplateInstantiation())) .bind("call"), this); }
/* * For each non-const attribute in template t, print the appropriate args * in the call to evl_log_write(). */ static void printAttArgs(const evltemplate_t *t, const char *prefix) { evl_listnode_t *head = t->tm_attributes, *end, *p; const evltemplate_t *st; /* struct attribute's template */ for (end=NULL, p=head; p!=end; end=head, p=p->li_next) { evlattribute_t *att = (evlattribute_t*) p->li_data; int ty; if (isConstAtt(att)) { continue; } if (isBitField(att)) { notSupported("bit-fields"); continue; } ty = evlatt_gettype(att); if (isArray(att)) { char *dimString; dimString = getDimensionString(att, prefix); if (ty == TY_STRUCT) { /* Array of structs */ st = att->ta_type->u.st_template; if ((st->tm_flags & TMPL_TF_ALIGNED) != 0) { /* Array of aligned structs */ printf( "\t\"char[]\",\t%s*sizeof(struct %s),\t%s%s,\n", dimString, st->tm_name, prefix, att->ta_name); } else { notSupported("arrays of unaligned structs"); } } else { /* Array of scalars or strings */ printf( "\t\"%s[]\",\t%s,\t%s%s,\n", typeName(ty), dimString, prefix, att->ta_name); } free(dimString); } else { /* Not an array */ if (ty == TY_STRUCT) { st = att->ta_type->u.st_template; if ((st->tm_flags & TMPL_TF_ALIGNED) != 0) { printf( "\t\"char[]\",\tsizeof(struct %s),\t%s%s,\n", st->tm_name, prefix, att->ta_name); } else { /* Unaligned struct. Print all its members. */ size_t newPrefixSize = strlen(prefix) + strlen(att->ta_name) + 1; char *newPrefix = (char*) malloc(newPrefixSize); assert(newPrefix != NULL); snprintf(newPrefix, newPrefixSize, "%s%s.", prefix, att->ta_name); printAttArgs(st, newPrefix); free(newPrefix); } } else { /* Not an array or struct */ printf( "\t\"%s\",\t%s%s,\n", typeName(ty), prefix, att->ta_name); } } } }