[Flang] remove whole-archive option for AIX linker (#76039)
[llvm-project.git] / clang / lib / Tooling / DumpTool / generate_cxx_src_locs.py
blob7671f9691c09610a3cb1c046e13315bbc4a1db52
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
4 import os
5 import sys
6 import json
7 import filecmp
8 import shutil
9 import argparse
12 class Generator(object):
14 implementationContent = ""
16 RefClades = {
17 "DeclarationNameInfo",
18 "NestedNameSpecifierLoc",
19 "TemplateArgumentLoc",
20 "TypeLoc",
23 def __init__(self, templateClasses):
24 self.templateClasses = templateClasses
26 def GeneratePrologue(self):
28 self.implementationContent += r"""
29 /*===- Generated file -------------------------------------------*- C++ -*-===*\
30 |* *|
31 |* Introspection of available AST node SourceLocations *|
32 |* *|
33 |* Automatically generated file, do not edit! *|
34 |* *|
35 \*===----------------------------------------------------------------------===*/
37 namespace clang {
38 namespace tooling {
40 using LocationAndString = SourceLocationMap::value_type;
41 using RangeAndString = SourceRangeMap::value_type;
43 bool NodeIntrospection::hasIntrospectionSupport() { return true; }
45 struct RecursionPopper
47 RecursionPopper(std::vector<clang::TypeLoc> &TypeLocRecursionGuard)
48 : TLRG(TypeLocRecursionGuard)
53 ~RecursionPopper()
55 TLRG.pop_back();
58 private:
59 std::vector<clang::TypeLoc> &TLRG;
61 """
63 def GenerateBaseGetLocationsDeclaration(self, CladeName):
64 InstanceDecoration = "*"
65 if CladeName in self.RefClades:
66 InstanceDecoration = "&"
68 self.implementationContent += """
69 void GetLocationsImpl(SharedLocationCall const& Prefix,
70 clang::{0} const {1}Object, SourceLocationMap &Locs,
71 SourceRangeMap &Rngs,
72 std::vector<clang::TypeLoc> &TypeLocRecursionGuard);
73 """.format(
74 CladeName, InstanceDecoration
77 def GenerateSrcLocMethod(self, ClassName, ClassData, CreateLocalRecursionGuard):
79 NormalClassName = ClassName
80 RecursionGuardParam = (
82 if CreateLocalRecursionGuard
83 else ", std::vector<clang::TypeLoc>& TypeLocRecursionGuard"
86 if "templateParms" in ClassData:
87 TemplatePreamble = "template <typename "
88 ClassName += "<"
89 First = True
90 for TA in ClassData["templateParms"]:
91 if not First:
92 ClassName += ", "
93 TemplatePreamble += ", typename "
95 First = False
96 ClassName += TA
97 TemplatePreamble += TA
99 ClassName += ">"
100 TemplatePreamble += ">\n"
101 self.implementationContent += TemplatePreamble
103 self.implementationContent += """
104 static void GetLocations{0}(SharedLocationCall const& Prefix,
105 clang::{1} const &Object,
106 SourceLocationMap &Locs, SourceRangeMap &Rngs {2})
108 """.format(
109 NormalClassName, ClassName, RecursionGuardParam
112 if "sourceLocations" in ClassData:
113 for locName in ClassData["sourceLocations"]:
114 self.implementationContent += """
115 Locs.insert(LocationAndString(Object.{0}(),
116 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
117 """.format(
118 locName
121 self.implementationContent += "\n"
123 if "sourceRanges" in ClassData:
124 for rngName in ClassData["sourceRanges"]:
125 self.implementationContent += """
126 Rngs.insert(RangeAndString(Object.{0}(),
127 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}")));
128 """.format(
129 rngName
132 self.implementationContent += "\n"
134 if (
135 "typeLocs" in ClassData
136 or "typeSourceInfos" in ClassData
137 or "nestedNameLocs" in ClassData
138 or "declNameInfos" in ClassData
140 if CreateLocalRecursionGuard:
141 self.implementationContent += (
142 "std::vector<clang::TypeLoc> TypeLocRecursionGuard;\n"
145 self.implementationContent += "\n"
147 if "typeLocs" in ClassData:
148 for typeLoc in ClassData["typeLocs"]:
150 self.implementationContent += """
151 if (Object.{0}()) {{
152 GetLocationsImpl(
153 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
154 Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
156 """.format(
157 typeLoc
160 self.implementationContent += "\n"
161 if "typeSourceInfos" in ClassData:
162 for tsi in ClassData["typeSourceInfos"]:
163 self.implementationContent += """
164 if (Object.{0}()) {{
165 GetLocationsImpl(llvm::makeIntrusiveRefCnt<LocationCall>(
166 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}",
167 LocationCall::ReturnsPointer), "getTypeLoc"),
168 Object.{0}()->getTypeLoc(), Locs, Rngs, TypeLocRecursionGuard);
170 """.format(
174 self.implementationContent += "\n"
176 if "nestedNameLocs" in ClassData:
177 for NN in ClassData["nestedNameLocs"]:
178 self.implementationContent += """
179 if (Object.{0}())
180 GetLocationsImpl(
181 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
182 Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
183 """.format(
187 if "declNameInfos" in ClassData:
188 for declName in ClassData["declNameInfos"]:
190 self.implementationContent += """
191 GetLocationsImpl(
192 llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "{0}"),
193 Object.{0}(), Locs, Rngs, TypeLocRecursionGuard);
194 """.format(
195 declName
198 self.implementationContent += "}\n"
200 def GenerateFiles(self, OutputFile):
201 with open(os.path.join(os.getcwd(), OutputFile), "w") as f:
202 f.write(self.implementationContent)
204 def GenerateBaseGetLocationsFunction(
205 self,
206 ASTClassNames,
207 ClassEntries,
208 CladeName,
209 InheritanceMap,
210 CreateLocalRecursionGuard,
213 MethodReturnType = "NodeLocationAccessors"
214 InstanceDecoration = "*"
215 if CladeName in self.RefClades:
216 InstanceDecoration = "&"
218 Signature = "GetLocations(clang::{0} const {1}Object)".format(
219 CladeName, InstanceDecoration
221 ImplSignature = """
222 GetLocationsImpl(SharedLocationCall const& Prefix,
223 clang::{0} const {1}Object, SourceLocationMap &Locs,
224 SourceRangeMap &Rngs,
225 std::vector<clang::TypeLoc> &TypeLocRecursionGuard)
226 """.format(
227 CladeName, InstanceDecoration
230 self.implementationContent += "void {0} {{ ".format(ImplSignature)
232 if CladeName == "TypeLoc":
233 self.implementationContent += "if (Object.isNull()) return;"
235 self.implementationContent += """
236 if (llvm::find(TypeLocRecursionGuard, Object) != TypeLocRecursionGuard.end())
237 return;
238 TypeLocRecursionGuard.push_back(Object);
239 RecursionPopper RAII(TypeLocRecursionGuard);
242 RecursionGuardParam = ""
243 if not CreateLocalRecursionGuard:
244 RecursionGuardParam = ", TypeLocRecursionGuard"
246 ArgPrefix = "*"
247 if CladeName in self.RefClades:
248 ArgPrefix = ""
249 self.implementationContent += (
250 "GetLocations{0}(Prefix, {1}Object, Locs, Rngs {2});".format(
251 CladeName, ArgPrefix, RecursionGuardParam
255 if CladeName == "TypeLoc":
256 self.implementationContent += """
257 if (auto QTL = Object.getAs<clang::QualifiedTypeLoc>()) {
258 auto Dequalified = QTL.getNextTypeLoc();
259 return GetLocationsImpl(llvm::makeIntrusiveRefCnt<LocationCall>(Prefix, "getNextTypeLoc"),
260 Dequalified,
261 Locs,
262 Rngs,
263 TypeLocRecursionGuard);
264 }"""
266 for ASTClassName in ASTClassNames:
267 if ASTClassName in self.templateClasses:
268 continue
269 if ASTClassName == CladeName:
270 continue
271 if CladeName != "TypeLoc":
272 self.implementationContent += """
273 if (auto Derived = llvm::dyn_cast<clang::{0}>(Object)) {{
274 GetLocations{0}(Prefix, *Derived, Locs, Rngs {1});
276 """.format(
277 ASTClassName, RecursionGuardParam
279 continue
281 self.GenerateBaseTypeLocVisit(
282 ASTClassName, ClassEntries, RecursionGuardParam, InheritanceMap
285 self.implementationContent += "}"
287 self.implementationContent += """
288 {0} NodeIntrospection::{1} {{
289 NodeLocationAccessors Result;
290 SharedLocationCall Prefix;
291 std::vector<clang::TypeLoc> TypeLocRecursionGuard;
293 GetLocationsImpl(Prefix, Object, Result.LocationAccessors,
294 Result.RangeAccessors, TypeLocRecursionGuard);
295 """.format(
296 MethodReturnType, Signature
299 self.implementationContent += "return Result; }"
301 def GenerateBaseTypeLocVisit(
302 self, ASTClassName, ClassEntries, RecursionGuardParam, InheritanceMap
304 CallPrefix = "Prefix"
305 if ASTClassName != "TypeLoc":
306 CallPrefix = """llvm::makeIntrusiveRefCnt<LocationCall>(Prefix,
307 "getAs<clang::{0}>", LocationCall::IsCast)
308 """.format(
309 ASTClassName
312 if ASTClassName in ClassEntries:
314 self.implementationContent += """
315 if (auto ConcreteTL = Object.getAs<clang::{0}>())
316 GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3});
317 """.format(
318 ASTClassName, ASTClassName, CallPrefix, RecursionGuardParam
321 if ASTClassName in InheritanceMap:
322 for baseTemplate in self.templateClasses:
323 if baseTemplate in InheritanceMap[ASTClassName]:
324 self.implementationContent += """
325 if (auto ConcreteTL = Object.getAs<clang::{0}>())
326 GetLocations{1}({2}, ConcreteTL, Locs, Rngs {3});
327 """.format(
328 InheritanceMap[ASTClassName],
329 baseTemplate,
330 CallPrefix,
331 RecursionGuardParam,
334 def GenerateDynNodeVisitor(self, CladeNames):
335 MethodReturnType = "NodeLocationAccessors"
337 Signature = "GetLocations(clang::DynTypedNode const &Node)"
339 self.implementationContent += (
340 MethodReturnType + " NodeIntrospection::" + Signature + "{"
343 for CladeName in CladeNames:
344 if CladeName == "DeclarationNameInfo":
345 continue
346 self.implementationContent += """
347 if (const auto *N = Node.get<{0}>())
348 """.format(
349 CladeName
351 ArgPrefix = ""
352 if CladeName in self.RefClades:
353 ArgPrefix = "*"
354 self.implementationContent += """
355 return GetLocations({0}const_cast<{1} *>(N));""".format(
356 ArgPrefix, CladeName
359 self.implementationContent += "\nreturn {}; }"
361 def GenerateEpilogue(self):
363 self.implementationContent += """
369 def main():
371 parser = argparse.ArgumentParser()
372 parser.add_argument(
373 "--json-input-path", help="Read API description from FILE", metavar="FILE"
375 parser.add_argument(
376 "--output-file", help="Generate output in FILEPATH", metavar="FILEPATH"
378 parser.add_argument(
379 "--use-empty-implementation",
380 help="Generate empty implementation",
381 action="store",
382 type=int,
384 parser.add_argument(
385 "--empty-implementation",
386 help="Copy empty implementation from FILEPATH",
387 action="store",
388 metavar="FILEPATH",
391 options = parser.parse_args()
393 use_empty_implementation = options.use_empty_implementation
395 if not use_empty_implementation and not os.path.exists(options.json_input_path):
396 use_empty_implementation = True
398 if not use_empty_implementation:
399 with open(options.json_input_path) as f:
400 jsonData = json.load(f)
402 if not "classesInClade" in jsonData or not jsonData["classesInClade"]:
403 use_empty_implementation = True
405 if use_empty_implementation:
406 if not os.path.exists(options.output_file) or not filecmp.cmp(
407 options.empty_implementation, options.output_file
409 shutil.copyfile(options.empty_implementation, options.output_file)
410 sys.exit(0)
412 templateClasses = []
413 for (ClassName, ClassAccessors) in jsonData["classEntries"].items():
414 if "templateParms" in ClassAccessors:
415 templateClasses.append(ClassName)
417 g = Generator(templateClasses)
419 g.GeneratePrologue()
421 for (CladeName, ClassNameData) in jsonData["classesInClade"].items():
422 g.GenerateBaseGetLocationsDeclaration(CladeName)
424 def getCladeName(ClassName):
425 for (CladeName, ClassNameData) in jsonData["classesInClade"].items():
426 if ClassName in ClassNameData:
427 return CladeName
429 for (ClassName, ClassAccessors) in jsonData["classEntries"].items():
430 cladeName = getCladeName(ClassName)
431 g.GenerateSrcLocMethod(
432 ClassName, ClassAccessors, cladeName not in Generator.RefClades
435 for (CladeName, ClassNameData) in jsonData["classesInClade"].items():
436 g.GenerateBaseGetLocationsFunction(
437 ClassNameData,
438 jsonData["classEntries"],
439 CladeName,
440 jsonData["classInheritance"],
441 CladeName not in Generator.RefClades,
444 g.GenerateDynNodeVisitor(jsonData["classesInClade"].keys())
446 g.GenerateEpilogue()
448 g.GenerateFiles(options.output_file)
451 if __name__ == "__main__":
452 main()