diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h --- a/clang/include/clang/AST/ASTConcept.h +++ b/clang/include/clang/AST/ASTConcept.h @@ -14,7 +14,9 @@ #ifndef LLVM_CLANG_AST_ASTCONCEPT_H #define LLVM_CLANG_AST_ASTCONCEPT_H +#include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" @@ -107,9 +109,13 @@ Rebuild(const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction); }; +/* +NOTE(massberg): This will be our new AST node. +It is a reference to a conecpt and it template arguments. +*/ /// \brief Common data class for constructs that reference concepts with /// template arguments. -class ConceptReference { +class ConceptLoc { protected: // \brief The optional nested name specifier used when naming the concept. NestedNameSpecifierLoc NestedNameSpec; @@ -135,17 +141,26 @@ const ASTTemplateArgumentListInfo *ArgsAsWritten; public: - ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, - DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten) + ConceptLoc(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, + DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, + ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten) : NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {} - ConceptReference() + ConceptLoc() : FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {} + static ConceptLoc *Create(const ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, + DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten) { + return new (C) ConceptLoc(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, + NamedConcept, ArgsAsWritten); + } + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { return NestedNameSpec; } @@ -175,22 +190,27 @@ bool hasExplicitTemplateArgs() const { return ArgsAsWritten != nullptr; } + + void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const; }; -class TypeConstraint : public ConceptReference { +/* +NOTE(massberg): +A concept reference that uses abbreviated syntax to constrains a template +type parameter: + template T> void print(T object); + +*/ +class TypeConstraint { /// \brief The immediately-declared constraint expression introduced by this /// type-constraint. Expr *ImmediatelyDeclaredConstraint = nullptr; + ConceptLoc *Loc; public: - TypeConstraint(NestedNameSpecifierLoc NNS, - DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - Expr *ImmediatelyDeclaredConstraint) : - ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo, - FoundDecl, NamedConcept, ArgsAsWritten), - ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {} + TypeConstraint(ConceptLoc *Loc, Expr *ImmediatelyDeclaredConstraint) + : ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint), Loc(Loc) { + } /// \brief Get the immediately-declared constraint expression introduced by /// this type-constraint, that is - the constraint expression that is added to @@ -199,7 +219,38 @@ return ImmediatelyDeclaredConstraint; } - void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const; + ConceptLoc *getConceptLoc() const { return Loc; } + + // NOTE(massberg): For the first minimal prototype we keep the + // following functions to prevent. Later these functions should + // be accessed getConceptLoc(). + ConceptDecl *getNamedConcept() const { return Loc->getNamedConcept(); } + + SourceLocation getConceptNameLoc() const { return Loc->getConceptNameLoc(); } + + bool hasExplicitTemplateArgs() const { + return Loc->hasExplicitTemplateArgs(); + } + + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return Loc->getTemplateArgsAsWritten(); + } + + SourceLocation getTemplateKWLoc() const { return Loc->getTemplateKWLoc(); } + + NamedDecl *getFoundDecl() const { return Loc->getFoundDecl(); } + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return Loc->getNestedNameSpecifierLoc(); + } + + const DeclarationNameInfo &getConceptNameInfo() const { + return Loc->getConceptNameInfo(); + } + + void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { + Loc->print(OS, Policy); + } }; } // clang diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -1373,11 +1373,7 @@ nullptr; } - void setTypeConstraint(NestedNameSpecifierLoc NNS, - DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, - ConceptDecl *CD, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - Expr *ImmediatelyDeclaredConstraint); + void setTypeConstraint(ConceptLoc *Loc, Expr *ImmediatelyDeclaredConstraint); /// Determine whether this template parameter has a type-constraint. bool hasTypeConstraint() const { diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h --- a/clang/include/clang/AST/ExprConcepts.h +++ b/clang/include/clang/AST/ExprConcepts.h @@ -38,7 +38,7 @@ /// /// According to C++2a [expr.prim.id]p3 an id-expression that denotes the /// specialization of a concept results in a prvalue of type bool. -class ConceptSpecializationExpr final : public Expr, public ConceptReference { +class ConceptSpecializationExpr final : public Expr { friend class ASTReader; friend class ASTStmtReader; @@ -46,6 +46,8 @@ using SubstitutionDiagnostic = std::pair; protected: + ConceptLoc *Loc; + /// \brief The Implicit Concept Specialization Decl, which holds the template /// arguments for this specialization. ImplicitConceptSpecializationDecl *SpecDecl; @@ -55,16 +57,11 @@ /// ignored. ASTConstraintSatisfaction *Satisfaction; - ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, - DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, + ConceptSpecializationExpr(const ASTContext &C, ConceptLoc *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); - ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, + ConceptSpecializationExpr(const ASTContext &C, ConceptLoc *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, @@ -73,16 +70,12 @@ public: static ConceptSpecializationExpr * - Create(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, + Create(const ASTContext &C, ConceptLoc *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); static ConceptSpecializationExpr * - Create(const ASTContext &C, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, + Create(const ASTContext &C, ConceptLoc *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack); @@ -91,6 +84,34 @@ return SpecDecl->getTemplateArguments(); } + const ConceptLoc *getConceptLoc() const { return Loc; } + + // NOTE(massberg): For the first minimal prototype we keep the + // following functions to prevent. Later these functions should + // be accessed getConceptLoc(). + ConceptDecl *getNamedConcept() const { return Loc->getNamedConcept(); } + + bool hasExplicitTemplateArgs() const { + return Loc->hasExplicitTemplateArgs(); + } + + SourceLocation getConceptNameLoc() const { return Loc->getConceptNameLoc(); } + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return Loc->getTemplateArgsAsWritten(); + } + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return Loc->getNestedNameSpecifierLoc(); + } + + SourceLocation getTemplateKWLoc() const { return Loc->getTemplateKWLoc(); } + + NamedDecl *getFoundDecl() const { return Loc->getFoundDecl(); } + + const DeclarationNameInfo &getConceptNameInfo() const { + return Loc->getConceptNameInfo(); + } + const ImplicitConceptSpecializationDecl *getSpecializationDecl() const { assert(SpecDecl && "Template Argument Decl not initialized"); return SpecDecl; @@ -119,17 +140,19 @@ } SourceLocation getBeginLoc() const LLVM_READONLY { - if (auto QualifierLoc = getNestedNameSpecifierLoc()) + if (auto QualifierLoc = Loc->getNestedNameSpecifierLoc()) return QualifierLoc.getBeginLoc(); - return ConceptName.getBeginLoc(); + return Loc->getConceptNameInfo().getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { // If the ConceptSpecializationExpr is the ImmediatelyDeclaredConstraint // of a TypeConstraint written syntactically as a constrained-parameter, // there may not be a template argument list. - return ArgsAsWritten->RAngleLoc.isValid() ? ArgsAsWritten->RAngleLoc - : ConceptName.getEndLoc(); + return Loc->hasExplicitTemplateArgs() && + Loc->getTemplateArgsAsWritten()->getRAngleLoc().isValid() + ? Loc->getTemplateArgsAsWritten()->getRAngleLoc() + : Loc->getConceptNameInfo().getEndLoc(); } // Iterators diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -312,6 +312,10 @@ /// \returns false if the visitation was terminated early, true otherwise. bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc); + /// Recursively visit concept reference with location information. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseConceptLoc(const ConceptLoc *CL); // ---- Methods on Attrs ---- // Visit an attribute. @@ -469,9 +473,6 @@ private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - /// Traverses the qualifier, name and template arguments of a concept - /// reference. - bool TraverseConceptReferenceHelper(const ConceptReference &C); // Traverses template parameter lists of either a DeclaratorDecl or TagDecl. template @@ -507,17 +508,17 @@ bool RecursiveASTVisitor::TraverseTypeConstraint( const TypeConstraint *C) { if (!getDerived().shouldVisitImplicitCode()) { - TRY_TO(TraverseConceptReferenceHelper(*C)); + TRY_TO(TraverseConceptLoc(C->getConceptLoc())); return true; } if (Expr *IDC = C->getImmediatelyDeclaredConstraint()) { TRY_TO(TraverseStmt(IDC)); } else { - // Avoid traversing the ConceptReference in the TypeConstraint + // Avoid traversing the ConceptLoc in the TypeConstraint // if we have an immediately-declared-constraint, otherwise // we'll end up visiting the concept and the arguments in // the TC twice. - TRY_TO(TraverseConceptReferenceHelper(*C)); + TRY_TO(TraverseConceptLoc(C->getConceptLoc())); } return true; } @@ -540,18 +541,6 @@ llvm_unreachable("unexpected case"); } -template -bool RecursiveASTVisitor::TraverseConceptReferenceHelper( - const ConceptReference &C) { - TRY_TO(TraverseNestedNameSpecifierLoc(C.getNestedNameSpecifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(C.getConceptNameInfo())); - if (C.hasExplicitTemplateArgs()) - TRY_TO(TraverseTemplateArgumentLocsHelper( - C.getTemplateArgsAsWritten()->getTemplateArgs(), - C.getTemplateArgsAsWritten()->NumTemplateArgs)); - return true; -} - template bool RecursiveASTVisitor::dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) { @@ -1356,10 +1345,7 @@ DEF_TRAVERSE_TYPELOC(AutoType, { TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType())); if (TL.isConstrained()) { - TRY_TO(TraverseNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc())); - TRY_TO(TraverseDeclarationNameInfo(TL.getConceptNameInfo())); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + TRY_TO(TraverseConceptLoc(TL.getConceptLoc())); } }) @@ -2522,6 +2508,17 @@ return true; } +template +bool RecursiveASTVisitor::TraverseConceptLoc(const ConceptLoc *CL) { + TRY_TO(TraverseNestedNameSpecifierLoc(CL->getNestedNameSpecifierLoc())); + TRY_TO(TraverseDeclarationNameInfo(CL->getConceptNameInfo())); + if (CL->hasExplicitTemplateArgs()) + TRY_TO(TraverseTemplateArgumentLocsHelper( + CL->getTemplateArgsAsWritten()->getTemplateArgs(), + CL->getTemplateArgsAsWritten()->NumTemplateArgs)); + return true; +} + // If shouldVisitImplicitCode() returns false, this method traverses only the // syntactic form of InitListExpr. // If shouldVisitImplicitCode() return true, this method is called once for @@ -2900,7 +2897,7 @@ }) DEF_TRAVERSE_STMT(ConceptSpecializationExpr, - { TRY_TO(TraverseConceptReferenceHelper(*S)); }) + { TRY_TO(TraverseConceptLoc(S->getConceptLoc())); }) DEF_TRAVERSE_STMT(RequiresExpr, { TRY_TO(TraverseDecl(S->getBody())); diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_TYPELOC_H #define LLVM_CLANG_AST_TYPELOC_H +#include "clang/AST/ASTConcept.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" @@ -2104,16 +2105,14 @@ DeducedType> {}; struct AutoTypeLocInfo : TypeSpecLocInfo { - NestedNameSpecifierLoc NestedNameSpec; - SourceLocation TemplateKWLoc; - SourceLocation ConceptNameLoc; - NamedDecl *FoundDecl = nullptr; SourceLocation LAngleLoc; SourceLocation RAngleLoc; // For decltype(auto). SourceLocation RParenLoc; + SourceLocation DefaultLoc; + ConceptLoc *CL = nullptr; // Followed by a TemplateArgumentLocInfo[] }; @@ -2135,43 +2134,51 @@ return getTypePtr()->isConstrained(); } - const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { - return getLocalData()->NestedNameSpec; + void setConceptLoc(ConceptLoc *Loc) { + getLocalData()->CL = Loc; + if (Loc == nullptr) + return; } - void setNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { - getLocalData()->NestedNameSpec = NNS; - } + ConceptLoc *getConceptLoc() const { return getLocalData()->CL; } - SourceLocation getTemplateKWLoc() const { - return getLocalData()->TemplateKWLoc; - } + void setDefaultLoc(SourceLocation Loc) { getLocalData()->DefaultLoc = Loc; } - void setTemplateKWLoc(SourceLocation Loc) { - getLocalData()->TemplateKWLoc = Loc; - } + SourceLocation getDefaultLoc() const { return getLocalData()->DefaultLoc; } - SourceLocation getConceptNameLoc() const { - return getLocalData()->ConceptNameLoc; + const NestedNameSpecifierLoc getNestedNameSpecifierLoc() const { + if (getConceptLoc()) + return getConceptLoc()->getNestedNameSpecifierLoc(); + return NestedNameSpecifierLoc(); } - void setConceptNameLoc(SourceLocation Loc) { - getLocalData()->ConceptNameLoc = Loc; + SourceLocation getTemplateKWLoc() const { + if (getConceptLoc()) + return getConceptLoc()->getTemplateKWLoc(); + return getDefaultLoc(); } - NamedDecl *getFoundDecl() const { - return getLocalData()->FoundDecl; + SourceLocation getConceptNameLoc() const { + if (getConceptLoc()) + return getConceptLoc()->getConceptNameLoc(); + return getDefaultLoc(); } - void setFoundDecl(NamedDecl *D) { - getLocalData()->FoundDecl = D; + NamedDecl *getFoundDecl() const { + if (getConceptLoc()) + return getConceptLoc()->getFoundDecl(); + return nullptr; } ConceptDecl *getNamedConcept() const { - return getTypePtr()->getTypeConstraintConcept(); + if (getConceptLoc()) + return getConceptLoc()->getNamedConcept(); + return nullptr; } - DeclarationNameInfo getConceptNameInfo() const; + DeclarationNameInfo getConceptNameInfo() const { + return getConceptLoc()->getConceptNameInfo(); + } bool hasExplicitTemplateArgs() const { return getLocalData()->LAngleLoc.isValid(); @@ -2197,17 +2204,13 @@ return getTypePtr()->getTypeConstraintArguments().size(); } - void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { - getArgInfos()[i] = AI; - } - - TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { - return getArgInfos()[i]; - } - TemplateArgumentLoc getArgLoc(unsigned i) const { + if (getConceptLoc()) + return getConceptLoc()->getTemplateArgsAsWritten()->getTemplateArgs()[i]; + // FIXME: Check why we still need this fallback in case that there is no + // ConceptLoc. return TemplateArgumentLoc(getTypePtr()->getTypeConstraintArguments()[i], - getArgLocInfo(i)); + getArgInfos()[i]); } SourceRange getLocalSourceRange() const { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6345,11 +6345,12 @@ auto *NCY = YTC->getNamedConcept(); if (!NCX || !NCY || !isSameEntity(NCX, NCY)) return false; - if (XTC->hasExplicitTemplateArgs() != YTC->hasExplicitTemplateArgs()) + if (XTC->getConceptLoc()->hasExplicitTemplateArgs() != + YTC->getConceptLoc()->hasExplicitTemplateArgs()) return false; - if (XTC->hasExplicitTemplateArgs()) - if (XTC->getTemplateArgsAsWritten()->NumTemplateArgs != - YTC->getTemplateArgsAsWritten()->NumTemplateArgs) + if (XTC->getConceptLoc()->hasExplicitTemplateArgs()) + if (XTC->getConceptLoc()->getTemplateArgsAsWritten()->NumTemplateArgs != + YTC->getConceptLoc()->getTemplateArgsAsWritten()->NumTemplateArgs) return false; // Compare slowly by profiling. diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5652,13 +5652,14 @@ if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo)) return std::move(Err); - - ToD->setTypeConstraint(ToNNS, DeclarationNameInfo(ToName, ToNameLoc), - ToFoundDecl, ToNamedConcept, - ASTTemplateArgs ? - ASTTemplateArgumentListInfo::Create(Importer.getToContext(), - ToTAInfo) : nullptr, - ToIDC); + auto *CL = ConceptLoc::Create( + Importer.getToContext(), ToNNS, + ToNameLoc, // What is the right Loc here? + DeclarationNameInfo(ToName, ToNameLoc), ToFoundDecl, ToNamedConcept, + ASTTemplateArgs ? ASTTemplateArgumentListInfo::Create( + Importer.getToContext(), ToTAInfo) + : nullptr); + ToD->setTypeConstraint(CL, ToIDC); } if (D->hasDefaultArgument()) { diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -697,17 +697,15 @@ return getTypeForDecl()->castAs()->isParameterPack(); } -void TemplateTypeParmDecl::setTypeConstraint(NestedNameSpecifierLoc NNS, - DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, ConceptDecl *CD, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - Expr *ImmediatelyDeclaredConstraint) { +void TemplateTypeParmDecl::setTypeConstraint( + ConceptLoc *Loc, Expr *ImmediatelyDeclaredConstraint) { assert(HasTypeConstraint && "HasTypeConstraint=true must be passed at construction in order to " "call setTypeConstraint"); assert(!TypeConstraintInitialized && "TypeConstraint was already initialized!"); - new (getTrailingObjects()) TypeConstraint(NNS, NameInfo, - FoundDecl, CD, ArgsAsWritten, ImmediatelyDeclaredConstraint); + new (getTrailingObjects()) + TypeConstraint(Loc, ImmediatelyDeclaredConstraint); TypeConstraintInitialized = true; } @@ -1554,7 +1552,7 @@ createBuiltinTemplateParameterList(C, DC, BTK)), BTK(BTK) {} -void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { +void ConceptLoc::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { if (NestedNameSpec) NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy); ConceptName.printName(OS, Policy); diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp --- a/clang/lib/AST/ExprConcepts.cpp +++ b/clang/lib/AST/ExprConcepts.cpp @@ -31,26 +31,24 @@ using namespace clang; ConceptSpecializationExpr::ConceptSpecializationExpr( - const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, + const ASTContext &C, ConceptLoc *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction) : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), - ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, - NamedConcept, ArgsAsWritten), - SpecDecl(SpecDecl), + Loc(Loc), SpecDecl(SpecDecl), Satisfaction(Satisfaction ? ASTConstraintSatisfaction::Create(C, *Satisfaction) : nullptr) { setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction)); // Currently guaranteed by the fact concepts can only be at namespace-scope. - assert(!NestedNameSpec || - (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() && - !NestedNameSpec.getNestedNameSpecifier() - ->containsUnexpandedParameterPack())); + assert(!Loc->getNestedNameSpecifierLoc() || + (!Loc->getNestedNameSpecifierLoc() + .getNestedNameSpecifier() + ->isInstantiationDependent() && + !Loc->getNestedNameSpecifierLoc() + .getNestedNameSpecifier() + ->containsUnexpandedParameterPack())); assert((!isValueDependent() || isInstantiationDependent()) && "should not be value-dependent"); } @@ -58,29 +56,20 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty) : Expr(ConceptSpecializationExprClass, Empty) {} -ConceptSpecializationExpr *ConceptSpecializationExpr::Create( - const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ImplicitConceptSpecializationDecl *SpecDecl, - const ConstraintSatisfaction *Satisfaction) { - return new (C) ConceptSpecializationExpr( - C, NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, - ArgsAsWritten, SpecDecl, Satisfaction); +ConceptSpecializationExpr * +ConceptSpecializationExpr::Create(const ASTContext &C, ConceptLoc *Loc, + ImplicitConceptSpecializationDecl *SpecDecl, + const ConstraintSatisfaction *Satisfaction) { + return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction); } ConceptSpecializationExpr::ConceptSpecializationExpr( - const ASTContext &C, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, + const ASTContext &C, ConceptLoc *Loc, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack) : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), - ConceptReference(NestedNameSpecifierLoc(), SourceLocation(), - DeclarationNameInfo(), NamedConcept, NamedConcept, - ArgsAsWritten), - SpecDecl(SpecDecl), + Loc(Loc), SpecDecl(SpecDecl), Satisfaction(Satisfaction ? ASTConstraintSatisfaction::Create(C, *Satisfaction) : nullptr) { @@ -94,15 +83,15 @@ setDependence(D); } -ConceptSpecializationExpr *ConceptSpecializationExpr::Create( - const ASTContext &C, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ImplicitConceptSpecializationDecl *SpecDecl, - const ConstraintSatisfaction *Satisfaction, bool Dependent, - bool ContainsUnexpandedParameterPack) { - return new (C) ConceptSpecializationExpr(C, NamedConcept, ArgsAsWritten, - SpecDecl, Satisfaction, Dependent, - ContainsUnexpandedParameterPack); +ConceptSpecializationExpr * +ConceptSpecializationExpr::Create(const ASTContext &C, ConceptLoc *Loc, + ImplicitConceptSpecializationDecl *SpecDecl, + const ConstraintSatisfaction *Satisfaction, + bool Dependent, + bool ContainsUnexpandedParameterPack) { + return new (C) + ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent, + ContainsUnexpandedParameterPack); } const TypeConstraint * diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -621,25 +621,17 @@ } } -DeclarationNameInfo AutoTypeLoc::getConceptNameInfo() const { - return DeclarationNameInfo(getNamedConcept()->getDeclName(), - getLocalData()->ConceptNameLoc); -} - void AutoTypeLoc::initializeLocal(ASTContext &Context, SourceLocation Loc) { - setNestedNameSpecifierLoc(NestedNameSpecifierLoc()); - setTemplateKWLoc(Loc); - setConceptNameLoc(Loc); - setFoundDecl(nullptr); setRAngleLoc(Loc); setLAngleLoc(Loc); setRParenLoc(Loc); TemplateSpecializationTypeLoc::initializeArgLocs( Context, getTypePtr()->getTypeConstraintArguments(), getArgInfos(), Loc); setNameLoc(Loc); + setConceptLoc(nullptr); + setDefaultLoc(Loc); } - namespace { class GetContainedAutoTypeLocVisitor : diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -23,6 +23,7 @@ #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" @@ -1256,9 +1257,13 @@ if (ImmediatelyDeclaredConstraint.isInvalid()) return true; - ConstrainedParameter->setTypeConstraint(NS, NameInfo, - /*FoundDecl=*/NamedConcept, - NamedConcept, ArgsAsWritten, + auto *CL = ConceptLoc::Create(Context, /*NNS=*/NS, + /*TemplateKWLoc=*/SourceLocation{}, + /*ConceptNameInfo=*/NameInfo, + /*FoundDecl=*/NamedConcept, + /*NamedConcept=*/NamedConcept, + /*ArgsWritten=*/ArgsAsWritten); + ConstrainedParameter->setTypeConstraint(CL, ImmediatelyDeclaredConstraint.get()); return false; } @@ -4941,13 +4946,13 @@ TemplateArgs->getRAngleLoc()), Satisfaction)) return ExprError(); - - return ConceptSpecializationExpr::Create( + auto *CL = ConceptLoc::Create( Context, SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{}, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, - ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs), CSD, - AreArgsDependent ? nullptr : &Satisfaction); + ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs)); + return ConceptSpecializationExpr::Create( + Context, CL, CSD, AreArgsDependent ? nullptr : &Satisfaction); } ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2764,11 +2764,9 @@ TC->getTemplateArgsAsWritten(); if (!EvaluateConstraints) { - Inst->setTypeConstraint(TC->getNestedNameSpecifierLoc(), - TC->getConceptNameInfo(), TC->getNamedConcept(), - TC->getNamedConcept(), TemplArgInfo, - TC->getImmediatelyDeclaredConstraint()); - return false; + Inst->setTypeConstraint(TC->getConceptLoc(), + TC->getImmediatelyDeclaredConstraint()); + return false; } TemplateArgumentListInfo InstArgs; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -6300,24 +6300,33 @@ TemplateIdAnnotation *TemplateId = DS.getRepAsTemplateId(); if (!TemplateId) return; - if (DS.getTypeSpecScope().isNotEmpty()) - TL.setNestedNameSpecifierLoc( - DS.getTypeSpecScope().getWithLocInContext(Context)); - else - TL.setNestedNameSpecifierLoc(NestedNameSpecifierLoc()); - TL.setTemplateKWLoc(TemplateId->TemplateKWLoc); - TL.setConceptNameLoc(TemplateId->TemplateNameLoc); - TL.setFoundDecl(nullptr); + + NestedNameSpecifierLoc NNS = + (DS.getTypeSpecScope().isNotEmpty() + ? DS.getTypeSpecScope().getWithLocInContext(Context) + : NestedNameSpecifierLoc()); TL.setLAngleLoc(TemplateId->LAngleLoc); TL.setRAngleLoc(TemplateId->RAngleLoc); - if (TemplateId->NumArgs == 0) - return; TemplateArgumentListInfo TemplateArgsInfo; - ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), - TemplateId->NumArgs); - SemaRef.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo); - for (unsigned I = 0; I < TemplateId->NumArgs; ++I) - TL.setArgLocInfo(I, TemplateArgsInfo.arguments()[I].getLocInfo()); + if (TemplateId->NumArgs > 0) { + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + SemaRef.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo); + /*for (unsigned I = 0; I < TemplateId->NumArgs; ++I) + TL.setArgLocInfo(I, TemplateArgsInfo.arguments()[I].getLocInfo());*/ + } + // FIXME: Move to VisitConceptLoc, + DeclarationNameInfo DNI = DeclarationNameInfo( + TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(), + TemplateId->TemplateNameLoc); + auto *CL = ConceptLoc::Create( + Context, NNS, TemplateId->TemplateKWLoc, DNI, + /*FoundDecl=*/nullptr, + /*NamedDecl=*/TL.getTypePtr()->getTypeConstraintConcept(), + (TemplateId->NumArgs > 0 + ? ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo) + : nullptr)); + TL.setConceptLoc(CL); } void VisitTagTypeLoc(TagTypeLoc TL) { TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -41,6 +41,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorHandling.h" #include +#include #include using namespace llvm::omp; @@ -783,6 +784,8 @@ StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S); + // ActionResult TransformConceptLoc(const ConceptLoc *L); + // FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous // amount of stack usage with clang. #define STMT(Node, Parent) \ @@ -3597,6 +3600,8 @@ return Result; } + /* NOTE(massberg) We need probably a RebuildConceptLoc here.*/ + /// \brief Build a new requires expression. /// /// By default, performs semantic analysis to build the new expression. @@ -6846,15 +6851,28 @@ AutoTypeLoc NewTL = TLB.push(Result); NewTL.setNameLoc(TL.getNameLoc()); - NewTL.setNestedNameSpecifierLoc(NewNestedNameSpec); - NewTL.setTemplateKWLoc(TL.getTemplateKWLoc()); - NewTL.setConceptNameLoc(TL.getConceptNameLoc()); - NewTL.setFoundDecl(TL.getFoundDecl()); NewTL.setLAngleLoc(TL.getLAngleLoc()); NewTL.setRAngleLoc(TL.getRAngleLoc()); NewTL.setRParenLoc(TL.getRParenLoc()); - for (unsigned I = 0; I < NewTL.getNumArgs(); ++I) - NewTL.setArgLocInfo(I, NewTemplateArgs.arguments()[I].getLocInfo()); + + if (T->isConstrained()) { + // FIXME: move to TransformConceptLoc + DeclarationNameInfo DNI = DeclarationNameInfo(); + DNI.setLoc(TL.getConceptNameLoc()); + if (T->isConstrained()) { + DNI.setName(TL.getTypePtr()->getTypeConstraintConcept()->getDeclName()); + DNI.setInfo(TL.getTypePtr()->getTypeConstraintConcept()->getDeclName()); + } + auto *CL = ConceptLoc::Create( + SemaRef.Context, NewNestedNameSpec, TL.getTemplateKWLoc(), DNI, + TL.getFoundDecl(), + (T->isConstrained() ? TL.getTypePtr()->getTypeConstraintConcept() + : nullptr), + (NewTemplateArgs.size() > 0 ? ASTTemplateArgumentListInfo::Create( + SemaRef.Context, NewTemplateArgs) + : nullptr)); + NewTL.setConceptLoc(CL); + } return Result; } @@ -12869,6 +12887,21 @@ &TransArgs); } +/*template +ExprResult +TreeTransform::TransformConceptLoc(const ConceptLoc *CL) { + const ASTTemplateArgumentListInfo *Old = CL->getTemplateArgsAsWritten(); + TemplateArgumentListInfo TransArgs(Old->LAngleLoc, Old->RAngleLoc); + if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(), + Old->NumTemplateArgs, TransArgs)) + return ExprError; + + return getDerived().RebuildConceptLoc( + CL->getNestedNameSpecifierLoc(), CL->getTemplateKWLoc(), + CL->getConceptNameInfo(), CL->getFoundDecl(), CL->getNamedConcept(), + &TransArgs); +}*/ + template ExprResult TreeTransform::TransformRequiresExpr(RequiresExpr *E) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -6809,16 +6809,24 @@ void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) { TL.setNameLoc(readSourceLocation()); if (Reader.readBool()) { - TL.setNestedNameSpecifierLoc(ReadNestedNameSpecifierLoc()); - TL.setTemplateKWLoc(readSourceLocation()); - TL.setConceptNameLoc(readSourceLocation()); - TL.setFoundDecl(Reader.readDeclAs()); TL.setLAngleLoc(readSourceLocation()); TL.setRAngleLoc(readSourceLocation()); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo( - i, Reader.readTemplateArgumentLocInfo( - TL.getTypePtr()->getTypeConstraintArguments()[i].getKind())); + // FIXME: Move to VisitConceptLoc() + TL.setDefaultLoc(readSourceLocation()); + if (Reader.readBool()) { + auto NNS = ReadNestedNameSpecifierLoc(); + auto TemplateKWLoc = readSourceLocation(); + auto ConceptNameLoc = Reader.readDeclarationNameInfo(); + auto FoundDecl = Reader.readDeclAs(); + auto NamedConcept = Reader.readDeclAs(); + + auto *CL = ConceptLoc::Create( + Reader.getContext(), NNS, TemplateKWLoc, ConceptNameLoc, FoundDecl, + NamedConcept, + (Reader.readBool() ? Reader.readASTTemplateArgumentListInfo() + : nullptr)); + TL.setConceptLoc(CL); + } } if (Reader.readBool()) TL.setRParenLoc(readSourceLocation()); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2627,8 +2627,12 @@ if (Record.readBool()) ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); Expr *ImmediatelyDeclaredConstraint = Record.readExpr(); - D->setTypeConstraint(NNS, DN, /*FoundDecl=*/nullptr, NamedConcept, - ArgsAsWritten, ImmediatelyDeclaredConstraint); + auto *CL = ConceptLoc::Create( + Reader.getContext(), NNS, + SourceLocation{}, // What is the correct value here? + DN, /*FoundDecl=*/nullptr, NamedConcept, ArgsAsWritten); + + D->setTypeConstraint(CL, ImmediatelyDeclaredConstraint); if ((D->ExpandedParameterPack = Record.readInt())) D->NumExpanded = Record.readInt(); } diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -795,13 +795,16 @@ void ASTStmtReader::VisitConceptSpecializationExpr( ConceptSpecializationExpr *E) { VisitExpr(E); - E->NestedNameSpec = Record.readNestedNameSpecifierLoc(); - E->TemplateKWLoc = Record.readSourceLocation(); - E->ConceptName = Record.readDeclarationNameInfo(); - E->NamedConcept = readDeclAs(); - E->FoundDecl = Record.readDeclAs(); + auto NestedNameSpec = Record.readNestedNameSpecifierLoc(); + auto TemplateKWLoc = Record.readSourceLocation(); + auto ConceptName = Record.readDeclarationNameInfo(); + auto NamedConcept = readDeclAs(); + auto FoundDecl = Record.readDeclAs(); E->SpecDecl = Record.readDeclAs(); - E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); + auto ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); + E->Loc = + ConceptLoc::Create(Record.getContext(), NestedNameSpec, TemplateKWLoc, + ConceptName, FoundDecl, NamedConcept, ArgsAsWritten); E->Satisfaction = E->isValueDependent() ? nullptr : ASTConstraintSatisfaction::Create(Record.getContext(), readConstraintSatisfaction(Record)); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -473,16 +473,23 @@ addSourceLocation(TL.getNameLoc()); Record.push_back(TL.isConstrained()); if (TL.isConstrained()) { - Record.AddNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc()); - addSourceLocation(TL.getTemplateKWLoc()); - addSourceLocation(TL.getConceptNameLoc()); - Record.AddDeclRef(TL.getFoundDecl()); addSourceLocation(TL.getLAngleLoc()); addSourceLocation(TL.getRAngleLoc()); - for (unsigned I = 0; I < TL.getNumArgs(); ++I) - Record.AddTemplateArgumentLocInfo( - TL.getTypePtr()->getTypeConstraintArguments()[I].getKind(), - TL.getArgLocInfo(I)); + Record.AddSourceLocation(TL.getDefaultLoc()); + + // FIXME: Move to VisitConceptLoc() + auto *CL = TL.getConceptLoc(); + Record.push_back(CL != nullptr); + if (CL) { + Record.AddNestedNameSpecifierLoc(CL->getNestedNameSpecifierLoc()); + Record.AddSourceLocation(CL->getTemplateKWLoc()); + Record.AddDeclarationNameInfo(CL->getConceptNameInfo()); + Record.AddDeclRef(CL->getFoundDecl()); + Record.AddDeclRef(CL->getNamedConcept()); + Record.push_back(CL->getTemplateArgsAsWritten() != nullptr); + if (CL->getTemplateArgsAsWritten()) + Record.AddASTTemplateArgumentListInfo(CL->getTemplateArgsAsWritten()); + } } Record.push_back(TL.isDecltypeAuto()); if (TL.isDecltypeAuto()) diff --git a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp --- a/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp +++ b/clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp @@ -29,12 +29,17 @@ ++ConceptRequirementsTraversed; return ExpectedLocationVisitor::TraverseConceptRequirement(R); } + bool TraverseConceptLoc(const ConceptLoc *CL) { + ++ConceptLocsTraversed; + return ExpectedLocationVisitor::TraverseConceptLoc(CL); + } bool shouldVisitImplicitCode() { return ShouldVisitImplicitCode; } int ConceptSpecializationExprsVisited = 0; int TypeConstraintsTraversed = 0; int ConceptRequirementsTraversed = 0; + int ConceptLocsTraversed = 0; bool ShouldVisitImplicitCode = false; }; @@ -50,6 +55,7 @@ EXPECT_EQ(1, Visitor.ConceptSpecializationExprsVisited); // Also check we traversed the TypeConstraint that produced the expr. EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); + EXPECT_EQ(1, Visitor.ConceptLocsTraversed); Visitor = {}; // Don't visit implicit code now. EXPECT_TRUE(Visitor.runOver("template concept Fooable = true;\n" @@ -59,6 +65,7 @@ // generated immediately declared expression. EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited); EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); + EXPECT_EQ(1, Visitor.ConceptLocsTraversed); Visitor = {}; EXPECT_TRUE(Visitor.runOver("template concept A = true;\n" @@ -70,6 +77,7 @@ "};", ConceptVisitor::Lang_CXX2a)); EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed); + EXPECT_EQ(1, Visitor.ConceptLocsTraversed); } struct VisitDeclOnlyOnce : ExpectedLocationVisitor {