diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 9947d3ef4f32..8c88e9ec43dc 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -414,6 +414,8 @@ public: virtual void ActOnStartOfObjCMethodDef(Scope *S, DeclPtrTy D); virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body); + DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body, + bool IsInstantiation); void DiagnoseInvalidJumps(Stmt *Body); virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index feb9595736f5..860dda001f13 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3002,7 +3002,8 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; } - PushDeclContext(FnBodyScope, FD); + if (FnBodyScope) + PushDeclContext(FnBodyScope, FD); // Check the validity of our function parameters CheckParmsForFunctionDef(FD); @@ -3013,7 +3014,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { Param->setOwningFunction(FD); // If this has an identifier, add it to the scope stack. - if (Param->getIdentifier()) + if (Param->getIdentifier() && FnBodyScope) PushOnScopeChains(Param, FnBodyScope); } @@ -3039,8 +3040,12 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { return DeclPtrTy::make(FD); } - Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) { + return ActOnFinishFunctionBody(D, move(BodyArg), false); +} + +Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, + bool IsInstantiation) { Decl *dcl = D.getAs(); Stmt *Body = BodyArg.takeAs(); if (FunctionDecl *FD = dyn_cast_or_null(dcl)) { @@ -3053,7 +3058,9 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) { Body->Destroy(Context); return DeclPtrTy(); } - PopDeclContext(); + if (!IsInstantiation) + PopDeclContext(); + // Verify and clean out per-function state. assert(&getLabelMap() == &FunctionLabelMap && "Didn't pop block right?"); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6f6528816412..09e32f7b65c5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2332,14 +2332,14 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // // This check comes when we actually try to perform the // instantiation. - if (SpecializationRequiresInstantiation && - InstantiateClassTemplateSpecialization(Specialization, true)) - return true; + if (SpecializationRequiresInstantiation) + InstantiateClassTemplateSpecialization(Specialization, true); + else { + // Instantiate the members of this class template specialization. + InstantiatingTemplate Inst(*this, TemplateLoc, Specialization); + InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization); + } - // Instantiate the members of this class template specialization. - InstantiatingTemplate Inst(*this, TemplateLoc, Specialization); - InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization); - return DeclPtrTy::make(Specialization); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 113003fd4428..f1a02c48dd12 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -587,6 +587,8 @@ void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) { // FIXME: add to the instantiation stack. + ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function)); + // Introduce a new scope where local variable instantiations will be // recorded. LocalInstantiationScope Scope(*this); @@ -605,10 +607,9 @@ void Sema::InstantiateFunctionDefinition(FunctionDecl *Function) { // Instantiate the function body. OwningStmtResult Body = InstantiateStmt(Pattern, getTemplateInstantiationArgs(Function)); - if (Body.isInvalid()) - Function->setInvalidDecl(true); - else - Function->setBody(Body.takeAs()); + + ActOnFinishFunctionBody(DeclPtrTy::make(Function), move(Body), + /*IsInstantiation=*/true); CurContext = PreviousContext; } diff --git a/clang/test/SemaTemplate/instantiate-function-1.cpp b/clang/test/SemaTemplate/instantiate-function-1.cpp index fd79902fdc92..482b466e8456 100644 --- a/clang/test/SemaTemplate/instantiate-function-1.cpp +++ b/clang/test/SemaTemplate/instantiate-function-1.cpp @@ -1,5 +1,4 @@ // RUN: clang-cc -fsyntax-only -verify %s - template struct X0 { void f(T x, U y) { @@ -50,3 +49,12 @@ template struct X4 { template struct X4; // expected-note{{in instantiation of template class 'X4' requested here}} template struct X4; // expected-note{{in instantiation of template class 'X4' requested here}} + +struct Incomplete; // expected-note{{forward declaration}} + +template struct X5 { + T f() { } // expected-error{{incomplete result type}} +}; +void test_X5(X5 x5); // okay! + +template struct X5; // expected-note{{instantiation}}