LocalInstantiationScope *StartingScope,
bool InstantiatingVarTemplate = false,
VarTemplateSpecializationDecl *PrevVTSD = nullptr);
+
+ VarDecl *getVarTemplateSpecialization(
+ VarTemplateDecl *VarTempl, const TemplateArgumentListInfo *TemplateArgs,
+ const DeclarationNameInfo &MemberNameInfo, SourceLocation TemplateKWLoc);
+
void InstantiateVariableInitializer(
VarDecl *Var, VarDecl *OldVar,
const MultiLevelTemplateArgumentList &TemplateArgs);
return false;
}
-static VarDecl *
-getVarTemplateSpecialization(Sema &S, VarTemplateDecl *VarTempl,
+VarDecl *
+Sema::getVarTemplateSpecialization(VarTemplateDecl *VarTempl,
const TemplateArgumentListInfo *TemplateArgs,
const DeclarationNameInfo &MemberNameInfo,
SourceLocation TemplateKWLoc) {
if (!TemplateArgs) {
- S.diagnoseMissingTemplateArguments(TemplateName(VarTempl),
- MemberNameInfo.getBeginLoc());
+ diagnoseMissingTemplateArguments(TemplateName(VarTempl),
+ MemberNameInfo.getBeginLoc());
return nullptr;
}
- DeclResult VDecl = S.CheckVarTemplateId(
- VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), *TemplateArgs);
+ DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,
+ MemberNameInfo.getLoc(), *TemplateArgs);
if (VDecl.isInvalid())
return nullptr;
VarDecl *Var = cast<VarDecl>(VDecl.get());
"How did we get template arguments here sans a variable template");
if (isa<VarTemplateDecl>(MemberDecl)) {
MemberDecl = getVarTemplateSpecialization(
- *this, cast<VarTemplateDecl>(MemberDecl), TemplateArgs,
+ cast<VarTemplateDecl>(MemberDecl), TemplateArgs,
R.getLookupNameInfo(), TemplateKWLoc);
if (!MemberDecl)
return ExprError();
}
if (VarTemplateDecl *VarTempl = dyn_cast<VarTemplateDecl>(MemberDecl)) {
if (VarDecl *Var = getVarTemplateSpecialization(
- *this, VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
+ VarTempl, TemplateArgs, MemberNameInfo, TemplateKWLoc))
return BuildMemberExpr(
BaseExpr, IsArrow, OpLoc, &SS, TemplateKWLoc, Var, FoundDecl,
/*HadMultipleCandidates=*/false, MemberNameInfo,
/// template struct X<int>;
/// \endcode
///
-/// In the instantiation of <tt>X<int>::getKind()</tt>, we need to map the
-/// \p EnumConstantDecl for \p KnownValue (which refers to
-/// <tt>X<T>::<Kind>::KnownValue</tt>) to its instantiation
-/// (<tt>X<int>::<Kind>::KnownValue</tt>). \p FindInstantiatedDecl performs
-/// this mapping from within the instantiation of <tt>X<int></tt>.
+/// In the instantiation of X<int>::getKind(), we need to map the \p
+/// EnumConstantDecl for \p KnownValue (which refers to
+/// X<T>::<Kind>::KnownValue) to its instantiation (X<int>::<Kind>::KnownValue).
+/// \p FindInstantiatedDecl performs this mapping from within the instantiation
+/// of X<int>.
NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool FindingInstantiatedContext) {
return cast<LabelDecl>(Inst);
}
- // For variable template specializations, update those that are still
- // type-dependent.
- if (VarTemplateSpecializationDecl *VarSpec =
- dyn_cast<VarTemplateSpecializationDecl>(D)) {
- bool InstantiationDependent = false;
- const TemplateArgumentListInfo &VarTemplateArgs =
- VarSpec->getTemplateArgsInfo();
- if (TemplateSpecializationType::anyDependentTemplateArguments(
- VarTemplateArgs, InstantiationDependent))
- D = cast<NamedDecl>(
- SubstDecl(D, VarSpec->getDeclContext(), TemplateArgs));
- return D;
- }
-
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
if (!Record->isDependentContext())
return D;
// find it. Does that ever matter?
if (auto Name = D->getDeclName()) {
DeclarationNameInfo NameInfo(Name, D->getLocation());
- Name = SubstDeclarationNameInfo(NameInfo, TemplateArgs).getName();
+ DeclarationNameInfo NewNameInfo =
+ SubstDeclarationNameInfo(NameInfo, TemplateArgs);
+ Name = NewNameInfo.getName();
if (!Name)
return nullptr;
DeclContext::lookup_result Found = ParentDC->lookup(Name);
- Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
+
+ if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ VarTemplateDecl *Templ = cast_or_null<VarTemplateDecl>(
+ findInstantiationOf(Context, VTSD->getSpecializedTemplate(),
+ Found.begin(), Found.end()));
+ if (!Templ)
+ return nullptr;
+ Result = getVarTemplateSpecialization(
+ Templ, &VTSD->getTemplateArgsInfo(), NewNameInfo, SourceLocation());
+ } else
+ Result = findInstantiationOf(Context, D, Found.begin(), Found.end());
} else {
// Since we don't have a name for the entity we're looking for,
// our only option is to walk through all of the declarations to
}
int &t = B::template n; // expected-error {{use of variable template 'n' requires template arguments}}
}
+
+#ifndef PRECXX11
+namespace template_vars_in_template {
+template <int> struct TakesInt {};
+
+template <class T2>
+struct S {
+ template <class T1>
+ static constexpr int v = 42;
+
+ template <class T>
+ void mf() {
+ constexpr int val = v<T>;
+ }
+
+ void mf2() {
+ constexpr int val = v<char>;
+ TakesInt<val> ti;
+ (void)ti.x; // expected-error{{no member named 'x' in 'template_vars_in_template::TakesInt<42>'}}
+ }
+};
+
+void useit() {
+ S<int> x;
+ x.mf<double>();
+ x.mf2(); // expected-note{{in instantiation of member function 'template_vars_in_template::S<int>::mf2' requested here}}
+}
+}
+#endif