ConstantInitBuilder.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- ConstantInitBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This class provides a convenient interface for building complex
  15. // global initializers of the sort that are frequently required for
  16. // language ABIs.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
  20. #define LLVM_CLANG_CODEGEN_CONSTANTINITBUILDER_H
  21. #include "llvm/ADT/ArrayRef.h"
  22. #include "llvm/ADT/SmallVector.h"
  23. #include "llvm/IR/Constants.h"
  24. #include "llvm/IR/GlobalValue.h"
  25. #include "clang/AST/CharUnits.h"
  26. #include "clang/CodeGen/ConstantInitFuture.h"
  27. #include <vector>
  28. namespace clang {
  29. namespace CodeGen {
  30. class CodeGenModule;
  31. /// A convenience builder class for complex constant initializers,
  32. /// especially for anonymous global structures used by various language
  33. /// runtimes.
  34. ///
  35. /// The basic usage pattern is expected to be something like:
  36. /// ConstantInitBuilder builder(CGM);
  37. /// auto toplevel = builder.beginStruct();
  38. /// toplevel.addInt(CGM.SizeTy, widgets.size());
  39. /// auto widgetArray = builder.beginArray();
  40. /// for (auto &widget : widgets) {
  41. /// auto widgetDesc = widgetArray.beginStruct();
  42. /// widgetDesc.addInt(CGM.SizeTy, widget.getPower());
  43. /// widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName()));
  44. /// widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl()));
  45. /// widgetDesc.finishAndAddTo(widgetArray);
  46. /// }
  47. /// widgetArray.finishAndAddTo(toplevel);
  48. /// auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align,
  49. /// /*constant*/ true);
  50. class ConstantInitBuilderBase {
  51. struct SelfReference {
  52. llvm::GlobalVariable *Dummy;
  53. llvm::SmallVector<llvm::Constant*, 4> Indices;
  54. SelfReference(llvm::GlobalVariable *dummy) : Dummy(dummy) {}
  55. };
  56. CodeGenModule &CGM;
  57. llvm::SmallVector<llvm::Constant*, 16> Buffer;
  58. std::vector<SelfReference> SelfReferences;
  59. bool Frozen = false;
  60. friend class ConstantInitFuture;
  61. friend class ConstantAggregateBuilderBase;
  62. template <class, class>
  63. friend class ConstantAggregateBuilderTemplateBase;
  64. protected:
  65. explicit ConstantInitBuilderBase(CodeGenModule &CGM) : CGM(CGM) {}
  66. ~ConstantInitBuilderBase() {
  67. assert(Buffer.empty() && "didn't claim all values out of buffer");
  68. assert(SelfReferences.empty() && "didn't apply all self-references");
  69. }
  70. private:
  71. llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
  72. const llvm::Twine &name,
  73. CharUnits alignment,
  74. bool constant = false,
  75. llvm::GlobalValue::LinkageTypes linkage
  76. = llvm::GlobalValue::InternalLinkage,
  77. unsigned addressSpace = 0);
  78. ConstantInitFuture createFuture(llvm::Constant *initializer);
  79. void setGlobalInitializer(llvm::GlobalVariable *GV,
  80. llvm::Constant *initializer);
  81. void resolveSelfReferences(llvm::GlobalVariable *GV);
  82. void abandon(size_t newEnd);
  83. };
  84. /// A concrete base class for struct and array aggregate
  85. /// initializer builders.
  86. class ConstantAggregateBuilderBase {
  87. protected:
  88. ConstantInitBuilderBase &Builder;
  89. ConstantAggregateBuilderBase *Parent;
  90. size_t Begin;
  91. mutable size_t CachedOffsetEnd = 0;
  92. bool Finished = false;
  93. bool Frozen = false;
  94. bool Packed = false;
  95. mutable CharUnits CachedOffsetFromGlobal;
  96. llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() {
  97. return Builder.Buffer;
  98. }
  99. const llvm::SmallVectorImpl<llvm::Constant*> &getBuffer() const {
  100. return Builder.Buffer;
  101. }
  102. ConstantAggregateBuilderBase(ConstantInitBuilderBase &builder,
  103. ConstantAggregateBuilderBase *parent)
  104. : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
  105. if (parent) {
  106. assert(!parent->Frozen && "parent already has child builder active");
  107. parent->Frozen = true;
  108. } else {
  109. assert(!builder.Frozen && "builder already has child builder active");
  110. builder.Frozen = true;
  111. }
  112. }
  113. ~ConstantAggregateBuilderBase() {
  114. assert(Finished && "didn't finish aggregate builder");
  115. }
  116. void markFinished() {
  117. assert(!Frozen && "child builder still active");
  118. assert(!Finished && "builder already finished");
  119. Finished = true;
  120. if (Parent) {
  121. assert(Parent->Frozen &&
  122. "parent not frozen while child builder active");
  123. Parent->Frozen = false;
  124. } else {
  125. assert(Builder.Frozen &&
  126. "builder not frozen while child builder active");
  127. Builder.Frozen = false;
  128. }
  129. }
  130. public:
  131. // Not copyable.
  132. ConstantAggregateBuilderBase(const ConstantAggregateBuilderBase &) = delete;
  133. ConstantAggregateBuilderBase &operator=(const ConstantAggregateBuilderBase &)
  134. = delete;
  135. // Movable, mostly to allow returning. But we have to write this out
  136. // properly to satisfy the assert in the destructor.
  137. ConstantAggregateBuilderBase(ConstantAggregateBuilderBase &&other)
  138. : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin),
  139. CachedOffsetEnd(other.CachedOffsetEnd),
  140. Finished(other.Finished), Frozen(other.Frozen), Packed(other.Packed),
  141. CachedOffsetFromGlobal(other.CachedOffsetFromGlobal) {
  142. other.Finished = true;
  143. }
  144. ConstantAggregateBuilderBase &operator=(ConstantAggregateBuilderBase &&other)
  145. = delete;
  146. /// Return the number of elements that have been added to
  147. /// this struct or array.
  148. size_t size() const {
  149. assert(!this->Finished && "cannot query after finishing builder");
  150. assert(!this->Frozen && "cannot query while sub-builder is active");
  151. assert(this->Begin <= this->getBuffer().size());
  152. return this->getBuffer().size() - this->Begin;
  153. }
  154. /// Return true if no elements have yet been added to this struct or array.
  155. bool empty() const {
  156. return size() == 0;
  157. }
  158. /// Abandon this builder completely.
  159. void abandon() {
  160. markFinished();
  161. Builder.abandon(Begin);
  162. }
  163. /// Add a new value to this initializer.
  164. void add(llvm::Constant *value) {
  165. assert(value && "adding null value to constant initializer");
  166. assert(!Finished && "cannot add more values after finishing builder");
  167. assert(!Frozen && "cannot add values while subbuilder is active");
  168. Builder.Buffer.push_back(value);
  169. }
  170. /// Add an integer value of type size_t.
  171. void addSize(CharUnits size);
  172. /// Add an integer value of a specific type.
  173. void addInt(llvm::IntegerType *intTy, uint64_t value,
  174. bool isSigned = false) {
  175. add(llvm::ConstantInt::get(intTy, value, isSigned));
  176. }
  177. /// Add a null pointer of a specific type.
  178. void addNullPointer(llvm::PointerType *ptrTy) {
  179. add(llvm::ConstantPointerNull::get(ptrTy));
  180. }
  181. /// Add a bitcast of a value to a specific type.
  182. void addBitCast(llvm::Constant *value, llvm::Type *type) {
  183. add(llvm::ConstantExpr::getBitCast(value, type));
  184. }
  185. /// Add a bunch of new values to this initializer.
  186. void addAll(llvm::ArrayRef<llvm::Constant *> values) {
  187. assert(!Finished && "cannot add more values after finishing builder");
  188. assert(!Frozen && "cannot add values while subbuilder is active");
  189. Builder.Buffer.append(values.begin(), values.end());
  190. }
  191. /// Add a relative offset to the given target address, i.e. the
  192. /// static difference between the target address and the address
  193. /// of the relative offset. The target must be known to be defined
  194. /// in the current linkage unit. The offset will have the given
  195. /// integer type, which must be no wider than intptr_t. Some
  196. /// targets may not fully support this operation.
  197. void addRelativeOffset(llvm::IntegerType *type, llvm::Constant *target) {
  198. add(getRelativeOffset(type, target));
  199. }
  200. /// Same as addRelativeOffset(), but instead relative to an element in this
  201. /// aggregate, identified by its index.
  202. void addRelativeOffsetToPosition(llvm::IntegerType *type,
  203. llvm::Constant *target, size_t position) {
  204. add(getRelativeOffsetToPosition(type, target, position));
  205. }
  206. /// Add a relative offset to the target address, plus a small
  207. /// constant offset. This is primarily useful when the relative
  208. /// offset is known to be a multiple of (say) four and therefore
  209. /// the tag can be used to express an extra two bits of information.
  210. void addTaggedRelativeOffset(llvm::IntegerType *type,
  211. llvm::Constant *address,
  212. unsigned tag) {
  213. llvm::Constant *offset = getRelativeOffset(type, address);
  214. if (tag) {
  215. offset = llvm::ConstantExpr::getAdd(offset,
  216. llvm::ConstantInt::get(type, tag));
  217. }
  218. add(offset);
  219. }
  220. /// Return the offset from the start of the initializer to the
  221. /// next position, assuming no padding is required prior to it.
  222. ///
  223. /// This operation will not succeed if any unsized placeholders are
  224. /// currently in place in the initializer.
  225. CharUnits getNextOffsetFromGlobal() const {
  226. assert(!Finished && "cannot add more values after finishing builder");
  227. assert(!Frozen && "cannot add values while subbuilder is active");
  228. return getOffsetFromGlobalTo(Builder.Buffer.size());
  229. }
  230. /// An opaque class to hold the abstract position of a placeholder.
  231. class PlaceholderPosition {
  232. size_t Index;
  233. friend class ConstantAggregateBuilderBase;
  234. PlaceholderPosition(size_t index) : Index(index) {}
  235. };
  236. /// Add a placeholder value to the structure. The returned position
  237. /// can be used to set the value later; it will not be invalidated by
  238. /// any intermediate operations except (1) filling the same position or
  239. /// (2) finishing the entire builder.
  240. ///
  241. /// This is useful for emitting certain kinds of structure which
  242. /// contain some sort of summary field, generally a count, before any
  243. /// of the data. By emitting a placeholder first, the structure can
  244. /// be emitted eagerly.
  245. PlaceholderPosition addPlaceholder() {
  246. assert(!Finished && "cannot add more values after finishing builder");
  247. assert(!Frozen && "cannot add values while subbuilder is active");
  248. Builder.Buffer.push_back(nullptr);
  249. return Builder.Buffer.size() - 1;
  250. }
  251. /// Add a placeholder, giving the expected type that will be filled in.
  252. PlaceholderPosition addPlaceholderWithSize(llvm::Type *expectedType);
  253. /// Fill a previously-added placeholder.
  254. void fillPlaceholderWithInt(PlaceholderPosition position,
  255. llvm::IntegerType *type, uint64_t value,
  256. bool isSigned = false) {
  257. fillPlaceholder(position, llvm::ConstantInt::get(type, value, isSigned));
  258. }
  259. /// Fill a previously-added placeholder.
  260. void fillPlaceholder(PlaceholderPosition position, llvm::Constant *value) {
  261. assert(!Finished && "cannot change values after finishing builder");
  262. assert(!Frozen && "cannot add values while subbuilder is active");
  263. llvm::Constant *&slot = Builder.Buffer[position.Index];
  264. assert(slot == nullptr && "placeholder already filled");
  265. slot = value;
  266. }
  267. /// Produce an address which will eventually point to the next
  268. /// position to be filled. This is computed with an indexed
  269. /// getelementptr rather than by computing offsets.
  270. ///
  271. /// The returned pointer will have type T*, where T is the given type. This
  272. /// type can differ from the type of the actual element.
  273. llvm::Constant *getAddrOfCurrentPosition(llvm::Type *type);
  274. /// Produce an address which points to a position in the aggregate being
  275. /// constructed. This is computed with an indexed getelementptr rather than by
  276. /// computing offsets.
  277. ///
  278. /// The returned pointer will have type T*, where T is the given type. This
  279. /// type can differ from the type of the actual element.
  280. llvm::Constant *getAddrOfPosition(llvm::Type *type, size_t position);
  281. llvm::ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition(
  282. llvm::SmallVectorImpl<llvm::Constant*> &indices) {
  283. getGEPIndicesTo(indices, Builder.Buffer.size());
  284. return indices;
  285. }
  286. protected:
  287. llvm::Constant *finishArray(llvm::Type *eltTy);
  288. llvm::Constant *finishStruct(llvm::StructType *structTy);
  289. private:
  290. void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices,
  291. size_t position) const;
  292. llvm::Constant *getRelativeOffset(llvm::IntegerType *offsetType,
  293. llvm::Constant *target);
  294. llvm::Constant *getRelativeOffsetToPosition(llvm::IntegerType *offsetType,
  295. llvm::Constant *target,
  296. size_t position);
  297. CharUnits getOffsetFromGlobalTo(size_t index) const;
  298. };
  299. template <class Impl, class Traits>
  300. class ConstantAggregateBuilderTemplateBase
  301. : public Traits::AggregateBuilderBase {
  302. using super = typename Traits::AggregateBuilderBase;
  303. public:
  304. using InitBuilder = typename Traits::InitBuilder;
  305. using ArrayBuilder = typename Traits::ArrayBuilder;
  306. using StructBuilder = typename Traits::StructBuilder;
  307. using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
  308. protected:
  309. ConstantAggregateBuilderTemplateBase(InitBuilder &builder,
  310. AggregateBuilderBase *parent)
  311. : super(builder, parent) {}
  312. Impl &asImpl() { return *static_cast<Impl*>(this); }
  313. public:
  314. ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
  315. return ArrayBuilder(static_cast<InitBuilder&>(this->Builder), this, eltTy);
  316. }
  317. StructBuilder beginStruct(llvm::StructType *ty = nullptr) {
  318. return StructBuilder(static_cast<InitBuilder&>(this->Builder), this, ty);
  319. }
  320. /// Given that this builder was created by beginning an array or struct
  321. /// component on the given parent builder, finish the array/struct
  322. /// component and add it to the parent.
  323. ///
  324. /// It is an intentional choice that the parent is passed in explicitly
  325. /// despite it being redundant with information already kept in the
  326. /// builder. This aids in readability by making it easier to find the
  327. /// places that add components to a builder, as well as "bookending"
  328. /// the sub-builder more explicitly.
  329. void finishAndAddTo(AggregateBuilderBase &parent) {
  330. assert(this->Parent == &parent && "adding to non-parent builder");
  331. parent.add(asImpl().finishImpl());
  332. }
  333. /// Given that this builder was created by beginning an array or struct
  334. /// directly on a ConstantInitBuilder, finish the array/struct and
  335. /// create a global variable with it as the initializer.
  336. template <class... As>
  337. llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
  338. assert(!this->Parent && "finishing non-root builder");
  339. return this->Builder.createGlobal(asImpl().finishImpl(),
  340. std::forward<As>(args)...);
  341. }
  342. /// Given that this builder was created by beginning an array or struct
  343. /// directly on a ConstantInitBuilder, finish the array/struct and
  344. /// set it as the initializer of the given global variable.
  345. void finishAndSetAsInitializer(llvm::GlobalVariable *global) {
  346. assert(!this->Parent && "finishing non-root builder");
  347. return this->Builder.setGlobalInitializer(global, asImpl().finishImpl());
  348. }
  349. /// Given that this builder was created by beginning an array or struct
  350. /// directly on a ConstantInitBuilder, finish the array/struct and
  351. /// return a future which can be used to install the initializer in
  352. /// a global later.
  353. ///
  354. /// This is useful for allowing a finished initializer to passed to
  355. /// an API which will build the global. However, the "future" preserves
  356. /// a dependency on the original builder; it is an error to pass it aside.
  357. ConstantInitFuture finishAndCreateFuture() {
  358. assert(!this->Parent && "finishing non-root builder");
  359. return this->Builder.createFuture(asImpl().finishImpl());
  360. }
  361. };
  362. template <class Traits>
  363. class ConstantArrayBuilderTemplateBase
  364. : public ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder,
  365. Traits> {
  366. using super =
  367. ConstantAggregateBuilderTemplateBase<typename Traits::ArrayBuilder, Traits>;
  368. public:
  369. using InitBuilder = typename Traits::InitBuilder;
  370. using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
  371. private:
  372. llvm::Type *EltTy;
  373. template <class, class>
  374. friend class ConstantAggregateBuilderTemplateBase;
  375. protected:
  376. ConstantArrayBuilderTemplateBase(InitBuilder &builder,
  377. AggregateBuilderBase *parent,
  378. llvm::Type *eltTy)
  379. : super(builder, parent), EltTy(eltTy) {}
  380. private:
  381. /// Form an array constant from the values that have been added to this
  382. /// builder.
  383. llvm::Constant *finishImpl() {
  384. return AggregateBuilderBase::finishArray(EltTy);
  385. }
  386. };
  387. /// A template class designed to allow other frontends to
  388. /// easily customize the builder classes used by ConstantInitBuilder,
  389. /// and thus to extend the API to work with the abstractions they
  390. /// prefer. This would probably not be necessary if C++ just
  391. /// supported extension methods.
  392. template <class Traits>
  393. class ConstantStructBuilderTemplateBase
  394. : public ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,
  395. Traits> {
  396. using super =
  397. ConstantAggregateBuilderTemplateBase<typename Traits::StructBuilder,Traits>;
  398. public:
  399. using InitBuilder = typename Traits::InitBuilder;
  400. using AggregateBuilderBase = typename Traits::AggregateBuilderBase;
  401. private:
  402. llvm::StructType *StructTy;
  403. template <class, class>
  404. friend class ConstantAggregateBuilderTemplateBase;
  405. protected:
  406. ConstantStructBuilderTemplateBase(InitBuilder &builder,
  407. AggregateBuilderBase *parent,
  408. llvm::StructType *structTy)
  409. : super(builder, parent), StructTy(structTy) {
  410. if (structTy) this->Packed = structTy->isPacked();
  411. }
  412. public:
  413. void setPacked(bool packed) {
  414. this->Packed = packed;
  415. }
  416. /// Use the given type for the struct if its element count is correct.
  417. /// Don't add more elements after calling this.
  418. void suggestType(llvm::StructType *structTy) {
  419. if (this->size() == structTy->getNumElements()) {
  420. StructTy = structTy;
  421. }
  422. }
  423. private:
  424. /// Form an array constant from the values that have been added to this
  425. /// builder.
  426. llvm::Constant *finishImpl() {
  427. return AggregateBuilderBase::finishStruct(StructTy);
  428. }
  429. };
  430. /// A template class designed to allow other frontends to
  431. /// easily customize the builder classes used by ConstantInitBuilder,
  432. /// and thus to extend the API to work with the abstractions they
  433. /// prefer. This would probably not be necessary if C++ just
  434. /// supported extension methods.
  435. template <class Traits>
  436. class ConstantInitBuilderTemplateBase : public ConstantInitBuilderBase {
  437. protected:
  438. ConstantInitBuilderTemplateBase(CodeGenModule &CGM)
  439. : ConstantInitBuilderBase(CGM) {}
  440. public:
  441. using InitBuilder = typename Traits::InitBuilder;
  442. using ArrayBuilder = typename Traits::ArrayBuilder;
  443. using StructBuilder = typename Traits::StructBuilder;
  444. ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
  445. return ArrayBuilder(static_cast<InitBuilder&>(*this), nullptr, eltTy);
  446. }
  447. StructBuilder beginStruct(llvm::StructType *structTy = nullptr) {
  448. return StructBuilder(static_cast<InitBuilder&>(*this), nullptr, structTy);
  449. }
  450. };
  451. class ConstantInitBuilder;
  452. class ConstantStructBuilder;
  453. class ConstantArrayBuilder;
  454. struct ConstantInitBuilderTraits {
  455. using InitBuilder = ConstantInitBuilder;
  456. using AggregateBuilderBase = ConstantAggregateBuilderBase;
  457. using ArrayBuilder = ConstantArrayBuilder;
  458. using StructBuilder = ConstantStructBuilder;
  459. };
  460. /// The standard implementation of ConstantInitBuilder used in Clang.
  461. class ConstantInitBuilder
  462. : public ConstantInitBuilderTemplateBase<ConstantInitBuilderTraits> {
  463. public:
  464. explicit ConstantInitBuilder(CodeGenModule &CGM) :
  465. ConstantInitBuilderTemplateBase(CGM) {}
  466. };
  467. /// A helper class of ConstantInitBuilder, used for building constant
  468. /// array initializers.
  469. class ConstantArrayBuilder
  470. : public ConstantArrayBuilderTemplateBase<ConstantInitBuilderTraits> {
  471. template <class Traits>
  472. friend class ConstantInitBuilderTemplateBase;
  473. // The use of explicit qualification is a GCC workaround.
  474. template <class Impl, class Traits>
  475. friend class CodeGen::ConstantAggregateBuilderTemplateBase;
  476. ConstantArrayBuilder(ConstantInitBuilder &builder,
  477. ConstantAggregateBuilderBase *parent,
  478. llvm::Type *eltTy)
  479. : ConstantArrayBuilderTemplateBase(builder, parent, eltTy) {}
  480. };
  481. /// A helper class of ConstantInitBuilder, used for building constant
  482. /// struct initializers.
  483. class ConstantStructBuilder
  484. : public ConstantStructBuilderTemplateBase<ConstantInitBuilderTraits> {
  485. template <class Traits>
  486. friend class ConstantInitBuilderTemplateBase;
  487. // The use of explicit qualification is a GCC workaround.
  488. template <class Impl, class Traits>
  489. friend class CodeGen::ConstantAggregateBuilderTemplateBase;
  490. ConstantStructBuilder(ConstantInitBuilder &builder,
  491. ConstantAggregateBuilderBase *parent,
  492. llvm::StructType *structTy)
  493. : ConstantStructBuilderTemplateBase(builder, parent, structTy) {}
  494. };
  495. } // end namespace CodeGen
  496. } // end namespace clang
  497. #endif
  498. #ifdef __GNUC__
  499. #pragma GCC diagnostic pop
  500. #endif