[cfe-dev] RetainCountChecker | Assertion Failure | check-clang-analysis

Malhar Thakkar via cfe-dev cfe-dev at lists.llvm.org
Sun Jul 2 00:53:36 PDT 2017


On Sun, Jul 2, 2017 at 12:40 PM, Artem Dergachev <noqnoqneo at gmail.com>
wrote:

> Uhm, why does this thing return `const Decl &` rather than `const Decl *`?
> Anyway, whatever, never mind.
>
>
> You're crashing in...
>
>   cast<FunctionDecl>(&EN->getCodeDecl())
>
> ...because this Decl returned by `EN->getCodeDecl()` isn't a FunctionDecl.
>
>
> You can easily see this from the backtrace:
>
> Assertion failed: (isa<X>(Val) && "cast<Ty>() argument of incompatible
> type!"), function cast, file (...censored...)/llvm/include/llvm/Support/Casting.h,
> line 254.
> 0  libLLVMSupport.dylib                 0x00000001148fb8fc
> llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 60
> 1  libLLVMSupport.dylib                 0x00000001148fbec9
> PrintStackTraceSignalHandler(void*) + 25
> 2  libLLVMSupport.dylib                 0x00000001148f7b59
> llvm::sys::RunSignalHandlers() + 425
> 3  libLLVMSupport.dylib                 0x00000001148fc212
> SignalHandler(int) + 354
> 4  libsystem_platform.dylib             0x00007fffd872cb3a _sigtramp + 26
> 5  libclangStaticAnalyzerCore.dylib     0x0000000122060c7b
> llvm::alignAddr(void const*, unsigned long) + 43
> 6  libsystem_c.dylib                    0x00007fffd85b1420 abort + 129
> 7  libsystem_c.dylib                    0x00007fffd8578893 basename_r + 0
> 8  libclangStaticAnalyzerCheckers.dylib 0x00000001202e6fe7
> llvm::cast_retty<clang::FunctionDecl, clang::Decl const*>::ret_type
> llvm::cast<clang::FunctionDecl, clang::Decl const>(clang::Decl const*) +
> 103
> 9  libclangStaticAnalyzerCheckers.dylib 0x00000001208b7aa6
> isAnnotatedToSkipDiagnostics(clang::ento::ExplodedNode const*) + 38
> (...more stuff...)
>
> You're calling llvm::cast<> (frame 8) from your new function (frame 9),
> the only cast you have is `cast<FunctionDecl>(&EN->getCodeDecl())`, and
> the assertion message says that the argument is of incompatible type.
>
>
> If you want to know what specific decl causes a problem, you can print it
> in the debugger:
>
> $ lldb -- (...censored...)/debug/./bin/clang -cc1 -internal-isystem
> (...censored...)/debug/lib/clang/5.0.0/include -nostdsysteminc -analyze
> -analyzer-constraints=range -analyzer-checker=core,osx.coc
> oa.RetainCount,osx.cocoa.Dealloc,debug.ExprInspection
> -analyzer-store=region -verify -Wno-objc-root-class
> (...censored...)/llvm/tools/clang/test/Analysis/properties.m
>
> (lldb) bt
> * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
>     frame #0: 0x00007fffd864bd42 libsystem_kernel.dylib`__pthread_kill +
> 10
>     frame #1: 0x00007fffd8739787 libsystem_pthread.dylib`pthread_kill + 90
>     frame #2: 0x00007fffd85b1420 libsystem_c.dylib`abort + 129
>     frame #3: 0x00007fffd8578893 libsystem_c.dylib`__assert_rtn + 320
>     frame #4: 0x0000000114983fe7 libclangStaticAnalyzerCheckers
> .dylib`llvm::cast_retty<clang::FunctionDecl, clang::Decl
> const*>::ret_type llvm::cast<clang::FunctionDecl, clang::Decl
> const>(Val=0x00000001170ab5c0) at Casting.h:254
>   * frame #5: 0x0000000114f54aa6 libclangStaticAnalyzerCheckers
> .dylib`isAnnotatedToSkipDiagnostics(EN=0x0000000118815ee0) at
> RetainCountChecker.cpp:1904
> (...more stuff...)
>
> (lldb) f 5
> frame #5: 0x0000000114f54aa6 libclangStaticAnalyzerCheckers
> .dylib`isAnnotatedToSkipDiagnostics(EN=0x0000000118815ee0) at
> RetainCountChecker.cpp:1904
>    1901
>    1902    bool
>    1903    isAnnotatedToSkipDiagnostics(const ExplodedNode *EN) {
> -> 1904      const FunctionDecl *FD = cast<FunctionDecl>(&EN->getCod
> eDecl());
>    1905      const IdentifierInfo *II = FD->getIdentifier();
>    1906
>    1907      if (II) {
>
> (lldb) p EN->getCodeDecl().dump()
> ObjCMethodDecl 0x1170ab5c0 <(...censored...)/llvm/tools/c
> lang/test/Analysis/properties.m:559:1, line:563:1> line:559:1 -
> testRetainAndRelease 'void'
> (...more stuff...)
>

Thanks a ton for this, Dr. Artem. This really helped.

>
> Note that frames are shifted in the debugger because it stops on the
> moment when the assertion has failed, so we're on frame 5 instead of frame
> 9 now.
>
> If you use gdb instead of lldb, just replace "lldb --" with "gdb --args"
> in the first command, the rest is the same. If you use an IDE, then you
> should know better how to debug this.
>
>
> So in this case it's ObjCMethodDecl, and Objective-C methods apparently
> aren't functions. I'd also worry about BlockDecl which may also appear here.
>
> You should use dyn_cast<> when you're not sure if the cast succeeds - it'd
> return nullptr instead of crashing, and you can handle it.

Okay, I'll try using dyn_cast<>.

>
>
>
> On 7/1/17 10:12 AM, Malhar Thakkar via cfe-dev wrote:
>
>> Dear all,
>>
>> I am currently trying to suppress diagnostics emitted if the function
>> under consideration has a certain annotate attribute
>> ("check_attribute_annotate" in this case).
>>
>> Hence, for that, I added the following piece of code to
>> RetainCountChecker.cpp but it is resulting in some assertion failures while
>> performing make -j4 check-clang-analysis.
>>
>>
>>
>> diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
>> b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
>> index 89b1291..9f367be 100644
>> --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
>> +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
>> @@ -1894,6 +1894,20 @@ static bool isSynthesizedAccessor(const
>> StackFrameContext *SFC) {
>> return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
>>  }
>> +bool
>> +isAnnotatedToSkipDiagnostics(const ExplodedNode *EN) {
>> + const FunctionDecl *FD = cast<FunctionDecl>(&EN->getCodeDecl());
>> + const IdentifierInfo *II = FD->getIdentifier();
>> +
>> + if (II) {
>> + for (const auto *Ann : FD->specific_attrs<AnnotateAttr>()){
>> + if (Ann->getAnnotation() == "check_attribute_annotate")
>> + return true;
>> +    }
>> +  }
>> + return false;
>> +}
>> +
>>  std::shared_ptr<PathDiagnosticPiece>
>>  CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode
>> *PrevN,
>>            BugReporterContext &BRC, BugReport &BR) {
>> @@ -3345,11 +3359,13 @@ void RetainCountChecker::processNonLeakError(ProgramStateRef
>> St,
>>    }
>>    assert(BT);
>> -  auto report = std::unique_ptr<BugReport>(
>> - new CFRefReport(*BT, C.getASTContext().getLangOpts(),
>> C.isObjCGCEnabled(),
>> -    SummaryLog, N, Sym));
>> -  report->addRange(ErrorRange);
>> -  C.emitReport(std::move(report));
>> + if (!isAnnotatedToSkipDiagnostics(N)){
>> +  auto report = std::unique_ptr<BugReport>(
>> + new CFRefReport(*BT, C.getASTContext().getLangOpts(),
>> C.isObjCGCEnabled(),
>> +                      SummaryLog, N, Sym));
>> +  report->addRange(ErrorRange);
>> +  C.emitReport(std::move(report));
>> +  }
>>  }
>> //===-------------------------------------------------------
>> ---------------===//
>>
>> More specifically, the code highlighted in red above is causing the two
>> assertion failures mentioned below.
>>
>> The following test-cases are the unexpected failures:
>>
>>   * Analysis/inlining/RetainCountExamples.m
>>   * Analysis/properties.m
>>
>> *Note:* The above diff is a subset of the code that I have changed. I
>> added the check *if (!isAnnotatedToSkipDiagnostics(N))* before every
>> invocation to *emitReport* to suppress raising warnings for functions
>> having the annotate attribute *check_attribute_annotate*. It seemed to work
>> for manually made test-cases but clearly there is something wrong with my
>> methodology.
>>
>>
>> Could anyone please tell me the reason behind these assertion failures?
>>
>>
>> Thank you.
>>
>>
>> Regards,
>> Malhar Thakkar
>>>>
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>
>
ᐧ
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170702/a3f9940c/attachment.html>


More information about the cfe-dev mailing list