From 69a0e5021c5c49a34aa25cd89b1e613a52097e65 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Fri, 27 Jul 2012 01:15:02 +0000 Subject: [PATCH] [analyzer] Look through SubstNonTypeTemplateParmExprs. 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160846 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/Environment.cpp | 3 +++ lib/StaticAnalyzer/Core/ExprEngine.cpp | 2 +- test/Analysis/templates.cpp | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/StaticAnalyzer/Core/Environment.cpp b/lib/StaticAnalyzer/Core/Environment.cpp index 29030914e7..52644f7702 100644 --- a/lib/StaticAnalyzer/Core/Environment.cpp +++ b/lib/StaticAnalyzer/Core/Environment.cpp @@ -96,6 +96,9 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry, case Stmt::CXXBindTemporaryExprClass: E = cast(E)->getSubExpr(); continue; + case Stmt::SubstNonTypeTemplateParmExprClass: + E = cast(E)->getReplacement(); + continue; case Stmt::ObjCStringLiteralClass: { MemRegionManager &MRMgr = svalBuilder.getRegionManager(); const ObjCStringLiteral *SL = cast(E); diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index d1ee60001e..7db519c578 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -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; diff --git a/test/Analysis/templates.cpp b/test/Analysis/templates.cpp index 6add18c190..671aa78582 100644 --- a/test/Analysis/templates.cpp +++ b/test/Analysis/templates.cpp @@ -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(); } + + +// +template +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}} +} + -- 2.40.0