[cfe-commits] r110324 - in /cfe/trunk: include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Sema/Sema.cpp test/PCH/cxx-templates.cpp test/PCH/cxx-templates.h

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Aug 5 02:48:16 PDT 2010


Author: akirtzidis
Date: Thu Aug  5 04:48:16 2010
New Revision: 110324

URL: http://llvm.org/viewvc/llvm-project?rev=110324&view=rev
Log:
Store the pending implicit instantiations in the PCH and perform them at the end of the translation unit that
included the PCH, as God intended.

Modified:
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/test/PCH/cxx-templates.cpp
    cfe/trunk/test/PCH/cxx-templates.h

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=110324&r1=110323&r2=110324&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Thu Aug  5 04:48:16 2010
@@ -253,7 +253,10 @@
       SEMA_DECL_REFS = 30,
 
       /// \brief Record code for weak undeclared identifiers.
-      WEAK_UNDECLARED_IDENTIFIERS = 31
+      WEAK_UNDECLARED_IDENTIFIERS = 31,
+
+      /// \brief Record code for pending implicit instantiations.
+      PENDING_IMPLICIT_INSTANTIATIONS = 32
     };
 
     /// \brief Record types used within a source manager block.

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=110324&r1=110323&r2=110324&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Aug  5 04:48:16 2010
@@ -397,6 +397,9 @@
   /// \brief The set of dynamic CXXRecord declarations stored in the PCH file.
   llvm::SmallVector<uint64_t, 16> DynamicClasses;
 
+  /// \brief The set of pending implicit instantiations stored in the PCH file.
+  llvm::SmallVector<uint64_t, 64> PendingImplicitInstantiations;
+
   /// \brief The set of Sema declaration references, stored in PCH.
   llvm::SmallVector<uint64_t, 4> SemaDeclRefs;
 

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=110324&r1=110323&r2=110324&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Aug  5 04:48:16 2010
@@ -1739,6 +1739,15 @@
       DynamicClasses.swap(Record);
       break;
 
+    case pch::PENDING_IMPLICIT_INSTANTIATIONS:
+      // Optimization for the first block.
+      if (PendingImplicitInstantiations.empty())
+        PendingImplicitInstantiations.swap(Record);
+      else
+        PendingImplicitInstantiations.insert(
+             PendingImplicitInstantiations.end(), Record.begin(), Record.end());
+      break;
+
     case pch::SEMA_DECL_REFS:
       if (!SemaDeclRefs.empty()) {
         Error("duplicate SEMA_DECL_REFS record in PCH file");
@@ -3191,6 +3200,16 @@
     SemaObj->DynamicClasses.push_back(
                                cast<CXXRecordDecl>(GetDecl(DynamicClasses[I])));
 
+  // If there were any pending implicit instantiations, deserialize them
+  // and add them to Sema's queue of such instantiations.
+  assert(PendingImplicitInstantiations.size() % 2 == 0 &&
+         "Expected pairs of entries");
+  for (unsigned Idx = 0, N = PendingImplicitInstantiations.size(); Idx < N;) {
+    ValueDecl *D=cast<ValueDecl>(GetDecl(PendingImplicitInstantiations[Idx++]));
+    SourceLocation Loc = ReadSourceLocation(PendingImplicitInstantiations, Idx);
+    SemaObj->PendingImplicitInstantiations.push_back(std::make_pair(D, Loc));
+  }
+
   // Load the offsets of the declarations that Sema references.
   // They will be lazily deserialized when needed.
   if (!SemaDeclRefs.empty()) {

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=110324&r1=110323&r2=110324&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Aug  5 04:48:16 2010
@@ -2255,6 +2255,17 @@
   for (unsigned I = 0, N = SemaRef.DynamicClasses.size(); I != N; ++I)
     AddDeclRef(SemaRef.DynamicClasses[I], DynamicClasses);
 
+  // Build a record containing all of pending implicit instantiations.
+  RecordData PendingImplicitInstantiations;
+  for (std::deque<Sema::PendingImplicitInstantiation>::iterator
+         I = SemaRef.PendingImplicitInstantiations.begin(),
+         N = SemaRef.PendingImplicitInstantiations.end(); I != N; ++I) {
+    AddDeclRef(I->first, PendingImplicitInstantiations);
+    AddSourceLocation(I->second, PendingImplicitInstantiations);
+  }
+  assert(SemaRef.PendingLocalImplicitInstantiations.empty() &&
+         "There are local ones at end of translation unit!");
+
   // Build a record containing some declaration references.
   RecordData SemaDeclRefs;
   if (SemaRef.StdNamespace || SemaRef.StdBadAlloc) {
@@ -2347,6 +2358,11 @@
   if (!DynamicClasses.empty())
     Stream.EmitRecord(pch::DYNAMIC_CLASSES, DynamicClasses);
 
+  // Write the record containing pending implicit instantiations.
+  if (!PendingImplicitInstantiations.empty())
+    Stream.EmitRecord(pch::PENDING_IMPLICIT_INSTANTIATIONS,
+                      PendingImplicitInstantiations);
+
   // Write the record containing declaration references of Sema.
   if (!SemaDeclRefs.empty())
     Stream.EmitRecord(pch::SEMA_DECL_REFS, SemaDeclRefs);

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=110324&r1=110323&r2=110324&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Aug  5 04:48:16 2010
@@ -215,26 +215,29 @@
 /// ActOnEndOfTranslationUnit - This is called at the very end of the
 /// translation unit when EOF is reached and all but the top-level scope is
 /// popped.
-void Sema::ActOnEndOfTranslationUnit() {  
-  while (1) {
-    // C++: Perform implicit template instantiations.
-    //
-    // FIXME: When we perform these implicit instantiations, we do not carefully
-    // keep track of the point of instantiation (C++ [temp.point]). This means
-    // that name lookup that occurs within the template instantiation will
-    // always happen at the end of the translation unit, so it will find
-    // some names that should not be found. Although this is common behavior
-    // for C++ compilers, it is technically wrong. In the future, we either need
-    // to be able to filter the results of name lookup or we need to perform
-    // template instantiations earlier.
-    PerformPendingImplicitInstantiations();
-    
-    /// If DefinedUsedVTables ends up marking any virtual member
-    /// functions it might lead to more pending template
-    /// instantiations, which is why we need to loop here.
-    if (!DefineUsedVTables())
-      break;
-  }
+void Sema::ActOnEndOfTranslationUnit() {
+  // At PCH writing, implicit instantiations and VTable handling info are
+  // stored and performed when the PCH is included.
+  if (CompleteTranslationUnit)
+    while (1) {
+      // C++: Perform implicit template instantiations.
+      //
+      // FIXME: When we perform these implicit instantiations, we do not
+      // carefully keep track of the point of instantiation (C++ [temp.point]).
+      // This means that name lookup that occurs within the template
+      // instantiation will always happen at the end of the translation unit,
+      // so it will find some names that should not be found. Although this is
+      // common behavior for C++ compilers, it is technically wrong. In the
+      // future, we either need to be able to filter the results of name lookup
+      // or we need to perform template instantiations earlier.
+      PerformPendingImplicitInstantiations();
+
+      /// If DefinedUsedVTables ends up marking any virtual member
+      /// functions it might lead to more pending template
+      /// instantiations, which is why we need to loop here.
+      if (!DefineUsedVTables())
+        break;
+    }
   
   // Remove functions that turned out to be used.
   UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(), 

Modified: cfe/trunk/test/PCH/cxx-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.cpp?rev=110324&r1=110323&r2=110324&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-templates.cpp (original)
+++ cfe/trunk/test/PCH/cxx-templates.cpp Thu Aug  5 04:48:16 2010
@@ -7,6 +7,7 @@
 // RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump  1>/dev/null
 // RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s
 
+// CHECK: define weak_odr void @_ZN2S4IiE1mEv
 // CHECK: define linkonce_odr void @_ZN2S3IiE1mEv
 
 struct A {
@@ -30,3 +31,5 @@
   S3<int> s3;
   s3.m();
 }
+
+template struct S4<int>;

Modified: cfe/trunk/test/PCH/cxx-templates.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.h?rev=110324&r1=110323&r2=110324&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx-templates.h (original)
+++ cfe/trunk/test/PCH/cxx-templates.h Thu Aug  5 04:48:16 2010
@@ -124,3 +124,14 @@
 
 template <typename T>
 inline void S3<T>::m() { }
+
+template <typename T>
+struct S4 {
+    void m() { }
+};
+extern template struct S4<int>;
+
+void S4ImplicitInst() {
+    S4<int> s;
+    s.m();
+}





More information about the cfe-commits mailing list