forked from OSchip/llvm-project
Revert "[Syntax] Build template declaration nodes"
This reverts commit dd12826808
.
Breaks tests on Windows, see https://reviews.llvm.org/D76346#1929208
This commit is contained in:
parent
04a309dd0b
commit
881f5b5a7b
|
@ -64,8 +64,6 @@ enum class NodeKind : uint16_t {
|
|||
StaticAssertDeclaration,
|
||||
LinkageSpecificationDeclaration,
|
||||
SimpleDeclaration,
|
||||
TemplateDeclaration,
|
||||
ExplicitTemplateInstantiation,
|
||||
NamespaceDefinition,
|
||||
NamespaceAliasDefinition,
|
||||
UsingNamespaceDirective,
|
||||
|
@ -114,9 +112,6 @@ enum class NodeRole : uint8_t {
|
|||
StaticAssertDeclaration_condition,
|
||||
StaticAssertDeclaration_message,
|
||||
SimpleDeclaration_declarator,
|
||||
TemplateDeclaration_declaration,
|
||||
ExplicitTemplateInstantiation_externKeyword,
|
||||
ExplicitTemplateInstantiation_declaration,
|
||||
ArraySubscript_sizeExpression,
|
||||
TrailingReturnType_arrow,
|
||||
TrailingReturnType_declarator,
|
||||
|
@ -401,34 +396,6 @@ public:
|
|||
std::vector<syntax::SimpleDeclarator *> declarators();
|
||||
};
|
||||
|
||||
/// template <template-parameters> <declaration>
|
||||
class TemplateDeclaration final : public Declaration {
|
||||
public:
|
||||
TemplateDeclaration() : Declaration(NodeKind::TemplateDeclaration) {}
|
||||
static bool classof(const Node *N) {
|
||||
return N->kind() == NodeKind::TemplateDeclaration;
|
||||
}
|
||||
syntax::Leaf *templateKeyword();
|
||||
syntax::Declaration *declaration();
|
||||
};
|
||||
|
||||
/// template <declaration>
|
||||
/// Examples:
|
||||
/// template struct X<int>
|
||||
/// template void foo<int>()
|
||||
/// template int var<double>
|
||||
class ExplicitTemplateInstantiation final : public Declaration {
|
||||
public:
|
||||
ExplicitTemplateInstantiation()
|
||||
: Declaration(NodeKind::ExplicitTemplateInstantiation) {}
|
||||
static bool classof(const Node *N) {
|
||||
return N->kind() == NodeKind::ExplicitTemplateInstantiation;
|
||||
}
|
||||
syntax::Leaf *templateKeyword();
|
||||
syntax::Leaf *externKeyword();
|
||||
syntax::Declaration *declaration();
|
||||
};
|
||||
|
||||
/// namespace <name> { <decls> }
|
||||
class NamespaceDefinition final : public Declaration {
|
||||
public:
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "clang/Tooling/Syntax/Nodes.h"
|
||||
|
@ -190,6 +189,7 @@ public:
|
|||
/// Should be called for expressions in non-statement position to avoid
|
||||
/// wrapping into expression statement.
|
||||
void markExprChild(Expr *Child, NodeRole Role);
|
||||
|
||||
/// Set role for a token starting at \p Loc.
|
||||
void markChildToken(SourceLocation Loc, NodeRole R);
|
||||
/// Set role for \p T.
|
||||
|
@ -199,9 +199,6 @@ public:
|
|||
void markChild(llvm::ArrayRef<syntax::Token> Range, NodeRole R);
|
||||
/// Set role for the delayed node that spans exactly \p Range.
|
||||
void markDelayedChild(llvm::ArrayRef<syntax::Token> Range, NodeRole R);
|
||||
/// Set role for the node that may or may not be delayed. Node must span
|
||||
/// exactly \p Range.
|
||||
void markMaybeDelayedChild(llvm::ArrayRef<syntax::Token> Range, NodeRole R);
|
||||
|
||||
/// Finish building the tree and consume the root node.
|
||||
syntax::TranslationUnit *finalize() && {
|
||||
|
@ -218,9 +215,6 @@ public:
|
|||
return TU;
|
||||
}
|
||||
|
||||
/// Finds a token starting at \p L. The token must exist if \p L is valid.
|
||||
const syntax::Token *findToken(SourceLocation L) const;
|
||||
|
||||
/// getRange() finds the syntax tokens corresponding to the passed source
|
||||
/// locations.
|
||||
/// \p First is the start position of the first token and \p Last is the start
|
||||
|
@ -233,22 +227,15 @@ public:
|
|||
Arena.sourceManager().isBeforeInTranslationUnit(First, Last));
|
||||
return llvm::makeArrayRef(findToken(First), std::next(findToken(Last)));
|
||||
}
|
||||
|
||||
llvm::ArrayRef<syntax::Token>
|
||||
getTemplateRange(const ClassTemplateSpecializationDecl *D) const {
|
||||
auto R = D->getSourceRange();
|
||||
auto Tokens = getRange(R.getBegin(), R.getEnd());
|
||||
return maybeAppendSemicolon(Tokens, D);
|
||||
}
|
||||
|
||||
llvm::ArrayRef<syntax::Token> getDeclRange(const Decl *D) const {
|
||||
llvm::ArrayRef<clang::syntax::Token> Tokens;
|
||||
// We want to drop the template parameters for specializations.
|
||||
if (const auto *S = llvm::dyn_cast<TagDecl>(D))
|
||||
Tokens = getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc());
|
||||
else
|
||||
Tokens = getRange(D->getBeginLoc(), D->getEndLoc());
|
||||
return maybeAppendSemicolon(Tokens, D);
|
||||
llvm::ArrayRef<syntax::Token> getRange(const Decl *D) const {
|
||||
auto Tokens = getRange(D->getBeginLoc(), D->getEndLoc());
|
||||
if (llvm::isa<NamespaceDecl>(D))
|
||||
return Tokens;
|
||||
if (DeclsWithoutSemicolons.count(D))
|
||||
return Tokens;
|
||||
// FIXME: do not consume trailing semicolon on function definitions.
|
||||
// Most declarations own a semicolon in syntax trees, but not in clang AST.
|
||||
return withTrailingSemicolon(Tokens);
|
||||
}
|
||||
llvm::ArrayRef<syntax::Token> getExprRange(const Expr *E) const {
|
||||
return getRange(E->getBeginLoc(), E->getEndLoc());
|
||||
|
@ -268,18 +255,6 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
llvm::ArrayRef<syntax::Token>
|
||||
maybeAppendSemicolon(llvm::ArrayRef<syntax::Token> Tokens,
|
||||
const Decl *D) const {
|
||||
if (llvm::isa<NamespaceDecl>(D))
|
||||
return Tokens;
|
||||
if (DeclsWithoutSemicolons.count(D))
|
||||
return Tokens;
|
||||
// FIXME: do not consume trailing semicolon on function definitions.
|
||||
// Most declarations own a semicolon in syntax trees, but not in clang AST.
|
||||
return withTrailingSemicolon(Tokens);
|
||||
}
|
||||
|
||||
llvm::ArrayRef<syntax::Token>
|
||||
withTrailingSemicolon(llvm::ArrayRef<syntax::Token> Tokens) const {
|
||||
assert(!Tokens.empty());
|
||||
|
@ -290,6 +265,9 @@ private:
|
|||
return Tokens;
|
||||
}
|
||||
|
||||
/// Finds a token starting at \p L. The token must exist.
|
||||
const syntax::Token *findToken(SourceLocation L) const;
|
||||
|
||||
/// A collection of trees covering the input tokens.
|
||||
/// When created, each tree corresponds to a single token in the file.
|
||||
/// Clients call 'foldChildren' to attach one or more subtrees to a parent
|
||||
|
@ -320,15 +298,6 @@ private:
|
|||
It->second.Role = Role;
|
||||
}
|
||||
|
||||
void assignRoleMaybeDelayed(llvm::ArrayRef<syntax::Token> Range,
|
||||
syntax::NodeRole Role) {
|
||||
auto It = DelayedFolds.find(Range.begin());
|
||||
if (It == DelayedFolds.end())
|
||||
return assignRole(Range, Role);
|
||||
assert(It->second.End == Range.end());
|
||||
It->second.Role = Role;
|
||||
}
|
||||
|
||||
void assignRole(llvm::ArrayRef<syntax::Token> Range,
|
||||
syntax::NodeRole Role) {
|
||||
assert(!Range.empty());
|
||||
|
@ -491,7 +460,7 @@ public:
|
|||
|
||||
bool WalkUpFromDeclaratorDecl(DeclaratorDecl *DD) {
|
||||
// Ensure declarators are covered by SimpleDeclaration.
|
||||
Builder.noticeDeclRange(Builder.getDeclRange(DD));
|
||||
Builder.noticeDeclRange(Builder.getRange(DD));
|
||||
|
||||
// Build the declarator node.
|
||||
SourceRange Initializer;
|
||||
|
@ -516,7 +485,7 @@ public:
|
|||
|
||||
bool WalkUpFromTypedefNameDecl(TypedefNameDecl *D) {
|
||||
// Ensure declarators are covered by SimpleDeclaration.
|
||||
Builder.noticeDeclRange(Builder.getDeclRange(D));
|
||||
Builder.noticeDeclRange(Builder.getRange(D));
|
||||
|
||||
auto R = getDeclaratorRange(
|
||||
Builder.sourceManager(), D->getTypeSourceInfo()->getTypeLoc(),
|
||||
|
@ -531,59 +500,19 @@ public:
|
|||
|
||||
bool VisitDecl(Decl *D) {
|
||||
assert(!D->isImplicit());
|
||||
Builder.foldNode(Builder.getDeclRange(D),
|
||||
Builder.foldNode(Builder.getRange(D),
|
||||
new (allocator()) syntax::UnknownDeclaration());
|
||||
return true;
|
||||
}
|
||||
|
||||
// RAV does not call WalkUpFrom* on explicit instantiations, so we have to
|
||||
// override Traverse.
|
||||
// FIXME: make RAV call WalkUpFrom* instead.
|
||||
bool
|
||||
TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *C) {
|
||||
if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C))
|
||||
return false;
|
||||
if (C->isExplicitSpecialization())
|
||||
return true; // we are only interested in explicit instantiations.
|
||||
if (!WalkUpFromClassTemplateSpecializationDecl(C))
|
||||
return false;
|
||||
foldExplicitTemplateInstantiation(
|
||||
Builder.getTemplateRange(C), Builder.findToken(C->getExternLoc()),
|
||||
Builder.findToken(C->getTemplateKeywordLoc()), Builder.getDeclRange(C));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromTemplateDecl(TemplateDecl *S) {
|
||||
foldTemplateDeclaration(
|
||||
Builder.getDeclRange(S),
|
||||
Builder.findToken(S->getTemplateParameters()->getTemplateLoc()),
|
||||
Builder.getDeclRange(S->getTemplatedDecl()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromTagDecl(TagDecl *C) {
|
||||
// FIXME: build the ClassSpecifier node.
|
||||
if (!C->isFreeStanding()) {
|
||||
assert(C->getNumTemplateParameterLists() == 0);
|
||||
if (C->isFreeStanding()) {
|
||||
// Class is a declaration specifier and needs a spanning declaration node.
|
||||
Builder.foldNode(Builder.getRange(C),
|
||||
new (allocator()) syntax::SimpleDeclaration);
|
||||
return true;
|
||||
}
|
||||
// Class is a declaration specifier and needs a spanning declaration node.
|
||||
auto DeclarationRange = Builder.getDeclRange(C);
|
||||
Builder.foldNode(DeclarationRange,
|
||||
new (allocator()) syntax::SimpleDeclaration);
|
||||
|
||||
// Build TemplateDeclaration nodes if we had template parameters.
|
||||
auto ConsumeTemplateParameters = [&](const TemplateParameterList &L) {
|
||||
const auto *TemplateKW = Builder.findToken(L.getTemplateLoc());
|
||||
auto R = llvm::makeArrayRef(TemplateKW, DeclarationRange.end());
|
||||
foldTemplateDeclaration(R, TemplateKW, DeclarationRange);
|
||||
|
||||
DeclarationRange = R;
|
||||
};
|
||||
if (auto *S = llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(C))
|
||||
ConsumeTemplateParameters(*S->getTemplateParameters());
|
||||
for (unsigned I = C->getNumTemplateParameterLists(); 0 < I; --I)
|
||||
ConsumeTemplateParameters(*C->getTemplateParameterList(I - 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -652,7 +581,7 @@ public:
|
|||
}
|
||||
|
||||
bool WalkUpFromNamespaceDecl(NamespaceDecl *S) {
|
||||
auto Tokens = Builder.getDeclRange(S);
|
||||
auto Tokens = Builder.getRange(S);
|
||||
if (Tokens.front().kind() == tok::coloncolon) {
|
||||
// Handle nested namespace definitions. Those start at '::' token, e.g.
|
||||
// namespace a^::b {}
|
||||
|
@ -693,7 +622,7 @@ public:
|
|||
Builder.markChildToken(L.getLParenLoc(), syntax::NodeRole::OpenParen);
|
||||
for (auto *P : L.getParams())
|
||||
Builder.markDelayedChild(
|
||||
Builder.getDeclRange(P),
|
||||
Builder.getRange(P),
|
||||
syntax::NodeRole::ParametersAndQualifiers_parameter);
|
||||
Builder.markChildToken(L.getRParenLoc(), syntax::NodeRole::CloseParen);
|
||||
Builder.foldNode(Builder.getRange(L.getLParenLoc(), L.getEndLoc()),
|
||||
|
@ -827,7 +756,7 @@ public:
|
|||
}
|
||||
|
||||
bool WalkUpFromEmptyDecl(EmptyDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::EmptyDeclaration);
|
||||
return true;
|
||||
}
|
||||
|
@ -837,49 +766,49 @@ public:
|
|||
syntax::NodeRole::StaticAssertDeclaration_condition);
|
||||
Builder.markExprChild(S->getMessage(),
|
||||
syntax::NodeRole::StaticAssertDeclaration_message);
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::StaticAssertDeclaration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromLinkageSpecDecl(LinkageSpecDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::LinkageSpecificationDeclaration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromNamespaceAliasDecl(NamespaceAliasDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::NamespaceAliasDefinition);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromUsingDirectiveDecl(UsingDirectiveDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::UsingNamespaceDirective);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromUsingDecl(UsingDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::UsingDeclaration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::UsingDeclaration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::UsingDeclaration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WalkUpFromTypeAliasDecl(TypeAliasDecl *S) {
|
||||
Builder.foldNode(Builder.getDeclRange(S),
|
||||
Builder.foldNode(Builder.getRange(S),
|
||||
new (allocator()) syntax::TypeAliasDeclaration);
|
||||
return true;
|
||||
}
|
||||
|
@ -916,36 +845,6 @@ private:
|
|||
Builder.foldNode(Tokens, new (allocator()) syntax::TrailingReturnType);
|
||||
return Tokens;
|
||||
}
|
||||
|
||||
void
|
||||
foldExplicitTemplateInstantiation(ArrayRef<syntax::Token> Range,
|
||||
const syntax::Token *ExternKW,
|
||||
const syntax::Token *TemplateKW,
|
||||
ArrayRef<syntax::Token> InnerDeclaration) {
|
||||
assert(!ExternKW || ExternKW->kind() == tok::kw_extern);
|
||||
assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
|
||||
Builder.markChildToken(
|
||||
ExternKW,
|
||||
syntax::NodeRole::ExplicitTemplateInstantiation_externKeyword);
|
||||
Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
|
||||
Builder.markChild(
|
||||
InnerDeclaration,
|
||||
syntax::NodeRole::ExplicitTemplateInstantiation_declaration);
|
||||
Builder.foldNode(Range,
|
||||
new (allocator()) syntax::ExplicitTemplateInstantiation);
|
||||
}
|
||||
|
||||
void foldTemplateDeclaration(ArrayRef<syntax::Token> Range,
|
||||
const syntax::Token *TemplateKW,
|
||||
ArrayRef<syntax::Token> TemplatedDeclaration) {
|
||||
assert(TemplateKW && TemplateKW->kind() == tok::kw_template);
|
||||
Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
|
||||
Builder.markMaybeDelayedChild(
|
||||
TemplatedDeclaration,
|
||||
syntax::NodeRole::TemplateDeclaration_declaration);
|
||||
Builder.foldNode(Range, new (allocator()) syntax::TemplateDeclaration);
|
||||
}
|
||||
|
||||
/// A small helper to save some typing.
|
||||
llvm::BumpPtrAllocator &allocator() { return Builder.allocator(); }
|
||||
|
||||
|
@ -992,11 +891,6 @@ void syntax::TreeBuilder::markDelayedChild(llvm::ArrayRef<syntax::Token> Range,
|
|||
Pending.assignRoleDelayed(Range, R);
|
||||
}
|
||||
|
||||
void syntax::TreeBuilder::markMaybeDelayedChild(
|
||||
llvm::ArrayRef<syntax::Token> Range, NodeRole R) {
|
||||
Pending.assignRoleMaybeDelayed(Range, R);
|
||||
}
|
||||
|
||||
void syntax::TreeBuilder::markStmtChild(Stmt *Child, NodeRole Role) {
|
||||
if (!Child)
|
||||
return;
|
||||
|
@ -1022,8 +916,6 @@ void syntax::TreeBuilder::markExprChild(Expr *Child, NodeRole Role) {
|
|||
}
|
||||
|
||||
const syntax::Token *syntax::TreeBuilder::findToken(SourceLocation L) const {
|
||||
if (L.isInvalid())
|
||||
return nullptr;
|
||||
auto It = LocationToToken.find(L.getRawEncoding());
|
||||
assert(It != LocationToToken.end());
|
||||
return It->second;
|
||||
|
|
|
@ -58,10 +58,6 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) {
|
|||
return OS << "LinkageSpecificationDeclaration";
|
||||
case NodeKind::SimpleDeclaration:
|
||||
return OS << "SimpleDeclaration";
|
||||
case NodeKind::TemplateDeclaration:
|
||||
return OS << "TemplateDeclaration";
|
||||
case NodeKind::ExplicitTemplateInstantiation:
|
||||
return OS << "ExplicitTemplateInstantiation";
|
||||
case NodeKind::NamespaceDefinition:
|
||||
return OS << "NamespaceDefinition";
|
||||
case NodeKind::NamespaceAliasDefinition:
|
||||
|
@ -122,12 +118,6 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeRole R) {
|
|||
return OS << "StaticAssertDeclaration_message";
|
||||
case syntax::NodeRole::SimpleDeclaration_declarator:
|
||||
return OS << "SimpleDeclaration_declarator";
|
||||
case syntax::NodeRole::TemplateDeclaration_declaration:
|
||||
return OS << "TemplateDeclaration_declaration";
|
||||
case syntax::NodeRole::ExplicitTemplateInstantiation_externKeyword:
|
||||
return OS << "ExplicitTemplateInstantiation_externKeyword";
|
||||
case syntax::NodeRole::ExplicitTemplateInstantiation_declaration:
|
||||
return OS << "ExplicitTemplateInstantiation_declaration";
|
||||
case syntax::NodeRole::ArraySubscript_sizeExpression:
|
||||
return OS << "ArraySubscript_sizeExpression";
|
||||
case syntax::NodeRole::TrailingReturnType_arrow:
|
||||
|
@ -291,31 +281,6 @@ syntax::SimpleDeclaration::declarators() {
|
|||
return Children;
|
||||
}
|
||||
|
||||
syntax::Leaf *syntax::TemplateDeclaration::templateKeyword() {
|
||||
return llvm::cast_or_null<syntax::Leaf>(
|
||||
findChild(syntax::NodeRole::IntroducerKeyword));
|
||||
}
|
||||
|
||||
syntax::Declaration *syntax::TemplateDeclaration::declaration() {
|
||||
return llvm::cast_or_null<syntax::Declaration>(
|
||||
findChild(syntax::NodeRole::TemplateDeclaration_declaration));
|
||||
}
|
||||
|
||||
syntax::Leaf *syntax::ExplicitTemplateInstantiation::templateKeyword() {
|
||||
return llvm::cast_or_null<syntax::Leaf>(
|
||||
findChild(syntax::NodeRole::IntroducerKeyword));
|
||||
}
|
||||
|
||||
syntax::Leaf *syntax::ExplicitTemplateInstantiation::externKeyword() {
|
||||
return llvm::cast_or_null<syntax::Leaf>(
|
||||
findChild(syntax::NodeRole::ExplicitTemplateInstantiation_externKeyword));
|
||||
}
|
||||
|
||||
syntax::Declaration *syntax::ExplicitTemplateInstantiation::declaration() {
|
||||
return llvm::cast_or_null<syntax::Declaration>(
|
||||
findChild(syntax::NodeRole::ExplicitTemplateInstantiation_declaration));
|
||||
}
|
||||
|
||||
syntax::Leaf *syntax::ParenDeclarator::lparen() {
|
||||
return llvm::cast_or_null<syntax::Leaf>(
|
||||
findChild(syntax::NodeRole::OpenParen));
|
||||
|
|
|
@ -678,212 +678,6 @@ struct {} *a1;
|
|||
`-;
|
||||
)txt"},
|
||||
{R"cpp(
|
||||
template <class T> struct cls {};
|
||||
template <class T> int var = 10;
|
||||
template <class T> int fun() {}
|
||||
)cpp",
|
||||
R"txt(
|
||||
*: TranslationUnit
|
||||
|-TemplateDeclaration
|
||||
| |-template
|
||||
| |-<
|
||||
| |-UnknownDeclaration
|
||||
| | |-class
|
||||
| | `-T
|
||||
| |->
|
||||
| `-SimpleDeclaration
|
||||
| |-struct
|
||||
| |-cls
|
||||
| |-{
|
||||
| |-}
|
||||
| `-;
|
||||
|-TemplateDeclaration
|
||||
| |-template
|
||||
| |-<
|
||||
| |-UnknownDeclaration
|
||||
| | |-class
|
||||
| | `-T
|
||||
| |->
|
||||
| `-SimpleDeclaration
|
||||
| |-int
|
||||
| |-SimpleDeclarator
|
||||
| | |-var
|
||||
| | |-=
|
||||
| | `-UnknownExpression
|
||||
| | `-10
|
||||
| `-;
|
||||
`-TemplateDeclaration
|
||||
|-template
|
||||
|-<
|
||||
|-UnknownDeclaration
|
||||
| |-class
|
||||
| `-T
|
||||
|->
|
||||
`-SimpleDeclaration
|
||||
|-int
|
||||
|-SimpleDeclarator
|
||||
| |-fun
|
||||
| `-ParametersAndQualifiers
|
||||
| |-(
|
||||
| `-)
|
||||
`-CompoundStatement
|
||||
|-{
|
||||
`-}
|
||||
)txt"},
|
||||
{R"cpp(
|
||||
template <class T>
|
||||
struct X {
|
||||
template <class U>
|
||||
U foo();
|
||||
};
|
||||
)cpp",
|
||||
R"txt(
|
||||
*: TranslationUnit
|
||||
`-TemplateDeclaration
|
||||
|-template
|
||||
|-<
|
||||
|-UnknownDeclaration
|
||||
| |-class
|
||||
| `-T
|
||||
|->
|
||||
`-SimpleDeclaration
|
||||
|-struct
|
||||
|-X
|
||||
|-{
|
||||
|-TemplateDeclaration
|
||||
| |-template
|
||||
| |-<
|
||||
| |-UnknownDeclaration
|
||||
| | |-class
|
||||
| | `-U
|
||||
| |->
|
||||
| `-SimpleDeclaration
|
||||
| |-U
|
||||
| |-SimpleDeclarator
|
||||
| | |-foo
|
||||
| | `-ParametersAndQualifiers
|
||||
| | |-(
|
||||
| | `-)
|
||||
| `-;
|
||||
|-}
|
||||
`-;
|
||||
)txt"},
|
||||
{R"cpp(
|
||||
template <class T> struct X {};
|
||||
template <class T> struct X<T*> {};
|
||||
template <> struct X<int> {};
|
||||
|
||||
template struct X<double>;
|
||||
extern template struct X<float>;
|
||||
)cpp",
|
||||
R"txt(
|
||||
*: TranslationUnit
|
||||
|-TemplateDeclaration
|
||||
| |-template
|
||||
| |-<
|
||||
| |-UnknownDeclaration
|
||||
| | |-class
|
||||
| | `-T
|
||||
| |->
|
||||
| `-SimpleDeclaration
|
||||
| |-struct
|
||||
| |-X
|
||||
| |-{
|
||||
| |-}
|
||||
| `-;
|
||||
|-TemplateDeclaration
|
||||
| |-template
|
||||
| |-<
|
||||
| |-UnknownDeclaration
|
||||
| | |-class
|
||||
| | `-T
|
||||
| |->
|
||||
| `-SimpleDeclaration
|
||||
| |-struct
|
||||
| |-X
|
||||
| |-<
|
||||
| |-T
|
||||
| |-*
|
||||
| |->
|
||||
| |-{
|
||||
| |-}
|
||||
| `-;
|
||||
|-TemplateDeclaration
|
||||
| |-template
|
||||
| |-<
|
||||
| |->
|
||||
| `-SimpleDeclaration
|
||||
| |-struct
|
||||
| |-X
|
||||
| |-<
|
||||
| |-int
|
||||
| |->
|
||||
| |-{
|
||||
| |-}
|
||||
| `-;
|
||||
|-ExplicitTemplateInstantiation
|
||||
| |-template
|
||||
| `-SimpleDeclaration
|
||||
| |-struct
|
||||
| |-X
|
||||
| |-<
|
||||
| |-double
|
||||
| |->
|
||||
| `-;
|
||||
`-ExplicitTemplateInstantiation
|
||||
|-extern
|
||||
|-template
|
||||
`-SimpleDeclaration
|
||||
|-struct
|
||||
|-X
|
||||
|-<
|
||||
|-float
|
||||
|->
|
||||
`-;
|
||||
)txt"},
|
||||
{R"cpp(
|
||||
template <class T> struct X { struct Y; };
|
||||
template <class T> struct X<T>::Y {};
|
||||
)cpp",
|
||||
R"txt(
|
||||
*: TranslationUnit
|
||||
|-TemplateDeclaration
|
||||
| |-template
|
||||
| |-<
|
||||
| |-UnknownDeclaration
|
||||
| | |-class
|
||||
| | `-T
|
||||
| |->
|
||||
| `-SimpleDeclaration
|
||||
| |-struct
|
||||
| |-X
|
||||
| |-{
|
||||
| |-SimpleDeclaration
|
||||
| | |-struct
|
||||
| | |-Y
|
||||
| | `-;
|
||||
| |-}
|
||||
| `-;
|
||||
`-TemplateDeclaration
|
||||
|-template
|
||||
|-<
|
||||
|-UnknownDeclaration
|
||||
| |-class
|
||||
| `-T
|
||||
|->
|
||||
`-SimpleDeclaration
|
||||
|-struct
|
||||
|-X
|
||||
|-<
|
||||
|-T
|
||||
|->
|
||||
|-::
|
||||
|-Y
|
||||
|-{
|
||||
|-}
|
||||
`-;
|
||||
)txt"},
|
||||
{R"cpp(
|
||||
namespace ns {}
|
||||
using namespace ::ns;
|
||||
)cpp",
|
||||
|
@ -932,7 +726,7 @@ template <class T> struct X {
|
|||
)cpp",
|
||||
R"txt(
|
||||
*: TranslationUnit
|
||||
`-TemplateDeclaration
|
||||
`-UnknownDeclaration
|
||||
|-template
|
||||
|-<
|
||||
|-UnknownDeclaration
|
||||
|
|
Loading…
Reference in New Issue