r279164 - PR28794: Don't try to instantiate function templates which are not visible.
Vassil Vassilev via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 18 15:01:26 PDT 2016
Author: vvassilev
Date: Thu Aug 18 17:01:25 2016
New Revision: 279164
URL: http://llvm.org/viewvc/llvm-project?rev=279164&view=rev
Log:
PR28794: Don't try to instantiate function templates which are not visible.
Reviewed by Richard Smith.
Added:
cfe/trunk/test/Modules/Inputs/PR28794/
cfe/trunk/test/Modules/Inputs/PR28794/LibAHeader.h
cfe/trunk/test/Modules/Inputs/PR28794/Subdir/
cfe/trunk/test/Modules/Inputs/PR28794/Subdir/Empty.h
cfe/trunk/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h
cfe/trunk/test/Modules/Inputs/PR28794/module.modulemap
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=279164&r1=279163&r2=279164&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Aug 18 17:01:25 2016
@@ -5711,6 +5711,14 @@ public:
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);
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=279164&r1=279163&r2=279164&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Aug 18 17:01:25 2016
@@ -456,6 +456,70 @@ Sema::BuildDependentDeclRefExpr(const CX
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
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=279164&r1=279163&r2=279164&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Thu Aug 18 17:01:25 2016
@@ -1844,62 +1844,6 @@ namespace clang {
}
}
-/// 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 @@ Sema::InstantiateClass(SourceLocation Po
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;
@@ -2159,7 +2103,7 @@ bool Sema::InstantiateEnum(SourceLocatio
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;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=279164&r1=279163&r2=279164&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Thu Aug 18 17:01:25 2016
@@ -3545,7 +3545,8 @@ void Sema::InstantiateFunctionDefinition
// 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;
@@ -3561,6 +3562,16 @@ void Sema::InstantiateFunctionDefinition
}
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) {
@@ -3593,10 +3604,8 @@ void Sema::InstantiateFunctionDefinition
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())
@@ -3612,13 +3621,11 @@ void Sema::InstantiateFunctionDefinition
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;
@@ -3637,8 +3644,7 @@ void Sema::InstantiateFunctionDefinition
// 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 +3666,10 @@ void Sema::InstantiateFunctionDefinition
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());
Added: cfe/trunk/test/Modules/Inputs/PR28794/LibAHeader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28794/LibAHeader.h?rev=279164&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR28794/LibAHeader.h (added)
+++ cfe/trunk/test/Modules/Inputs/PR28794/LibAHeader.h Thu Aug 18 17:01:25 2016
@@ -0,0 +1,12 @@
+#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
Added: cfe/trunk/test/Modules/Inputs/PR28794/Subdir/Empty.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28794/Subdir/Empty.h?rev=279164&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR28794/Subdir/Empty.h (added)
+++ cfe/trunk/test/Modules/Inputs/PR28794/Subdir/Empty.h Thu Aug 18 17:01:25 2016
@@ -0,0 +1 @@
+
Added: cfe/trunk/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h?rev=279164&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h (added)
+++ cfe/trunk/test/Modules/Inputs/PR28794/Subdir/LibBHeader.h Thu Aug 18 17:01:25 2016
@@ -0,0 +1,12 @@
+#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
Added: cfe/trunk/test/Modules/Inputs/PR28794/module.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/PR28794/module.modulemap?rev=279164&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/PR28794/module.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/PR28794/module.modulemap Thu Aug 18 17:01:25 2016
@@ -0,0 +1,3 @@
+module M {
+ umbrella "Subdir" module * {export *}
+}
More information about the cfe-commits
mailing list