From: Jordan Rose Date: Wed, 7 May 2014 03:29:56 +0000 (+0000) Subject: [analyzer] Functions marked __attribute__((const)) don't modify any memory. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3560c1ef5b66880a4f0950f041463a8a515fed5c;p=clang [analyzer] Functions marked __attribute__((const)) don't modify any memory. This applies to __attribute__((pure)) as well, but 'const' is more interesting because many of our builtins are marked 'const'. PR19661 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208154 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 84a769fa31..9426f790dd 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -139,6 +139,11 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount, ProgramStateRef Orig) const { ProgramStateRef Result = (Orig ? Orig : getState()); + // Don't invalidate anything if the callee is marked pure/const. + if (const Decl *callee = getDecl()) + if (callee->hasAttr() || callee->hasAttr()) + return Result; + SmallVector ValuesToInvalidate; RegionAndSymbolInvalidationTraits ETraits; diff --git a/test/Analysis/call-invalidation.cpp b/test/Analysis/call-invalidation.cpp index 54281cc98a..7297d1ebec 100644 --- a/test/Analysis/call-invalidation.cpp +++ b/test/Analysis/call-invalidation.cpp @@ -89,3 +89,32 @@ void testConstReferenceStruct() { clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} } + +void usePointerPure(int * const *) __attribute__((pure)); +void usePointerConst(int * const *) __attribute__((const)); + +void testPureConst() { + extern int global; + int x; + int *p; + + p = &x; + x = 42; + global = -5; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + clang_analyzer_eval(global == -5); // expected-warning{{TRUE}} + + usePointerPure(&p); + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + clang_analyzer_eval(global == -5); // expected-warning{{TRUE}} + + usePointerConst(&p); + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + clang_analyzer_eval(global == -5); // expected-warning{{TRUE}} + + usePointer(&p); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} + clang_analyzer_eval(global == -5); // expected-warning{{UNKNOWN}} +} + +