clang 22.0.0git
HLSLBuiltinTypeDeclBuilder.cpp
Go to the documentation of this file.
1//===--- HLSLBuiltinTypeDeclBuilder.cpp - HLSL Builtin Type Decl Builder --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Helper classes for creating HLSL builtin class types. Used by external HLSL
10// sema source.
11//
12//===----------------------------------------------------------------------===//
13
16#include "clang/AST/Attr.h"
17#include "clang/AST/Decl.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/Type.h"
22#include "clang/Sema/Lookup.h"
23#include "clang/Sema/Sema.h"
24#include "clang/Sema/SemaHLSL.h"
25#include "llvm/ADT/SmallVector.h"
26
27using namespace llvm::hlsl;
28
29namespace clang {
30
31namespace hlsl {
32
33namespace {
34
35static FunctionDecl *lookupBuiltinFunction(Sema &S, StringRef Name) {
36 IdentifierInfo &II =
37 S.getASTContext().Idents.get(Name, tok::TokenKind::identifier);
38 DeclarationNameInfo NameInfo =
39 DeclarationNameInfo(DeclarationName(&II), SourceLocation());
40 LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
41 // AllowBuiltinCreation is false but LookupDirect will create
42 // the builtin when searching the global scope anyways...
43 S.LookupName(R, S.getCurScope());
44 // FIXME: If the builtin function was user-declared in global scope,
45 // this assert *will* fail. Should this call LookupBuiltin instead?
46 assert(R.isSingleResult() &&
47 "Since this is a builtin it should always resolve!");
48 return cast<FunctionDecl>(R.getFoundDecl());
49}
50} // namespace
51
52// Builder for template arguments of builtin types. Used internally
53// by BuiltinTypeDeclBuilder.
57
60
62 addTypeParameter(StringRef Name, QualType DefaultValue = QualType());
63
66
68};
69
70// Builder for methods or constructors of builtin types. Allows creating methods
71// or constructors of builtin types using the builder pattern like this:
72//
73// BuiltinTypeMethodBuilder(RecordBuilder, "MethodName", ReturnType)
74// .addParam("param_name", Type, InOutModifier)
75// .callBuiltin("builtin_name", BuiltinParams...)
76// .finalize();
77//
78// The builder needs to have all of the parameters before it can create
79// a CXXMethodDecl or CXXConstructorDecl. It collects them in addParam calls and
80// when a first method that builds the body is called or when access to 'this`
81// is needed it creates the CXXMethodDecl/CXXConstructorDecl and ParmVarDecls
82// instances. These can then be referenced from the body building methods.
83// Destructor or an explicit call to finalize() will complete the method
84// definition.
85//
86// The callBuiltin helper method accepts constants via `Expr *` or placeholder
87// value arguments to indicate which function arguments to forward to the
88// builtin.
89//
90// If the method that is being built has a non-void return type the
91// finalize() will create a return statement with the value of the last
92// statement (unless the last statement is already a ReturnStmt or the return
93// value is void).
95private:
96 struct Param {
97 const IdentifierInfo &NameII;
98 QualType Ty;
99 HLSLParamModifierAttr::Spelling Modifier;
100 Param(const IdentifierInfo &NameII, QualType Ty,
101 HLSLParamModifierAttr::Spelling Modifier)
102 : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
103 };
104
105 BuiltinTypeDeclBuilder &DeclBuilder;
106 DeclarationName Name;
107 QualType ReturnTy;
108 // method or constructor declaration
109 // (CXXConstructorDecl derives from CXXMethodDecl)
110 CXXMethodDecl *Method;
111 bool IsConst;
112 bool IsCtor;
115
116 // Argument placeholders, inspired by std::placeholder. These are the indices
117 // of arguments to forward to `callBuiltin` and other method builder methods.
118 // Additional special values are:
119 // Handle - refers to the resource handle.
120 // LastStmt - refers to the last statement in the method body; referencing
121 // LastStmt will remove the statement from the method body since
122 // it will be linked from the new expression being constructed.
123 enum class PlaceHolder { _0, _1, _2, _3, _4, Handle = 128, LastStmt };
124
125 Expr *convertPlaceholder(PlaceHolder PH);
126 Expr *convertPlaceholder(Expr *E) { return E; }
127
128public:
130
132 QualType ReturnTy, bool IsConst = false,
133 bool IsCtor = false)
134 : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr),
135 IsConst(IsConst), IsCtor(IsCtor) {}
136
138 QualType ReturnTy, bool IsConst = false,
139 bool IsCtor = false);
141
143
146
147 BuiltinTypeMethodBuilder &addParam(StringRef Name, QualType Ty,
148 HLSLParamModifierAttr::Spelling Modifier =
149 HLSLParamModifierAttr::Keyword_in);
150 template <typename... Ts>
151 BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName,
152 QualType ReturnType, Ts... ArgSpecs);
153 template <typename TLHS, typename TRHS>
154 BuiltinTypeMethodBuilder &assign(TLHS LHS, TRHS RHS);
155 template <typename T> BuiltinTypeMethodBuilder &dereference(T Ptr);
158
159private:
160 void createDecl();
161
162 // Makes sure the declaration is created; should be called before any
163 // statement added to the body or when access to 'this' is needed.
164 void ensureCompleteDecl() {
165 if (!Method)
166 createDecl();
167 }
168};
169
172}
173
176 QualType DefaultValue) {
177 assert(!Builder.Record->isCompleteDefinition() &&
178 "record is already complete");
179 ASTContext &AST = Builder.SemaRef.getASTContext();
180 unsigned Position = static_cast<unsigned>(Params.size());
183 /* TemplateDepth */ 0, Position,
184 &AST.Idents.get(Name, tok::TokenKind::identifier),
185 /* Typename */ true,
186 /* ParameterPack */ false,
187 /* HasTypeConstraint*/ false);
188 if (!DefaultValue.isNull())
189 Decl->setDefaultArgument(AST,
191 DefaultValue, QualType(), SourceLocation()));
192
193 Params.emplace_back(Decl);
194 return *this;
195}
196
197// The concept specialization expression (CSE) constructed in
198// constructConceptSpecializationExpr is constructed so that it
199// matches the CSE that is constructed when parsing the below C++ code:
200//
201// template<typename T>
202// concept is_typed_resource_element_compatible =
203// __builtin_hlsl_typed_resource_element_compatible<T>
204//
205// template<typename element_type> requires
206// is_typed_resource_element_compatible<element_type>
207// struct RWBuffer {
208// element_type Val;
209// };
210//
211// int fn() {
212// RWBuffer<int> Buf;
213// }
214//
215// When dumping the AST and filtering for "RWBuffer", the resulting AST
216// structure is what we're trying to construct below, specifically the
217// CSE portion.
220 Sema &S, ConceptDecl *CD) {
221 ASTContext &Context = S.getASTContext();
225 DeclContext *DC = Builder.Record->getDeclContext();
227
228 // Assume that the concept decl has just one template parameter
229 // This parameter should have been added when CD was constructed
230 // in getTypedBufferConceptDecl
231 assert(CD->getTemplateParameters()->size() == 1 &&
232 "unexpected concept decl parameter count");
233 TemplateTypeParmDecl *ConceptTTPD =
234 dyn_cast<TemplateTypeParmDecl>(CD->getTemplateParameters()->getParam(0));
235
236 // this TemplateTypeParmDecl is the template for the resource, and is
237 // used to construct a template argumentthat will be used
238 // to construct the ImplicitConceptSpecializationDecl
240 Context, // AST context
241 Builder.Record->getDeclContext(), // DeclContext
243 /*D=*/0, // Depth in the template parameter list
244 /*P=*/0, // Position in the template parameter list
245 /*Id=*/nullptr, // Identifier for 'T'
246 /*Typename=*/true, // Indicates this is a 'typename' or 'class'
247 /*ParameterPack=*/false, // Not a parameter pack
248 /*HasTypeConstraint=*/false // Has no type constraint
249 );
250
251 T->setDeclContext(DC);
252
253 QualType ConceptTType = Context.getTypeDeclType(ConceptTTPD);
254
255 // this is the 2nd template argument node, on which
256 // the concept constraint is actually being applied: 'element_type'
257 TemplateArgument ConceptTA = TemplateArgument(ConceptTType);
258
259 QualType CSETType = Context.getTypeDeclType(T);
260
261 // this is the 1st template argument node, which represents
262 // the abstract type that a concept would refer to: 'T'
263 TemplateArgument CSETA = TemplateArgument(CSETType);
264
265 ImplicitConceptSpecializationDecl *ImplicitCSEDecl =
267 Context, Builder.Record->getDeclContext(), Loc, {CSETA});
268
269 // Constraint satisfaction is used to construct the
270 // ConceptSpecailizationExpr, and represents the 2nd Template Argument,
271 // located at the bottom of the sample AST above.
272 const ConstraintSatisfaction CS(CD, {ConceptTA});
274 S.getTrivialTemplateArgumentLoc(ConceptTA, QualType(), SourceLocation());
275
276 TALI.addArgument(TAL);
277 const ASTTemplateArgumentListInfo *ATALI =
279
280 // In the concept reference, ATALI is what adds the extra
281 // TemplateArgument node underneath CSE
282 ConceptReference *CR =
283 ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI);
284
286 ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS);
287
288 return CSE;
289}
290
293 if (Params.empty())
294 return Builder;
295
296 ASTContext &AST = Builder.SemaRef.Context;
298 CD ? constructConceptSpecializationExpr(Builder.SemaRef, CD) : nullptr;
299 auto *ParamList = TemplateParameterList::Create(
302 AST, Builder.Record->getDeclContext(), SourceLocation(),
303 DeclarationName(Builder.Record->getIdentifier()), ParamList,
304 Builder.Record);
305
306 Builder.Record->setDescribedClassTemplate(Builder.Template);
307 Builder.Template->setImplicit(true);
309
310 // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
311 // make visible.
312 Builder.Template->setPreviousDecl(Builder.PrevTemplate);
313 Builder.Record->getDeclContext()->addDecl(Builder.Template);
314 Params.clear();
315
316 return Builder;
317}
318
319Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
320 if (PH == PlaceHolder::Handle)
321 return getResourceHandleExpr();
322
323 if (PH == PlaceHolder::LastStmt) {
324 assert(!StmtsList.empty() && "no statements in the list");
325 Stmt *LastStmt = StmtsList.pop_back_val();
326 assert(isa<ValueStmt>(LastStmt) && "last statement does not have a value");
327 return cast<ValueStmt>(LastStmt)->getExprStmt();
328 }
329
330 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
331 ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
332 return DeclRefExpr::Create(
333 AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
335 ParamDecl->getType(), VK_PRValue);
336}
337
339 StringRef NameStr,
340 QualType ReturnTy,
341 bool IsConst, bool IsCtor)
342 : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr), IsConst(IsConst),
343 IsCtor(IsCtor) {
344
345 assert((!NameStr.empty() || IsCtor) && "method needs a name");
346 assert(((IsCtor && !IsConst) || !IsCtor) && "constructor cannot be const");
347
348 ASTContext &AST = DB.SemaRef.getASTContext();
349 if (IsCtor) {
351 AST.getCanonicalTagType(DB.Record));
352 } else {
353 const IdentifierInfo &II =
354 AST.Idents.get(NameStr, tok::TokenKind::identifier);
355 Name = DeclarationName(&II);
356 }
357}
358
361 HLSLParamModifierAttr::Spelling Modifier) {
362 assert(Method == nullptr && "Cannot add param, method already created");
363 const IdentifierInfo &II = DeclBuilder.SemaRef.getASTContext().Idents.get(
364 Name, tok::TokenKind::identifier);
365 Params.emplace_back(II, Ty, Modifier);
366 return *this;
367}
368
369void BuiltinTypeMethodBuilder::createDecl() {
370 assert(Method == nullptr && "Method or constructor is already created");
371
372 // create method or constructor type
373 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
374 SmallVector<QualType> ParamTypes;
375 for (Param &MP : Params)
376 ParamTypes.emplace_back(MP.Ty);
377
379 if (IsConst)
380 ExtInfo.TypeQuals.addConst();
381
382 QualType FuncTy = AST.getFunctionType(ReturnTy, ParamTypes, ExtInfo);
383
384 // create method or constructor decl
385 auto *TSInfo = AST.getTrivialTypeSourceInfo(FuncTy, SourceLocation());
387 if (IsCtor)
389 AST, DeclBuilder.Record, SourceLocation(), NameInfo, FuncTy, TSInfo,
390 ExplicitSpecifier(), false, true, false,
392 else
393 Method =
394 CXXMethodDecl::Create(AST, DeclBuilder.Record, SourceLocation(),
395 NameInfo, FuncTy, TSInfo, SC_None, false, false,
397
398 // create params & set them to the function prototype
400 unsigned CurScopeDepth = DeclBuilder.SemaRef.getCurScope()->getDepth();
401 auto FnProtoLoc =
402 Method->getTypeSourceInfo()->getTypeLoc().getAs<FunctionProtoTypeLoc>();
403 for (int I = 0, E = Params.size(); I != E; I++) {
404 Param &MP = Params[I];
406 AST, Method->getDeclContext(), SourceLocation(), SourceLocation(),
407 &MP.NameII, MP.Ty,
409 nullptr);
410 if (MP.Modifier != HLSLParamModifierAttr::Keyword_in) {
411 auto *Mod =
412 HLSLParamModifierAttr::Create(AST, SourceRange(), MP.Modifier);
413 Parm->addAttr(Mod);
414 }
415 Parm->setScopeInfo(CurScopeDepth, I);
416 ParmDecls.push_back(Parm);
417 FnProtoLoc.setParam(I, Parm);
418 }
419 Method->setParams({ParmDecls});
420}
421
423 ensureCompleteDecl();
424
425 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
427 AST, SourceLocation(), Method->getFunctionObjectParameterType(), true);
428 FieldDecl *HandleField = DeclBuilder.getResourceHandleField();
429 return MemberExpr::CreateImplicit(AST, This, false, HandleField,
430 HandleField->getType(), VK_LValue,
432}
433
434template <typename... Ts>
437 QualType ReturnType, Ts... ArgSpecs) {
438 std::array<Expr *, sizeof...(ArgSpecs)> Args{
439 convertPlaceholder(std::forward<Ts>(ArgSpecs))...};
440
441 ensureCompleteDecl();
442
443 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
444 FunctionDecl *FD = lookupBuiltinFunction(DeclBuilder.SemaRef, BuiltinName);
446 AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
448
449 auto *ImpCast = ImplicitCastExpr::Create(
450 AST, AST.getPointerType(FD->getType()), CK_BuiltinFnToFnPtr, DRE, nullptr,
452
453 if (ReturnType.isNull())
454 ReturnType = FD->getReturnType();
455
456 Expr *Call = CallExpr::Create(AST, ImpCast, Args, ReturnType, VK_PRValue,
458 StmtsList.push_back(Call);
459 return *this;
460}
461
462template <typename TLHS, typename TRHS>
464 Expr *LHSExpr = convertPlaceholder(LHS);
465 Expr *RHSExpr = convertPlaceholder(RHS);
466 Stmt *AssignStmt = BinaryOperator::Create(
467 DeclBuilder.SemaRef.getASTContext(), LHSExpr, RHSExpr, BO_Assign,
470 StmtsList.push_back(AssignStmt);
471 return *this;
472}
473
474template <typename T>
476 Expr *PtrExpr = convertPlaceholder(Ptr);
477 Expr *Deref =
478 UnaryOperator::Create(DeclBuilder.SemaRef.getASTContext(), PtrExpr,
479 UO_Deref, PtrExpr->getType()->getPointeeType(),
481 /*CanOverflow=*/false, FPOptionsOverride());
482 StmtsList.push_back(Deref);
483 return *this;
484}
485
487 assert(!DeclBuilder.Record->isCompleteDefinition() &&
488 "record is already complete");
489
490 ensureCompleteDecl();
491
492 if (!Method->hasBody()) {
493 ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
494 assert((ReturnTy == AST.VoidTy || !StmtsList.empty()) &&
495 "nothing to return from non-void method");
496 if (ReturnTy != AST.VoidTy) {
497 if (Expr *LastExpr = dyn_cast<Expr>(StmtsList.back())) {
498 assert(AST.hasSameUnqualifiedType(LastExpr->getType(),
499 ReturnTy.getNonReferenceType()) &&
500 "Return type of the last statement must match the return type "
501 "of the method");
502 if (!isa<ReturnStmt>(LastExpr)) {
503 StmtsList.pop_back();
504 StmtsList.push_back(
505 ReturnStmt::Create(AST, SourceLocation(), LastExpr, nullptr));
506 }
507 }
508 }
509
510 Method->setBody(CompoundStmt::Create(AST, StmtsList, FPOptionsOverride(),
512 Method->setLexicalDeclContext(DeclBuilder.Record);
514 Method->addAttr(AlwaysInlineAttr::CreateImplicit(
515 AST, SourceRange(), AlwaysInlineAttr::CXX11_clang_always_inline));
516 DeclBuilder.Record->addDecl(Method);
517 }
518 return DeclBuilder;
519}
520
522 : SemaRef(SemaRef), Record(R) {
523 Record->startDefinition();
524 Template = Record->getDescribedClassTemplate();
525}
526
528 NamespaceDecl *Namespace,
529 StringRef Name)
530 : SemaRef(SemaRef), HLSLNamespace(Namespace) {
531 ASTContext &AST = SemaRef.getASTContext();
532 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
533
535 CXXRecordDecl *PrevDecl = nullptr;
536 if (SemaRef.LookupQualifiedName(Result, HLSLNamespace)) {
537 // Declaration already exists (from precompiled headers)
538 NamedDecl *Found = Result.getFoundDecl();
539 if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
540 PrevDecl = TD->getTemplatedDecl();
541 PrevTemplate = TD;
542 } else
543 PrevDecl = dyn_cast<CXXRecordDecl>(Found);
544 assert(PrevDecl && "Unexpected lookup result type.");
545 }
546
547 if (PrevDecl && PrevDecl->isCompleteDefinition()) {
548 Record = PrevDecl;
549 Template = PrevTemplate;
550 return;
551 }
552
553 Record =
554 CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, HLSLNamespace,
555 SourceLocation(), SourceLocation(), &II, PrevDecl);
556 Record->setImplicit(true);
557 Record->setLexicalDeclContext(HLSLNamespace);
558 Record->setHasExternalLexicalStorage();
559
560 // Don't let anyone derive from built-in types.
561 Record->addAttr(
562 FinalAttr::CreateImplicit(AST, SourceRange(), FinalAttr::Keyword_final));
563}
564
566 if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
567 HLSLNamespace->addDecl(Record);
568}
569
573 AccessSpecifier Access) {
574 assert(!Record->isCompleteDefinition() && "record is already complete");
575 assert(Record->isBeingDefined() &&
576 "Definition must be started before adding members!");
577 ASTContext &AST = Record->getASTContext();
578
579 IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
580 TypeSourceInfo *MemTySource =
582 auto *Field = FieldDecl::Create(
583 AST, Record, SourceLocation(), SourceLocation(), &II, Type, MemTySource,
584 nullptr, false, InClassInitStyle::ICIS_NoInit);
585 Field->setAccess(Access);
586 Field->setImplicit(true);
587 for (Attr *A : Attrs) {
588 if (A)
589 Field->addAttr(A);
590 }
591
592 Record->addDecl(Field);
593 Fields[Name] = Field;
594 return *this;
595}
596
598 ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access) {
599 assert(!Record->isCompleteDefinition() && "record is already complete");
600
601 ASTContext &Ctx = SemaRef.getASTContext();
602 TypeSourceInfo *ElementTypeInfo =
603 Ctx.getTrivialTypeSourceInfo(getHandleElementType(), SourceLocation());
604
605 // add handle member with resource type attributes
606 QualType AttributedResTy = QualType();
608 HLSLResourceClassAttr::CreateImplicit(Ctx, RC),
609 IsROV ? HLSLROVAttr::CreateImplicit(Ctx) : nullptr,
610 RawBuffer ? HLSLRawBufferAttr::CreateImplicit(Ctx) : nullptr,
611 ElementTypeInfo
612 ? HLSLContainedTypeAttr::CreateImplicit(Ctx, ElementTypeInfo)
613 : nullptr};
614 if (CreateHLSLAttributedResourceType(SemaRef, Ctx.HLSLResourceTy, Attrs,
615 AttributedResTy))
616 addMemberVariable("__handle", AttributedResTy, {}, Access);
617 return *this;
618}
619
620// Adds default constructor to the resource class:
621// Resource::Resource()
623 if (Record->isCompleteDefinition())
624 return *this;
625
626 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
627 QualType HandleType = getResourceHandleField()->getType();
628 return BuiltinTypeMethodBuilder(*this, "", SemaRef.getASTContext().VoidTy,
629 false, true)
630 .callBuiltin("__builtin_hlsl_resource_uninitializedhandle", HandleType,
631 PH::Handle)
632 .assign(PH::Handle, PH::LastStmt)
633 .finalize();
634}
635
638 if (Record->isCompleteDefinition())
639 return *this;
640
641 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
642 ASTContext &AST = SemaRef.getASTContext();
643 QualType HandleType = getResourceHandleField()->getType();
644
645 return BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true)
646 .addParam("registerNo", AST.UnsignedIntTy)
647 .addParam("spaceNo", AST.UnsignedIntTy)
648 .addParam("range", AST.IntTy)
649 .addParam("index", AST.UnsignedIntTy)
650 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
651 .callBuiltin("__builtin_hlsl_resource_handlefrombinding", HandleType,
652 PH::Handle, PH::_0, PH::_1, PH::_2, PH::_3, PH::_4)
653 .assign(PH::Handle, PH::LastStmt)
654 .finalize();
655}
656
659 if (Record->isCompleteDefinition())
660 return *this;
661
662 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
663 ASTContext &AST = SemaRef.getASTContext();
664 QualType HandleType = getResourceHandleField()->getType();
665
666 return BuiltinTypeMethodBuilder(*this, "", AST.VoidTy, false, true)
667 .addParam("spaceNo", AST.UnsignedIntTy)
668 .addParam("range", AST.IntTy)
669 .addParam("index", AST.UnsignedIntTy)
670 .addParam("orderId", AST.UnsignedIntTy)
671 .addParam("name", AST.getPointerType(AST.CharTy.withConst()))
672 .callBuiltin("__builtin_hlsl_resource_handlefromimplicitbinding",
673 HandleType, PH::Handle, PH::_0, PH::_1, PH::_2, PH::_3,
674 PH::_4)
675 .assign(PH::Handle, PH::LastStmt)
676 .finalize();
677}
678
680 ASTContext &AST = Record->getASTContext();
681 DeclarationName Subscript =
682 AST.DeclarationNames.getCXXOperatorName(OO_Subscript);
683
684 addHandleAccessFunction(Subscript, /*IsConst=*/true, /*IsRef=*/true);
685 if (getResourceAttrs().ResourceClass == llvm::dxil::ResourceClass::UAV)
686 addHandleAccessFunction(Subscript, /*IsConst=*/false, /*IsRef=*/true);
687
688 return *this;
689}
690
692 if (Record->isCompleteDefinition())
693 return *this;
694
695 ASTContext &AST = Record->getASTContext();
696 IdentifierInfo &II = AST.Idents.get("Load", tok::TokenKind::identifier);
697 DeclarationName Load(&II);
698 // TODO: We also need versions with status for CheckAccessFullyMapped.
699 addHandleAccessFunction(Load, /*IsConst=*/false, /*IsRef=*/false);
700
701 return *this;
702}
703
704FieldDecl *BuiltinTypeDeclBuilder::getResourceHandleField() const {
705 auto I = Fields.find("__handle");
706 assert(I != Fields.end() &&
707 I->second->getType()->isHLSLAttributedResourceType() &&
708 "record does not have resource handle field");
709 return I->second;
710}
711
712QualType BuiltinTypeDeclBuilder::getFirstTemplateTypeParam() {
713 assert(Template && "record it not a template");
714 if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
715 Template->getTemplateParameters()->getParam(0))) {
716 return QualType(TTD->getTypeForDecl(), 0);
717 }
718 return QualType();
719}
720
721QualType BuiltinTypeDeclBuilder::getHandleElementType() {
722 if (Template)
723 return getFirstTemplateTypeParam();
724 // TODO: Should we default to VoidTy? Using `i8` is arguably ambiguous.
725 return SemaRef.getASTContext().Char8Ty;
726}
727
728HLSLAttributedResourceType::Attributes
729BuiltinTypeDeclBuilder::getResourceAttrs() const {
730 QualType HandleType = getResourceHandleField()->getType();
731 return cast<HLSLAttributedResourceType>(HandleType)->getAttrs();
732}
733
734// BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::startDefinition() {
735// assert(!Record->isCompleteDefinition() && "record is already complete");
736// Record->startDefinition();
737// return *this;
738// }
739
741 assert(!Record->isCompleteDefinition() && "record is already complete");
742 assert(Record->isBeingDefined() &&
743 "Definition must be started before completing it.");
744
745 Record->completeDefinition();
746 return *this;
747}
748
749Expr *BuiltinTypeDeclBuilder::getConstantIntExpr(int value) {
750 ASTContext &AST = SemaRef.getASTContext();
752 AST, llvm::APInt(AST.getTypeSize(AST.IntTy), value, true), AST.IntTy,
754}
755
756BuiltinTypeDeclBuilder &
758 ConceptDecl *CD = nullptr) {
759 if (Record->isCompleteDefinition()) {
760 assert(Template && "existing record it not a template");
761 assert(Template->getTemplateParameters()->size() == Names.size() &&
762 "template param count mismatch");
763 return *this;
764 }
765
767 for (StringRef Name : Names)
768 Builder.addTypeParameter(Name);
769 return Builder.finalizeTemplateArgs(CD);
770}
771
773 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
774 return BuiltinTypeMethodBuilder(*this, "IncrementCounter",
776 .callBuiltin("__builtin_hlsl_buffer_update_counter", QualType(),
777 PH::Handle, getConstantIntExpr(1))
778 .finalize();
779}
780
782 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
783 return BuiltinTypeMethodBuilder(*this, "DecrementCounter",
785 .callBuiltin("__builtin_hlsl_buffer_update_counter", QualType(),
786 PH::Handle, getConstantIntExpr(-1))
787 .finalize();
788}
789
792 bool IsConst, bool IsRef) {
793 assert(!Record->isCompleteDefinition() && "record is already complete");
794 ASTContext &AST = SemaRef.getASTContext();
795 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
796
797 QualType ElemTy = getHandleElementType();
798 QualType AddrSpaceElemTy =
800 QualType ElemPtrTy = AST.getPointerType(AddrSpaceElemTy);
801 QualType ReturnTy;
802
803 if (IsRef) {
804 ReturnTy = AddrSpaceElemTy;
805 if (IsConst)
806 ReturnTy.addConst();
807 ReturnTy = AST.getLValueReferenceType(ReturnTy);
808 } else {
809 ReturnTy = ElemTy;
810 if (IsConst)
811 ReturnTy.addConst();
812 }
813
814 return BuiltinTypeMethodBuilder(*this, Name, ReturnTy, IsConst)
815 .addParam("Index", AST.UnsignedIntTy)
816 .callBuiltin("__builtin_hlsl_resource_getpointer", ElemPtrTy, PH::Handle,
817 PH::_0)
818 .dereference(PH::LastStmt)
819 .finalize();
820}
821
823 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
824 ASTContext &AST = SemaRef.getASTContext();
825 QualType ElemTy = getHandleElementType();
826 QualType AddrSpaceElemTy =
828 return BuiltinTypeMethodBuilder(*this, "Append", AST.VoidTy)
829 .addParam("value", ElemTy)
830 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
831 PH::Handle, getConstantIntExpr(1))
832 .callBuiltin("__builtin_hlsl_resource_getpointer",
833 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
834 PH::LastStmt)
835 .dereference(PH::LastStmt)
836 .assign(PH::LastStmt, PH::_0)
837 .finalize();
838}
839
841 using PH = BuiltinTypeMethodBuilder::PlaceHolder;
842 ASTContext &AST = SemaRef.getASTContext();
843 QualType ElemTy = getHandleElementType();
844 QualType AddrSpaceElemTy =
846 return BuiltinTypeMethodBuilder(*this, "Consume", ElemTy)
847 .callBuiltin("__builtin_hlsl_buffer_update_counter", AST.UnsignedIntTy,
848 PH::Handle, getConstantIntExpr(-1))
849 .callBuiltin("__builtin_hlsl_resource_getpointer",
850 AST.getPointerType(AddrSpaceElemTy), PH::Handle,
851 PH::LastStmt)
852 .dereference(PH::LastStmt)
853 .finalize();
854}
855
856} // namespace hlsl
857} // namespace clang
Defines the clang::ASTContext interface.
llvm::dxil::ResourceClass ResourceClass
Definition: CGHLSLRuntime.h:50
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
llvm::MachO::Record Record
Definition: MachO.h:31
This file declares semantic analysis for HLSL constructs.
SourceLocation Loc
Definition: SemaObjC.cpp:754
Defines the clang::SourceLocation class and associated facilities.
C Language Family Type Representation.
a trap message and trap category.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:744
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition: ASTContext.h:740
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType CharTy
Definition: ASTContext.h:1224
CanQualType IntTy
Definition: ASTContext.h:1231
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2898
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
CanQualType BuiltinFnTy
Definition: ASTContext.h:1252
CanQualType VoidTy
Definition: ASTContext.h:1222
CanQualType UnsignedIntTy
Definition: ASTContext.h:1232
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1750
QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const
Return the uniqued reference to the type for an address space qualified type with the specified type ...
CanQualType getCanonicalTagType(const TagDecl *TD) const
CanQualType Char8Ty
Definition: ASTContext.h:1228
Attr - This represents one attribute.
Definition: Attr.h:44
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Definition: Expr.cpp:4938
static CXXConstructorDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, ExplicitSpecifier ES, bool UsesFPIntrin, bool isInline, bool isImplicitlyDeclared, ConstexprSpecKind ConstexprKind, InheritedConstructor Inherited=InheritedConstructor(), const AssociatedConstraint &TrailingRequiresClause={})
Definition: DeclCXX.cpp:2968
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2129
static CXXMethodDecl * Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin, bool isInline, ConstexprSpecKind ConstexprKind, SourceLocation EndLocation, const AssociatedConstraint &TrailingRequiresClause={})
Definition: DeclCXX.cpp:2488
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
static CXXRecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl=nullptr)
Definition: DeclCXX.cpp:132
void setDescribedClassTemplate(ClassTemplateDecl *Template)
Definition: DeclCXX.cpp:2046
Represents the this expression in C++.
Definition: ExprCXX.h:1155
static CXXThisExpr * Create(const ASTContext &Ctx, SourceLocation L, QualType Ty, bool IsImplicit)
Definition: ExprCXX.cpp:1585
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition: Expr.cpp:1513
QualType withConst() const
Retrieves a version of this type with const applied.
static ClassTemplateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl)
Create a class template node.
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:390
Declaration of a C++20 concept.
A reference to a concept and its template args, as it appears in the code.
Definition: ASTConcept.h:126
static ConceptReference * Create(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten)
Definition: ASTConcept.cpp:87
Represents the specialization of a concept - evaluates to a prvalue of type bool.
Definition: ExprConcepts.h:42
static ConceptSpecializationExpr * Create(const ASTContext &C, ConceptReference *ConceptRef, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:37
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1449
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1793
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:484
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
void addAttr(Attr *A)
Definition: DeclBase.cpp:1022
void setImplicit(bool I=true)
Definition: DeclBase.h:594
DeclContext * getDeclContext()
Definition: DeclBase.h:448
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:364
DeclarationName getCXXOperatorName(OverloadedOperatorKind Op)
Get the name of the overloadable C++ operator corresponding to Op.
DeclarationName getCXXConstructorName(CanQualType Ty)
Returns the name of a C++ constructor for the given Type.
The name of a declaration.
Store information needed for an explicit specifier.
Definition: DeclCXX.h:1924
This represents one expression.
Definition: Expr.h:112
QualType getType() const
Definition: Expr.h:144
Represents difference between two FPOptions values.
Definition: LangOptions.h:919
Represents a member of a struct/union/class.
Definition: Decl.h:3153
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Definition: Decl.cpp:4637
Represents a function declaration or definition.
Definition: Decl.h:1999
QualType getReturnType() const
Definition: Decl.h:2838
DeclarationNameInfo getNameInfo() const
Definition: Decl.h:2210
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2068
static ImplicitConceptSpecializationDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, ArrayRef< TemplateArgument > ConvertedArgs)
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition: Expr.cpp:971
Represents the results of name lookup.
Definition: Lookup.h:147
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
Definition: Expr.h:3361
This represents a decl that may have a name.
Definition: Decl.h:273
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:294
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:339
Represent a C++ namespace.
Definition: Decl.h:591
A C++ nested-name-specifier augmented with source location information.
Represents a parameter to a function.
Definition: Decl.h:1789
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition: Decl.h:1822
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition: Decl.cpp:2946
A (possibly-)qualified type.
Definition: TypeBase.h:937
void addConst()
Add the const type qualifier to this QualType.
Definition: TypeBase.h:1156
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: TypeBase.h:1004
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: TypeBase.h:8528
void setPreviousDecl(decl_type *PrevDecl)
Set the previous declaration.
Definition: Decl.h:5288
static ReturnStmt * Create(const ASTContext &Ctx, SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
Create a return statement.
Definition: Stmt.cpp:1248
unsigned getDepth() const
Returns the depth of this scope. The translation-unit has scope depth 0.
Definition: Scope.h:327
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, NamedDecl *TemplateParam=nullptr)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:1113
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition: Sema.h:9281
@ LookupTagName
Tag name lookup, which finds the names of enums, classes, structs, and unions.
Definition: Sema.h:9284
ASTContext & Context
Definition: Sema.h:1276
ASTContext & getASTContext() const
Definition: Sema.h:918
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
Definition: Stmt.h:85
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition: Decl.h:3805
A convenient class for passing around template argument information.
Definition: TemplateBase.h:634
void addArgument(const TemplateArgumentLoc &Loc)
Definition: TemplateBase.h:669
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:528
Represents a template argument.
Definition: TemplateBase.h:61
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:415
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:146
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
Declaration of a template type parameter.
static TemplateTypeParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack, bool HasTypeConstraint=false, UnsignedOrNone NumExpanded=std::nullopt)
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:3540
A container of type source information.
Definition: TypeBase.h:8314
The base class of the type hierarchy.
Definition: TypeBase.h:1833
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Definition: Expr.cpp:4995
QualType getType() const
Definition: Decl.h:722
BuiltinTypeDeclBuilder & addHandleConstructorFromImplicitBinding()
BuiltinTypeDeclBuilder(Sema &SemaRef, CXXRecordDecl *R)
BuiltinTypeDeclBuilder & addSimpleTemplateParams(ArrayRef< StringRef > Names, ConceptDecl *CD)
BuiltinTypeDeclBuilder & addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef< Attr * > Attrs, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addHandleConstructorFromBinding()
BuiltinTypeDeclBuilder & addHandleAccessFunction(DeclarationName &Name, bool IsConst, bool IsRef)
BuiltinTypeDeclBuilder & addArraySubscriptOperators()
BuiltinTypeDeclBuilder & addIncrementCounterMethod()
BuiltinTypeDeclBuilder & addHandleMember(ResourceClass RC, bool IsROV, bool RawBuffer, AccessSpecifier Access=AccessSpecifier::AS_private)
BuiltinTypeDeclBuilder & addDefaultHandleConstructor()
BuiltinTypeDeclBuilder & addDecrementCounterMethod()
__inline void unsigned int _2
Definition: larchintrin.h:181
The JSON file list parser is used to communicate input to InstallAPI.
@ ICIS_NoInit
No in-class initializer.
Definition: Specifiers.h:272
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:123
@ AS_public
Definition: Specifiers.h:124
@ SC_None
Definition: Specifiers.h:250
@ Result
The result type of a method or function.
bool CreateHLSLAttributedResourceType(Sema &S, QualType Wrapped, ArrayRef< const Attr * > AttrList, QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo=nullptr)
Definition: SemaHLSL.cpp:1666
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
@ Other
Other implicit parameter.
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Definition: TemplateBase.h:678
static const ASTTemplateArgumentListInfo * Create(const ASTContext &C, const TemplateArgumentListInfo &List)
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
Extra information about a function prototype.
Definition: TypeBase.h:5367
BuiltinTypeMethodBuilder & addParam(StringRef Name, QualType Ty, HLSLParamModifierAttr::Spelling Modifier=HLSLParamModifierAttr::Keyword_in)
BuiltinTypeMethodBuilder & operator=(const BuiltinTypeMethodBuilder &Other)=delete
BuiltinTypeMethodBuilder & callBuiltin(StringRef BuiltinName, QualType ReturnType, Ts... ArgSpecs)
BuiltinTypeMethodBuilder & dereference(T Ptr)
BuiltinTypeMethodBuilder & assign(TLHS LHS, TRHS RHS)
BuiltinTypeMethodBuilder(const BuiltinTypeMethodBuilder &Other)=delete
BuiltinTypeMethodBuilder(BuiltinTypeDeclBuilder &DB, DeclarationName &Name, QualType ReturnTy, bool IsConst=false, bool IsCtor=false)
TemplateParameterListBuilder & addTypeParameter(StringRef Name, QualType DefaultValue=QualType())
BuiltinTypeDeclBuilder & finalizeTemplateArgs(ConceptDecl *CD=nullptr)
ConceptSpecializationExpr * constructConceptSpecializationExpr(Sema &S, ConceptDecl *CD)