<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><span class="Apple-style-span" style="line-height: 21px; "><div style="font-family: 'Andale Mono'; "></div><div style="font-family: 'Andale Mono'; "><br></div><div style="font-family: 'Andale Mono'; ">UNREACHABLE executed at ASTContext.cpp:820!</div><div style="font-family: 'Andale Mono'; ">0 clang 0x0000000102326955 PrintStackTrace(void*) + 53</div><div style="font-family: 'Andale Mono'; ">1 clang 0x000000010232700b SignalHandler(int) + 379</div><div style="font-family: 'Andale Mono'; ">2 libSystem.B.dylib 0x00007fff8a58f1ba _sigtramp + 26</div><div style="font-family: 'Andale Mono'; ">3 libSystem.B.dylib 0x00007fff8a5331e1 szone_malloc_should_clear + 2070</div><div style="font-family: 'Andale Mono'; ">4 clang 0x0000000102326cdb raise + 27</div><div style="font-family: 'Andale Mono'; ">5 clang 0x0000000102326d9a abort + 26</div><div style="font-family: 'Andale Mono'; ">6 clang 0x000000010230ada4 llvm::llvm_unreachable_internal(char const*, char const*, unsigned int) + 244</div><div style="font-family: 'Andale Mono'; ">7 clang 0x0000000100f06278 clang::ASTContext::getTypeInfo(clang::Type const*) const + 120</div><div style="font-family: 'Andale Mono'; ">8 clang 0x0000000100f2e8e9 clang::ASTContext::getTypeAlign(clang::Type const*) const + 25</div><div style="font-family: 'Andale Mono'; ">9 clang 0x0000000100f06025 clang::ASTContext::getPreferredTypeAlign(clang::Type const*) const + 37</div><div style="font-family: 'Andale Mono'; ">10 clang 0x0000000100f055ae clang::ASTContext::getDeclAlign(clang::Decl const*, bool) const + 1166</div><div style="font-family: 'Andale Mono'; ">11 clang 0x00000001002b6977 clang::CodeGen::CodeGenFunction::EmitAutoVarAlloca(clang::VarDecl const&) + 215</div><div style="font-family: 'Andale Mono'; ">12 clang 0x00000001002b4cbd clang::CodeGen::CodeGenFunction::EmitAutoVarDecl(clang::VarDecl const&) + 45</div><div style="font-family: 'Andale Mono'; ">13 clang 0x00000001002b4b91 clang::CodeGen::CodeGenFunction::EmitVarDecl(clang::VarDecl const&) + 81</div><div style="font-family: 'Andale Mono'; ">14 clang 0x00000001002b49f4 clang::CodeGen::CodeGenFunction::EmitDecl(clang::Decl const&) + 212</div><div style="font-family: 'Andale Mono'; ">15 clang 0x000000010038b84f clang::CodeGen::CodeGenFunction::EmitDeclStmt(clang::DeclStmt const&) + 143</div><div style="font-family: 'Andale Mono'; ">16 clang 0x0000000100385c92 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*) + 290</div><div style="font-family: 'Andale Mono'; ">17 clang 0x0000000100385591 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 113</div><div style="font-family: 'Andale Mono'; ">18 clang 0x000000010038b59f clang::CodeGen::CodeGenFunction::EmitCompoundStmt(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 447</div><div style="font-family: 'Andale Mono'; ">19 clang 0x0000000100385c70 clang::CodeGen::CodeGenFunction::EmitSimpleStmt(clang::Stmt const*) + 256</div><div style="font-family: 'Andale Mono'; ">20 clang 0x0000000100385591 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*) + 113</div><div style="font-family: 'Andale Mono'; ">21 clang 0x00000001003a62ac clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::CodeGen::FunctionArgList&) + 172</div><div style="font-family: 'Andale Mono'; ">22 clang 0x00000001003a6751 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) + 1169</div><div style="font-family: 'Andale Mono'; ">23 clang 0x00000001003b2bfd clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl) + 1277</div><div style="font-family: 'Andale Mono'; ">24 clang 0x00000001003b011f clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl) + 623</div><div style="font-family: 'Andale Mono'; ">25 clang 0x00000001003ad161 clang::CodeGen::CodeGenModule::EmitDeferred() + 561</div><div style="font-family: 'Andale Mono'; ">26 clang 0x00000001003acd99 clang::CodeGen::CodeGenModule::Release() + 25</div><div style="font-family: 'Andale Mono'; ">27 clang 0x00000001003fbea1 (anonymous namespace)::CodeGeneratorImpl::HandleTranslationUnit(clang::ASTContext&) + 161</div><div style="font-family: 'Andale Mono'; ">28 clang 0x00000001003a2fb3 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) + 163</div><div style="font-family: 'Andale Mono'; ">29 clang 0x000000010040ea1c clang::ParseAST(clang::Sema&, bool) + 924</div><div style="font-family: 'Andale Mono'; ">30 clang 0x0000000100083526 clang::ASTFrontendAction::ExecuteAction() + 278</div><div style="font-family: 'Andale Mono'; ">31 clang 0x00000001003a0a7b clang::CodeGenAction::ExecuteAction() + 1291</div><div style="font-family: 'Andale Mono'; ">32 clang 0x00000001000830e8 clang::FrontendAction::Execute() + 360</div><div style="font-family: 'Andale Mono'; ">33 clang 0x000000010004c4a6 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 1078</div><div style="font-family: 'Andale Mono'; ">34 clang 0x000000010001a125 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 1237</div><div style="font-family: 'Andale Mono'; ">35 clang 0x0000000100001763 cc1_main(char const**, char const**, char const*, void*) + 1283</div><div style="font-family: 'Andale Mono'; ">36 clang 0x000000010001328d main + 701</div><div style="font-family: 'Andale Mono'; ">37 clang 0x0000000100001234 start + 52</div><div style="font-family: 'Andale Mono'; "><br></div></span><div><div>On Nov 2, 2011, at 10:38 AM, Douglas Gregor wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: dgregor<br>Date: Wed Nov 2 12:38:53 2011<br>New Revision: 143551<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=143551&view=rev">http://llvm.org/viewvc/llvm-project?rev=143551&view=rev</a><br>Log:<br>Drastically simplify the mapping from the declaration corresponding to<br>the injected-class-name of a class (or class template) to the<br>declaration that results from substituting the given template<br>arguments. Previously, we would actually perform a substitution into<br>the injected-class-name type and then retrieve the resulting<br>declaration. However, in certain, rare circumstances involving<br>deeply-nested member templates, we would get the wrong substitution<br>arguments.<br><br>This new approach just matches up the declaration with a declaration<br>that's part of the current context (or one of its parents), which will<br>either be an instantiation (during template instantiation) or the<br>declaration itself (during the definition of the template). This is<br>both more efficient (we're avoiding a substitution) and more correct<br>(we can't get the template arguments wrong in the member-template<br>case). <br><br>Fixes <<a href="rdar://problem/9676205">rdar://problem/9676205</a>>.<br><br>Modified:<br> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br> cfe/trunk/test/SemaTemplate/class-template-decl.cpp<br><br>Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=143551&r1=143550&r2=143551&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=143551&r1=143550&r2=143551&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Nov 2 12:38:53 2011<br>@@ -3148,75 +3148,49 @@<br> if (!Record->isDependentContext())<br> return D;<br><br>- // If the RecordDecl is actually the injected-class-name or a<br>- // "templated" declaration for a class template, class template<br>- // partial specialization, or a member class of a class template,<br>- // substitute into the injected-class-name of the class template<br>- // or partial specialization to find the new DeclContext.<br>- QualType T;<br>+ // Determine whether this record is the "templated" declaration describing<br>+ // a class template or class template partial specialization.<br> ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate();<br>-<br>- if (ClassTemplate) {<br>- T = ClassTemplate->getInjectedClassNameSpecialization();<br>- } else if (ClassTemplatePartialSpecializationDecl *PartialSpec<br>- = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {<br>- ClassTemplate = PartialSpec->getSpecializedTemplate();<br>-<br>- // If we call SubstType with an InjectedClassNameType here we<br>- // can end up in an infinite loop.<br>- T = Context.getTypeDeclType(Record);<br>- assert(isa<InjectedClassNameType>(T) &&<br>- "type of partial specialization is not an InjectedClassNameType");<br>- T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType();<br>- }<br>-<br>- if (!T.isNull()) {<br>- // Substitute into the injected-class-name to get the type<br>- // corresponding to the instantiation we want, which may also be<br>- // the current instantiation (if we're in a template<br>- // definition). This substitution should never fail, since we<br>- // know we can instantiate the injected-class-name or we<br>- // wouldn't have gotten to the injected-class-name!<br>-<br>- // FIXME: Can we use the CurrentInstantiationScope to avoid this<br>- // extra instantiation in the common case?<br>- T = SubstType(T, TemplateArgs, Loc, DeclarationName());<br>- assert(!T.isNull() && "Instantiation of injected-class-name cannot fail.");<br>-<br>- if (!T->isDependentType()) {<br>- assert(T->isRecordType() && "Instantiation must produce a record type");<br>- return T->getAs<RecordType>()->getDecl();<br>+ if (ClassTemplate)<br>+ ClassTemplate = ClassTemplate->getCanonicalDecl();<br>+ else if (ClassTemplatePartialSpecializationDecl *PartialSpec<br>+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record))<br>+ ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl();<br>+ <br>+ // Walk the current context to find either the record or an instantiation of<br>+ // it.<br>+ DeclContext *DC = CurContext;<br>+ while (!DC->isFileContext()) {<br>+ // If we're performing substitution while we're inside the template<br>+ // definition, we'll find our own context. We're done.<br>+ if (DC->Equals(Record))<br>+ return Record;<br>+ <br>+ if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) {<br>+ // Check whether we're in the process of instantiating a class template<br>+ // specialization of the template we're mapping.<br>+ if (ClassTemplateSpecializationDecl *InstSpec<br>+ = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){<br>+ ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate();<br>+ if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate))<br>+ return InstRecord;<br>+ }<br>+ <br>+ // Check whether we're in the process of instantiating a member class.<br>+ if (isInstantiationOf(Record, InstRecord))<br>+ return InstRecord;<br> }<br>-<br>- // We are performing "partial" template instantiation to create<br>- // the member declarations for the members of a class template<br>- // specialization. Therefore, D is actually referring to something<br>- // in the current instantiation. Look through the current<br>- // context, which contains actual instantiations, to find the<br>- // instantiation of the "current instantiation" that D refers<br>- // to.<br>- bool SawNonDependentContext = false;<br>- for (DeclContext *DC = CurContext; !DC->isFileContext();<br>- DC = DC->getParent()) {<br>- if (ClassTemplateSpecializationDecl *Spec<br>- = dyn_cast<ClassTemplateSpecializationDecl>(DC))<br>- if (isInstantiationOf(ClassTemplate,<br>- Spec->getSpecializedTemplate()))<br>- return Spec;<br>-<br>- if (!DC->isDependentContext())<br>- SawNonDependentContext = true;<br>+ <br>+ <br>+ // Move to the outer template scope.<br>+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) {<br>+ if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){<br>+ DC = FD->getLexicalDeclContext();<br>+ continue;<br>+ }<br> }<br>-<br>- // We're performing "instantiation" of a member of the current<br>- // instantiation while we are type-checking the<br>- // definition. Compute the declaration context and return that.<br>- assert(!SawNonDependentContext &&<br>- "No dependent context while instantiating record");<br>- DeclContext *DC = computeDeclContext(T);<br>- assert(DC &&<br>- "Unable to find declaration for the current instantiation");<br>- return cast<CXXRecordDecl>(DC);<br>+ <br>+ DC = DC->getParent();<br> }<br><br> // Fall through to deal with other dependent record types (e.g.,<br><br>Modified: cfe/trunk/test/SemaTemplate/class-template-decl.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=143551&r1=143550&r2=143551&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/class-template-decl.cpp?rev=143551&r1=143550&r2=143551&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/SemaTemplate/class-template-decl.cpp (original)<br>+++ cfe/trunk/test/SemaTemplate/class-template-decl.cpp Wed Nov 2 12:38:53 2011<br>@@ -75,3 +75,23 @@<br> }<br> }<br><br>+namespace rdar9676205 {<br>+ template <unsigned, class _Tp> class tuple_element;<br>+<br>+ template <class _T1, class _T2> class pair;<br>+<br>+ template <class _T1, class _T2><br>+ class tuple_element<0, pair<_T1, _T2> ><br>+ {<br>+ template <class _Tp><br>+ struct X<br>+ {<br>+ template <class _Up, bool = X<_Up>::value><br>+ struct Y<br>+ : public X<_Up>,<br>+ public Y<_Up><br>+ { };<br>+ };<br>+ };<br>+}<br>+<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits<br></div></blockquote></div><br></div></body></html>