diff options
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 4 | ||||
-rw-r--r-- | test/Analysis/templates.cpp | 29 |
2 files changed, 32 insertions, 1 deletions
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 41a6d8f503..3d502d230f 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1241,7 +1241,9 @@ bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc())); + TypeSourceInfo *TInfo = D->getSignatureAsWritten(); + if (TInfo) + TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); // This return statement makes sure the traversal of nodes in // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) diff --git a/test/Analysis/templates.cpp b/test/Analysis/templates.cpp new file mode 100644 index 0000000000..6add18c190 --- /dev/null +++ b/test/Analysis/templates.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -fblocks -verify %s + +// Do not crash on this templated code which uses a block. +typedef void (^my_block)(void); +static void useBlock(my_block block){} +template<class T> class MyClass; +typedef MyClass<float> Mf; + +template<class T> +class MyClass +{ +public: + MyClass() {} + MyClass(T a); + void I(); +private: + static const T one; +}; + +template<class T> const T MyClass<T>::one = static_cast<T>(1); +template<class T> inline MyClass<T>::MyClass(T a){} +template<class T> void MyClass<T>::I() { + static MyClass<T>* mPtr = 0; + useBlock(^{ mPtr = new MyClass<T> (MyClass<T>::one); }); +}; +int main(){ + Mf m; + m.I(); +} |