]> granicus.if.org Git - clang/commitdiff
[analyzer] Don't crash if a block doesn't have a type signature.
authorJordan Rose <jordan_rose@apple.com>
Wed, 22 May 2013 18:09:44 +0000 (18:09 +0000)
committerJordan Rose <jordan_rose@apple.com>
Wed, 22 May 2013 18:09:44 +0000 (18:09 +0000)
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.

<rdar://problem/13954714>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182497 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/CallEvent.cpp
lib/StaticAnalyzer/Core/MemRegion.cpp
test/Analysis/templates.cpp

index dfd20b8b332b30da1004428fe04163b539a23fe6..8ac09ebb2d1f750359b26563e0813383a220dcc9 100644 (file)
@@ -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<FunctionType>())
+    // 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<FunctionType>();
       if (!FT->getResultType()->isDependentType())
         return FT->getResultType();
+    }
 
     return QualType();
   }
index 42073d4841f74c20bac499c9f1b2f3f86432b56c..31ac86bea663d2016e3d3ddeb57e607d0686bd22 100644 (file)
@@ -806,10 +806,19 @@ const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
           sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
                                   getFunctionTextRegion(cast<NamedDecl>(STCD)));
         else if (const BlockDecl *BD = dyn_cast<BlockDecl>(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);
         }
index faa5c1a762094c1104b80ea1616f669f82b8cbab..131794a7c9319933464d75982e0ea75149484f58 100644 (file)
@@ -48,3 +48,25 @@ void testNonTypeTemplateInstantiation() {
 #endif
 }
 
+namespace rdar13954714 {
+  template <bool VALUE>
+  bool blockInTemplate() {
+    return (^() {
+      return VALUE;
+    })();
+  }
+
+  // force instantiation
+  template bool blockInTemplate<true>();
+
+  template <bool VALUE>
+  void blockWithStatic() {
+    (void)^() {
+      static int x;
+      return ++x;
+    };
+  }
+
+  // force instantiation
+  template void blockWithStatic<true>();
+}