]> granicus.if.org Git - clang/commitdiff
[analyzer] Look through SubstNonTypeTemplateParmExprs.
authorJordan Rose <jordan_rose@apple.com>
Fri, 27 Jul 2012 01:15:02 +0000 (01:15 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 27 Jul 2012 01:15:02 +0000 (01:15 +0000)
We were treating this like a CXXDefaultArgExpr, but
SubstNonTypeTemplateParmExpr actually appears when a template is
instantiated, i.e. we have all the information necessary to evaluate it.
This allows us to inline functions like llvm::array_lengthof.

<rdar://problem/11949235>

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

lib/StaticAnalyzer/Core/Environment.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
test/Analysis/templates.cpp

index 29030914e7e7113822fd4c93d6414b956a536650..52644f7702fcdd1085c6e439e1fc4cba136c2ce5 100644 (file)
@@ -96,6 +96,9 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry,
       case Stmt::CXXBindTemporaryExprClass:
         E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
         continue;
+      case Stmt::SubstNonTypeTemplateParmExprClass:
+        E = cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement();
+        continue;
       case Stmt::ObjCStringLiteralClass: {
         MemRegionManager &MRMgr = svalBuilder.getRegionManager();
         const ObjCStringLiteral *SL = cast<ObjCStringLiteral>(E);
index d1ee60001e11f839f9de52702f8bce31676d9c66..7db519c5781ed53911b0ca8510fd4a038ded4f0d 100644 (file)
@@ -528,7 +528,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     
     // We don't handle default arguments either yet, but we can fake it
     // for now by just skipping them.
-    case Stmt::SubstNonTypeTemplateParmExprClass:
     case Stmt::CXXDefaultArgExprClass:
       break;
 
@@ -622,6 +621,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
     case Stmt::StringLiteralClass:
     case Stmt::ObjCStringLiteralClass:
     case Stmt::CXXBindTemporaryExprClass:
+    case Stmt::SubstNonTypeTemplateParmExprClass:
     case Stmt::CXXNullPtrLiteralExprClass: {
       Bldr.takeNodes(Pred);
       ExplodedNodeSet preVisit;
index 6add18c19081186fd3811918a0447f67a8dd6300..671aa7858204190985e7abd71ac4f30890c31d37 100644 (file)
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fblocks -verify %s
+
+void clang_analyzer_eval(bool);
 
 // Do not crash on this templated code which uses a block.
 typedef void (^my_block)(void);
@@ -27,3 +29,16 @@ int main(){
   Mf m;
   m.I();
 }
+
+
+// <rdar://problem/11949235>
+template<class T, unsigned N>
+inline unsigned array_lengthof(T (&)[N]) {
+  return N;
+}
+
+void testNonTypeTemplateInstantiation() {
+  const char *S[] = { "a", "b" };
+  clang_analyzer_eval(array_lengthof(S) == 2); // expected-warning{{TRUE}}
+}
+