[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.

<rdar://problem/11949235>

llvm-svn: 160846
This commit is contained in:
Jordan Rose 2012-07-27 01:15:02 +00:00
parent de76c92b15
commit 41c98d9dc3
3 changed files with 20 additions and 2 deletions

View 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);

View 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;

View 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}}
}