diff --git a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp --- a/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp @@ -266,21 +266,15 @@ return T; } - /// Try our best to figure out if the call expression is the call of + /// Try our best to figure out if the summary's signature matches /// *the* library function to which this specification applies. - bool matchesCall(const FunctionDecl *FD) const; + bool matchesSignature(const FunctionDecl *FD) 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 Summaries; - // The map of all functions supported by the checker. It is initialized // lazily, and it doesn't change after initialization. - mutable llvm::StringMap FunctionSummaryMap; + using FunctionSummaryMapType = llvm::DenseMap; + mutable FunctionSummaryMapType FunctionSummaryMap; mutable std::unique_ptr BT_InvalidArg; @@ -289,14 +283,6 @@ static QualType getArgType(const Summary &Summary, ArgNo ArgN) { return Summary.getArgType(ArgN); } - static QualType getArgType(const CallEvent &Call, ArgNo ArgN) { - return ArgN == Ret ? Call.getResultType().getCanonicalType() - : Call.getArgExpr(ArgN)->getType().getCanonicalType(); - } - static QualType getArgType(const CallExpr *CE, ArgNo ArgN) { - return ArgN == Ret ? CE->getType().getCanonicalType() - : CE->getArg(ArgN)->getType().getCanonicalType(); - } static SVal getArgSVal(const CallEvent &Call, ArgNo ArgN) { return ArgN == Ret ? Call.getReturnValue() : Call.getArgSVal(ArgN); } @@ -440,7 +426,7 @@ BinaryOperator::Opcode Op = getOpcode(); ArgNo OtherArg = getOtherArgNo(); SVal OtherV = getArgSVal(Call, OtherArg); - QualType OtherT = getArgType(Call, OtherArg); + QualType OtherT = getArgType(Summary, OtherArg); // Note: we avoid integral promotion for comparison. OtherV = SVB.evalCast(OtherV, T, OtherT); if (auto CompV = SVB.evalBinOp(State, Op, V, OtherV, CondT) @@ -530,7 +516,7 @@ llvm_unreachable("Unknown invalidation kind!"); } -bool StdLibraryFunctionsChecker::Summary::matchesCall( +bool StdLibraryFunctionsChecker::Summary::matchesSignature( const FunctionDecl *FD) const { // Check number of arguments: if (FD->param_size() != ArgTys.size()) @@ -565,28 +551,10 @@ initFunctionSummaries(C); - IdentifierInfo *II = FD->getIdentifier(); - if (!II) - return None; - StringRef Name = II->getName(); - if (Name.empty() || !C.isCLibraryFunction(FD, Name)) - return None; - - auto FSMI = FunctionSummaryMap.find(Name); + auto FSMI = FunctionSummaryMap.find(FD->getCanonicalDecl()); if (FSMI == FunctionSummaryMap.end()) return None; - - // Verify that function signature matches the spec in advance. - // Otherwise we might be modeling the wrong function. - // Strict checking is important because we will be conducting - // very integral-type-sensitive operations on arguments and - // return values. - const Summaries &SpecVariants = FSMI->second; - for (const Summary &Spec : SpecVariants) - if (Spec.matchesCall(FD)) - return Spec; - - return None; + return FSMI->second; } Optional @@ -598,6 +566,21 @@ return findFunctionSummary(FD, C); } +llvm::Optional +lookupGlobalCFunction(StringRef Name, const ASTContext &ACtx) { + IdentifierInfo &II = ACtx.Idents.get(Name); + auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II); + if (LookupRes.size() == 0) + return None; + + assert(LookupRes.size() == 1 && "In C, identifiers should be unique"); + Decl *D = LookupRes.front()->getCanonicalDecl(); + auto *FD = dyn_cast(D); + if (!FD) + return None; + return FD->getCanonicalDecl(); +} + void StdLibraryFunctionsChecker::initFunctionSummaries( CheckerContext &C) const { if (!FunctionSummaryMap.empty()) @@ -652,6 +635,38 @@ return -1; }(); + // Auxiliary class to aid adding summaries to the summary map. + struct AddToFunctionSummaryMap { + const ASTContext &ACtx; + FunctionSummaryMapType ⤅ + AddToFunctionSummaryMap(const ASTContext &ACtx, FunctionSummaryMapType &FSM) + : ACtx(ACtx), Map(FSM) {} + // Add a summary to a FunctionDecl found by lookup. The lookup is performed + // by the given Name, and in the global scope. The summary will be attached + // to the found FunctionDecl only if the signatures match. + void operator()(StringRef Name, const Summary &S) { + IdentifierInfo &II = ACtx.Idents.get(Name); + auto LookupRes = ACtx.getTranslationUnitDecl()->lookup(&II); + if (LookupRes.size() == 0) + return; + for (Decl *D : LookupRes) { + if (auto *FD = dyn_cast(D)) { + if (S.matchesSignature(FD)) { + auto Res = Map.insert({FD->getCanonicalDecl(), S}); + assert(Res.second && "Function already has a summary set!"); + (void)Res; + return; + } + } + } + } + // Add several summaries for the given name. + void operator()(StringRef Name, const std::vector &Summaries) { + for (const Summary &S : Summaries) + operator()(Name, S); + } + } addToFunctionSummaryMap(ACtx, FunctionSummaryMap); + // We are finally ready to define specifications for all supported functions. // // The signature needs to have the correct number of arguments. @@ -677,7 +692,6 @@ // return value, however the correct range is [-1, 10]. // // Please update the list of functions in the header after editing! - // // Below are helpers functions to create the summaries. auto ArgumentCondition = [](ArgNo ArgN, RangeKind Kind, @@ -739,238 +753,186 @@ .Case({ReturnValueCondition(WithinRange, {{-1, -1}, {1, Max}})}); }; - FunctionSummaryMap = { - // The isascii() family of functions. - // The behavior is undefined if the value of the argument is not - // representable as unsigned char or is not equal to EOF. See e.g. C99 - // 7.4.1.2 The isalpha function (p: 181-182). - { - "isalnum", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - // Boils down to isupper() or islower() or isdigit(). - .Case( - {ArgumentCondition(0U, WithinRange, - {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - // The locale-specific range. - // No post-condition. We are completely unaware of - // locale-specific return values. - .Case({ArgumentCondition(0U, WithinRange, - {{128, UCharRangeMax}})}) - .Case({ArgumentCondition(0U, OutOfRange, - {{'0', '9'}, - {'A', 'Z'}, - {'a', 'z'}, - {128, UCharRangeMax}}), - ReturnValueCondition(WithinRange, SingleValue(0))}) - .ArgConstraint(ArgumentCondition( - 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))}, - }, - { - "isalpha", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition(0U, WithinRange, - {{'A', 'Z'}, {'a', 'z'}}), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - // The locale-specific range. - .Case({ArgumentCondition(0U, WithinRange, - {{128, UCharRangeMax}})}) - .Case({ArgumentCondition( - 0U, OutOfRange, - {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isascii", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isblank", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition(0U, WithinRange, - {{'\t', '\t'}, {' ', ' '}}), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case({ArgumentCondition(0U, OutOfRange, - {{'\t', '\t'}, {' ', ' '}}), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "iscntrl", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition(0U, WithinRange, - {{0, 32}, {127, 127}}), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case( - {ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isdigit", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isgraph", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case({ArgumentCondition(0U, OutOfRange, Range(33, 126)), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "islower", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - // Is certainly lowercase. - .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - // Is ascii but not lowercase. - .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), - ArgumentCondition(0U, OutOfRange, Range('a', 'z')), - ReturnValueCondition(WithinRange, SingleValue(0))}) - // The locale-specific range. - .Case({ArgumentCondition(0U, WithinRange, - {{128, UCharRangeMax}})}) - // Is not an unsigned char. - .Case({ArgumentCondition(0U, OutOfRange, - Range(0, UCharRangeMax)), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isprint", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "ispunct", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case({ArgumentCondition( - 0U, WithinRange, - {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case({ArgumentCondition( - 0U, OutOfRange, - {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isspace", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - // Space, '\f', '\n', '\r', '\t', '\v'. - .Case({ArgumentCondition(0U, WithinRange, - {{9, 13}, {' ', ' '}}), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - // The locale-specific range. - .Case({ArgumentCondition(0U, WithinRange, - {{128, UCharRangeMax}})}) - .Case({ArgumentCondition( - 0U, OutOfRange, - {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isupper", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - // Is certainly uppercase. - .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - // The locale-specific range. - .Case({ArgumentCondition(0U, WithinRange, - {{128, UCharRangeMax}})}) - // Other. - .Case({ArgumentCondition(0U, OutOfRange, - {{'A', 'Z'}, {128, UCharRangeMax}}), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - { - "isxdigit", - Summaries{ - Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .Case( - {ArgumentCondition(0U, WithinRange, - {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), - ReturnValueCondition(OutOfRange, SingleValue(0))}) - .Case( - {ArgumentCondition(0U, OutOfRange, - {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), - ReturnValueCondition(WithinRange, SingleValue(0))})}, - }, - - // The getc() family of functions that returns either a char or an EOF. - {"getc", Summaries{Getc()}}, - {"fgetc", Summaries{Getc()}}, - {"getchar", - Summaries{Summary(ArgTypes{}, RetType{IntTy}, NoEvalCall) + // The isascii() family of functions. + // The behavior is undefined if the value of the argument is not + // representable as unsigned char or is not equal to EOF. See e.g. C99 + // 7.4.1.2 The isalpha function (p: 181-182). + addToFunctionSummaryMap( + "isalnum", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + // Boils down to isupper() or islower() or isdigit(). + .Case({ArgumentCondition(0U, WithinRange, + {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}}), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + // The locale-specific range. + // No post-condition. We are completely unaware of + // locale-specific return values. + .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) + .Case( + {ArgumentCondition( + 0U, OutOfRange, + {{'0', '9'}, {'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}), + ReturnValueCondition(WithinRange, SingleValue(0))}) + .ArgConstraint(ArgumentCondition( + 0U, WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}}))); + addToFunctionSummaryMap( + "isalpha", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, {{'A', 'Z'}, {'a', 'z'}}), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + // The locale-specific range. + .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) + .Case({ArgumentCondition( + 0U, OutOfRange, + {{'A', 'Z'}, {'a', 'z'}, {128, UCharRangeMax}}), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isascii", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition(0U, OutOfRange, Range(0, 127)), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isblank", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, {{'\t', '\t'}, {' ', ' '}}), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition(0U, OutOfRange, {{'\t', '\t'}, {' ', ' '}}), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "iscntrl", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, {{0, 32}, {127, 127}}), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition(0U, OutOfRange, {{0, 32}, {127, 127}}), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isdigit", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, Range('0', '9')), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition(0U, OutOfRange, Range('0', '9')), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isgraph", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, Range(33, 126)), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition(0U, OutOfRange, Range(33, 126)), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "islower", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + // Is certainly lowercase. + .Case({ArgumentCondition(0U, WithinRange, Range('a', 'z')), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + // Is ascii but not lowercase. + .Case({ArgumentCondition(0U, WithinRange, Range(0, 127)), + ArgumentCondition(0U, OutOfRange, Range('a', 'z')), + ReturnValueCondition(WithinRange, SingleValue(0))}) + // The locale-specific range. + .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) + // Is not an unsigned char. + .Case({ArgumentCondition(0U, OutOfRange, Range(0, UCharRangeMax)), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isprint", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, Range(32, 126)), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition(0U, OutOfRange, Range(32, 126)), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "ispunct", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition( + 0U, WithinRange, + {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition( + 0U, OutOfRange, + {{'!', '/'}, {':', '@'}, {'[', '`'}, {'{', '~'}}), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isspace", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + // Space, '\f', '\n', '\r', '\t', '\v'. + .Case({ArgumentCondition(0U, WithinRange, {{9, 13}, {' ', ' '}}), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + // The locale-specific range. + .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) + .Case({ArgumentCondition(0U, OutOfRange, + {{9, 13}, {' ', ' '}, {128, UCharRangeMax}}), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isupper", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + // Is certainly uppercase. + .Case({ArgumentCondition(0U, WithinRange, Range('A', 'Z')), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + // The locale-specific range. + .Case({ArgumentCondition(0U, WithinRange, {{128, UCharRangeMax}})}) + // Other. + .Case({ArgumentCondition(0U, OutOfRange, + {{'A', 'Z'}, {128, UCharRangeMax}}), + ReturnValueCondition(WithinRange, SingleValue(0))})); + addToFunctionSummaryMap( + "isxdigit", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .Case({ArgumentCondition(0U, WithinRange, + {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), + ReturnValueCondition(OutOfRange, SingleValue(0))}) + .Case({ArgumentCondition(0U, OutOfRange, + {{'0', '9'}, {'A', 'F'}, {'a', 'f'}}), + ReturnValueCondition(WithinRange, SingleValue(0))})); + + // The getc() family of functions that returns either a char or an EOF. + addToFunctionSummaryMap("getc", Getc()); + addToFunctionSummaryMap("fgetc", Getc()); + addToFunctionSummaryMap( + "getchar", Summary(ArgTypes{}, RetType{IntTy}, NoEvalCall) .Case({ReturnValueCondition( - WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})})}}, - - // read()-like functions that never return more than buffer size. - // We are not sure how ssize_t is defined on every platform, so we - // provide three variants that should cover common cases. - {"read", Summaries{Read(IntTy, IntMax), Read(LongTy, LongMax), - Read(LongLongTy, LongLongMax)}}, - {"write", Summaries{Read(IntTy, IntMax), Read(LongTy, LongMax), - Read(LongLongTy, LongLongMax)}}, - {"fread", Summaries{Fread()}}, - {"fwrite", Summaries{Fwrite()}}, - // getline()-like functions either fail or read at least the delimiter. - {"getline", Summaries{Getline(IntTy, IntMax), Getline(LongTy, LongMax), - Getline(LongLongTy, LongLongMax)}}, - {"getdelim", Summaries{Getline(IntTy, IntMax), Getline(LongTy, LongMax), - Getline(LongLongTy, LongLongMax)}}, - }; + WithinRange, {{EOFv, EOFv}, {0, UCharRangeMax}})})); + + // read()-like functions that never return more than buffer size. + // We are not sure how ssize_t is defined on every platform, so we + // provide three variants that should cover common cases. + addToFunctionSummaryMap("read", {Read(IntTy, IntMax), Read(LongTy, LongMax), + Read(LongLongTy, LongLongMax)}); + addToFunctionSummaryMap("write", {Read(IntTy, IntMax), Read(LongTy, LongMax), + Read(LongLongTy, LongLongMax)}); + addToFunctionSummaryMap("fread", Fread()); + addToFunctionSummaryMap("fwrite", Fwrite()); + // getline()-like functions either fail or read at least the delimiter. + addToFunctionSummaryMap("getline", + {Getline(IntTy, IntMax), Getline(LongTy, LongMax), + Getline(LongLongTy, LongLongMax)}); + addToFunctionSummaryMap("getdelim", + {Getline(IntTy, IntMax), Getline(LongTy, LongMax), + Getline(LongLongTy, LongLongMax)}); // Functions for testing. if (ChecksEnabled[CK_StdCLibraryFunctionsTesterChecker]) { - llvm::StringMap TestFunctionSummaryMap = { - {"__two_constrained_args", - Summaries{ - Summary(ArgTypes{IntTy, IntTy}, RetType{IntTy}, EvalCallAsPure) - .ArgConstraint( - ArgumentCondition(0U, WithinRange, SingleValue(1))) - .ArgConstraint( - ArgumentCondition(1U, WithinRange, SingleValue(1)))}}, - {"__arg_constrained_twice", - Summaries{Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) - .ArgConstraint( - ArgumentCondition(0U, OutOfRange, SingleValue(1))) - .ArgConstraint( - ArgumentCondition(0U, OutOfRange, SingleValue(2)))}}, - {"__defaultparam", Summaries{Summary(ArgTypes{Irrelevant, IntTy}, - RetType{IntTy}, EvalCallAsPure) - .ArgConstraint(NotNull(ArgNo(0)))}}, - {"__variadic", Summaries{Summary(ArgTypes{VoidPtrTy, ConstCharPtrTy}, - RetType{IntTy}, EvalCallAsPure) - .ArgConstraint(NotNull(ArgNo(0))) - .ArgConstraint(NotNull(ArgNo(1)))}}}; - for (auto &E : TestFunctionSummaryMap) { - auto InsertRes = - FunctionSummaryMap.insert({std::string(E.getKey()), E.getValue()}); - assert(InsertRes.second && - "Test functions must not clash with modeled functions"); - (void)InsertRes; - } + addToFunctionSummaryMap( + "__two_constrained_args", + Summary(ArgTypes{IntTy, IntTy}, RetType{IntTy}, EvalCallAsPure) + .ArgConstraint(ArgumentCondition(0U, WithinRange, SingleValue(1))) + .ArgConstraint(ArgumentCondition(1U, WithinRange, SingleValue(1)))); + addToFunctionSummaryMap( + "__arg_constrained_twice", + Summary(ArgTypes{IntTy}, RetType{IntTy}, EvalCallAsPure) + .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(1))) + .ArgConstraint(ArgumentCondition(0U, OutOfRange, SingleValue(2)))); + addToFunctionSummaryMap( + "__defaultparam", + Summary(ArgTypes{Irrelevant, IntTy}, RetType{IntTy}, EvalCallAsPure) + .ArgConstraint(NotNull(ArgNo(0)))); + addToFunctionSummaryMap("__variadic", + Summary(ArgTypes{VoidPtrTy, ConstCharPtrTy}, + RetType{IntTy}, EvalCallAsPure) + .ArgConstraint(NotNull(ArgNo(0))) + .ArgConstraint(NotNull(ArgNo(1)))); } }