v.g.vassilev updated this revision to Diff 68354.
v.g.vassilev added a comment.
Add forgotten change.
https://reviews.llvm.org/D23492
Files:
include/clang/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/Modules/Inputs/PR28794/LibAHeader.h
test/Modules/Inputs/PR28794/Subdir/Empty.h
test/Modules/Inputs/PR28794/Subdir/LibBHeader.h
test/Modules/Inputs/PR28794/module.modulemap
test/Modules/pr28794.cpp
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
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/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 <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
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/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 <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
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;
@@ -3596,7 +3597,16 @@
// 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 (DiagnoseUninstantiableTemplate(PointOfInstantiation, Function,
+ Function->getInstantiatedFromMemberFunction(),
+ PatternDecl,
+ const_cast<FunctionDecl*>(PatternDecl),
+ TSK, /*Complain*/DefinitionRequired))
+ return;
+
+ // TODO: Check if we could sink these diagnostics in
+ // DiagnoseUninstantiableTemplate.
if (!Pattern && !PatternDecl->isDefaulted()) {
if (DefinitionRequired) {
if (Function->getPrimaryTemplate())
@@ -3612,13 +3622,11 @@
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 +3645,7 @@
// 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 +3667,11 @@
PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(),
"instantiating function definition");
+ // Q: Shall we add this here for consistency with InstantiateClass and InstantiateEnum.
+ // 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: 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<CXXRecordDecl>(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/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -456,6 +456,70 @@
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,
+ 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(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
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5708,6 +5708,14 @@
TemplateTy &SuggestedTemplate,
TemplateNameKind &SuggestedKind);
+ bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
+ NamedDecl *Instantiation,
+ bool InstantiatedFromMember,
+ const NamedDecl *Pattern,
+ NamedDecl *PatternDef,
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
+
void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl);
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits