mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 01:07:04 +08:00
[clang] Remove written template args from implicit var tpl spec (#156329)
`VarTemplateSpecializationDecl::getTemplateArgsAsWritten()` function
should return `nullptr` in the case of implicit instantiation, as its
`ClassTemplateSpecializationDecl` counterpart does, and not the
arguments written in `DeclRefExpr` referencing the specialization in the
first place. Otherwise, for such code:
```cpp
template <typename>
int VarTpl;
template <typename T>
void tplFn() {
(void)VarTpl<T>; // (1)
}
void fn() {
tplFn<char>();
}
```
Clang treats the `char` argument of the `VarTpl` specialization as if it
were written in the line marked as (1), which is misleading and hardly
makes sense.
Moreover, "template args as written" are stored inside `ExplicitInfo`
field of `VarTemplateSpecializationDecl`, but it is
[documented](13357e8a12/clang/include/clang/AST/DeclTemplate.h (L2653))
that it is not for implicit instantiations.
Moreover, it is assumed in `TraverseVarTemplateSpecializationDecl`
method of `RecursiveASTVisitor` that `getTemplateArgsAsWritten()`
returns `nullptr` for implicit instantiations, as it is stated in the
comment
[there](13357e8a12/clang/include/clang/AST/RecursiveASTVisitor.h (L2196)).
That said, `setTemplateArgsAsWritten` should be called only for variable
template explicit specializations (it is [already done inside
`Sema::ActOnVarTemplateSpecialization`](4c91627304/clang/lib/Sema/SemaTemplate.cpp (L4459)))
and explicit instantiations (hence `true` is passed to the new
`SetWrittenArgs` parameter of `CheckVarTemplateId` function inside
`Sema::ActOnExplicitInstantiation`, but not when handling expressions
referencing a variable template specialization).
`InstantiateVariableDefinition` function just passes the arguments from
the corresponding declaration. I'm not sure about instantiating a class
template containing a variable template explicit specialization and thus
have tried to leave the logic of the first overload of
`TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl` as it
was.
This commit is contained in:
committed by
GitHub
parent
f6e8b26eab
commit
1cb47c19f8
@@ -84,6 +84,9 @@ C++ Specific Potentially Breaking Changes
|
||||
static_assert((b.*mp)() == 1); // newly rejected
|
||||
static_assert((c.*mp)() == 1); // accepted
|
||||
|
||||
- ``VarTemplateSpecializationDecl::getTemplateArgsAsWritten()`` method now
|
||||
returns ``nullptr`` for implicitly instantiated declarations.
|
||||
|
||||
ABI Changes in This Version
|
||||
---------------------------
|
||||
|
||||
|
||||
@@ -11668,7 +11668,8 @@ public:
|
||||
DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation TemplateNameLoc,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
const TemplateArgumentListInfo &TemplateArgs,
|
||||
bool SetWrittenArgs);
|
||||
|
||||
/// Form a reference to the specialization of the given variable template
|
||||
/// corresponding to the specified argument list, or a null-but-valid result
|
||||
@@ -14028,7 +14029,6 @@ public:
|
||||
VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
|
||||
VarTemplateDecl *VarTemplate, VarDecl *FromVar,
|
||||
const TemplateArgumentList *PartialSpecArgs,
|
||||
const TemplateArgumentListInfo &TemplateArgsInfo,
|
||||
SmallVectorImpl<TemplateArgument> &Converted,
|
||||
SourceLocation PointOfInstantiation,
|
||||
LateInstantiatedAttrVec *LateAttrs = nullptr,
|
||||
|
||||
@@ -723,9 +723,8 @@ enum class TemplateSubstitutionKind : char {
|
||||
bool SubstQualifier(const TagDecl *OldDecl,
|
||||
TagDecl *NewDecl);
|
||||
|
||||
Decl *VisitVarTemplateSpecializationDecl(
|
||||
VarTemplateSpecializationDecl *VisitVarTemplateSpecializationDecl(
|
||||
VarTemplateDecl *VarTemplate, VarDecl *FromVar,
|
||||
const TemplateArgumentListInfo &TemplateArgsInfo,
|
||||
ArrayRef<TemplateArgument> Converted,
|
||||
VarTemplateSpecializationDecl *PrevDecl = nullptr);
|
||||
|
||||
|
||||
@@ -1126,8 +1126,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc,
|
||||
MemberNameInfo.getLoc(), *TemplateArgs);
|
||||
DeclResult VDecl =
|
||||
CheckVarTemplateId(VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(),
|
||||
*TemplateArgs, /*SetWrittenArgs=*/false);
|
||||
if (VDecl.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
|
||||
@@ -4542,7 +4542,8 @@ static bool IsLibstdcxxStdFormatKind(Preprocessor &PP, VarDecl *Var) {
|
||||
DeclResult
|
||||
Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
||||
SourceLocation TemplateNameLoc,
|
||||
const TemplateArgumentListInfo &TemplateArgs) {
|
||||
const TemplateArgumentListInfo &TemplateArgs,
|
||||
bool SetWrittenArgs) {
|
||||
assert(Template && "A variable template id without template?");
|
||||
|
||||
// Check that the template argument list is well-formed for this template.
|
||||
@@ -4725,10 +4726,12 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
||||
// in DoMarkVarDeclReferenced().
|
||||
// FIXME: LateAttrs et al.?
|
||||
VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation(
|
||||
Template, InstantiationPattern, PartialSpecArgs, TemplateArgs,
|
||||
CTAI.CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/);
|
||||
Template, InstantiationPattern, PartialSpecArgs, CTAI.CanonicalConverted,
|
||||
TemplateNameLoc /*, LateAttrs, StartingScope*/);
|
||||
if (!Decl)
|
||||
return true;
|
||||
if (SetWrittenArgs)
|
||||
Decl->setTemplateArgsAsWritten(TemplateArgs);
|
||||
|
||||
if (AmbiguousPartialSpec) {
|
||||
// Partial ordering did not produce a clear winner. Complain.
|
||||
@@ -4760,7 +4763,7 @@ ExprResult Sema::CheckVarTemplateId(
|
||||
const TemplateArgumentListInfo *TemplateArgs) {
|
||||
|
||||
DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(),
|
||||
*TemplateArgs);
|
||||
*TemplateArgs, /*SetWrittenArgs=*/false);
|
||||
if (Decl.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
@@ -10707,8 +10710,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
||||
TemplateArgumentListInfo TemplateArgs =
|
||||
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
|
||||
|
||||
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
|
||||
D.getIdentifierLoc(), TemplateArgs);
|
||||
DeclResult Res =
|
||||
CheckVarTemplateId(PrevTemplate, TemplateLoc, D.getIdentifierLoc(),
|
||||
TemplateArgs, /*SetWrittenArgs=*/true);
|
||||
if (Res.isInvalid())
|
||||
return true;
|
||||
|
||||
|
||||
@@ -4542,14 +4542,17 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
||||
PrevDecl->getPointOfInstantiation(), Ignored))
|
||||
return nullptr;
|
||||
|
||||
return VisitVarTemplateSpecializationDecl(InstVarTemplate, D,
|
||||
VarTemplateArgsInfo,
|
||||
CTAI.CanonicalConverted, PrevDecl);
|
||||
if (VarTemplateSpecializationDecl *VTSD = VisitVarTemplateSpecializationDecl(
|
||||
InstVarTemplate, D, CTAI.CanonicalConverted, PrevDecl)) {
|
||||
VTSD->setTemplateArgsAsWritten(VarTemplateArgsInfo);
|
||||
return VTSD;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
||||
VarTemplateSpecializationDecl *
|
||||
TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
||||
VarTemplateDecl *VarTemplate, VarDecl *D,
|
||||
const TemplateArgumentListInfo &TemplateArgsInfo,
|
||||
ArrayRef<TemplateArgument> Converted,
|
||||
VarTemplateSpecializationDecl *PrevDecl) {
|
||||
|
||||
@@ -4570,7 +4573,6 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
||||
VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create(
|
||||
SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(),
|
||||
VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted);
|
||||
Var->setTemplateArgsAsWritten(TemplateArgsInfo);
|
||||
if (!PrevDecl) {
|
||||
void *InsertPos = nullptr;
|
||||
VarTemplate->findSpecialization(Converted, InsertPos);
|
||||
@@ -5880,7 +5882,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
|
||||
VarTemplateDecl *VarTemplate, VarDecl *FromVar,
|
||||
const TemplateArgumentList *PartialSpecArgs,
|
||||
const TemplateArgumentListInfo &TemplateArgsInfo,
|
||||
SmallVectorImpl<TemplateArgument> &Converted,
|
||||
SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs,
|
||||
LocalInstantiationScope *StartingScope) {
|
||||
@@ -5922,9 +5923,8 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
|
||||
|
||||
// TODO: Set LateAttrs and StartingScope ...
|
||||
|
||||
return cast_or_null<VarTemplateSpecializationDecl>(
|
||||
Instantiator.VisitVarTemplateSpecializationDecl(
|
||||
VarTemplate, FromVar, TemplateArgsInfo, Converted));
|
||||
return Instantiator.VisitVarTemplateSpecializationDecl(VarTemplate, FromVar,
|
||||
Converted);
|
||||
}
|
||||
|
||||
VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
|
||||
@@ -6340,10 +6340,15 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
TemplateArgInfo.addArgument(Arg);
|
||||
}
|
||||
|
||||
Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl(
|
||||
VarSpec->getSpecializedTemplate(), Def, TemplateArgInfo,
|
||||
VarSpec->getTemplateArgs().asArray(), VarSpec));
|
||||
VarTemplateSpecializationDecl *VTSD =
|
||||
Instantiator.VisitVarTemplateSpecializationDecl(
|
||||
VarSpec->getSpecializedTemplate(), Def,
|
||||
VarSpec->getTemplateArgs().asArray(), VarSpec);
|
||||
Var = VTSD;
|
||||
|
||||
if (Var) {
|
||||
VTSD->setTemplateArgsAsWritten(TemplateArgInfo);
|
||||
|
||||
llvm::PointerUnion<VarTemplateDecl *,
|
||||
VarTemplatePartialSpecializationDecl *> PatternPtr =
|
||||
VarSpec->getSpecializedTemplateOrPartial();
|
||||
|
||||
@@ -586,3 +586,22 @@ namespace x::y {
|
||||
ASSERT_NE(FD, nullptr);
|
||||
ASSERT_EQ(FD->getQualifiedNameAsString(), "x::y::Foo::Foo<T>");
|
||||
}
|
||||
|
||||
TEST(Decl, NoWrittenArgsInImplicitlyInstantiatedVarSpec) {
|
||||
const char *Code = R"cpp(
|
||||
template <typename>
|
||||
int VarTpl;
|
||||
|
||||
void fn() {
|
||||
(void)VarTpl<char>;
|
||||
}
|
||||
)cpp";
|
||||
|
||||
auto AST = tooling::buildASTFromCode(Code);
|
||||
ASTContext &Ctx = AST->getASTContext();
|
||||
|
||||
const auto *VTSD = selectFirst<VarTemplateSpecializationDecl>(
|
||||
"id", match(varDecl(isTemplateInstantiation()).bind("id"), Ctx));
|
||||
ASSERT_NE(VTSD, nullptr);
|
||||
EXPECT_EQ(VTSD->getTemplateArgsAsWritten(), nullptr);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user