[cfe-commits] r164993 - in /cfe/trunk: include/clang/Serialization/ASTReader.h lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp test/Modules/Inputs/module.map test/Modules/Inputs/redecl-merge-bottom.h test/Modules/Inputs/redecl-merge-left.h test/Modules/Inputs/redecl-merge-right.h test/Modules/Inputs/redecl-merge-top.h test/Modules/Inputs/templates-left.h test/Modules/Inputs/templates-right.h test/Modules/Inputs/templates-top.h test/Modules/redecl-merge.m test/Modules/templates.mm

Axel Naumann Axel.Naumann at cern.ch
Tue Oct 2 02:09:44 PDT 2012


Author: axel
Date: Tue Oct  2 04:09:43 2012
New Revision: 164993

URL: http://llvm.org/viewvc/llvm-project?rev=164993&view=rev
Log:
Merge pending instantiations instead of overwriting existing ones.
Check whether a pending instantiation needs to be instantiated (or whether an instantiation already exists).
Verify the size of the PendingInstantiations record (was only checking size of existing PendingInstantiations).

Migrate Obj-C++ part of redecl-merge into separate test, now that this is growing.
templates.mm: test that CodeGen has seen exactly one definition of template instantiations.
redecl-merge.m: use "@" specifier for expected-diagnostics.

Added:
    cfe/trunk/test/Modules/Inputs/templates-left.h   (with props)
    cfe/trunk/test/Modules/Inputs/templates-right.h   (with props)
    cfe/trunk/test/Modules/Inputs/templates-top.h   (with props)
    cfe/trunk/test/Modules/templates.mm
Modified:
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Modules/Inputs/module.map
    cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h
    cfe/trunk/test/Modules/Inputs/redecl-merge-left.h
    cfe/trunk/test/Modules/Inputs/redecl-merge-right.h
    cfe/trunk/test/Modules/Inputs/redecl-merge-top.h
    cfe/trunk/test/Modules/redecl-merge.m

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Oct  2 04:09:43 2012
@@ -687,7 +687,7 @@
   /// Objective-C protocols.
   std::deque<Decl *> InterestingDecls;
 
-  /// \brief The set of redeclarable declaraations that have been deserialized
+  /// \brief The set of redeclarable declarations that have been deserialized
   /// since the last time the declaration chains were linked.
   llvm::SmallPtrSet<Decl *, 16> RedeclsDeserialized;
   
@@ -854,6 +854,10 @@
 
   void finishPendingActions();
 
+  /// \brief Whether D needs to be instantiated, i.e. whether an instantiation
+  /// for D does not exist yet.
+  bool needPendingInstantiation(ValueDecl* D) const;
+
   /// \brief Produce an error diagnostic and return true.
   ///
   /// This routine should only be used for fatal errors that have to

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Oct  2 04:09:43 2012
@@ -2223,13 +2223,15 @@
 
     case PENDING_IMPLICIT_INSTANTIATIONS:
       if (PendingInstantiations.size() % 2 != 0) {
+        Error("Invalid existing PendingInstantiations");
+        return Failure;
+      }
+
+      if (Record.size() % 2 != 0) {
         Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
         return Failure;
       }
-        
-      // Later lists of pending instantiations overwrite earlier ones.
-      // FIXME: This is most certainly wrong for modules.
-      PendingInstantiations.clear();
+
       for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
         PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
         PendingInstantiations.push_back(
@@ -5592,7 +5594,11 @@
     ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
     SourceLocation Loc
       = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
-    Pending.push_back(std::make_pair(D, Loc));
+
+    // For modules, find out whether an instantiation already exists
+    if (!getContext().getLangOpts().Modules
+        || needPendingInstantiation(D))
+      Pending.push_back(std::make_pair(D, Loc));
   }  
   PendingInstantiations.clear();
 }

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Oct  2 04:09:43 2012
@@ -2156,7 +2156,7 @@
   // loading, and some declarations may still be initializing.
   if (isConsumerInterestedIn(D))
     InterestingDecls.push_back(D);
-  
+
   return D;
 }
 
@@ -2504,3 +2504,60 @@
     }
   }
 }
+
+/// \brief Return a template specialization of ND (should be a TemplateDecl)
+///  that matches FD or TD.
+static NamedDecl* findMatchingSpecialization(FunctionDecl* FD,
+                                             ClassTemplateSpecializationDecl*TD,
+                                             NamedDecl* ND) {
+  TemplateDecl* Templt = dyn_cast<TemplateDecl>(ND);
+  if (!Templt) return 0;
+  if (FD) {
+    FunctionTemplateDecl* FTD = dyn_cast<FunctionTemplateDecl>(Templt);
+    if (!FTD) return 0;
+    const TemplateArgumentList* TmpltArgs = FD->getTemplateSpecializationArgs();
+    assert(TmpltArgs || "Template without arguments");
+    void* InsertionPoint;
+    return FTD->findSpecialization(TmpltArgs->data(), TmpltArgs->size(),
+                                   InsertionPoint);
+  } else {
+    ClassTemplateDecl* CTD = dyn_cast<ClassTemplateDecl>(Templt);
+    if (!CTD) return 0;
+    const TemplateArgumentList& TmpltArgs = TD->getTemplateArgs();
+    void* InsertionPoint;
+    return CTD->findSpecialization(TmpltArgs.data(), TmpltArgs.size(),
+                                   InsertionPoint);
+  }
+  return 0;
+}
+
+/// \brief Find out whether an instantiation (outside the module) already exists
+bool ASTReader::needPendingInstantiation(ValueDecl* D) const {
+  DeclContext *DC = D->getDeclContext()->getRedeclContext();
+  DeclarationName Name = D->getDeclName();
+  assert(Name && "unnamed template");
+
+  FunctionDecl* FD = dyn_cast<FunctionDecl>(D);
+  ClassTemplateSpecializationDecl* CD
+    = FD ? 0 : dyn_cast<ClassTemplateSpecializationDecl>(D);
+
+  NamedDecl* FoundSpecialization = 0;
+  if (DC->isTranslationUnit() && SemaObj) {
+    IdentifierResolver &IdResolver = SemaObj->IdResolver;
+    for (IdentifierResolver::iterator I = IdResolver.begin(Name), 
+           IEnd = IdResolver.end();
+         I != IEnd && !FoundSpecialization; ++I)
+      FoundSpecialization = findMatchingSpecialization(FD, CD, *I);
+  } else {
+    // templates are redeclarables, i.e. they must have been merged into
+    // the primary context. Use localUncachedLookup to not pick up template
+    // decls from modules again.
+    llvm::SmallVector<NamedDecl*, 6> Results;
+    DC->getPrimaryContext()->localUncachedLookup(Name, Results);
+    for (llvm::SmallVector<NamedDecl *, 6>::const_iterator
+           I = Results.begin(), E = Results.end();
+         I != E && FoundSpecialization; ++I)
+      FoundSpecialization = findMatchingSpecialization(FD, CD, *I);
+  }
+  return FoundSpecialization && isSameEntity(FoundSpecialization, D);
+}

Modified: cfe/trunk/test/Modules/Inputs/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/module.map?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/module.map (original)
+++ cfe/trunk/test/Modules/Inputs/module.map Tue Oct  2 04:09:43 2012
@@ -78,6 +78,18 @@
   header "namespaces-right.h"
   export *
 }
+module templates_top { 
+  header "templates-top.h"
+  export *
+}
+module templates_left { 
+  header "templates-left.h"
+  export *
+}
+module templates_right { 
+  header "templates-right.h"
+  export *
+}
 module MethodPoolA {
   header "MethodPoolA.h"
 }

Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-bottom.h Tue Oct  2 04:09:43 2012
@@ -18,11 +18,3 @@
 
 void refers_to_C4(C4*);
 
-#ifdef __cplusplus
-template<typename T> class Vector;
-
-template<typename T> class Vector;
-
-template<typename T> class Vector;
-#endif
-

Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-left.h?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-left.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-left.h Tue Oct  2 04:09:43 2012
@@ -78,27 +78,6 @@
 
 extern double var3;
 
-#ifdef __cplusplus
-template<typename T> class Vector;
-
-template<typename T> class Vector;
-
-template<typename T> class List;
-template<> class List<bool> {
-public:
-  void push_back(int);
-};
-namespace N {
-  template<typename T> class Set;
-}
-namespace N {
-  template<typename T> class Set {
-  public:
-    void insert(T);
-  };
-}
-#endif
-
 // Make sure this doesn't introduce an ambiguity-creating 'id' at the
 // top level.
 typedef void funcptr_with_id(int id);

Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-right.h?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-right.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-right.h Tue Oct  2 04:09:43 2012
@@ -78,26 +78,6 @@
 
 static double var3;
 
-#ifdef __cplusplus
-template<typename T> class Vector { 
-public:
-  void push_back(const T&);
-};
-
-template<typename T> class List;
-template<> class List<bool> {
-public:
-  void push_back(int);
-};
-
-namespace N {
-  template<typename T> class Set {
-  public:
-    void insert(T);
-  };
-}
-#endif
-
 int ONE;
 @__experimental_modules_import redecl_merge_top.Explicit;
 const int one = ONE;

Modified: cfe/trunk/test/Modules/Inputs/redecl-merge-top.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/redecl-merge-top.h?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/redecl-merge-top.h (original)
+++ cfe/trunk/test/Modules/Inputs/redecl-merge-top.h Tue Oct  2 04:09:43 2012
@@ -14,12 +14,3 @@
 struct S1;
 struct S2;
 struct S2;
-
-#ifdef __cplusplus
-template<typename T> class Vector;
-
-template<typename T> class List {
-public:
-  void push_back(T);
-};
-#endif

Added: cfe/trunk/test/Modules/Inputs/templates-left.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/templates-left.h?rev=164993&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/templates-left.h (added)
+++ cfe/trunk/test/Modules/Inputs/templates-left.h Tue Oct  2 04:09:43 2012
@@ -0,0 +1,27 @@
+ at __experimental_modules_import templates_top;
+
+template<typename T> class Vector;
+
+template<typename T> class Vector;
+
+template<typename T> class List;
+template<> class List<bool> {
+public:
+  void push_back(int);
+};
+namespace N {
+  template<typename T> class Set;
+}
+namespace N {
+  template<typename T> class Set {
+  public:
+    void insert(T);
+  };
+}
+
+template <typename T>
+void pendingInstantiation(T) {}
+void triggerPendingInstantiation() {
+  pendingInstantiation(12);
+  pendingInstantiation(42.);
+}

Propchange: cfe/trunk/test/Modules/Inputs/templates-left.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Propchange: cfe/trunk/test/Modules/Inputs/templates-left.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cfe/trunk/test/Modules/Inputs/templates-right.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/templates-right.h?rev=164993&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/templates-right.h (added)
+++ cfe/trunk/test/Modules/Inputs/templates-right.h Tue Oct  2 04:09:43 2012
@@ -0,0 +1,25 @@
+ at __experimental_modules_import templates_top;
+
+template<typename T> class Vector { 
+public:
+  void push_back(const T&);
+};
+
+template<typename T> class List;
+template<> class List<bool> {
+public:
+  void push_back(int);
+};
+
+namespace N {
+  template<typename T> class Set {
+  public:
+    void insert(T);
+  };
+}
+
+template <typename T>
+void pendingInstantiation(T) {}
+void triggerPendingInstantiationToo() {
+  pendingInstantiation(12);
+}

Propchange: cfe/trunk/test/Modules/Inputs/templates-right.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Propchange: cfe/trunk/test/Modules/Inputs/templates-right.h
------------------------------------------------------------------------------
    svn:keywords = Id

Added: cfe/trunk/test/Modules/Inputs/templates-top.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/templates-top.h?rev=164993&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/templates-top.h (added)
+++ cfe/trunk/test/Modules/Inputs/templates-top.h Tue Oct  2 04:09:43 2012
@@ -0,0 +1,6 @@
+template<typename T> class Vector;
+
+template<typename T> class List {
+public:
+  void push_back(T);
+};

Propchange: cfe/trunk/test/Modules/Inputs/templates-top.h
------------------------------------------------------------------------------
    svn:eol-style = LF

Propchange: cfe/trunk/test/Modules/Inputs/templates-top.h
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: cfe/trunk/test/Modules/redecl-merge.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/redecl-merge.m?rev=164993&r1=164992&r2=164993&view=diff
==============================================================================
--- cfe/trunk/test/Modules/redecl-merge.m (original)
+++ cfe/trunk/test/Modules/redecl-merge.m Tue Oct  2 04:09:43 2012
@@ -1,6 +1,5 @@
 // RUN: rm -rf %t
 // RUN: %clang_cc1 -fmodules -fmodule-cache-path %t -I %S/Inputs %s -verify -Wno-objc-root-class
-// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodule-cache-path %t -I %S/Inputs %s -verify -Wno-objc-root-class
 @class C2;
 @class C3;
 @class C3;
@@ -57,26 +56,26 @@
 
 void testTypedefMerge(int i, double d) {
   T1 *ip = &i;
-  // in other file: expected-note{{candidate found by name lookup is 'T2'}}
   // FIXME: Typedefs aren't actually merged in the sense of other merges, because
   // we should only merge them when the types are identical.
-  // in other file: expected-note{{candidate found by name lookup is 'T2'}}
-  // in other file: expected-note{{candidate function}}
+  // in other file: expected-note at 60{{candidate found by name lookup is 'T2'}}
+  // in other file: expected-note at 63{{candidate found by name lookup is 'T2'}}
   T2 *dp = &d; // expected-error{{reference to 'T2' is ambiguous}}
 }
 
 void testFuncMerge(int i) {
   func0(i);
-  // in other file: expected-note{{candidate function}}
   func1(i);
+  // in other file: expected-note at 64{{candidate function}}
+  // in other file: expected-note at 70{{candidate function}}
   func2(i); // expected-error{{call to 'func2' is ambiguous}}
 }
 
 void testVarMerge(int i) {
   var1 = i;
-  // in other files: expected-note 2{{candidate found by name lookup is 'var2'}}
+  // in other files: expected-note at 77 2{{candidate found by name lookup is 'var2'}}
   var2 = i; // expected-error{{reference to 'var2' is ambiguous}}
-  // in other files: expected-note 2{{candidate found by name lookup is 'var3'}}
+  // in other files: expected-note at 79 2{{candidate found by name lookup is 'var3'}}
   var3 = i; // expected-error{{reference to 'var3' is ambiguous}}
 }
 
@@ -146,19 +145,6 @@
 id<P4> p4;
 id<P3> p3;
 
-#ifdef __cplusplus
-void testVector() {
-  Vector<int> vec_int;
-  vec_int.push_back(0);
-
-  List<bool> list_bool;
-  list_bool.push_back(false);
-
-  N::Set<char> set_char;
-  set_char.insert('A');
-}
-#endif
-
 // Make sure we don't get conflicts with 'id'.
 funcptr_with_id fid;
 id id_global;

Added: cfe/trunk/test/Modules/templates.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/templates.mm?rev=164993&view=auto
==============================================================================
--- cfe/trunk/test/Modules/templates.mm (added)
+++ cfe/trunk/test/Modules/templates.mm Tue Oct  2 04:09:43 2012
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodule-cache-path %t -I %S/Inputs -verify %s -Wno-objc-root-class
+// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodule-cache-path %t -I %S/Inputs -emit-llvm %s -o - -Wno-objc-root-class | grep pendingInstantiation | FileCheck %s
+
+ at __experimental_modules_import templates_left;
+ at __experimental_modules_import templates_right;
+
+
+void testTemplateClasses() {
+  Vector<int> vec_int;
+  vec_int.push_back(0);
+
+  List<bool> list_bool;
+  list_bool.push_back(false);
+
+  N::Set<char> set_char;
+  set_char.insert('A');
+}
+
+void testPendingInstantiations() {
+  // CHECK: call
+  // CHECK: call
+  // CHECK: {{define .*pendingInstantiation.*[(]i}}
+  // CHECK: {{define .*pendingInstantiation.*[(]double}}
+  // CHECK: call
+  triggerPendingInstantiation();
+  triggerPendingInstantiationToo();
+}





More information about the cfe-commits mailing list