@@ -89,21 +89,24 @@ struct TemplateParameterListBuilder {
8989// statement (unless the last statement is already a ReturnStmt).
9090struct BuiltinTypeMethodBuilder {
9191private:
92- struct MethodParam {
92+ struct Param {
9393 const IdentifierInfo &NameII;
9494 QualType Ty;
9595 HLSLParamModifierAttr::Spelling Modifier;
96- MethodParam (const IdentifierInfo &NameII, QualType Ty,
97- HLSLParamModifierAttr::Spelling Modifier)
96+ Param (const IdentifierInfo &NameII, QualType Ty,
97+ HLSLParamModifierAttr::Spelling Modifier)
9898 : NameII(NameII), Ty(Ty), Modifier(Modifier) {}
9999 };
100100
101101 BuiltinTypeDeclBuilder &DeclBuilder;
102- DeclarationNameInfo NameInfo ;
102+ DeclarationName Name ;
103103 QualType ReturnTy;
104+ // method or constructor declaration (CXXConstructorDecl derives from
105+ // CXXMethodDecl)
104106 CXXMethodDecl *Method;
105107 bool IsConst;
106- llvm::SmallVector<MethodParam> Params;
108+ bool IsConstructor;
109+ llvm::SmallVector<Param> Params;
107110 llvm::SmallVector<Stmt *> StmtsList;
108111
109112 // Argument placeholders, inspired by std::placeholder. These are the indices
@@ -122,12 +125,14 @@ struct BuiltinTypeMethodBuilder {
122125 friend BuiltinTypeDeclBuilder;
123126
124127 BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, DeclarationName &Name,
125- QualType ReturnTy, bool IsConst = false )
126- : DeclBuilder(DB), NameInfo(DeclarationNameInfo(Name, SourceLocation())),
127- ReturnTy (ReturnTy), Method(nullptr ), IsConst(IsConst) {}
128-
129- BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef Name,
130- QualType ReturnTy, bool IsConst = false );
128+ QualType ReturnTy, bool IsConst = false ,
129+ bool IsConstructor = false )
130+ : DeclBuilder(DB), Name(Name), ReturnTy(ReturnTy), Method(nullptr ),
131+ IsConst (IsConst), IsConstructor(IsConstructor) {}
132+
133+ BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB, StringRef NameStr,
134+ QualType ReturnTy, bool IsConst = false ,
135+ bool IsConstructor = false );
131136 BuiltinTypeMethodBuilder (const BuiltinTypeMethodBuilder &Other) = delete;
132137
133138 ~BuiltinTypeMethodBuilder () { finalizeMethod (); }
@@ -148,7 +153,14 @@ struct BuiltinTypeMethodBuilder {
148153 Expr *getResourceHandleExpr ();
149154
150155private:
151- void createMethodDecl ();
156+ void createDecl ();
157+
158+ // Makes sure the declaration is created; should be called before any
159+ // statement added or when access to 'this' is needed.
160+ void ensureCompleteDecl () {
161+ if (!Method)
162+ createDecl ();
163+ }
152164};
153165
154166TemplateParameterListBuilder::~TemplateParameterListBuilder () {
@@ -323,13 +335,26 @@ Expr *BuiltinTypeMethodBuilder::convertPlaceholder(PlaceHolder PH) {
323335}
324336
325337BuiltinTypeMethodBuilder::BuiltinTypeMethodBuilder (BuiltinTypeDeclBuilder &DB,
326- StringRef Name ,
338+ StringRef NameStr ,
327339 QualType ReturnTy,
328- bool IsConst)
329- : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst) {
330- const IdentifierInfo &II =
331- DB.SemaRef .getASTContext ().Idents .get (Name, tok::TokenKind::identifier);
332- NameInfo = DeclarationNameInfo (DeclarationName (&II), SourceLocation ());
340+ bool IsConst,
341+ bool IsConstructor)
342+ : DeclBuilder(DB), ReturnTy(ReturnTy), Method(nullptr ), IsConst(IsConst),
343+ IsConstructor (IsConstructor) {
344+
345+ assert ((!NameStr.empty () || IsConstructor) && " method needs a name" );
346+ assert (((IsConstructor && !IsConst) || !IsConstructor) &&
347+ " constructor cannot be const" );
348+
349+ ASTContext &AST = DB.SemaRef .getASTContext ();
350+ if (IsConstructor) {
351+ Name = AST.DeclarationNames .getCXXConstructorName (
352+ DB.Record ->getTypeForDecl ()->getCanonicalTypeUnqualified ());
353+ } else {
354+ const IdentifierInfo &II =
355+ AST.Idents .get (NameStr, tok::TokenKind::identifier);
356+ Name = DeclarationName (&II);
357+ }
333358}
334359
335360BuiltinTypeMethodBuilder &
@@ -342,13 +367,13 @@ BuiltinTypeMethodBuilder::addParam(StringRef Name, QualType Ty,
342367 return *this ;
343368}
344369
345- void BuiltinTypeMethodBuilder::createMethodDecl () {
346- assert (Method == nullptr && " Method already created" );
370+ void BuiltinTypeMethodBuilder::createDecl () {
371+ assert (Method == nullptr && " Method or constructor is already created" );
347372
348- // create method type
373+ // create method or constructor type
349374 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
350375 SmallVector<QualType> ParamTypes;
351- for (MethodParam &MP : Params)
376+ for (Param &MP : Params)
352377 ParamTypes.emplace_back (MP.Ty );
353378
354379 FunctionProtoType::ExtProtoInfo ExtInfo;
@@ -357,18 +382,26 @@ void BuiltinTypeMethodBuilder::createMethodDecl() {
357382
358383 QualType MethodTy = AST.getFunctionType (ReturnTy, ParamTypes, ExtInfo);
359384
360- // create method decl
385+ // create method or constructor decl
361386 auto *TSInfo = AST.getTrivialTypeSourceInfo (MethodTy, SourceLocation ());
362- Method = CXXMethodDecl::Create (
363- AST, DeclBuilder.Record , SourceLocation (), NameInfo, MethodTy, TSInfo,
364- SC_None, false , false , ConstexprSpecKind::Unspecified, SourceLocation ());
387+ DeclarationNameInfo NameInfo = DeclarationNameInfo (Name, SourceLocation ());
388+ if (IsConstructor)
389+ Method = CXXConstructorDecl::Create (
390+ AST, DeclBuilder.Record , SourceLocation (), NameInfo, MethodTy, TSInfo,
391+ ExplicitSpecifier (), false , true , false ,
392+ ConstexprSpecKind::Unspecified);
393+ else
394+ Method =
395+ CXXMethodDecl::Create (AST, DeclBuilder.Record , SourceLocation (),
396+ NameInfo, MethodTy, TSInfo, SC_None, false , false ,
397+ ConstexprSpecKind::Unspecified, SourceLocation ());
365398
366399 // create params & set them to the function prototype
367400 SmallVector<ParmVarDecl *> ParmDecls;
368401 auto FnProtoLoc =
369402 Method->getTypeSourceInfo ()->getTypeLoc ().getAs <FunctionProtoTypeLoc>();
370403 for (int I = 0 , E = Params.size (); I != E; I++) {
371- MethodParam &MP = Params[I];
404+ Param &MP = Params[I];
372405 ParmVarDecl *Parm = ParmVarDecl::Create (
373406 AST, Method->getDeclContext (), SourceLocation (), SourceLocation (),
374407 &MP.NameII , MP.Ty ,
@@ -386,10 +419,7 @@ void BuiltinTypeMethodBuilder::createMethodDecl() {
386419}
387420
388421Expr *BuiltinTypeMethodBuilder::getResourceHandleExpr () {
389- // The first statement added to a method or access to 'this' creates the
390- // declaration.
391- if (!Method)
392- createMethodDecl ();
422+ ensureCompleteDecl ();
393423
394424 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
395425 CXXThisExpr *This = CXXThisExpr::Create (
@@ -407,10 +437,7 @@ BuiltinTypeMethodBuilder::callBuiltin(StringRef BuiltinName,
407437 std::array<Expr *, sizeof ...(ArgSpecs)> Args{
408438 convertPlaceholder (std::forward<Ts>(ArgSpecs))...};
409439
410- // The first statement added to a method or access to 'this` creates the
411- // declaration.
412- if (!Method)
413- createMethodDecl ();
440+ ensureCompleteDecl ();
414441
415442 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
416443 FunctionDecl *FD = lookupBuiltinFunction (DeclBuilder.SemaRef , BuiltinName);
@@ -454,8 +481,8 @@ BuiltinTypeMethodBuilder &BuiltinTypeMethodBuilder::dereference(T Ptr) {
454481BuiltinTypeDeclBuilder &BuiltinTypeMethodBuilder::finalizeMethod () {
455482 assert (!DeclBuilder.Record ->isCompleteDefinition () &&
456483 " record is already complete" );
457- assert (Method != nullptr &&
458- " method decl not created; are you missing a call to build the body? " );
484+
485+ ensureCompleteDecl ( );
459486
460487 if (!Method->hasBody ()) {
461488 ASTContext &AST = DeclBuilder.SemaRef .getASTContext ();
@@ -600,27 +627,18 @@ BuiltinTypeDeclBuilder::addHandleMember(ResourceClass RC, ResourceKind RK,
600627 return *this ;
601628}
602629
630+ // Adds default constructor to the resource class:
631+ // Resource::Resource()
603632BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDefaultHandleConstructor () {
604633 if (Record->isCompleteDefinition ())
605634 return *this ;
606- ASTContext &AST = Record->getASTContext ();
607635
608- QualType ConstructorType =
609- AST.getFunctionType (AST.VoidTy , {}, FunctionProtoType::ExtProtoInfo ());
610-
611- CanQualType CanTy = Record->getTypeForDecl ()->getCanonicalTypeUnqualified ();
612- DeclarationName Name = AST.DeclarationNames .getCXXConstructorName (CanTy);
613- CXXConstructorDecl *Constructor = CXXConstructorDecl::Create (
614- AST, Record, SourceLocation (),
615- DeclarationNameInfo (Name, SourceLocation ()), ConstructorType,
616- AST.getTrivialTypeSourceInfo (ConstructorType, SourceLocation ()),
617- ExplicitSpecifier (), false , true , false , ConstexprSpecKind::Unspecified);
618-
619- Constructor->setBody (CompoundStmt::Create (
620- AST, {}, FPOptionsOverride (), SourceLocation (), SourceLocation ()));
621- Constructor->setAccess (AccessSpecifier::AS_public);
622- Record->addDecl (Constructor);
623- return *this ;
636+ // FIXME: initialize handle to poison value; this can be added after
637+ // resource constructor from binding is implemented, otherwise the handle
638+ // value will get overwritten.
639+ return BuiltinTypeMethodBuilder (*this , " " , SemaRef.getASTContext ().VoidTy ,
640+ false , true )
641+ .finalizeMethod ();
624642}
625643
626644BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addArraySubscriptOperators () {
0 commit comments