Instantiator
Generate c++ template instantiations
Loading...
Searching...
No Matches
DeleteInstantiations.cpp
Go to the documentation of this file.
2
3#include <iostream>
4
5#include "spdlog/spdlog.h"
6
7#include "clang/AST/Decl.h"
8#include "clang/AST/DeclCXX.h"
9#include "clang/AST/DeclTemplate.h"
10#include "clang/Basic/SourceLocation.h"
11#include "clang/Basic/TokenKinds.h"
12#include "clang/Lex/Lexer.h"
13#include "clang/Rewrite/Core/Rewriter.h"
14
15auto findSemiAfterLocation(clang::SourceLocation loc, clang::ASTContext& Ctx, bool IsDecl = false)
16{
17 clang::SourceManager& SM = Ctx.getSourceManager();
18 // if(loc.isMacroID()) {
19 // if(!clang::Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc)) return clang::SourceLocation();
20 // }
21 loc = clang::Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts());
22
23 // Break down the source location.
24 std::pair<clang::FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
25
26 // Try to load the file buffer.
27 bool invalidTemp = false;
28 clang::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
29 if(invalidTemp) {
30 std::cout << "invalidtemp" << std::endl;
31 return std::make_pair(false, clang::SourceLocation());
32 }
33
34 const char* tokenBegin = file.data() + locInfo.second;
35
36 // Lex from the start of the given location.
37 clang::Lexer lexer(SM.getLocForStartOfFile(locInfo.first), Ctx.getLangOpts(), file.begin(), tokenBegin, file.end());
38 clang::Token tok;
39 lexer.LexFromRawLexer(tok);
40 if(tok.isNot(clang::tok::semi)) {
41 if(!IsDecl) { return std::make_pair(false, tok.getLocation()); }
42 // Declaration may be followed with other tokens; such as an __attribute,
43 // before ending with a semicolon.
44 return findSemiAfterLocation(tok.getLocation(), Ctx, /*IsDecl*/ true);
45 }
46
47 return std::make_pair(true, tok.getLocation());
48}
49
50auto getEndLoc(clang::SourceLocation begin, clang::ASTContext& Ctx)
51{
52 auto end = begin;
53 bool foundSemi = false;
54 while(not foundSemi) {
55 auto [x, y] = findSemiAfterLocation(end, Ctx);
56 foundSemi = x;
57 end = y;
58 }
59 return end;
60}
61
62auto getBeginLoc(clang::SourceLocation begin, clang::ASTContext& Ctx)
63{
64 clang::SourceManager& sm = Ctx.getSourceManager();
65 auto line = sm.getSpellingLineNumber(begin);
66 auto col = sm.getSpellingColumnNumber(begin);
67 auto previous_loc = begin;
68 auto previous2_loc = begin;
69 auto previous3_loc = begin;
70 clang::Token tok;
71 while(tok.isNot(clang::tok::semi) and tok.isNot(clang::tok::r_brace)) {
72 auto curr_loc = sm.translateLineCol(sm.getMainFileID(), line, col);
73 auto beginCurrToken = clang::Lexer::GetBeginningOfToken(curr_loc, sm, Ctx.getLangOpts());
74 line = sm.getSpellingLineNumber(beginCurrToken);
75 col = sm.getSpellingColumnNumber(beginCurrToken);
76 [[maybe_unused]] auto res = clang::Lexer::getRawToken(beginCurrToken, tok, sm, Ctx.getLangOpts());
77 assert(col >= 1 and "Invalid column in getBeginLoc()");
78 if(col > 1) {
79 col = col - 1;
80 } else if(col == 1) {
81 line = line - 1;
82 auto [fid, b_offset] = sm.getDecomposedSpellingLoc(curr_loc);
83 auto offsetEndOfNextLine = b_offset - 1;
84 col = sm.getColumnNumber(fid, offsetEndOfNextLine);
85 }
86 previous3_loc = previous2_loc;
87 previous2_loc = previous_loc;
88 previous_loc = beginCurrToken;
89 }
90 return previous3_loc;
91}
92
93void DeleteInstantiations::run(const clang::ast_matchers::MatchFinder::MatchResult& Result)
94{
95 clang::PrintingPolicy pp(Result.Context->getLangOpts());
96 pp.PrintInjectedClassNameWithArguments = true;
97 pp.PrintCanonicalTypes = true;
98 pp.SuppressDefaultTemplateArgs = true;
99 pp.FullyQualifiedName = true;
100 pp.SuppressScope = false;
101
102 clang::Rewriter::RewriteOptions opts;
103 opts.IncludeInsertsAtBeginOfRange = true;
104 opts.IncludeInsertsAtEndOfRange = true;
105 opts.RemoveLineIfEmpty = false;
106
107 clang::SourceManager& sm = Result.Context->getSourceManager();
108
109 if(const clang::CXXMethodDecl* MFS = Result.Nodes.getNodeAs<clang::CXXMethodDecl>("explicit_instantiation")) {
110 if(const clang::MemberSpecializationInfo* MSI = MFS->getMemberSpecializationInfo()) {
111 auto template_kind = MSI->getTemplateSpecializationKind();
112 if(template_kind == clang::TSK_ExplicitInstantiationDefinition) {
113 auto loc = MSI->getPointOfInstantiation();
114 if(loc.isValid()) {
115 spdlog::debug("Delete {} at: {} ({})", MFS->getNameAsString(), loc.printToString(sm), sm.getSpellingLineNumber(loc));
116 auto begin_loc = getBeginLoc(loc, *Result.Context);
117 auto end_loc = getEndLoc(begin_loc, *Result.Context);
118 rewriter->RemoveText(clang::SourceRange(begin_loc, end_loc), opts);
119 }
120 }
121 } else if(const clang::FunctionTemplateSpecializationInfo* TSI = MFS->getTemplateSpecializationInfo()) {
122 if(TSI->getTemplateSpecializationKind() == clang::TSK_ExplicitInstantiationDefinition) {
123 auto loc = TSI->getPointOfInstantiation();
124 if(loc.isValid()) {
125 spdlog::debug("Delete {} at: {} ({})", MFS->getNameAsString(), loc.printToString(sm), sm.getSpellingLineNumber(loc));
126 auto begin_loc = getBeginLoc(loc, *Result.Context);
127 auto end_loc = getEndLoc(begin_loc, *Result.Context);
128 rewriter->RemoveText(clang::SourceRange(begin_loc, end_loc), opts);
129 }
130 }
131 }
132 } else if(const clang::FunctionDecl* FS = Result.Nodes.getNodeAs<clang::FunctionDecl>("explicit_instantiation")) {
133 if(const clang::FunctionTemplateSpecializationInfo* TSI = FS->getTemplateSpecializationInfo()) {
134 if(TSI->getTemplateSpecializationKind() == clang::TSK_ExplicitInstantiationDefinition) {
135 auto loc = TSI->getPointOfInstantiation();
136 if(loc.isValid()) {
137 spdlog::debug("Delete {} at: {} ({})", FS->getNameAsString(), loc.printToString(sm), sm.getSpellingLineNumber(loc));
138 auto begin_loc = getBeginLoc(loc, *Result.Context);
139 auto end_loc = getEndLoc(begin_loc, *Result.Context);
140 rewriter->RemoveText(clang::SourceRange(begin_loc, end_loc), opts);
141 }
142 }
143 }
144 }
145}
auto getBeginLoc(clang::SourceLocation begin, clang::ASTContext &Ctx)
auto getEndLoc(clang::SourceLocation begin, clang::ASTContext &Ctx)
auto findSemiAfterLocation(clang::SourceLocation loc, clang::ASTContext &Ctx, bool IsDecl=false)
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult &Result) override