From eb41640fb417e25eb3218c2662a0dd512cdab04a Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Wed, 22 May 2013 18:09:44 +0000 Subject: [PATCH] [analyzer] Don't crash if a block doesn't have a type signature. Currently, blocks instantiated in templates lose their "signature as written"; it's not clear if this is intentional. Change the analyzer's use of BlockDecl::getSignatureAsWritten to check whether or not the signature is actually there. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182497 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/CallEvent.cpp | 7 +++++-- lib/StaticAnalyzer/Core/MemRegion.cpp | 15 ++++++++++++--- test/Analysis/templates.cpp | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index dfd20b8b33..8ac09ebb2d 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -245,10 +245,13 @@ QualType CallEvent::getDeclaredResultType(const Decl *D) { // Blocks are difficult because the return type may not be stored in the // BlockDecl itself. The AST should probably be enhanced, but for now we // just do what we can. - QualType Ty = BD->getSignatureAsWritten()->getType(); - if (const FunctionType *FT = Ty->getAs()) + // FIXME: All blocks should have signatures-as-written, even if the return + // type is inferred. (That's signified is with a dependent result type.) + if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) { + const FunctionType *FT = TSI->getType()->castAs(); if (!FT->getResultType()->isDependentType()) return FT->getResultType(); + } return QualType(); } diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 42073d4841..31ac86bea6 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -806,10 +806,19 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, getFunctionTextRegion(cast(STCD))); else if (const BlockDecl *BD = dyn_cast(STCD)) { + // FIXME: The fallback type here is totally bogus -- though it should + // never be queried, it will prevent uniquing with the real + // BlockTextRegion. Ideally we'd fix the AST so that we always had a + // signature. + QualType T; + if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten()) + T = TSI->getType(); + else + T = getContext().getFunctionNoProtoType(getContext().VoidTy); + const BlockTextRegion *BTR = - getBlockTextRegion(BD, - C.getCanonicalType(BD->getSignatureAsWritten()->getType()), - STC->getAnalysisDeclContext()); + getBlockTextRegion(BD, C.getCanonicalType(T), + STC->getAnalysisDeclContext()); sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind, BTR); } diff --git a/test/Analysis/templates.cpp b/test/Analysis/templates.cpp index faa5c1a762..131794a7c9 100644 --- a/test/Analysis/templates.cpp +++ b/test/Analysis/templates.cpp @@ -48,3 +48,25 @@ void testNonTypeTemplateInstantiation() { #endif } +namespace rdar13954714 { + template + bool blockInTemplate() { + return (^() { + return VALUE; + })(); + } + + // force instantiation + template bool blockInTemplate(); + + template + void blockWithStatic() { + (void)^() { + static int x; + return ++x; + }; + } + + // force instantiation + template void blockWithStatic(); +} -- 2.40.0