]> granicus.if.org Git - clang/commitdiff
Call ActOnStartOfFunctionDecl/ActOnFinishFunctionBody when
authorDouglas Gregor <dgregor@apple.com>
Fri, 15 May 2009 17:59:04 +0000 (17:59 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 15 May 2009 17:59:04 +0000 (17:59 +0000)
instantiating the definition of a function from a template.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71869 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-function-1.cpp

index 9947d3ef4f32ab285498229ccad094b6868ebfb2..8c88e9ec43dce5b0311cbb44c1c611bef41d736a 100644 (file)
@@ -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);
 
index feb9595736f5616a7a6b5994d50ea7ba17646027..860dda001f1398d3099f798ddfae66b597b7e484 100644 (file)
@@ -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<Decl>();
   Stmt *Body = BodyArg.takeAs<Stmt>();
   if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(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?");
index 6f6528816412bc9705b016b757361d70858f06e9..09e32f7b65c5e0cd97742f14556a93472f76e228 100644 (file)
@@ -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);
 }
 
index 113003fd44284f317dfadddd30bdf775471bb600..f1a02c48dd128e2ad1088f3386d4d2ed5ed9928b 100644 (file)
@@ -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<Stmt>());
+
+  ActOnFinishFunctionBody(DeclPtrTy::make(Function), move(Body), 
+                          /*IsInstantiation=*/true);
 
   CurContext = PreviousContext;
 }
index fd79902fdc92fe792f47c10da8fd4dd1b095a826..482b466e845666095c26289ae1cb74588368c1bb 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: clang-cc -fsyntax-only -verify %s
-
 template<typename T, typename U>
 struct X0 {
   void f(T x, U y) { 
@@ -50,3 +49,12 @@ template <typename T> struct X4 {
 
 template struct X4<void>; // expected-note{{in instantiation of template class 'X4<void>' requested here}}
 template struct X4<int>; // expected-note{{in instantiation of template class 'X4<int>' requested here}}
+
+struct Incomplete; // expected-note{{forward declaration}}
+
+template<typename T> struct X5 {
+  T f() { } // expected-error{{incomplete result type}}
+};
+void test_X5(X5<Incomplete> x5); // okay!
+
+template struct X5<Incomplete>; // expected-note{{instantiation}}