32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/ADT/DenseMap.h"
34#include "llvm/ADT/PointerUnion.h"
35#include "llvm/ADT/STLExtras.h"
36#include "llvm/ADT/SmallVector.h"
37#include "llvm/Support/Allocator.h"
38#include "llvm/Support/Compiler.h"
39#include "llvm/Support/FormatVariadic.h"
48 if (
auto *
C = dyn_cast<CXXConstructExpr>(
E)) {
49 auto NumArgs =
C->getNumArgs();
50 if (NumArgs == 1 || (NumArgs > 1 && isa<CXXDefaultArgExpr>(
C->getArg(1)))) {
51 Expr *A =
C->getArg(0);
52 if (
C->getParenOrBraceRange().isInvalid())
67 if (
auto *F = dyn_cast<CXXFunctionalCastExpr>(
E)) {
68 if (F->getCastKind() == CK_ConstructorConversion)
69 return F->getSubExpr();
98 auto L =
Visit(
T.getInnerLoc());
101 return T.getLParenLoc();
106 return HandlePointer(
T);
110 return HandlePointer(
T);
114 return HandlePointer(
T);
118 return HandlePointer(
T);
122 return HandlePointer(
T);
130 auto N =
T.getNextTypeLoc();
144 auto L =
Visit(
T.getPointeeLoc());
147 return T.getLocalSourceRange().getBegin();
153 auto FirstDefaultArg =
154 llvm::find_if(Args, [](
auto It) {
return isa<CXXDefaultArgExpr>(It); });
155 return llvm::make_range(Args.begin(), FirstDefaultArg);
159 switch (
E.getOperator()) {
162 case OO_ExclaimEqual:
164 case OO_GreaterEqual:
171 case OO_PercentEqual:
174 case OO_LessLessEqual:
175 case OO_GreaterGreaterEqual:
186 case OO_GreaterGreater:
191 return syntax::NodeKind::BinaryOperatorExpression;
194 return syntax::NodeKind::PrefixUnaryOperatorExpression;
198 switch (
E.getNumArgs()) {
200 return syntax::NodeKind::PrefixUnaryOperatorExpression;
202 return syntax::NodeKind::PostfixUnaryOperatorExpression;
204 llvm_unreachable(
"Invalid number of arguments for operator");
211 switch (
E.getNumArgs()) {
213 return syntax::NodeKind::PrefixUnaryOperatorExpression;
215 return syntax::NodeKind::BinaryOperatorExpression;
217 llvm_unreachable(
"Invalid number of arguments for operator");
219 return syntax::NodeKind::BinaryOperatorExpression;
224 case OO_Array_Delete:
228 return syntax::NodeKind::UnknownExpression;
230 return syntax::NodeKind::CallExpression;
234 llvm_unreachable(
"Not an overloadable operator");
236 llvm_unreachable(
"Unknown OverloadedOperatorKind enum");
245 assert((isa<DeclaratorDecl, TypedefNameDecl>(
D)) &&
246 "only DeclaratorDecl and TypedefNameDecl are supported.");
248 auto DN =
D->getDeclName();
249 bool IsAnonymous = DN.isIdentifier() && !DN.getAsIdentifierInfo();
253 if (
const auto *DD = dyn_cast<DeclaratorDecl>(
D)) {
254 if (DD->getQualifierLoc()) {
255 return DD->getQualifierLoc().getBeginLoc();
268 if (
auto *
V = dyn_cast<VarDecl>(
D)) {
269 auto *I =
V->getInit();
271 if (I && !
V->isCXXForRangeDecl())
272 return I->getSourceRange();
291 if (Name.isValid()) {
296 if (End.isInvalid() ||
SM.isBeforeInTranslationUnit(End, Name))
301 assert(
SM.isBeforeInTranslationUnit(End, InitializerEnd) ||
302 End == InitializerEnd);
303 End = InitializerEnd;
310using ASTPtr = llvm::PointerUnion<Stmt *, Decl *>;
314class ASTToSyntaxMapping {
317 assert(To !=
nullptr);
318 assert(!From.isNull());
320 bool Added =
Nodes.insert({From, To}).second;
322 assert(Added &&
"mapping added twice");
326 assert(To !=
nullptr);
329 bool Added = NNSNodes.insert({From, To}).second;
331 assert(Added &&
"mapping added twice");
337 return NNSNodes.lookup(
P);
341 llvm::DenseMap<ASTPtr, syntax::Tree *>
Nodes;
342 llvm::DenseMap<NestedNameSpecifierLoc, syntax::Tree *> NNSNodes;
366 Pending(
Arena, TBTM.tokenBuffer()) {
368 LocationToToken.insert({
T.location(), &
T});
382 Mapping.add(From,
New);
395 Mapping.add(From,
New);
403 auto ListRange = Pending.shrinkToFitList(SuperRange);
406 Mapping.add(From,
New);
436 assert(!Tokens.empty());
437 assert(Tokens.back().kind() == tok::eof);
440 Pending.foldChildren(TBTM.
tokenBuffer(), Tokens.drop_back(),
443 auto *TU = cast<syntax::TranslationUnit>(std::move(Pending).
finalize());
444 TU->assertInvariantsRecursive();
462 assert(
First.isValid());
463 assert(
Last.isValid());
472 return maybeAppendSemicolon(Tokens,
D);
478 assert((isa<DeclaratorDecl, TypedefNameDecl>(
D)) &&
479 "only DeclaratorDecl and TypedefNameDecl are supported.");
484 if (Next ==
nullptr) {
489 if (
D->
getKind() != Next->getKind()) {
506 if (
const auto *S = dyn_cast<TagDecl>(
D))
507 Tokens =
getRange(S->TypeDecl::getBeginLoc(), S->getEndLoc());
510 return maybeAppendSemicolon(Tokens,
D);
520 auto Tokens =
getRange(S->getSourceRange());
521 if (isa<CompoundStmt>(S))
526 if (Tokens.back().kind() == tok::semi)
528 return withTrailingSemicolon(Tokens);
533 const Decl *
D)
const {
534 if (isa<NamespaceDecl>(
D))
536 if (DeclsWithoutSemicolons.count(
D))
540 return withTrailingSemicolon(Tokens);
545 assert(!Tokens.empty());
546 assert(Tokens.back().kind() != tok::eof);
548 if (Tokens.back().kind() != tok::semi && Tokens.end()->kind() == tok::semi)
575 Trees.insert(Trees.end(), {&
T, L});
580 assert(!
Range.empty());
581 auto It = Trees.lower_bound(
Range.begin());
582 assert(It != Trees.end() &&
"no node found");
583 assert(It->first ==
Range.begin() &&
"no child with the specified range");
584 assert((std::next(It) == Trees.end() ||
585 std::next(It)->first ==
Range.end()) &&
586 "no child with the specified range");
588 "re-assigning role for a child");
589 It->second->setRole(Role);
595 auto BeginChildren = Trees.lower_bound(
Range.begin());
596 assert((BeginChildren == Trees.end() ||
597 BeginChildren->first ==
Range.begin()) &&
598 "Range crosses boundaries of existing subtrees");
600 auto EndChildren = Trees.lower_bound(
Range.end());
602 (EndChildren == Trees.end() || EndChildren->first ==
Range.end()) &&
603 "Range crosses boundaries of existing subtrees");
605 auto BelongsToList = [](
decltype(Trees)::value_type KV) {
606 auto Role = KV.second->getRole();
611 auto BeginListChildren =
612 std::find_if(BeginChildren, EndChildren, BelongsToList);
614 auto EndListChildren =
615 std::find_if_not(BeginListChildren, EndChildren, BelongsToList);
618 EndListChildren->first);
625 assert(
Node->getFirstChild() ==
nullptr &&
"node already has children");
627 auto *FirstToken = Tokens.begin();
628 auto BeginChildren = Trees.lower_bound(FirstToken);
630 assert((BeginChildren == Trees.end() ||
631 BeginChildren->first == FirstToken) &&
632 "fold crosses boundaries of existing subtrees");
633 auto EndChildren = Trees.lower_bound(Tokens.end());
635 (EndChildren == Trees.end() || EndChildren->first == Tokens.end()) &&
636 "fold crosses boundaries of existing subtrees");
638 for (
auto It = BeginChildren; It != EndChildren; ++It) {
639 auto *
C = It->second;
642 Node->appendChildLowLevel(
C);
646 Node->Original =
true;
650 Trees.erase(BeginChildren, EndChildren);
651 Trees.insert({FirstToken,
Node});
656 assert(Trees.size() == 1);
657 auto *Root = Trees.begin()->second;
664 for (
auto It = Trees.begin(); It != Trees.end(); ++It) {
665 unsigned CoveredTokens =
667 ? (std::next(It)->first - It->first)
671 formatv(
"- '{0}' covers '{1}'+{2} tokens\n", It->second->getKind(),
673 R += It->second->dump(STM);
682 std::map<const syntax::Token *, syntax::Node *> Trees;
686 std::string str() {
return Pending.str(TBTM); }
689 TokenBufferTokenManager& TBTM;
691 llvm::DenseMap<SourceLocation, const syntax::Token *> LocationToToken;
693 llvm::DenseSet<Decl *> DeclsWithoutSemicolons;
694 ASTToSyntaxMapping Mapping;
701 : Builder(Builder), Context(Context) {}
706 return processDeclaratorAndDeclaration(DD);
710 return processDeclaratorAndDeclaration(TD);
715 Builder.foldNode(Builder.getDeclarationRange(
D),
725 if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(
C))
727 if (
C->isExplicitSpecialization())
730 cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(
C));
731 foldExplicitTemplateInstantiation(
732 Builder.getTemplateRange(
C),
733 Builder.findToken(
C->getExternKeywordLoc()),
734 Builder.findToken(
C->getTemplateKeywordLoc()),
Declaration,
C);
739 foldTemplateDeclaration(
740 Builder.getDeclarationRange(S),
741 Builder.findToken(S->getTemplateParameters()->getTemplateLoc()),
742 Builder.getDeclarationRange(S->getTemplatedDecl()), S);
746 bool WalkUpFromTagDecl(
TagDecl *
C) {
748 if (!
C->isFreeStanding()) {
749 assert(
C->getNumTemplateParameterLists() == 0);
752 handleFreeStandingTagDecl(
C);
757 assert(
C->isFreeStanding());
759 auto DeclarationRange = Builder.getDeclarationRange(
C);
761 Builder.foldNode(DeclarationRange, Result,
nullptr);
765 const auto *TemplateKW = Builder.findToken(L.getTemplateLoc());
768 foldTemplateDeclaration(R, TemplateKW, DeclarationRange,
nullptr);
769 DeclarationRange = R;
771 if (
auto *S = dyn_cast<ClassTemplatePartialSpecializationDecl>(
C))
772 ConsumeTemplateParameters(*S->getTemplateParameters());
773 for (
unsigned I =
C->getNumTemplateParameterLists(); 0 < I; --I)
774 ConsumeTemplateParameters(*
C->getTemplateParameterList(I - 1));
787 Builder.markChildToken(S->getLBracLoc(), NodeRole::OpenParen);
788 for (
auto *Child : S->body())
789 Builder.markStmtChild(Child, NodeRole::Statement);
790 Builder.markChildToken(S->getRBracLoc(), NodeRole::CloseParen);
792 Builder.foldNode(Builder.getStmtRange(S),
799 Builder.foldNode(Builder.getStmtRange(S),
804 bool TraverseIfStmt(
IfStmt *S) {
805 bool Result = [&,
this]() {
812 if (S->hasVarStorage()) {
833 bool Result = [&,
this]() {
836 if (S->getLoopVariable() && !
TraverseDecl(S->getLoopVariable()))
838 if (S->getRangeInit() && !
TraverseStmt(S->getRangeInit()))
844 WalkUpFromCXXForRangeStmt(S);
849 if (
auto *DS = dyn_cast_or_null<DeclStmt>(S)) {
851 for (
auto *
D : DS->decls())
852 Builder.noticeDeclWithoutSemicolon(
D);
853 }
else if (
auto *
E = dyn_cast_or_null<Expr>(S)) {
865 bool WalkUpFromExpr(
Expr *
E) {
867 Builder.foldNode(Builder.getExprRange(
E),
878 return WalkUpFromUserDefinedLiteral(S);
881 syntax::UserDefinedLiteralExpression *
883 switch (S->getLiteralOperatorKind()) {
885 return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
887 return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
889 return new (allocator()) syntax::CharUserDefinedLiteralExpression;
891 return new (allocator()) syntax::StringUserDefinedLiteralExpression;
898 auto TokLoc = S->getBeginLoc();
905 if (
Literal.isIntegerLiteral())
906 return new (allocator()) syntax::IntegerUserDefinedLiteralExpression;
908 assert(
Literal.isFloatingLiteral());
909 return new (allocator()) syntax::FloatUserDefinedLiteralExpression;
912 llvm_unreachable(
"Unknown literal operator kind.");
916 Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
917 Builder.foldNode(Builder.getExprRange(S), buildUserDefinedLiteral(S), S);
921 syntax::NameSpecifier *buildIdentifier(
SourceRange SR,
922 bool DropBack =
false) {
923 auto NameSpecifierTokens = Builder.getRange(SR).drop_back(DropBack);
924 assert(NameSpecifierTokens.size() == 1);
925 Builder.markChildToken(NameSpecifierTokens.begin(),
926 syntax::NodeRole::Unknown);
927 auto *NS =
new (allocator()) syntax::IdentifierNameSpecifier;
928 Builder.foldNode(NameSpecifierTokens, NS,
nullptr);
932 syntax::NameSpecifier *buildSimpleTemplateName(
SourceRange SR) {
933 auto NameSpecifierTokens = Builder.getRange(SR);
939 auto *NS =
new (allocator()) syntax::SimpleTemplateNameSpecifier;
940 Builder.foldNode(NameSpecifierTokens, NS,
nullptr);
944 syntax::NameSpecifier *
949 return new (allocator()) syntax::GlobalNameSpecifier;
957 case TypeLoc::Record:
958 case TypeLoc::InjectedClassName:
961 case TypeLoc::Typedef:
963 case TypeLoc::UnresolvedUsing:
964 return buildIdentifier(
968 case TypeLoc::DependentName:
970 case TypeLoc::TemplateSpecialization: {
973 if (BeginLoc.isInvalid())
974 BeginLoc = TST.getTemplateNameLoc();
975 return buildSimpleTemplateName({BeginLoc, TST.getEndLoc()});
977 case TypeLoc::DependentTemplateSpecialization: {
980 if (BeginLoc.isInvalid())
981 BeginLoc = DT.getTemplateNameLoc();
982 return buildSimpleTemplateName({BeginLoc, DT.getEndLoc()});
984 case TypeLoc::Decltype: {
986 if (!RecursiveASTVisitor::TraverseDecltypeTypeLoc(
989 auto *NS =
new (allocator()) syntax::DecltypeNameSpecifier;
994 Builder.foldNode(Builder.getRange(DTL.getLocalSourceRange()), NS,
1004 llvm::report_fatal_error(
"We don't yet support the __super specifier",
1016 for (
auto It = QualifierLoc; It; ) {
1017 auto *NS = buildNameSpecifier(It);
1020 Builder.markChild(NS, syntax::NodeRole::ListElement);
1021 Builder.markChildToken(It.getEndLoc(), syntax::NodeRole::ListDelimiter);
1022 if (
TypeLoc TL = It.getAsTypeLoc())
1027 Builder.foldNode(Builder.getRange(QualifierLoc.
getSourceRange()),
1038 Builder.markChild(QualifierLoc, syntax::NodeRole::Qualifier);
1039 if (TemplateKeywordLoc.
isValid())
1040 Builder.markChildToken(TemplateKeywordLoc,
1041 syntax::NodeRole::TemplateKeyword);
1045 Builder.foldNode(Builder.getRange(UnqualifiedIdLoc), TheUnqualifiedId,
1047 Builder.markChild(TheUnqualifiedId, syntax::NodeRole::UnqualifiedId);
1049 auto IdExpressionBeginLoc =
1052 auto *TheIdExpression =
new (allocator()) syntax::IdExpression;
1054 Builder.getRange(IdExpressionBeginLoc, UnqualifiedIdLoc.
getEnd()),
1055 TheIdExpression, From);
1057 return TheIdExpression;
1064 if (S->isImplicitAccess()) {
1065 buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1066 SourceRange(S->getMemberLoc(), S->getEndLoc()), S);
1070 auto *TheIdExpression = buildIdExpression(
1071 S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1072 SourceRange(S->getMemberLoc(), S->getEndLoc()),
nullptr);
1074 Builder.markChild(TheIdExpression, syntax::NodeRole::Member);
1076 Builder.markExprChild(S->getBase(), syntax::NodeRole::Object);
1077 Builder.markChildToken(S->getOperatorLoc(), syntax::NodeRole::AccessToken);
1079 Builder.foldNode(Builder.getExprRange(S),
1080 new (allocator()) syntax::MemberExpression, S);
1085 buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1086 SourceRange(S->getLocation(), S->getEndLoc()), S);
1093 buildIdExpression(S->getQualifierLoc(), S->getTemplateKeywordLoc(),
1094 SourceRange(S->getLocation(), S->getEndLoc()), S);
1100 if (!S->isImplicit()) {
1101 Builder.markChildToken(S->getLocation(),
1102 syntax::NodeRole::IntroducerKeyword);
1103 Builder.foldNode(Builder.getExprRange(S),
1104 new (allocator()) syntax::ThisExpression, S);
1109 bool WalkUpFromParenExpr(
ParenExpr *S) {
1110 Builder.markChildToken(S->getLParen(), syntax::NodeRole::OpenParen);
1111 Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::SubExpression);
1112 Builder.markChildToken(S->getRParen(), syntax::NodeRole::CloseParen);
1113 Builder.foldNode(Builder.getExprRange(S),
1114 new (allocator()) syntax::ParenExpression, S);
1119 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1120 Builder.foldNode(Builder.getExprRange(S),
1121 new (allocator()) syntax::IntegerLiteralExpression, S);
1126 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1127 Builder.foldNode(Builder.getExprRange(S),
1128 new (allocator()) syntax::CharacterLiteralExpression, S);
1133 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1134 Builder.foldNode(Builder.getExprRange(S),
1135 new (allocator()) syntax::FloatingLiteralExpression, S);
1140 Builder.markChildToken(S->getBeginLoc(), syntax::NodeRole::LiteralToken);
1141 Builder.foldNode(Builder.getExprRange(S),
1142 new (allocator()) syntax::StringLiteralExpression, S);
1147 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1148 Builder.foldNode(Builder.getExprRange(S),
1149 new (allocator()) syntax::BoolLiteralExpression, S);
1154 Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
1155 Builder.foldNode(Builder.getExprRange(S),
1156 new (allocator()) syntax::CxxNullPtrExpression, S);
1161 Builder.markChildToken(S->getOperatorLoc(),
1162 syntax::NodeRole::OperatorToken);
1163 Builder.markExprChild(S->getSubExpr(), syntax::NodeRole::Operand);
1166 Builder.foldNode(Builder.getExprRange(S),
1170 Builder.foldNode(Builder.getExprRange(S),
1178 Builder.markExprChild(S->getLHS(), syntax::NodeRole::LeftHandSide);
1179 Builder.markChildToken(S->getOperatorLoc(),
1180 syntax::NodeRole::OperatorToken);
1181 Builder.markExprChild(S->getRHS(), syntax::NodeRole::RightHandSide);
1182 Builder.foldNode(Builder.getExprRange(S),
1192 for (
auto *Arg : Args) {
1193 Builder.markExprChild(Arg, syntax::NodeRole::ListElement);
1194 const auto *DelimiterToken =
1195 std::next(Builder.findToken(Arg->getEndLoc()));
1196 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1197 Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
1202 Builder.foldNode(Builder.getRange((*Args.begin())->getBeginLoc(),
1203 (*(Args.end() - 1))->getEndLoc()),
1209 bool WalkUpFromCallExpr(
CallExpr *S) {
1210 Builder.markExprChild(S->getCallee(), syntax::NodeRole::Callee);
1212 const auto *LParenToken =
1213 std::next(Builder.findToken(S->getCallee()->getEndLoc()));
1216 if (LParenToken->kind() == clang::tok::l_paren)
1217 Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);
1219 Builder.markChild(buildCallArguments(S->arguments()),
1220 syntax::NodeRole::Arguments);
1222 Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);
1224 Builder.foldNode(Builder.getRange(S->getSourceRange()),
1225 new (allocator()) syntax::CallExpression, S);
1231 if ((S->getNumArgs() == 0 || isa<CXXDefaultArgExpr>(S->getArg(0))) &&
1232 S->getParenOrBraceRange().isInvalid())
1234 return RecursiveASTVisitor::WalkUpFromCXXConstructExpr(S);
1242 for (
auto *child : S->arguments()) {
1249 if (child->getSourceRange().isInvalid()) {
1251 syntax::NodeKind::PostfixUnaryOperatorExpression);
1257 return WalkUpFromCXXOperatorCallExpr(S);
1262 case syntax::NodeKind::BinaryOperatorExpression:
1263 Builder.markExprChild(S->getArg(0), syntax::NodeRole::LeftHandSide);
1264 Builder.markChildToken(S->getOperatorLoc(),
1265 syntax::NodeRole::OperatorToken);
1266 Builder.markExprChild(S->getArg(1), syntax::NodeRole::RightHandSide);
1267 Builder.foldNode(Builder.getExprRange(S),
1270 case syntax::NodeKind::PrefixUnaryOperatorExpression:
1271 Builder.markChildToken(S->getOperatorLoc(),
1272 syntax::NodeRole::OperatorToken);
1273 Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);
1274 Builder.foldNode(Builder.getExprRange(S),
1278 case syntax::NodeKind::PostfixUnaryOperatorExpression:
1279 Builder.markChildToken(S->getOperatorLoc(),
1280 syntax::NodeRole::OperatorToken);
1281 Builder.markExprChild(S->getArg(0), syntax::NodeRole::Operand);
1282 Builder.foldNode(Builder.getExprRange(S),
1286 case syntax::NodeKind::CallExpression: {
1287 Builder.markExprChild(S->getArg(0), syntax::NodeRole::Callee);
1289 const auto *LParenToken =
1290 std::next(Builder.findToken(S->getArg(0)->getEndLoc()));
1293 if (LParenToken->kind() == clang::tok::l_paren)
1294 Builder.markChildToken(LParenToken, syntax::NodeRole::OpenParen);
1297 S->arg_begin() + 1, S->arg_end())),
1298 syntax::NodeRole::Arguments);
1300 Builder.markChildToken(S->getRParenLoc(), syntax::NodeRole::CloseParen);
1302 Builder.foldNode(Builder.getRange(S->getSourceRange()),
1303 new (allocator()) syntax::CallExpression, S);
1306 case syntax::NodeKind::UnknownExpression:
1307 return WalkUpFromExpr(S);
1309 llvm_unreachable(
"getOperatorNodeKind() does not return this value");
1316 auto Tokens = Builder.getDeclarationRange(S);
1317 if (Tokens.front().kind() == tok::coloncolon) {
1329 bool TraverseParenTypeLoc(
ParenTypeLoc L,
bool TraverseQualifier) {
1331 if (!WalkUpFromParenTypeLoc(L))
1337 Builder.markChildToken(L.
getLParenLoc(), syntax::NodeRole::OpenParen);
1338 Builder.markChildToken(L.
getRParenLoc(), syntax::NodeRole::CloseParen);
1346 Builder.markChildToken(L.
getLBracketLoc(), syntax::NodeRole::OpenParen);
1347 Builder.markExprChild(L.
getSizeExpr(), syntax::NodeRole::Size);
1348 Builder.markChildToken(L.
getRBracketLoc(), syntax::NodeRole::CloseParen);
1356 for (
auto *
P : Params) {
1357 Builder.markChild(
P, syntax::NodeRole::ListElement);
1358 const auto *DelimiterToken = std::next(Builder.findToken(
P->getEndLoc()));
1359 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1360 Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
1363 if (!Params.empty())
1364 Builder.foldNode(Builder.getRange(Params.front()->getBeginLoc(),
1365 Params.back()->getEndLoc()),
1371 Builder.markChildToken(L.
getLParenLoc(), syntax::NodeRole::OpenParen);
1373 Builder.markChild(buildParameterDeclarationList(L.
getParams()),
1374 syntax::NodeRole::Parameters);
1376 Builder.markChildToken(L.
getRParenLoc(), syntax::NodeRole::CloseParen);
1384 return WalkUpFromFunctionTypeLoc(L);
1386 auto *TrailingReturnTokens = buildTrailingReturn(L);
1388 Builder.markChild(TrailingReturnTokens, syntax::NodeRole::TrailingReturn);
1389 return WalkUpFromFunctionTypeLoc(L);
1393 bool TraverseQualifier) {
1398 if (!WalkUpFromMemberPointerTypeLoc(L))
1405 Builder.foldNode(Builder.getRange(SR),
1413 bool WalkUpFromDeclStmt(
DeclStmt *S) {
1414 Builder.foldNode(Builder.getStmtRange(S),
1419 bool WalkUpFromNullStmt(
NullStmt *S) {
1420 Builder.foldNode(Builder.getStmtRange(S),
1426 Builder.markChildToken(S->getSwitchLoc(),
1427 syntax::NodeRole::IntroducerKeyword);
1428 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1429 Builder.foldNode(Builder.getStmtRange(S),
1434 bool WalkUpFromCaseStmt(
CaseStmt *S) {
1435 Builder.markChildToken(S->getKeywordLoc(),
1436 syntax::NodeRole::IntroducerKeyword);
1437 Builder.markExprChild(S->getLHS(), syntax::NodeRole::CaseValue);
1438 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
1439 Builder.foldNode(Builder.getStmtRange(S),
1445 Builder.markChildToken(S->getKeywordLoc(),
1446 syntax::NodeRole::IntroducerKeyword);
1447 Builder.markStmtChild(S->getSubStmt(), syntax::NodeRole::BodyStatement);
1448 Builder.foldNode(Builder.getStmtRange(S),
1453 bool WalkUpFromIfStmt(
IfStmt *S) {
1454 Builder.markChildToken(S->getIfLoc(), syntax::NodeRole::IntroducerKeyword);
1455 Stmt *ConditionStatement = S->getCond();
1456 if (S->hasVarStorage())
1457 ConditionStatement = S->getConditionVariableDeclStmt();
1458 Builder.markStmtChild(ConditionStatement, syntax::NodeRole::Condition);
1459 Builder.markStmtChild(S->getThen(), syntax::NodeRole::ThenStatement);
1460 Builder.markChildToken(S->getElseLoc(), syntax::NodeRole::ElseKeyword);
1461 Builder.markStmtChild(S->getElse(), syntax::NodeRole::ElseStatement);
1462 Builder.foldNode(Builder.getStmtRange(S),
1467 bool WalkUpFromForStmt(
ForStmt *S) {
1468 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
1469 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1470 Builder.foldNode(Builder.getStmtRange(S),
1475 bool WalkUpFromWhileStmt(
WhileStmt *S) {
1476 Builder.markChildToken(S->getWhileLoc(),
1477 syntax::NodeRole::IntroducerKeyword);
1478 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1479 Builder.foldNode(Builder.getStmtRange(S),
1485 Builder.markChildToken(S->getKwLoc(), syntax::NodeRole::IntroducerKeyword);
1486 Builder.foldNode(Builder.getStmtRange(S),
1491 bool WalkUpFromBreakStmt(
BreakStmt *S) {
1492 Builder.markChildToken(S->getKwLoc(), syntax::NodeRole::IntroducerKeyword);
1493 Builder.foldNode(Builder.getStmtRange(S),
1499 Builder.markChildToken(S->getReturnLoc(),
1500 syntax::NodeRole::IntroducerKeyword);
1501 Builder.markExprChild(S->getRetValue(), syntax::NodeRole::ReturnValue);
1502 Builder.foldNode(Builder.getStmtRange(S),
1508 Builder.markChildToken(S->getForLoc(), syntax::NodeRole::IntroducerKeyword);
1509 Builder.markStmtChild(S->getBody(), syntax::NodeRole::BodyStatement);
1510 Builder.foldNode(Builder.getStmtRange(S),
1515 bool WalkUpFromEmptyDecl(
EmptyDecl *S) {
1516 Builder.foldNode(Builder.getDeclarationRange(S),
1522 Builder.markExprChild(S->getAssertExpr(), syntax::NodeRole::Condition);
1523 Builder.markExprChild(S->getMessage(), syntax::NodeRole::Message);
1524 Builder.foldNode(Builder.getDeclarationRange(S),
1530 Builder.foldNode(Builder.getDeclarationRange(S),
1537 Builder.foldNode(Builder.getDeclarationRange(S),
1543 Builder.foldNode(Builder.getDeclarationRange(S),
1548 bool WalkUpFromUsingDecl(
UsingDecl *S) {
1549 Builder.foldNode(Builder.getDeclarationRange(S),
1555 Builder.foldNode(Builder.getDeclarationRange(S),
1561 Builder.foldNode(Builder.getDeclarationRange(S),
1567 Builder.foldNode(Builder.getDeclarationRange(S),
1575 template <
class T>
bool processDeclaratorAndDeclaration(
T *
D) {
1577 Builder.sourceManager(),
D->getTypeSourceInfo()->getTypeLoc(),
1584 syntax::NodeRole::Declarators);
1585 Builder.foldNode(Builder.getDeclarationRange(
D),
1591 Builder.foldNode(Builder.getRange(
Range), N,
nullptr);
1592 Builder.markChild(N, syntax::NodeRole::ListElement);
1594 if (!Builder.isResponsibleForCreatingDeclaration(
D)) {
1597 const auto *DelimiterToken = std::next(Builder.findToken(
Range.
getEnd()));
1598 if (DelimiterToken->kind() == clang::tok::TokenKind::comma)
1599 Builder.markChildToken(DelimiterToken, syntax::NodeRole::ListDelimiter);
1602 auto DeclarationRange = Builder.getDeclarationRange(
D);
1603 Builder.foldList(DeclarationRange, DL,
nullptr);
1605 Builder.markChild(DL, syntax::NodeRole::Declarators);
1606 Builder.foldNode(DeclarationRange,
1618 auto ReturnDeclaratorRange =
SourceRange(GetStartLoc().Visit(ReturnedType),
1619 ReturnedType.getEndLoc());
1621 if (ReturnDeclaratorRange.isValid()) {
1623 Builder.foldNode(Builder.getRange(ReturnDeclaratorRange),
1624 ReturnDeclarator,
nullptr);
1628 auto Return = Builder.getRange(ReturnedType.getSourceRange());
1629 const auto *Arrow = Return.begin() - 1;
1630 assert(Arrow->kind() == tok::arrow);
1632 Builder.markChildToken(Arrow, syntax::NodeRole::ArrowToken);
1633 if (ReturnDeclarator)
1634 Builder.markChild(ReturnDeclarator, syntax::NodeRole::Declarator);
1636 Builder.foldNode(Tokens, R, L);
1640 void foldExplicitTemplateInstantiation(
1644 assert(!ExternKW || ExternKW->
kind() == tok::kw_extern);
1645 assert(TemplateKW && TemplateKW->
kind() == tok::kw_template);
1646 Builder.markChildToken(ExternKW, syntax::NodeRole::ExternKeyword);
1647 Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
1648 Builder.markChild(InnerDeclaration, syntax::NodeRole::Declaration);
1656 assert(TemplateKW && TemplateKW->
kind() == tok::kw_template);
1657 Builder.markChildToken(TemplateKW, syntax::NodeRole::IntroducerKeyword);
1660 Builder.foldNode(
Range, N, From);
1661 Builder.markChild(N, syntax::NodeRole::Declaration);
1666 llvm::BumpPtrAllocator &allocator() {
return Builder.allocator(); }
1674 DeclsWithoutSemicolons.insert(
D);
1680 Pending.assignRole(*findToken(
Loc), Role);
1686 Pending.assignRole(*
T, R);
1695 auto *SN = Mapping.find(N);
1696 assert(SN !=
nullptr);
1700 auto *SN = Mapping.find(NNSLoc);
1701 assert(SN !=
nullptr);
1710 if (
Expr *ChildExpr = dyn_cast<Expr>(Child)) {
1716 Pending.foldChildren(TBTM.tokenBuffer(), getStmtRange(Child), ChildNode);
1718 ChildNode = Mapping.find(Child);
1720 assert(ChildNode !=
nullptr);
1721 setRole(ChildNode, Role);
1730 assert(ChildNode !=
nullptr);
1731 setRole(ChildNode, Role);
1737 auto It = LocationToToken.find(L);
1738 assert(It != LocationToToken.end());
1746 BuildTreeVisitor(Context, Builder).TraverseAST(Context);
1747 return std::move(Builder).finalize();
Forward declaration of all AST node types.
BoundNodesTreeBuilder Nodes
static SourceRange getDeclaratorRange(const SourceManager &SM, TypeLoc T, SourceLocation Name, SourceRange Initializer)
Gets the range of declarator as defined by the C++ grammar.
static Expr * IgnoreImplicit(Expr *E)
static CallExpr::arg_range dropDefaultArgs(CallExpr::arg_range Args)
static LLVM_ATTRIBUTE_UNUSED bool isImplicitExpr(Expr *E)
static Expr * IgnoreCXXFunctionalCastExprWrappingConstructor(Expr *E)
static syntax::NodeKind getOperatorNodeKind(const CXXOperatorCallExpr &E)
static SourceLocation getQualifiedNameStart(NamedDecl *D)
Get the start of the qualified name.
static SourceRange getInitializerRange(Decl *D)
Gets the range of the initializer inside an init-declarator C++ [dcl.decl].
static Expr * IgnoreImplicitConstructorSingleStep(Expr *E)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines the clang::SourceLocation class and associated facilities.
Defines the SourceManager interface.
Defines the clang::TokenKind enum and support functions.
Defines the clang::TypeLoc interface and its subclasses.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
Wrapper for source info for arrays.
SourceLocation getLBracketLoc() const
Expr * getSizeExpr() const
SourceLocation getRBracketLoc() const
A builtin binary operation expression such as "x + y" or "x <= y".
Wrapper for source info for block pointers.
BreakStmt - This represents a break.
A boolean literal, per ([C++ lex.bool] Boolean literals).
Represents a call to a C++ constructor.
A default argument (C++ [dcl.fct.default]).
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
The null pointer literal (C++11 [lex.nullptr])
A call to an overloaded operator written using operator syntax.
Represents the this expression in C++.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
llvm::iterator_range< arg_iterator > arg_range
CaseStmt - Represent a case statement.
Represents a class template specialization, which refers to a class template with a given set of temp...
CompoundStmt - This represents a group of statements like { stmt stmt }.
ContinueStmt - This represents a continue.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Decl * getNextDeclInContext()
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Represents a ValueDecl that came out of a declarator.
SourceLocation getNameLoc() const
A qualified reference to a name whose declaration cannot yet be resolved.
SourceLocation getNameLoc() const
Represents an empty-declaration.
This represents one expression.
ForStmt - This represents a 'for (init;cond;inc)' stmt.
bool hasTrailingReturn() const
Whether this function prototype has a trailing return type.
Wrapper for source info for functions.
ArrayRef< ParmVarDecl * > getParams() const
TypeLoc getReturnLoc() const
SourceLocation getLParenLoc() const
SourceLocation getRParenLoc() const
IfStmt - This represents an if/then/else.
const TypeClass * getTypePtr() const
Represents a linkage specification.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Wrapper for source info for member pointers.
SourceRange getLocalSourceRange() const
This represents a decl that may have a name.
Represents a C++ namespace alias.
Represent a C++ namespace.
A C++ nested-name-specifier augmented with source location information.
NamespaceAndPrefixLoc getAsNamespaceAndPrefix() const
NestedNameSpecifier getNestedNameSpecifier() const
Retrieve the nested-name-specifier to which this instance refers.
SourceRange getSourceRange() const LLVM_READONLY
Retrieve the source range covering the entirety of this nested-name-specifier.
SourceLocation getBeginLoc() const
Retrieve the location of the beginning of this nested-name-specifier.
TypeLoc castAsTypeLoc() const
For a nested-name-specifier that refers to a type, retrieve the type with source-location information...
bool hasQualifier() const
Evaluates true when this nested-name-specifier location is non-empty.
SourceRange getLocalSourceRange() const
Retrieve the source range covering just the last part of this nested-name-specifier,...
@ Global
The global specifier '::'. There is no stored value.
@ Type
A type, stored as a Type*.
@ Namespace
A namespace-like entity, stored as a NamespaceBaseDecl*.
NullStmt - This is the null statement ";": C99 6.8.3p3.
NumericLiteralParser - This performs strict semantic analysis of the content of a ppnumber,...
Wraps an ObjCPointerType with source location information.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
ParenExpr - This represents a parenthesized expression, e.g.
SourceLocation getRParenLoc() const
SourceLocation getLParenLoc() const
TypeLoc getInnerLoc() const
TypeLoc getPointeeLoc() const
Wrapper for source info for pointers.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue=nullptr)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)
Recursively visit a C++ nested-name-specifier with location information.
bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier=true)
Recursively visit a type with location, by dispatching to Traverse*TypeLoc() based on the argument ty...
bool TraverseDecl(Decl *D)
Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...
bool WalkUpFromStmt(Stmt *S)
bool shouldTraversePostOrder() const
Return whether this visitor should traverse post-order.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Represents a C++11 static_assert declaration.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
StringLiteral - This represents a string literal expression, e.g.
SwitchStmt - This represents a 'switch' stmt.
Represents the declaration of a struct/union/class/enum.
SourceLocation getNameLoc() const
The base class of all kinds of template declarations (e.g., class, function, etc.).
Stores a list of template parameters for a TemplateDecl and its derived classes.
The top declaration context.
Represents the declaration of a typedef-name via a C++11 alias-declaration.
RetTy Visit(TypeLoc TyLoc)
RetTy VisitTypeLoc(TypeLoc TyLoc)
Base wrapper for a particular "section" of type source info.
NestedNameSpecifierLoc getPrefix() const
If this type represents a qualified-id, this returns it's nested name specifier.
T castAs() const
Convert to the specified TypeLoc type, asserting that this TypeLoc is of the desired type.
SourceRange getLocalSourceRange() const
Get the local source range.
TypeLocClass getTypeLocClass() const
SourceLocation getEndLoc() const
Get the end source location.
Base class for declarations which introduce a typedef-name.
Wrapper for source info for typedefs.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Wrapper for source info for unresolved typename using decls.
Represents a dependent using declaration which was marked with typename.
Represents a dependent using declaration which was not marked with typename.
A call to a literal operator (C++11 [over.literal]) written as a user-defined literal (C++11 [lit....
@ LOK_String
operator "" X (const CharT *, size_t)
@ LOK_Raw
Raw form: operator "" X (const char *)
@ LOK_Floating
operator "" X (long double)
@ LOK_Integer
operator "" X (unsigned long long)
@ LOK_Template
Raw form: operator "" X<cs...> ()
@ LOK_Character
operator "" X (CharT)
Represents a C++ using-declaration.
Represents C++ using-directive.
Wrapper for source info for types used via transparent aliases.
WhileStmt - This represents a 'while' stmt.
A memory arena for syntax trees.
llvm::BumpPtrAllocator & getAllocator()
Array size specified inside a declarator.
Models arguments of a function call.
{ statement1; statement2; … }
A declaration that can appear at the top-level.
A semicolon in the top-level context. Does not declare anything.
The no-op statement, i.e. ';'.
template <declaration> Examples: template struct X<int> template void foo<int>() template int var<dou...
Expression in a statement position, e.g.
for (<init>; <cond>; <increment>) <body>
if (cond) <then-statement> else <else-statement> FIXME: add condition that models 'expression or vari...
A leaf node points to a single token.
extern <string-literal> declaration extern <string-literal> { <decls> }
A list of Elements separated or terminated by a fixed token.
Member pointer inside a declarator E.g.
namespace <name> = <namespace-reference>
namespace <name> { <decls> }
Models a nested-name-specifier.
Models a parameter-declaration-list which appears within parameters-and-qualifiers.
Parameter list for a function type and a trailing return type, if the function has one.
Declarator inside parentheses.
for (<decl> : <init>) <body>
Groups multiple declarators (e.g.
A top-level declarator without parentheses.
static_assert(<condition>, <message>) static_assert(<condition>)
template <template-parameters> <declaration>
A TokenBuffer-powered token manager.
const TokenBuffer & tokenBuffer() const
SourceManager & sourceManager()
A list of tokens obtained by preprocessing a text buffer and operations to map between the expanded a...
llvm::ArrayRef< syntax::Token > expandedTokens() const
All tokens produced by the preprocessor after all macro replacements, directives, etc.
std::optional< llvm::ArrayRef< syntax::Token > > spelledForExpanded(llvm::ArrayRef< syntax::Token > Expanded) const
Returns the subrange of spelled tokens corresponding to AST node spanning Expanded.
uintptr_t Key
A key to identify a specific token.
A token coming directly from a file or from a macro invocation.
tok::TokenKind kind() const
Trailing return type after the parameter list, including the arrow token.
A node that has children and represents a syntactic language construct.
Declaration of an unknown kind, e.g. not yet supported in syntax trees.
An expression of an unknown kind, i.e.
A statement of an unknown kind, i.e.
Models an unqualified-id.
using <scope>::<name> using typename <scope>::<name>
A helper class for constructing the syntax tree while traversing a clang AST.
ArrayRef< syntax::Token > getRange(SourceLocation First, SourceLocation Last) const
Finds the syntax tokens corresponding to the passed source locations.
ArrayRef< syntax::Token > getStmtRange(const Stmt *S) const
Find the adjusted range for the statement, consuming the trailing semicolon when needed.
void foldList(ArrayRef< syntax::Token > SuperRange, syntax::List *New, ASTPtr From)
Populate children for New list, assuming it covers tokens from a subrange of SuperRange.
void markExprChild(Expr *Child, NodeRole Role)
Should be called for expressions in non-statement position to avoid wrapping into expression statemen...
const SourceManager & sourceManager() const
void markChildToken(SourceLocation Loc, NodeRole R)
Set role for a token starting at Loc.
ArrayRef< syntax::Token > getDeclarationRange(Decl *D)
void markChild(syntax::Node *N, NodeRole R)
Set role for N.
void foldNode(ArrayRef< syntax::Token > Range, syntax::Tree *New, TypeLoc L)
const syntax::Token * findToken(SourceLocation L) const
Finds a token starting at L. The token must exist if L is valid.
void noticeDeclWithoutSemicolon(Decl *D)
Notifies that we should not consume trailing semicolon when computing token range of D.
ArrayRef< syntax::Token > getRange(SourceRange Range) const
Finds the syntax tokens corresponding to the SourceRange.
bool isResponsibleForCreatingDeclaration(const Decl *D) const
Returns true if D is the last declarator in a chain and is thus reponsible for creating SimpleDeclara...
syntax::TranslationUnit * finalize() &&
Finish building the tree and consume the root node.
void foldNode(ArrayRef< syntax::Token > Range, syntax::Tree *New, ASTPtr From)
Populate children for New node, assuming it covers tokens from Range.
TreeBuilder(syntax::Arena &Arena, TokenBufferTokenManager &TBTM)
ArrayRef< syntax::Token > getTemplateRange(const ClassTemplateSpecializationDecl *D) const
void foldNode(llvm::ArrayRef< syntax::Token > Range, syntax::Tree *New, NestedNameSpecifierLoc From)
ArrayRef< syntax::Token > getExprRange(const Expr *E) const
void markStmtChild(Stmt *Child, NodeRole Role)
Mark the Child node with a corresponding Role.
llvm::BumpPtrAllocator & allocator()
uint32_t Literal
Literals are represented as positive integers.
NodeRole
A relation between a parent and child node, e.g.
@ ListElement
List API roles.
@ Detached
A node without a parent.
@ Unknown
Children of an unknown semantic nature, e.g. skipped tokens, comments.
syntax::TranslationUnit * buildSyntaxTree(Arena &A, TokenBufferTokenManager &TBTM, ASTContext &Context)
Build a syntax tree for the main file.
NodeKind
A kind of a syntax node, used for implementing casts.
The JSON file list parser is used to communicate input to InstallAPI.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
Expr * IgnoreExprNodes(Expr *E, FnTys &&... Fns)
Given an expression E and functions Fn_1,...,Fn_n : Expr * -> Expr *, Recursively apply each of the f...
@ Result
The result type of a method or function.
Expr * IgnoreImplicitSingleStep(Expr *E)
const FunctionProtoType * T
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
NestedNameSpecifierLoc Prefix