Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -5708,6 +5708,15 @@ TemplateTy &SuggestedTemplate, TemplateNameKind &SuggestedKind); + bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, + NamedDecl *Instantiation, + bool InstantiatedFromMember, + const NamedDecl *Pattern, + const NamedDecl *PatternDef, + TemplateSpecializationKind TSK, + bool Complain = true, + bool AtEndOfTU = false); + void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl); TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -456,6 +456,91 @@ TemplateArgs); } +/// Determine whether we would be unable to instantiate this template (because +/// it either has no definition, or is in the process of being instantiated). +bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, + NamedDecl *Instantiation, + bool InstantiatedFromMember, + const NamedDecl *Pattern, + const NamedDecl *PatternDef, + TemplateSpecializationKind TSK, + bool Complain /*= true*/, + bool AtEndOfTU /*= false*/) { + assert(isa(Instantiation) || isa(Instantiation)); + + if (PatternDef && (isa(PatternDef) + || !cast(PatternDef)->isBeingDefined())) { + NamedDecl *SuggestedDef = nullptr; + if (!hasVisibleDefinition(const_cast(PatternDef), &SuggestedDef, + /*OnlyNeedComplete*/false)) { + // If we're allowed to diagnose this and recover, do so. + bool Recover = Complain && !isSFINAEContext(); + if (Complain) + diagnoseMissingImport(PointOfInstantiation, SuggestedDef, + Sema::MissingImportKind::Definition, Recover); + return !Recover; + } + return false; + } + + QualType InstantiationTy; + if (TagDecl *TD = dyn_cast(Instantiation)) + InstantiationTy = Context.getTypeDeclType(TD); + else + InstantiationTy = cast(Instantiation)->getType(); + + if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) { + // Say nothing + } + else if (FunctionDecl *FD = dyn_cast(Instantiation)) { + if (!PatternDef) { + if (Complain) { + if (FD->getPrimaryTemplate()) + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_func_template) + << FD->getPrimaryTemplate(); + else + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_member) + << 1 << FD->getDeclName() << FD->getDeclContext(); + + if (Pattern) + Diag(Pattern->getLocation(), + diag::note_explicit_instantiation_here); + FD->setInvalidDecl(); + } + } + } + else if (PatternDef) { + Diag(PointOfInstantiation, + diag::err_template_instantiate_within_definition) + << (TSK != TSK_ImplicitInstantiation) + << InstantiationTy; + // Not much point in noting the template declaration here, since + // we're lexically inside it. + Instantiation->setInvalidDecl(); + } else if (InstantiatedFromMember) { + Diag(PointOfInstantiation, + diag::err_implicit_instantiate_member_undefined) + << InstantiationTy; + Diag(Pattern->getLocation(), diag::note_member_declared_at); + } + else { + Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) + << (TSK != TSK_ImplicitInstantiation) + << InstantiationTy; + Diag(Pattern->getLocation(), diag::note_template_decl_here); + } + + // In general, Instantiation isn't marked invalid to get more than one + // error for multiple undefined instantiations. But the code that does + // explicit declaration -> explicit definition conversion can't handle + // invalid declarations, so mark as invalid in that case. + if (TSK == TSK_ExplicitInstantiationDeclaration) + Instantiation->setInvalidDecl(); + return true; +} + /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining /// that the template parameter 'PrevDecl' is being shadowed by a new /// declaration at location Loc. Returns true to indicate that this is Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -1844,62 +1844,6 @@ } } -/// Determine whether we would be unable to instantiate this template (because -/// it either has no definition, or is in the process of being instantiated). -static bool DiagnoseUninstantiableTemplate(Sema &S, - SourceLocation PointOfInstantiation, - TagDecl *Instantiation, - bool InstantiatedFromMember, - TagDecl *Pattern, - TagDecl *PatternDef, - TemplateSpecializationKind TSK, - bool Complain = true) { - if (PatternDef && !PatternDef->isBeingDefined()) { - NamedDecl *SuggestedDef = nullptr; - if (!S.hasVisibleDefinition(PatternDef, &SuggestedDef, - /*OnlyNeedComplete*/false)) { - // If we're allowed to diagnose this and recover, do so. - bool Recover = Complain && !S.isSFINAEContext(); - if (Complain) - S.diagnoseMissingImport(PointOfInstantiation, SuggestedDef, - Sema::MissingImportKind::Definition, Recover); - return !Recover; - } - return false; - } - - if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) { - // Say nothing - } else if (PatternDef) { - assert(PatternDef->isBeingDefined()); - S.Diag(PointOfInstantiation, - diag::err_template_instantiate_within_definition) - << (TSK != TSK_ImplicitInstantiation) - << S.Context.getTypeDeclType(Instantiation); - // Not much point in noting the template declaration here, since - // we're lexically inside it. - Instantiation->setInvalidDecl(); - } else if (InstantiatedFromMember) { - S.Diag(PointOfInstantiation, - diag::err_implicit_instantiate_member_undefined) - << S.Context.getTypeDeclType(Instantiation); - S.Diag(Pattern->getLocation(), diag::note_member_declared_at); - } else { - S.Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) - << (TSK != TSK_ImplicitInstantiation) - << S.Context.getTypeDeclType(Instantiation); - S.Diag(Pattern->getLocation(), diag::note_template_decl_here); - } - - // In general, Instantiation isn't marked invalid to get more than one - // error for multiple undefined instantiations. But the code that does - // explicit declaration -> explicit definition conversion can't handle - // invalid declarations, so mark as invalid in that case. - if (TSK == TSK_ExplicitInstantiationDeclaration) - Instantiation->setInvalidDecl(); - return true; -} - /// \brief Instantiate the definition of a class from a given pattern. /// /// \param PointOfInstantiation The point of instantiation within the @@ -1930,7 +1874,7 @@ bool Complain) { CXXRecordDecl *PatternDef = cast_or_null(Pattern->getDefinition()); - if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation, + if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation, Instantiation->getInstantiatedFromMemberClass(), Pattern, PatternDef, TSK, Complain)) return true; @@ -2159,7 +2103,7 @@ const MultiLevelTemplateArgumentList &TemplateArgs, TemplateSpecializationKind TSK) { EnumDecl *PatternDef = Pattern->getDefinition(); - if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation, + if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation, Instantiation->getInstantiatedFromMemberEnum(), Pattern, PatternDef, TSK,/*Complain*/true)) return true; Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3545,7 +3545,8 @@ // Never instantiate an explicit specialization except if it is a class scope // explicit specialization. - if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && + TemplateSpecializationKind TSK = Function->getTemplateSpecializationKind(); + if (TSK == TSK_ExplicitSpecialization && !Function->getClassScopeSpecializationPattern()) return; @@ -3593,32 +3594,12 @@ Pattern = PatternDecl->getBody(PatternDecl); } - // FIXME: Check that the definition is visible before trying to instantiate - // it. This requires us to track the instantiation stack in order to know - // which definitions should be visible. - - if (!Pattern && !PatternDecl->isDefaulted()) { - if (DefinitionRequired) { - if (Function->getPrimaryTemplate()) - Diag(PointOfInstantiation, - diag::err_explicit_instantiation_undefined_func_template) - << Function->getPrimaryTemplate(); - else - Diag(PointOfInstantiation, - diag::err_explicit_instantiation_undefined_member) - << 1 << Function->getDeclName() << Function->getDeclContext(); - - if (PatternDecl) - Diag(PatternDecl->getLocation(), - diag::note_explicit_instantiation_here); - Function->setInvalidDecl(); - } else if (Function->getTemplateSpecializationKind() - == TSK_ExplicitInstantiationDefinition) { + if (!Pattern && !PatternDecl->isDefaulted() && !DefinitionRequired) { + if (TSK == TSK_ExplicitInstantiationDefinition) { assert(!Recursive); PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); - } else if (Function->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) { + } else if (TSK == TSK_ImplicitInstantiation) { if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { Diag(PointOfInstantiation, diag::warn_func_template_missing) << Function; @@ -3628,17 +3609,25 @@ << Function; } } - - return; } + const FunctionDecl *PatternDef = PatternDecl; + if (!Pattern && !PatternDecl->isDefaulted()) + PatternDef = nullptr; + // FIXME: We need to track the instantiation stack in order to know which + // definitions should be visible within this instantiation. + if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Function, + Function->getInstantiatedFromMemberFunction(), + PatternDecl, PatternDef, TSK, + /*Complain*/DefinitionRequired, AtEndOfTU)) + return; + // C++1y [temp.explicit]p10: // Except for inline functions, declarations with types deduced from their // initializer or return value, and class template specializations, other // explicit instantiation declarations have the effect of suppressing the // implicit instantiation of the entity to which they refer. - if (Function->getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDeclaration && + if (TSK == TSK_ExplicitInstantiationDeclaration && !PatternDecl->isInlined() && !PatternDecl->getReturnType()->getContainedAutoType()) return; @@ -3660,6 +3649,10 @@ PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(), "instantiating function definition"); + // The instantiation is visible here, even if it was first declared in an + // unimported module. + Function->setHidden(false); + // Copy the inner loc start from the pattern. Function->setInnerLocStart(PatternDecl->getInnerLocStart()); Index: test/Modules/Inputs/PR28794/LibAHeader.h =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28794/LibAHeader.h @@ -0,0 +1,12 @@ +#ifndef LIB_A_HEADER +#define LIB_A_HEADER + +typedef __SIZE_TYPE__ size_t; + +template +class BumpPtrAllocatorImpl; + +template +void * operator new(size_t, BumpPtrAllocatorImpl &); + +#endif // LIB_A_HEADER Index: test/Modules/Inputs/PR28794/Subdir/Empty.h =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28794/Subdir/Empty.h @@ -0,0 +1 @@ + Index: test/Modules/Inputs/PR28794/Subdir/LibBHeader.h =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28794/Subdir/LibBHeader.h @@ -0,0 +1,12 @@ +#ifndef LIB_B_HEADER +#define LIB_B_HEADER + +#include "LibAHeader.h" + +template +void *operator new(size_t, BumpPtrAllocatorImpl &) { + struct S {}; + return (void*)0xdead; +} + +#endif // LIB_B_HEADER Index: test/Modules/Inputs/PR28794/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28794/module.modulemap @@ -0,0 +1,3 @@ +module M { + umbrella "Subdir" module * {export *} +} Index: test/Modules/pr28794.cpp =================================================================== --- /dev/null +++ test/Modules/pr28794.cpp @@ -0,0 +1,17 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++11 -I%S/Inputs/PR28794 -verify %s +// RUN: %clang_cc1 -std=c++11 -fmodules -fmodule-map-file=%S/Inputs/PR28794/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR28794/ -verify %s + +#include "Subdir/Empty.h" +#include "LibAHeader.h" + +BumpPtrAllocatorImpl<> &getPreprocessorAllocator(); +class B { + struct ModuleMacroInfo { + ModuleMacroInfo *getModuleInfo() { + return new (getPreprocessorAllocator()) ModuleMacroInfo(); + } + }; +}; + +// expected-no-diagnostics