NoQ updated this revision to Diff 76731.
NoQ added a comment.
Comment up on variants.
https://reviews.llvm.org/D25940
Files:
lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
test/Analysis/std-c-library-functions.c
Index: test/Analysis/std-c-library-functions.c
===================================================================
--- test/Analysis/std-c-library-functions.c
+++ test/Analysis/std-c-library-functions.c
@@ -27,7 +27,7 @@
}
-typedef unsigned long size_t;
+typedef typeof(sizeof(int)) size_t;
typedef signed long ssize_t;
ssize_t read(int, void *, size_t);
ssize_t write(int, const void *, size_t);
Index: lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
+++ lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp
@@ -194,9 +194,16 @@
bool matchesCall(const CallExpr *CE) const;
};
+ // The same function (as in, function identifier) may have different
+ // summaries assigned to it, with different argument and return value types.
+ // We call these "variants" of the function. This can be useful for handling
+ // C++ function overloads, and also it can be used when the same function
+ // may have different definitions on different platforms.
+ typedef std::vector<FunctionSummaryTy> FunctionVariantsTy;
+
// The map of all functions supported by the checker. It is initialized
// lazily, and it doesn't change after initialization.
- typedef llvm::StringMap<FunctionSummaryTy> FunctionSummaryMapTy;
+ typedef llvm::StringMap<FunctionVariantsTy> FunctionSummaryMapTy;
mutable FunctionSummaryMapTy FunctionSummaryMap;
// Auxiliary functions to support ArgNoTy within all structures
@@ -446,11 +453,12 @@
// Strict checking is important because we will be conducting
// very integral-type-sensitive operations on arguments and
// return values.
- const FunctionSummaryTy &Spec = FSMI->second;
- if (!Spec.matchesCall(CE))
- return None;
+ const FunctionVariantsTy &SpecVariants = FSMI->second;
+ for (const FunctionSummaryTy &Spec : SpecVariants)
+ if (Spec.matchesCall(CE))
+ return Spec;
- return Spec;
+ return None;
}
void StdLibraryFunctionsChecker::initFunctionSummaries(
@@ -462,17 +470,20 @@
// These types are useful for writing specifications quickly,
// New specifications should probably introduce more types.
+ // Some types are hard to obtain from the AST, eg. "ssize_t".
+ // In such cases it should be possible to provide multiple variants
+ // of function summary for common cases (eg. ssize_t could be int or long
+ // or long long, so three summary variants would be enough).
+ // Of course, function variants are also useful for C++ overloads.
QualType Irrelevant; // A placeholder, whenever we do not care about the type.
QualType IntTy = ACtx.IntTy;
+ QualType LongTy = ACtx.LongTy;
+ QualType LongLongTy = ACtx.LongLongTy;
QualType SizeTy = ACtx.getSizeType();
- QualType SSizeTy = ACtx.getIntTypeForBitwidth(ACtx.getTypeSize(SizeTy), true);
- // Don't worry about truncation here, it'd be cast back to SIZE_MAX when used.
- RangeIntTy SizeMax =
- BVF.getMaxValue(SizeTy).getLimitedValue();
- RangeIntTy SSizeMax =
- BVF.getMaxValue(SSizeTy).getLimitedValue();
- (void)SizeMax; // Unused.
+ RangeIntTy IntMax = BVF.getMaxValue(IntTy).getLimitedValue();
+ RangeIntTy LongMax = BVF.getMaxValue(LongTy).getLimitedValue();
+ RangeIntTy LongLongMax = BVF.getMaxValue(LongLongTy).getLimitedValue();
// We are finally ready to define specifications for all supported functions.
//
@@ -515,17 +526,22 @@
// }
//}
+#define SUMMARY_WITH_VARIANTS(identifier) {#identifier, {
+#define END_SUMMARY_WITH_VARIANTS }},
+#define VARIANT(argument_types, return_type, invalidation_approach) \
+ { argument_types, return_type, invalidation_approach, {
+#define END_VARIANT } },
#define SUMMARY(identifier, argument_types, return_type, \
invalidation_approach) \
- {#identifier, {argument_types, return_type, invalidation_approach, {
-#define END_SUMMARY }}},
+ { #identifier, { { argument_types, return_type, invalidation_approach, {
+#define END_SUMMARY } } } },
#define ARGUMENT_TYPES(...) { __VA_ARGS__ }
#define RETURN_TYPE(x) x
#define INVALIDATION_APPROACH(x) x
#define CASE {
#define END_CASE },
#define ARGUMENT_CONDITION(argument_number, condition_kind) \
- {argument_number, condition_kind, {
+ { argument_number, condition_kind, {
#define END_ARGUMENT_CONDITION }},
#define RETURN_VALUE_CONDITION(condition_kind) \
{ Ret, condition_kind, {
@@ -875,28 +891,80 @@
END_SUMMARY
// read()-like functions that never return more than buffer size.
- SUMMARY(read, ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
- RETURN_TYPE(SSizeTy), INVALIDATION_APPROACH(NoEvalCall))
- CASE
- RETURN_VALUE_CONDITION(ComparesToArgument)
- IS_LESS_THAN(ARG_NO(2))
- END_RETURN_VALUE_CONDITION
- RETURN_VALUE_CONDITION(WithinRange)
- RANGE(-1, SSizeMax)
- END_RETURN_VALUE_CONDITION
- END_CASE
- END_SUMMARY
- SUMMARY(write, ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
- RETURN_TYPE(SSizeTy), INVALIDATION_APPROACH(NoEvalCall))
- CASE
- RETURN_VALUE_CONDITION(ComparesToArgument)
- IS_LESS_THAN(ARG_NO(2))
- END_RETURN_VALUE_CONDITION
- RETURN_VALUE_CONDITION(WithinRange)
- RANGE(-1, SSizeMax)
- END_RETURN_VALUE_CONDITION
- END_CASE
- END_SUMMARY
+ // We are not sure how ssize_t is defined on every platform, so we provide
+ // three variants that should cover common cases.
+ SUMMARY_WITH_VARIANTS(read)
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
+ SUMMARY_WITH_VARIANTS(write)
+ // Again, due to elusive nature of ssize_t, we have duplicate
+ // our summaries to cover different variants.
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(ComparesToArgument)
+ IS_LESS_THAN(ARG_NO(2))
+ END_RETURN_VALUE_CONDITION
+ RETURN_VALUE_CONDITION(WithinRange)
+ RANGE(-1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
SUMMARY(fread,
ARGUMENT_TYPES(Irrelevant, Irrelevant, SizeTy, Irrelevant),
RETURN_TYPE(SizeTy), INVALIDATION_APPROACH(NoEvalCall))
@@ -917,25 +985,64 @@
END_SUMMARY
// getline()-like functions either fail or read at least the delimiter.
- SUMMARY(getline, ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
- RETURN_TYPE(SSizeTy), INVALIDATION_APPROACH(NoEvalCall))
- CASE
- RETURN_VALUE_CONDITION(WithinRange)
- SINGLE_VALUE(-1)
- RANGE(1, SSizeMax)
- END_RETURN_VALUE_CONDITION
- END_CASE
- END_SUMMARY
- SUMMARY(getdelim,
- ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
- RETURN_TYPE(SSizeTy), INVALIDATION_APPROACH(NoEvalCall))
- CASE
- RETURN_VALUE_CONDITION(WithinRange)
- SINGLE_VALUE(-1)
- RANGE(1, SSizeMax)
- END_RETURN_VALUE_CONDITION
- END_CASE
- END_SUMMARY
+ SUMMARY_WITH_VARIANTS(getline)
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
+ SUMMARY_WITH_VARIANTS(getdelim)
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(IntTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, IntMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ VARIANT(ARGUMENT_TYPES(Irrelevant, Irrelevant, Irrelevant, Irrelevant),
+ RETURN_TYPE(LongLongTy), INVALIDATION_APPROACH(NoEvalCall))
+ CASE
+ RETURN_VALUE_CONDITION(WithinRange)
+ SINGLE_VALUE(-1)
+ RANGE(1, LongLongMax)
+ END_RETURN_VALUE_CONDITION
+ END_CASE
+ END_VARIANT
+ END_SUMMARY_WITH_VARIANTS
};
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits