[cfe-commits] r143551 - in /cfe/trunk: lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/class-template-decl.cpp

Devang Patel dpatel at apple.com
Fri Nov 4 10:34:37 PDT 2011


Doug,

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



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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111104/70f99c50/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: crash52.C
Type: application/octet-stream
Size: 172 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111104/70f99c50/attachment.obj>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20111104/70f99c50/attachment-0001.html>


More information about the cfe-commits mailing list