[cfe-dev] RetainCountChecker | Assertion Failure | check-clang-analysis
Artem Dergachev via cfe-dev
cfe-dev at lists.llvm.org
Sun Jul 2 00:10:27 PDT 2017
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.cocoa.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->getCodeDecl());
1905 const IdentifierInfo *II = FD->getIdentifier();
1906
1907 if (II) {
(lldb) p EN->getCodeDecl().dump()
ObjCMethodDecl 0x1170ab5c0
<(...censored...)/llvm/tools/clang/test/Analysis/properties.m:559:1,
line:563:1> line:559:1 - testRetainAndRelease 'void'
(...more stuff...)
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.
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
More information about the cfe-dev
mailing list