Reviewed by Richard Smith.
llvm-svn: 279164
TemplateTy &SuggestedTemplate,
TemplateNameKind &SuggestedKind);
+ bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+ NamedDecl *Instantiation,
+ bool InstantiatedFromMember,
+ const NamedDecl *Pattern,
+ const NamedDecl *PatternDef,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
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*/) {
+ assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation));
+
+ if (PatternDef && (isa<FunctionDecl>(PatternDef)
+ || !cast<TagDecl>(PatternDef)->isBeingDefined())) {
+ NamedDecl *SuggestedDef = nullptr;
+ if (!hasVisibleDefinition(const_cast<NamedDecl*>(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<TagDecl>(Instantiation))
+ InstantiationTy = Context.getTypeDeclType(TD);
+ else
+ InstantiationTy = cast<FunctionDecl>(Instantiation)->getType();
+ if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
+ // Say nothing
+ } 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
}
}
-/// 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
bool Complain) {
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
- if (DiagnoseUninstantiableTemplate(*this, PointOfInstantiation, Instantiation,
+ if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Instantiation,
Instantiation->getInstantiatedFromMemberClass(),
Pattern, PatternDef, TSK, Complain))
return true;
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;
// 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;
}
assert(PatternDecl && "template definition is not a template");
+ // 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, PatternDecl, TSK,
+ /*Complain*/DefinitionRequired))
+ return;
+
+
+
// Postpone late parsed template instantiations.
if (PatternDecl->isLateTemplateParsed() &&
!LateTemplateParser) {
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.
-
+ // FIXME: Check if we could sink these diagnostics in
+ // DiagnoseUninstantiableTemplate.
if (!Pattern && !PatternDecl->isDefaulted()) {
if (DefinitionRequired) {
if (Function->getPrimaryTemplate())
Diag(PatternDecl->getLocation(),
diag::note_explicit_instantiation_here);
Function->setInvalidDecl();
- } else if (Function->getTemplateSpecializationKind()
- == TSK_ExplicitInstantiationDefinition) {
+ } else 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;
// 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;
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());
--- /dev/null
+#ifndef LIB_A_HEADER
+#define LIB_A_HEADER
+
+typedef __SIZE_TYPE__ size_t;
+
+template <typename = int, size_t SlabSize = 4096, size_t = SlabSize>
+class BumpPtrAllocatorImpl;
+
+template <typename T, size_t SlabSize, size_t SizeThreshold>
+void * operator new(size_t, BumpPtrAllocatorImpl<T, SlabSize, SizeThreshold> &);
+
+#endif // LIB_A_HEADER
--- /dev/null
+#ifndef LIB_B_HEADER
+#define LIB_B_HEADER
+
+#include "LibAHeader.h"
+
+template <typename T, size_t SlabSize, size_t SizeThreshold>
+void *operator new(size_t, BumpPtrAllocatorImpl<T, SlabSize, SizeThreshold> &) {
+ struct S {};
+ return (void*)0xdead;
+}
+
+#endif // LIB_B_HEADER
--- /dev/null
+module M {
+ umbrella "Subdir" module * {export *}
+}