[clang] Fix returning the underlying VarDecl as top-level decl for VarTemplateDecl.

Given the following VarTemplateDecl AST,

```
VarTemplateDecl col:26 X
|-TemplateTypeParmDecl typename depth 0 index 0
`-VarDecl X 'bool' cinit
  `-CXXBoolLiteralExpr 'bool' true
```

previously, we returned the VarDecl as the top-level decl, which was not
correct, the top-level decl should be VarTemplateDecl.

Differential Revision: https://reviews.llvm.org/D89098
This commit is contained in:
Haojian Wu 2020-10-12 10:45:37 +02:00
parent 60cf8453d0
commit 702529d899
2 changed files with 19 additions and 5 deletions

View File

@ -57,6 +57,12 @@ MATCHER_P(DeclNamed, Name, "") {
return false;
}
MATCHER_P(DeclKind, Kind, "") {
if (NamedDecl *ND = dyn_cast<NamedDecl>(arg))
return ND->getDeclKindName() == Kind;
return false;
}
// Matches if the Decl has template args equal to ArgName. If the decl is a
// NamedDecl and ArgName is an empty string it also matches.
MATCHER_P(WithTemplateArgs, ArgName, "") {
@ -99,9 +105,15 @@ TEST(ParsedASTTest, TopLevelDecls) {
int header1();
int header2;
)";
TU.Code = "int main();";
TU.Code = R"cpp(
int main();
template <typename> bool X = true;
)cpp";
auto AST = TU.build();
EXPECT_THAT(AST.getLocalTopLevelDecls(), ElementsAre(DeclNamed("main")));
EXPECT_THAT(
AST.getLocalTopLevelDecls(),
ElementsAreArray({AllOf(DeclNamed("main"), DeclKind("Function")),
AllOf(DeclNamed("X"), DeclKind("VarTemplate"))}));
}
TEST(ParsedASTTest, DoesNotGetIncludedTopDecls) {

View File

@ -2195,6 +2195,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
// Inform the current actions module that we just parsed this declarator.
Decl *ThisDecl = nullptr;
Decl *OuterDecl = nullptr;
switch (TemplateInfo.Kind) {
case ParsedTemplateInfo::NonTemplate:
ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
@ -2205,10 +2206,12 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
*TemplateInfo.TemplateParams,
D);
if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl))
if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl)) {
// Re-direct this decl to refer to the templated decl so that we can
// initialize it.
ThisDecl = VT->getTemplatedDecl();
OuterDecl = VT;
}
break;
}
case ParsedTemplateInfo::ExplicitInstantiation: {
@ -2385,8 +2388,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
}
Actions.FinalizeDeclaration(ThisDecl);
return ThisDecl;
return OuterDecl ? OuterDecl : ThisDecl;
}
/// ParseSpecifierQualifierList