r204547 - Emit an update record if we instantiate the definition of a function template

Richard Smith richard-llvm at metafoo.co.uk
Sat Mar 22 16:33:22 PDT 2014


Author: rsmith
Date: Sat Mar 22 18:33:22 2014
New Revision: 204547

URL: http://llvm.org/viewvc/llvm-project?rev=204547&view=rev
Log:
Emit an update record if we instantiate the definition of a function template
specialization from a module. (This can also happen for function template
specializations in PCHs if they're instantiated eagerly, because they're
constexpr or have a deduced return type.)

Added:
    cfe/trunk/test/Modules/Inputs/cxx-irgen-left.h
    cfe/trunk/test/Modules/Inputs/cxx-irgen-right.h
    cfe/trunk/test/Modules/Inputs/cxx-irgen-top.h
    cfe/trunk/test/Modules/cxx-irgen.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTMutationListener.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTCommon.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp

Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=204547&r1=204546&r2=204547&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTMutationListener.h (original)
+++ cfe/trunk/include/clang/AST/ASTMutationListener.h Sat Mar 22 18:33:22 2014
@@ -78,6 +78,9 @@ public:
   /// \brief A static data member was implicitly instantiated.
   virtual void StaticDataMemberInstantiated(const VarDecl *D) {}
 
+  /// \brief A function template's definition was instantiated.
+  virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {}
+
   /// \brief A new objc category class was added for an interface.
   virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                             const ObjCInterfaceDecl *IFD) {}

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=204547&r1=204546&r2=204547&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Sat Mar 22 18:33:22 2014
@@ -503,6 +503,7 @@ private:
 
   void WriteDeclsBlockAbbrevs();
   void WriteDecl(ASTContext &Context, Decl *D);
+  void AddFunctionDefinition(const FunctionDecl *FD, RecordData &Record);
 
   void WriteASTCore(Sema &SemaRef,
                     StringRef isysroot, const std::string &OutputFile,
@@ -766,6 +767,7 @@ public:
   void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType) override;
   void CompletedImplicitDefinition(const FunctionDecl *D) override;
   void StaticDataMemberInstantiated(const VarDecl *D) override;
+  void FunctionDefinitionInstantiated(const FunctionDecl *D) override;
   void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD,
                                     const ObjCInterfaceDecl *IFD) override;
   void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop,

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=204547&r1=204546&r2=204547&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Mar 22 18:33:22 2014
@@ -12,6 +12,7 @@
 #include "clang/Sema/SemaInternal.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTMutationListener.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/DeclVisitor.h"
 #include "clang/AST/DependentDiagnostic.h"
@@ -3439,7 +3440,8 @@ void Sema::InstantiateFunctionDefinition
 
     PerformDependentDiagnostics(PatternDecl, TemplateArgs);
 
-    // FIXME: Notify the ASTMutationListener that we did this.
+    if (auto *Listener = getASTMutationListener())
+      Listener->FunctionDefinitionInstantiated(Function);
 
     savedContext.pop();
   }

Modified: cfe/trunk/lib/Serialization/ASTCommon.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.h?rev=204547&r1=204546&r2=204547&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTCommon.h (original)
+++ cfe/trunk/lib/Serialization/ASTCommon.h Sat Mar 22 18:33:22 2014
@@ -26,6 +26,7 @@ enum DeclUpdateKind {
   UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION,
   UPD_CXX_ADDED_ANONYMOUS_NAMESPACE,
   UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER,
+  UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION,
   UPD_CXX_RESOLVED_EXCEPTION_SPEC,
   UPD_CXX_DEDUCED_RETURN_TYPE,
   UPD_DECL_MARKED_USED,

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=204547&r1=204546&r2=204547&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sat Mar 22 18:33:22 2014
@@ -2944,6 +2944,24 @@ void ASTDeclReader::UpdateDecl(Decl *D,
           Reader.ReadSourceLocation(ModuleFile, Record, Idx));
       break;
 
+    case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION: {
+      FunctionDecl *FD = cast<FunctionDecl>(D);
+      if (FD->hasBody() || Reader.PendingBodies[FD])
+        // FIXME: Maybe check for ODR violations.
+        break;
+
+      if (Record[Idx++])
+        FD->setImplicitlyInline();
+      FD->setInnerLocStart(Reader.ReadSourceLocation(ModuleFile, Record, Idx));
+      if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
+        std::tie(CD->CtorInitializers, CD->NumCtorInitializers) =
+            Reader.ReadCXXCtorInitializers(ModuleFile, Record, Idx);
+      // Store the offset of the body so we can lazily load it later.
+      Reader.PendingBodies[FD] = GetCurrentCursorOffset();
+      assert(Idx == Record.size() && "lazy body must be last");
+      break;
+    }
+
     case UPD_CXX_RESOLVED_EXCEPTION_SPEC: {
       auto *FD = cast<FunctionDecl>(D);
       auto *FPT = FD->getType()->castAs<FunctionProtoType>();

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=204547&r1=204546&r2=204547&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Sat Mar 22 18:33:22 2014
@@ -4358,6 +4358,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(R
     OffsetsRecord.push_back(GetDeclRef(D));
     OffsetsRecord.push_back(Stream.GetCurrentBitNo());
 
+    bool HasUpdatedBody = false;
     RecordData Record;
     for (auto &Update : DeclUpdate.second) {
       DeclUpdateKind Kind = (DeclUpdateKind)Update.getKind();
@@ -4374,6 +4375,13 @@ void ASTWriter::WriteDeclUpdatesBlocks(R
         AddSourceLocation(Update.getLoc(), Record);
         break;
 
+      case UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION:
+        // An updated body is emitted last, so that the reader doesn't need
+        // to skip over the lazy body to reach statements for other records.
+        Record.pop_back();
+        HasUpdatedBody = true;
+        break;
+
       case UPD_CXX_RESOLVED_EXCEPTION_SPEC:
         addExceptionSpec(
             *this,
@@ -4395,6 +4403,14 @@ void ASTWriter::WriteDeclUpdatesBlocks(R
       }
     }
 
+    if (HasUpdatedBody) {
+      const FunctionDecl *Def = cast<FunctionDecl>(D);
+      Record.push_back(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION);
+      Record.push_back(Def->isInlined());
+      AddSourceLocation(Def->getInnerLocStart(), Record);
+      AddFunctionDefinition(Def, Record);
+    }
+
     Stream.EmitRecord(DECL_UPDATES, Record);
 
     // Flush any statements that were written as part of this update record.
@@ -5381,6 +5397,17 @@ void ASTWriter::CompletedImplicitDefinit
   RewriteDecl(D);
 }
 
+void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) {
+  assert(!WritingAST && "Already writing the AST!");
+  if (!D->isFromASTFile())
+    return;
+
+  // Since the actual instantiation is delayed, this really means that we need
+  // to update the instantiation location.
+  DeclUpdates[D].push_back(
+      DeclUpdate(UPD_CXX_INSTANTIATED_FUNCTION_DEFINITION));
+}
+
 void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) {
   assert(!WritingAST && "Already writing the AST!");
   if (!D->isFromASTFile())

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=204547&r1=204546&r2=204547&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Sat Mar 22 18:33:22 2014
@@ -130,6 +130,14 @@ namespace clang {
     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
     void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D);
+
+    void AddFunctionDefinition(const FunctionDecl *FD) {
+      assert(FD->doesThisDeclarationHaveABody());
+      if (auto *CD = dyn_cast<CXXConstructorDecl>(FD))
+        Writer.AddCXXCtorInitializers(CD->CtorInitializers,
+                                      CD->NumCtorInitializers, Record);
+      Writer.AddStmt(FD->getBody());
+    }
   };
 }
 
@@ -1894,3 +1902,11 @@ void ASTWriter::WriteDecl(ASTContext &Co
   if (isRequiredDecl(D, Context))
     EagerlyDeserializedDecls.push_back(ID);
 }
+
+void ASTWriter::AddFunctionDefinition(const FunctionDecl *FD,
+                                      RecordData &Record) {
+  ClearSwitchCaseIDs();
+
+  ASTDeclWriter W(*this, FD->getASTContext(), Record);
+  W.AddFunctionDefinition(FD);
+}

Added: cfe/trunk/test/Modules/Inputs/cxx-irgen-left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-irgen-left.h?rev=204547&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-irgen-left.h (added)
+++ cfe/trunk/test/Modules/Inputs/cxx-irgen-left.h Sat Mar 22 18:33:22 2014
@@ -0,0 +1,3 @@
+#include "cxx-irgen-top.h"
+
+S<int> s;

Added: cfe/trunk/test/Modules/Inputs/cxx-irgen-right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-irgen-right.h?rev=204547&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-irgen-right.h (added)
+++ cfe/trunk/test/Modules/Inputs/cxx-irgen-right.h Sat Mar 22 18:33:22 2014
@@ -0,0 +1,3 @@
+#include "cxx-irgen-top.h"
+
+inline int h() { return S<int>::f(); }

Added: cfe/trunk/test/Modules/Inputs/cxx-irgen-top.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/cxx-irgen-top.h?rev=204547&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/cxx-irgen-top.h (added)
+++ cfe/trunk/test/Modules/Inputs/cxx-irgen-top.h Sat Mar 22 18:33:22 2014
@@ -0,0 +1,6 @@
+template<typename T> struct S {
+  __attribute__((always_inline)) static int f() { return 0; }
+  __attribute__((always_inline, visibility("hidden"))) static int g() { return 0; }
+};
+
+extern template struct S<int>;

Added: cfe/trunk/test/Modules/cxx-irgen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cxx-irgen.cpp?rev=204547&view=auto
==============================================================================
--- cfe/trunk/test/Modules/cxx-irgen.cpp (added)
+++ cfe/trunk/test/Modules/cxx-irgen.cpp Sat Mar 22 18:33:22 2014
@@ -0,0 +1,15 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -x objective-c++ -fmodules-cache-path=%t -I %S/Inputs -triple %itanium_abi_triple -disable-llvm-optzns -emit-llvm -o - %s | FileCheck %s
+// FIXME: When we have a syntax for modules in C++, use that.
+
+ at import cxx_irgen_top;
+ at import cxx_irgen_left;
+ at import cxx_irgen_right;
+
+// CHECK: define available_externally hidden i32 @_ZN1SIiE1gEv({{.*}} #[[ALWAYS_INLINE:.*]] align
+int a = S<int>::g();
+
+// CHECK: define available_externally i32 @_ZN1SIiE1fEv({{.*}} #[[ALWAYS_INLINE]] align
+int b = h();
+
+// CHECK: attributes #[[ALWAYS_INLINE]] = {{.*}} alwaysinline





More information about the cfe-commits mailing list