From 604c30299d8d94d29ad1db8c571c19d1e4699fa5 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 1 Mar 2010 18:27:54 +0000 Subject: [PATCH] Robustify instantiation of templates when there are errors in the template definition. Do this both by being more tolerant of errors in our asserts and by not dropping a variable declaration completely when its initializer is ill-formed. Fixes the crash-on-invalid in PR6375, but not the original issue. llvm-svn: 97463 --- clang/include/clang/Parse/Action.h | 6 +++ clang/lib/Parse/ParseDecl.cpp | 8 +-- clang/lib/Sema/Sema.h | 3 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 +- .../test/SemaTemplate/instantiate-invalid.cpp | 52 +++++++++++++++++++ 5 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaTemplate/instantiate-invalid.cpp diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 469816caa552..f211b5ca3a69 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -503,6 +503,12 @@ public: return; } + /// \brief Note that the given declaration had an initializer that could not + /// be parsed. + virtual void ActOnInitializerError(DeclPtrTy Dcl) { + return; + } + /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this /// gives the actions implementation a chance to process the group as a whole. virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 4405dcb974a8..8a32f35b64b0 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -564,10 +564,10 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, } if (Init.isInvalid()) { - SkipUntil(tok::semi, true, true); - return DeclPtrTy(); - } - Actions.AddInitializerToDecl(ThisDecl, move(Init)); + SkipUntil(tok::comma, true, true); + Actions.ActOnInitializerError(ThisDecl); + } else + Actions.AddInitializerToDecl(ThisDecl, move(Init)); } } else if (Tok.is(tok::l_paren)) { // Parse C++ direct initializer: '(' expression-list ')' diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 0fe9b7fa2187..da192dd88795 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -3413,7 +3413,8 @@ public: Decl *getInstantiationOf(const Decl *D) { Decl *Result = LocalDecls[D]; - assert(Result && "declaration was not instantiated in this scope!"); + assert((Result || D->isInvalidDecl()) && + "declaration was not instantiated in this scope!"); return Result; } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3d9899e112ea..0f7bae835fde 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2323,7 +2323,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, } // UsingShadowDecls can instantiate to nothing because of using hiding. - assert((Result || isa(D)) + assert((Result || isa(D) || D->isInvalidDecl() || + cast(ParentDC)->isInvalidDecl()) && "Unable to find instantiation of declaration!"); D = Result; diff --git a/clang/test/SemaTemplate/instantiate-invalid.cpp b/clang/test/SemaTemplate/instantiate-invalid.cpp new file mode 100644 index 000000000000..b8a59015c09f --- /dev/null +++ b/clang/test/SemaTemplate/instantiate-invalid.cpp @@ -0,0 +1,52 @@ +// RUN: not %clang_cc1 -fsyntax-only %s +namespace PR6375 { + template class rasterizer_sl_clip Conv::xi(x2), Conv::yi(y2)); +namespace agg +{ + template class rasterizer_scanline_aa + { + template bool sweep_scanline(Scanline& sl) + { + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + while(num_cells) { } + } + } + class scanline_u8 {} + template class renderer_base { } +} + template + void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, const ColorT& color) + { + while(ras.sweep_scanline(sl)) + { + } + }; +namespace agg +{ + struct rgba8 + { + }; + template + void render_ctrl(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + render_scanlines_aa_solid(ras, sl, r, c.color(i)); + } + template class rbox_ctrl : public rbox_ctrl_impl + { + const ColorT& color(unsigned i) const { return *m_colors[i]; } + } +class the_application : public agg::platform_support +{ + agg::rbox_ctrl m_polygons; + virtual void on_init() + { + typedef agg::renderer_base base_ren_type; + base_ren_type ren_base(pf); + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + agg::render_ctrl(ras, sl, ren_base, m_polygons); + } +}; +} +}