v.g.vassilev created this revision. v.g.vassilev added a reviewer: rsmith. v.g.vassilev added a subscriber: cfe-commits. v.g.vassilev set the repository for this revision to rL LLVM.
Repository: rL LLVM https://reviews.llvm.org/D24508 Files: lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/Modules/Inputs/PR28752/Subdir1/b.h test/Modules/Inputs/PR28752/Subdir1/c.h test/Modules/Inputs/PR28752/Subdir1/module.modulemap test/Modules/Inputs/PR28752/a.h test/Modules/Inputs/PR28752/module.modulemap test/Modules/Inputs/PR28752/vector test/Modules/pr28752.cpp
Index: test/Modules/pr28752.cpp =================================================================== --- /dev/null +++ test/Modules/pr28752.cpp @@ -0,0 +1,19 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -I%S/Inputs/PR28752 -verify %s +// RUN: %clang_cc1 -std=c++11 -nostdsysteminc -fmodules -fmodule-map-file=%S/Inputs/PR28752/Subdir1/module.modulemap -fmodule-map-file=%S/Inputs/PR28752/module.modulemap -fmodules-cache-path=%t -I%S/Inputs/PR28752 -I%S/Inputs/PR28752/Subdir1 -verify %s + +#include "a.h" +#include "Subdir1/c.h" +#include <vector> + +class TClingClassInfo { + std::vector<int> fIterStack; +}; + +TClingClassInfo *a; +class TClingBaseClassInfo { + TClingBaseClassInfo() { new TClingClassInfo(*a); } +}; + +// expected-no-diagnostics + Index: test/Modules/Inputs/PR28752/vector =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28752/vector @@ -0,0 +1,28 @@ +#ifndef VECTOR +#define VECTOR +template <bool, typename> struct B; +template <typename _Tp> struct B<true, _Tp> { typedef _Tp type; }; +namespace std { +template <typename> struct D { + + template <typename _Alloc2> struct F { + static const bool value = 0; + }; + + template <typename _Alloc2> + typename B<F<_Alloc2>::value, _Alloc2>::type _S_select(_Alloc2); + template <typename _Alloc2> + static + typename B<!F<_Alloc2>::value, _Alloc2>::type _S_select(_Alloc2); +}; +template <typename _Alloc> +template <typename _Alloc2> +const bool D<_Alloc>::F<_Alloc2>::value; + +template <typename> class vector { +public: + vector(int); + vector(vector &) : vector(D<bool>::_S_select((bool)0)) {} +}; +} +#endif // VECTOR \ No newline at end of file Index: test/Modules/Inputs/PR28752/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28752/module.modulemap @@ -0,0 +1 @@ +module a { header "a.h" export * } Index: test/Modules/Inputs/PR28752/a.h =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28752/a.h @@ -0,0 +1 @@ +#include <vector> Index: test/Modules/Inputs/PR28752/Subdir1/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28752/Subdir1/module.modulemap @@ -0,0 +1,5 @@ +module b { + module "b.h" { header "b.h" export * } + module "c.h" { header "c.h" export * } + export * +} Index: test/Modules/Inputs/PR28752/Subdir1/b.h =================================================================== --- /dev/null +++ test/Modules/Inputs/PR28752/Subdir1/b.h @@ -0,0 +1 @@ +#include <vector> Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4067,6 +4067,10 @@ PrettyDeclStackTraceEntry CrashInfo(*this, Var, SourceLocation(), "instantiating variable initializer"); + // The instantiation is visible here, even if it was first declared in an + // unimported module. + Var->setHidden(false); + // If we're performing recursive template instantiation, create our own // queue of pending implicit instantiations that we will instantiate // later, while we're still within our own instantiation context. @@ -4115,47 +4119,38 @@ Def = PatternDecl->getDefinition(); } - // 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. + TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); // If we don't have a definition of the variable template, we won't perform // any instantiation. Rather, we rely on the user to instantiate this // definition (or provide a specialization for it) in another translation // unit. - if (!Def) { - if (DefinitionRequired) { - if (VarSpec) - Diag(PointOfInstantiation, - diag::err_explicit_instantiation_undefined_var_template) << Var; - else - Diag(PointOfInstantiation, - diag::err_explicit_instantiation_undefined_member) - << 2 << Var->getDeclName() << Var->getDeclContext(); - Diag(PatternDecl->getLocation(), - diag::note_explicit_instantiation_here); - if (VarSpec) - Var->setInvalidDecl(); - } else if (Var->getTemplateSpecializationKind() - == TSK_ExplicitInstantiationDefinition) { + if (!Def && !DefinitionRequired) { + if (TSK == TSK_ExplicitInstantiationDefinition) { PendingInstantiations.push_back( std::make_pair(Var, PointOfInstantiation)); - } else if (Var->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) { + } else if (TSK == TSK_ImplicitInstantiation) { // Warn about missing definition at the end of translation unit. if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { Diag(PointOfInstantiation, diag::warn_var_template_missing) << Var; Diag(PatternDecl->getLocation(), diag::note_forward_template_decl); if (getLangOpts().CPlusPlus11) Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var; } + return; } - return; } - TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); + // FIXME: We need to track the instantiation stack in order to know which + // definitions should be visible within this instantiation. + if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Var, + /*InstantiatedFromMember*/false, + PatternDecl, Def, TSK, + /*Complain*/DefinitionRequired)) + return; + // Never instantiate an explicit specialization. if (TSK == TSK_ExplicitSpecialization) Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -466,10 +466,14 @@ const NamedDecl *PatternDef, TemplateSpecializationKind TSK, bool Complain /*= true*/) { - assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation)); + assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) + || isa<VarDecl>(Instantiation)); - if (PatternDef && (isa<FunctionDecl>(PatternDef) - || !cast<TagDecl>(PatternDef)->isBeingDefined())) { + bool isEntityBeingDefined = false; + if (const TagDecl *TD = dyn_cast_or_null<TagDecl>(PatternDef)) + isEntityBeingDefined = TD->isBeingDefined(); + + if (PatternDef && !isEntityBeingDefined) { NamedDecl *SuggestedDef = nullptr; if (!hasVisibleDefinition(const_cast<NamedDecl*>(PatternDef), &SuggestedDef, /*OnlyNeedComplete*/false)) { @@ -502,26 +506,40 @@ Diag(PointOfInstantiation, diag::err_explicit_instantiation_undefined_member) << 1 << Instantiation->getDeclName() << Instantiation->getDeclContext(); - } else { + } else if (isa<TagDecl>(Instantiation)) { Diag(PointOfInstantiation, diag::err_implicit_instantiate_member_undefined) << InstantiationTy; } Diag(Pattern->getLocation(), isa<FunctionDecl>(Instantiation) ? diag::note_explicit_instantiation_here : diag::note_member_declared_at); } else { - if (isa<FunctionDecl>(Instantiation)) + unsigned Note = 0; + if (isa<FunctionDecl>(Instantiation)) { Diag(PointOfInstantiation, diag::err_explicit_instantiation_undefined_func_template) << Pattern; - else + Note = diag::note_explicit_instantiation_here; + } else if (isa<TagDecl>(Instantiation)) { Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) << (TSK != TSK_ImplicitInstantiation) << InstantiationTy; - Diag(Pattern->getLocation(), isa<FunctionDecl>(Instantiation) - ? diag::note_explicit_instantiation_here - : diag::note_template_decl_here); + Note = diag::note_template_decl_here; + } else if (isa<VarDecl>(Instantiation)) { + if (isa<VarTemplateSpecializationDecl>(Instantiation)) { + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_var_template) + << Instantiation; + Instantiation->setInvalidDecl(); + } else + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_member) + << 2 << Instantiation->getDeclName() + << Instantiation->getDeclContext(); + Note = diag::note_explicit_instantiation_here; + } + Diag(Pattern->getLocation(), Note); } // In general, Instantiation isn't marked invalid to get more than one
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits