[cfe-commits] r80425 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclCXX.h lib/Sema/SemaTemplateInstantiateDecl.cpp

John McCall rjmccall at apple.com
Sat Aug 29 01:11:14 PDT 2009


Author: rjmccall
Date: Sat Aug 29 03:11:13 2009
New Revision: 80425

URL: http://llvm.org/viewvc/llvm-project?rev=80425&view=rev
Log:
Fix the breakage by handling indirect instantiations.  This would be much
improved if there were a consistent name for getInstantiatedFromMemberX()
across all classes.  Cheap refactor if someone wants to do it, but let's get the
buildbots happy first.


Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=80425&r1=80424&r2=80425&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sat Aug 29 03:11:13 2009
@@ -1379,6 +1379,10 @@
       IntegerType = QualType();
     }
 public:
+  EnumDecl *getCanonicalDecl() {
+    return cast<EnumDecl>(TagDecl::getCanonicalDecl());
+  }
+
   static EnumDecl *Create(ASTContext &C, DeclContext *DC,
                           SourceLocation L, IdentifierInfo *Id,
                           SourceLocation TKL, EnumDecl *PrevDecl);

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=80425&r1=80424&r2=80425&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Sat Aug 29 03:11:13 2009
@@ -405,8 +405,12 @@
 
   /// reverse_base_class_iterator = Iterator that traverses the base classes
   /// of a class in reverse order.
- typedef std::reverse_iterator<base_class_const_iterator>
-   reverse_base_class_const_iterator;
+  typedef std::reverse_iterator<base_class_const_iterator>
+    reverse_base_class_const_iterator;
+
+  virtual CXXRecordDecl *getCanonicalDecl() {
+    return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl());
+  }
 
   static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC,
                                SourceLocation L, IdentifierInfo *Id,
@@ -712,7 +716,7 @@
     
     return dyn_cast<FunctionDecl>(getDeclContext());
   }
-  
+
   /// viewInheritance - Renders and displays an inheritance diagram
   /// for this C++ class and all of its base classes (transitively) using
   /// GraphViz.

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=80425&r1=80424&r2=80425&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Aug 29 03:11:13 2009
@@ -1166,38 +1166,94 @@
                        NewInits.data(), NewInits.size()); 
 }
 
+// TODO: this could be templated if the various decl types used the
+// same method name.
+static bool isInstantiationOf(ClassTemplateDecl *Pattern,
+                              ClassTemplateDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberTemplate();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(CXXRecordDecl *Pattern,
+                              CXXRecordDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberClass();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(FunctionDecl *Pattern,
+                              FunctionDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberFunction();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOf(EnumDecl *Pattern,
+                              EnumDecl *Instance) {
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromMemberEnum();
+  } while (Instance);
+
+  return false;
+}
+
+static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
+                                              VarDecl *Instance) {
+  assert(Instance->isStaticDataMember());
+
+  Pattern = Pattern->getCanonicalDecl();
+
+  do {
+    Instance = Instance->getCanonicalDecl();
+    if (Pattern == Instance) return true;
+    Instance = Instance->getInstantiatedFromStaticDataMember();
+  } while (Instance);
+
+  return false;
+}
+
 static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
   if (D->getKind() != Other->getKind())
     return false;
 
-  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other)) {
-    if (CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass())
-      return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
-    else
-      return false;
-  }
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other))
+    return isInstantiationOf(cast<CXXRecordDecl>(D), Record);
   
-  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other)) {
-    if (FunctionDecl *Pattern = Function->getInstantiatedFromMemberFunction())
-      return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
-    else
-      return false;
-  }
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other))
+    return isInstantiationOf(cast<FunctionDecl>(D), Function);
 
-  if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other)) {
-    if (EnumDecl *Pattern = Enum->getInstantiatedFromMemberEnum())
-      return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
-    else
-      return false;
-  }
+  if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other))
+    return isInstantiationOf(cast<EnumDecl>(D), Enum);
 
   if (VarDecl *Var = dyn_cast<VarDecl>(Other))
-    if (Var->isStaticDataMember()) {
-      if (VarDecl *Pattern = Var->getInstantiatedFromStaticDataMember())
-        return Pattern->getCanonicalDecl() == D->getCanonicalDecl();
-      else
-        return false;
-    }
+    if (Var->isStaticDataMember())
+      return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var);
+
+  if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other))
+    return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp);
 
   // FIXME: How can we find instantiations of anonymous unions?
 
@@ -1262,6 +1318,28 @@
     return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D));
   }
 
+  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
+    if (ClassTemplateDecl *ClassTemplate 
+          = Record->getDescribedClassTemplate()) {
+      // When the declaration D was parsed, it referred to the current
+      // instantiation. Therefore, look through the current context,
+      // which contains actual instantiations, to find the
+      // instantiation of the "current instantiation" that D refers
+      // to. Alternatively, we could just instantiate the
+      // injected-class-name with the current template arguments, but
+      // such an instantiation is far more expensive.
+      for (DeclContext *DC = CurContext; !DC->isFileContext(); 
+           DC = DC->getParent()) {
+        if (ClassTemplateSpecializationDecl *Spec 
+              = dyn_cast<ClassTemplateSpecializationDecl>(DC))
+          if (isInstantiationOf(ClassTemplate, Spec->getSpecializedTemplate()))
+            return Spec;
+      }
+
+      assert(false && 
+             "Unable to find declaration for the current instantiation");
+    }
+
   ParentDC = FindInstantiatedContext(ParentDC);
   if (!ParentDC) return 0;
 
@@ -1286,33 +1364,11 @@
                                    ParentDC->decls_begin(),
                                    ParentDC->decls_end());
     }
+    
     assert(Result && "Unable to find instantiation of declaration!");
     D = Result;
   }
 
-  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D))
-    if (ClassTemplateDecl *ClassTemplate 
-          = Record->getDescribedClassTemplate()) {
-      // When the declaration D was parsed, it referred to the current
-      // instantiation. Therefore, look through the current context,
-      // which contains actual instantiations, to find the
-      // instantiation of the "current instantiation" that D refers
-      // to. Alternatively, we could just instantiate the
-      // injected-class-name with the current template arguments, but
-      // such an instantiation is far more expensive.
-      for (DeclContext *DC = CurContext; !DC->isFileContext(); 
-           DC = DC->getParent()) {
-        if (ClassTemplateSpecializationDecl *Spec 
-              = dyn_cast<ClassTemplateSpecializationDecl>(DC))
-          if (Spec->getSpecializedTemplate()->getCanonicalDecl()
-              == ClassTemplate->getCanonicalDecl())
-            return Spec;
-      }
-
-      assert(false && 
-             "Unable to find declaration for the current instantiation");
-    }
-
   return D;
 }
 





More information about the cfe-commits mailing list