Doug,

This causes a crash in g++.dg/template/crash52.C
Please investigate.
Thanks!
-
Devang

Attachment: crash52.C
Description: Binary data


UNREACHABLE executed at ASTContext.cpp:820!
0  clang             0x0000000102326955 PrintStackTrace(void*) + 53
1  clang             0x000000010232700b SignalHandler(int) + 379
2  libSystem.B.dylib 0x00007fff8a58f1ba _sigtramp + 26
3  libSystem.B.dylib 0x00007fff8a5331e1 szone_malloc_should_clear + 2070
4  clang             0x0000000102326cdb raise + 27
5  clang             0x0000000102326d9a abort + 26
6  clang             0x000000010230ada4 llvm::llvm_unreachable_internal(char const*, char const*, unsigned int) + 244
7  clang             0x0000000100f06278 clang::ASTContext::getTypeInfo(clang::Type const*) const + 120
8  clang             0x0000000100f2e8e9 clang::ASTContext::getTypeAlign(clang::Type const*) const + 25
9  clang             0x0000000100f06025 clang::ASTContext::getPreferredTypeAlign(clang::Type const*) const + 37
10 clang             0x0000000100f055ae clang::ASTContext::getDeclAlign(clang::Decl const*, bool) const + 1166
11 clang             0x00000001002b6977 clang::CodeGen::CodeGenFunction::EmitAutoVarAlloca(clang::VarDecl const&) + 215
12 clang             0x00000001002b4cbd clang::CodeGen::CodeGenFunction::EmitAutoVarDecl(clang::VarDecl const&) + 45
13 clang             0x00000001002b4b91 clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) + 81
14 clang             0x00000001002b49f4 clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&) + 212
15 clang             0x000000010038b84f clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&) + 143
16 clang             0x0000000100385c92 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*) + 290
17 clang             0x0000000100385591 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 113
18 clang             0x000000010038b59f clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 447
19 clang             0x0000000100385c70 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*) + 256
20 clang             0x0000000100385591 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 113
21 clang             0x00000001003a62ac clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::CodeGen::FunctionArgList&) + 172
22 clang             0x00000001003a6751 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) + 1169
23 clang             0x00000001003b2bfd clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl) + 1277
24 clang             0x00000001003b011f clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl) + 623
25 clang             0x00000001003ad161 clang::CodeGen::CodeGenModule::EmitDeferred() + 561
26 clang             0x00000001003acd99 clang::CodeGen::CodeGenModule::Release() + 25
27 clang             0x00000001003fbea1 (anonymous namespace)::CodeGeneratorImpl::HandleTranslationUnit(clang::ASTContext&) + 161
28 clang             0x00000001003a2fb3 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) + 163
29 clang             0x000000010040ea1c clang::ParseAST(clang::Sema&, bool) + 924
30 clang             0x0000000100083526 clang::ASTFrontendAction::ExecuteAction() + 278
31 clang             0x00000001003a0a7b clang::CodeGenAction::ExecuteAction() + 1291
32 clang             0x00000001000830e8 clang::FrontendAction::Execute() + 360
33 clang             0x000000010004c4a6 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 1078
34 clang             0x000000010001a125 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 1237
35 clang             0x0000000100001763 cc1_main(char const**, char const**, char const*, void*) + 1283
36 clang             0x000000010001328d main + 701
37 clang             0x0000000100001234 start + 52

On Nov 2, 2011, at 10:38 AM, Douglas Gregor wrote:

Author: dgregor
Date: Wed Nov  2 12:38:53 2011
New Revision: 143551

URL: http://llvm.org/viewvc/llvm-project?rev=143551&view=rev
Log:
Drastically simplify the mapping from the declaration corresponding to
the injected-class-name of a class (or class template) to the
declaration that results from substituting the given template
arguments. Previously, we would actually perform a substitution into
the injected-class-name type and then retrieve the resulting
declaration. However, in certain, rare circumstances involving
deeply-nested member templates, we would get the wrong substitution
arguments.

This new approach just matches up the declaration with a declaration
that's part of the current context (or one of its parents), which will
either be an instantiation (during template instantiation) or the
declaration itself (during the definition of the template). This is
both more efficient (we're avoiding a substitution) and more correct
(we can't get the template arguments wrong in the member-template
case).

Fixes <rdar://problem/9676205>.

Modified:
   cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
   cfe/trunk/test/SemaTemplate/class-template-decl.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=143551&r1=143550&r2=143551&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Nov  2 12:38:53 2011
@@ -3148,75 +3148,49 @@
    if (!Record->isDependentContext())
      return D;

-    // If the RecordDecl is actually the injected-class-name or a
-    // "templated" declaration for a class template, class template
-    // partial specialization, or a member class of a class template,
-    // substitute into the injected-class-name of the class template
-    // or partial specialization to find the new DeclContext.
-    QualType T;
+    // Determine whether this record is the "templated" declaration describing
+    // a class template or class template partial specialization.
    ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();
-
-    if (ClassTemplate) {
-      T = ClassTemplate->getInjectedClassNameSpecialization();
-    } else if (ClassTemplatePartialSpecializationDecl *PartialSpec
-                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
-      ClassTemplate = PartialSpec->getSpecializedTemplate();
-
-      // If we call SubstType with an InjectedClassNameType here we
-      // can end up in an infinite loop.
-      T = Context.getTypeDeclType(Record);
-      assert(isa<InjectedClassNameType>(T) &&
-             "type of partial specialization is not an InjectedClassNameType");
-      T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();
-    }
-
-    if (!T.isNull()) {
-      // Substitute into the injected-class-name to get the type
-      // corresponding to the instantiation we want, which may also be
-      // the current instantiation (if we're in a template
-      // definition). This substitution should never fail, since we
-      // know we can instantiate the injected-class-name or we
-      // wouldn't have gotten to the injected-class-name!
-
-      // FIXME: Can we use the CurrentInstantiationScope to avoid this
-      // extra instantiation in the common case?
-      T = SubstType(T, TemplateArgs, Loc, DeclarationName());
-      assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");
-
-      if (!T->isDependentType()) {
-        assert(T->isRecordType() && "Instantiation must produce a record type");
-        return T->getAs<RecordType>()->getDecl();
+    if (ClassTemplate)
+      ClassTemplate = ClassTemplate->getCanonicalDecl();
+    else if (ClassTemplatePartialSpecializationDecl *PartialSpec
+               = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))
+      ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();
+    
+    // Walk the current context to find either the record or an instantiation of
+    // it.
+    DeclContext *DC = CurContext;
+    while (!DC->isFileContext()) {
+      // If we're performing substitution while we're inside the template
+      // definition, we'll find our own context. We're done.
+      if (DC->Equals(Record))
+        return Record;
+      
+      if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {
+        // Check whether we're in the process of instantiating a class template
+        // specialization of the template we're mapping.
+        if (ClassTemplateSpecializationDecl *InstSpec
+                      = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){
+          ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate();
+          if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))
+            return InstRecord;
+        }
+      
+        // Check whether we're in the process of instantiating a member class.
+        if (isInstantiationOf(Record, InstRecord))
+          return InstRecord;
      }
-
-      // We are performing "partial" template instantiation to create
-      // the member declarations for the members of a class template
-      // specialization. Therefore, D is actually referring to something
-      // in the current instantiation. Look through the current
-      // context, which contains actual instantiations, to find the
-      // instantiation of the "current instantiation" that D refers
-      // to.
-      bool SawNonDependentContext = false;
-      for (DeclContext *DC = CurContext; !DC->isFileContext();
-           DC = DC->getParent()) {
-        if (ClassTemplateSpecializationDecl *Spec
-                          = dyn_cast<ClassTemplateSpecializationDecl>(DC))
-          if (isInstantiationOf(ClassTemplate,
-                                Spec->getSpecializedTemplate()))
-            return Spec;
-
-        if (!DC->isDependentContext())
-          SawNonDependentContext = true;
+      
+      
+      // Move to the outer template scope.
+      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {
+        if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){
+          DC = FD->getLexicalDeclContext();
+          continue;
+        }
      }
-
-      // We're performing "instantiation" of a member of the current
-      // instantiation while we are type-checking the
-      // definition. Compute the declaration context and return that.
-      assert(!SawNonDependentContext &&
-             "No dependent context while instantiating record");
-      DeclContext *DC = computeDeclContext(T);
-      assert(DC &&
-             "Unable to find declaration for the current instantiation");
-      return cast<CXXRecordDecl>(DC);
+      
+      DC = DC->getParent();
    }

    // Fall through to deal with other dependent record types (e.g.,

Modified: cfe/trunk/test/SemaTemplate/class-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=143551&r1=143550&r2=143551&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/class-template-decl.cpp (original)
+++ cfe/trunk/test/SemaTemplate/class-template-decl.cpp Wed Nov  2 12:38:53 2011
@@ -75,3 +75,23 @@
  }
}

+namespace rdar9676205 {
+  template <unsigned, class _Tp> class tuple_element;
+
+  template <class _T1, class _T2> class pair;
+
+  template <class _T1, class _T2>
+  class tuple_element<0, pair<_T1, _T2> >
+  {
+    template <class _Tp>
+    struct X
+    {
+      template <class _Up, bool = X<_Up>::value>
+      struct Y
+        : public X<_Up>,
+          public Y<_Up>
+      { };
+    };
+  };
+}
+


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to