diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 47 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 4 |
4 files changed, 72 insertions, 35 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7baa85a6464..fa15b530add 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9708,6 +9708,22 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->getDeclContext()->isDependentContext())) { // The previous definition is hidden, and multiple definitions are // permitted (in separate TUs). Form another definition of it. + if (!isa<ParmVarDecl>(VDecl)) { + // Demote the newly parsed definition to a fake declaration. + if (!VDecl->isThisDeclarationADemotedDefinition()) + VDecl->demoteThisDefinitionToDeclaration(); + + // Make the definition visible from the point of the demotion on. + assert (!Hidden || Def == Hidden && + "We were suggested another hidden definition!"); + makeMergedDefinitionVisible(Def, VDecl->getLocation()); + + // If this is a variable template definition, make its enclosing template + // visible. + if (VarDecl *VarPattern = Def->getTemplateInstantiationPattern()) + if (VarPattern->isThisDeclarationADefinition()) + makeMergedDefinitionVisible(VarPattern, VDecl->getLocation()); + } } else { Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0a03f8efc14..71b2153d05a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -466,10 +466,14 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, 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)) { @@ -486,13 +490,14 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) return true; + llvm::Optional<unsigned> Note; QualType InstantiationTy; if (TagDecl *TD = dyn_cast<TagDecl>(Instantiation)) InstantiationTy = Context.getTypeDeclType(TD); if (PatternDef) { Diag(PointOfInstantiation, diag::err_template_instantiate_within_definition) - << (TSK != TSK_ImplicitInstantiation) + << /*implicit|explicit*/(TSK != TSK_ImplicitInstantiation) << InstantiationTy; // Not much point in noting the template declaration here, since // we're lexically inside it. @@ -501,28 +506,44 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, if (isa<FunctionDecl>(Instantiation)) { Diag(PointOfInstantiation, diag::err_explicit_instantiation_undefined_member) - << 1 << Instantiation->getDeclName() << Instantiation->getDeclContext(); + << /*member function*/ 1 << Instantiation->getDeclName() + << Instantiation->getDeclContext(); + Note = diag::note_explicit_instantiation_here; } else { + assert(isa<TagDecl>(Instantiation) && "Must be a TagDecl!"); Diag(PointOfInstantiation, diag::err_implicit_instantiate_member_undefined) << InstantiationTy; + Note = diag::note_member_declared_at; } - Diag(Pattern->getLocation(), isa<FunctionDecl>(Instantiation) - ? diag::note_explicit_instantiation_here - : diag::note_member_declared_at); } else { - if (isa<FunctionDecl>(Instantiation)) + 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 { + assert(isa<VarDecl>(Instantiation) && "Must be a VarDecl!"); + 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) + << /*static data member*/ 2 << Instantiation->getDeclName() + << Instantiation->getDeclContext(); + Note = diag::note_explicit_instantiation_here; + } } + if (Note) // Diagnostics were emitted. + Diag(Pattern->getLocation(), Note.getValue()); // In general, Instantiation isn't marked invalid to get more than one // error for multiple undefined instantiations. But the code that does diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 09068d71ffb..911bc512c87 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4068,6 +4068,10 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, 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. @@ -4116,33 +4120,17 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, 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; - Var->setInvalidDecl(); - } - else - Diag(PointOfInstantiation, - diag::err_explicit_instantiation_undefined_member) - << 2 << Var->getDeclName() << Var->getDeclContext(); - Diag(PatternDecl->getLocation(), - diag::note_explicit_instantiation_here); - } 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) @@ -4151,12 +4139,20 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, 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. + // FIXME: Produce diagnostics when Var->getInstantiatedFromStaticDataMember(). + if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Var, + /*InstantiatedFromMember*/false, + PatternDecl, Def, TSK, + /*Complain*/DefinitionRequired)) + return; + // Never instantiate an explicit specialization. if (TSK == TSK_ExplicitSpecialization) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 0f2ec79ba38..41ff13a1037 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6888,6 +6888,10 @@ bool Sema::hasVisibleDefinition(NamedDecl *D, NamedDecl **Suggested, if (auto *Pattern = FD->getTemplateInstantiationPattern()) FD = Pattern; D = FD->getDefinition(); + } else if (auto *VD = dyn_cast<VarDecl>(D)) { + if (auto *Pattern = VD->getTemplateInstantiationPattern()) + VD = Pattern; + D = VD->getDefinition(); } assert(D && "missing definition for pattern of instantiated definition"); |