From 49f25ecf7ff358039ce4c9254b867f32110e660e Mon Sep 17 00:00:00 2001 From: Douglas Gregor <dgregor@apple.com> Date: Fri, 15 May 2009 21:18:27 +0000 Subject: [PATCH] Make sure that we use the canonical type for the names of instantiated constructors and destructors. This is a requirement of DeclarationNameTable::getCXXSpecialName that we weren't assert()'ing, so it should have been caught much earlier :( Big thanks to Anders for the test case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71895 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/DeclarationName.cpp | 3 ++- lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 +++++-- test/SemaTemplate/instantiate-function-1.cpp | 8 ++++++-- test/SemaTemplate/instantiate-function-2.cpp | 12 ++++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 test/SemaTemplate/instantiate-function-2.cpp diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 15461bb99b..a17abde777 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -302,7 +302,8 @@ DeclarationNameTable::getCXXSpecialName(DeclarationName::NameKind Kind, assert(Kind >= DeclarationName::CXXConstructorName && Kind <= DeclarationName::CXXConversionFunctionName && "Kind must be a C++ special name kind"); - + assert(Ty->isCanonical() && + "Can only build C++ special names from canonical types"); llvm::FoldingSet<CXXSpecialName> *SpecialNames = static_cast<llvm::FoldingSet<CXXSpecialName>*>(CXXSpecialNamesImpl); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f1a02c48dd..382c2fa98a 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -333,7 +333,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) { CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner); QualType ClassTy = SemaRef.Context.getTypeDeclType(Record); DeclarationName Name - = SemaRef.Context.DeclarationNames.getCXXConstructorName(ClassTy); + = SemaRef.Context.DeclarationNames.getCXXConstructorName( + SemaRef.Context.getCanonicalType(ClassTy)); CXXConstructorDecl *Constructor = CXXConstructorDecl::Create(SemaRef.Context, Record, D->getLocation(), Name, T, D->isExplicit(), D->isInline(), @@ -362,6 +363,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) { SemaRef.CheckFunctionDeclaration(Constructor, PrevDecl, Redeclaration, /*FIXME:*/OverloadableAttrRequired); + Record->addedConstructor(SemaRef.Context, Constructor); Owner->addDecl(SemaRef.Context, Constructor); return Constructor; } @@ -377,7 +379,8 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) { // Build the instantiated destructor declaration. CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner); - QualType ClassTy = SemaRef.Context.getTypeDeclType(Record); + QualType ClassTy = + SemaRef.Context.getCanonicalType(SemaRef.Context.getTypeDeclType(Record)); CXXDestructorDecl *Destructor = CXXDestructorDecl::Create(SemaRef.Context, Record, D->getLocation(), diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp index 51de6bca38..e7c4af163a 100644 --- a/test/SemaTemplate/instantiate-function-1.cpp +++ b/test/SemaTemplate/instantiate-function-1.cpp @@ -64,8 +64,12 @@ template<typename T, typename U, typename V> struct X6 { // IfStmt if (t > 0) return u; - else - return v; // expected-error{{incompatible type}} + else { + if (t < 0) + return v; // expected-error{{incompatible type}} + } + + return v; } }; diff --git a/test/SemaTemplate/instantiate-function-2.cpp b/test/SemaTemplate/instantiate-function-2.cpp new file mode 100644 index 0000000000..51a60146d4 --- /dev/null +++ b/test/SemaTemplate/instantiate-function-2.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template <typename T> struct S { + S() { } + S(T t); +}; + +template struct S<int>; + +void f() { + S<int> s1; + S<int> s2(10); +} -- 2.40.0