================ @@ -323,30 +324,127 @@ struct TemplateParameterListBuilder { S.Context, Builder.Record->getDeclContext(), SourceLocation(), SourceLocation(), /* TemplateDepth */ 0, Position, &S.Context.Idents.get(Name, tok::TokenKind::identifier), - /* Typename */ false, - /* ParameterPack */ false); + /* Typename */ true, + /* ParameterPack */ false, + /* HasTypeConstraint*/ false); if (!DefaultValue.isNull()) Decl->setDefaultArgument( S.Context, S.getTrivialTemplateArgumentLoc(DefaultValue, QualType(), SourceLocation())); - Params.emplace_back(Decl); return *this; } - BuiltinTypeDeclBuilder &finalizeTemplateArgs() { + /* + The concept specialization expression (CSE) constructed below is constructed + so that it matches the CSE that is constructed when parsing + the below C++ code: + + template<typename T> + concept is_valid_line_vector =sizeof(T) <= 16; + + template<typename element_type> requires is_valid_line_vector<element_type> + + struct RWBuffer { + element_type Val; + }; + + int fn() { + RWBuffer<int> Buf; + } + + When dumping the AST and filtering for "RWBuffer", the resulting AST + structure is what we're trying to construct below, specifically the + CSE portion. + */ + ConceptSpecializationExpr * + constructConceptSpecializationExpr(Sema &S, ConceptDecl *CD) { + ASTContext &Context = S.getASTContext(); + SourceLocation Loc = Builder.Record->getBeginLoc(); + DeclarationNameInfo DNI(CD->getDeclName(), Loc); + NestedNameSpecifierLoc NNSLoc; + DeclContext *DC = Builder.Record->getDeclContext(); + TemplateArgumentListInfo TALI(Loc, Loc); + + // Assume that the concept decl has just one template parameter + // This parameter should have been added when CD was constructed + // in getTypedBufferConceptDecl + assert(CD->getTemplateParameters()->size() == 1 && + "unexpected concept decl parameter count"); + TemplateTypeParmDecl *ConceptTTPD = dyn_cast<TemplateTypeParmDecl>( + CD->getTemplateParameters()->getParam(0)); + + // this fake TemplateTypeParmDecl is used to construct a template argument + // that will be used to construct the ImplicitConceptSpecializationDecl + TemplateTypeParmDecl *T = TemplateTypeParmDecl::Create( + Context, // AST context + Context.getTranslationUnitDecl(), // DeclContext + SourceLocation(), SourceLocation(), + /*depth=*/0, // Depth in the template parameter list + /*position=*/0, // Position in the template parameter list + /*id=*/nullptr, // Identifier for 'T' + /*Typename=*/true, // Indicates this is a 'typename' or 'class' + /*ParameterPack=*/false, // Not a parameter pack + /*HasTypeConstraint=*/false // Has no type constraint + ); + + T->setDeclContext(DC); + T->setReferenced(); ---------------- bob80905 wrote:
Setting the decl context is necessary because it puts the decl into the right indentation in the AST dump. Otherwise, I believe the decl would be placed at the same scope as one indentation below the translation unit decl, which is not where the decl belongs. I'll see if I can get away with removing setReferenced here. https://github.com/llvm/llvm-project/pull/112600 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits