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,13 @@ /// \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); + + // Visit concept loc. + bool VisitConceptLoc(const ConceptLoc *CL) { return true; } // ---- Methods on Attrs ---- // Visit an attribute. @@ -469,9 +476,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 +511,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 +544,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 +1348,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 +2511,18 @@ return true; } +template +bool RecursiveASTVisitor::TraverseConceptLoc(const ConceptLoc *CL) { + TRY_TO(VisitConceptLoc(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 +2901,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,10 @@ DeducedType> {}; struct AutoTypeLocInfo : TypeSpecLocInfo { - NestedNameSpecifierLoc NestedNameSpec; - SourceLocation TemplateKWLoc; - SourceLocation ConceptNameLoc; - NamedDecl *FoundDecl = nullptr; - SourceLocation LAngleLoc; - SourceLocation RAngleLoc; - // For decltype(auto). SourceLocation RParenLoc; + ConceptLoc *CL = nullptr; // Followed by a TemplateArgumentLocInfo[] }; @@ -2135,79 +2130,75 @@ return getTypePtr()->isConstrained(); } - const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { - return getLocalData()->NestedNameSpec; - } + void setConceptLoc(ConceptLoc *Loc) { getLocalData()->CL = Loc; } - void setNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { - getLocalData()->NestedNameSpec = NNS; - } + ConceptLoc *getConceptLoc() const { return getLocalData()->CL; } - SourceLocation getTemplateKWLoc() const { - return getLocalData()->TemplateKWLoc; + // FIXME: Deprecate the following function and let the caller directly + // work with the ConceptLoc. + const NestedNameSpecifierLoc getNestedNameSpecifierLoc() const { + if (getConceptLoc()) + return getConceptLoc()->getNestedNameSpecifierLoc(); + return NestedNameSpecifierLoc(); } - void setTemplateKWLoc(SourceLocation Loc) { - getLocalData()->TemplateKWLoc = Loc; + SourceLocation getTemplateKWLoc() const { + if (getConceptLoc()) + return getConceptLoc()->getTemplateKWLoc(); + return SourceLocation(); } SourceLocation getConceptNameLoc() const { - return getLocalData()->ConceptNameLoc; - } - - void setConceptNameLoc(SourceLocation Loc) { - getLocalData()->ConceptNameLoc = Loc; + if (getConceptLoc()) + return getConceptLoc()->getConceptNameLoc(); + return SourceLocation(); } NamedDecl *getFoundDecl() const { - return getLocalData()->FoundDecl; - } - - void setFoundDecl(NamedDecl *D) { - getLocalData()->FoundDecl = D; + 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(); + return ( + getConceptLoc() && getConceptLoc()->getTemplateArgsAsWritten() && + getConceptLoc()->getTemplateArgsAsWritten()->getLAngleLoc().isValid()); } SourceLocation getLAngleLoc() const { - return this->getLocalData()->LAngleLoc; - } - - void setLAngleLoc(SourceLocation Loc) { - this->getLocalData()->LAngleLoc = Loc; + if (getConceptLoc() && getConceptLoc()->getTemplateArgsAsWritten()) + return getConceptLoc()->getTemplateArgsAsWritten()->getLAngleLoc(); + return SourceLocation(); } SourceLocation getRAngleLoc() const { - return this->getLocalData()->RAngleLoc; - } - - void setRAngleLoc(SourceLocation Loc) { - this->getLocalData()->RAngleLoc = Loc; + if (getConceptLoc() && getConceptLoc()->getTemplateArgsAsWritten()) + return getConceptLoc()->getTemplateArgsAsWritten()->getRAngleLoc(); + return SourceLocation(); } unsigned getNumArgs() const { 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/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -158,6 +158,9 @@ const ASTTemplateArgumentListInfo* readASTTemplateArgumentListInfo(); + // Reads a concept location from the given record. + ConceptLoc *readConceptLoc(); + /// Reads a declarator info from the given record, advancing Idx. TypeSourceInfo *readTypeSourceInfo(); diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h --- a/clang/include/clang/Serialization/ASTRecordWriter.h +++ b/clang/include/clang/Serialization/ASTRecordWriter.h @@ -222,6 +222,9 @@ void AddASTTemplateArgumentListInfo( const ASTTemplateArgumentListInfo *ASTTemplArgList); + // Emits a concept location. + void AddConceptLoc(const ConceptLoc *CL); + /// Emit a reference to a declaration. void AddDeclRef(const Decl *D) { return Writer->AddDeclRef(D, *Record); 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,14 @@ } } -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); } - 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,27 @@ 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); - 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()); + + NestedNameSpecifierLoc NNS = + (DS.getTypeSpecScope().isNotEmpty() + ? DS.getTypeSpecScope().getWithLocInContext(Context) + : NestedNameSpecifierLoc()); + TemplateArgumentListInfo TemplateArgsInfo(TemplateId->LAngleLoc, + TemplateId->RAngleLoc); + if (TemplateId->NumArgs > 0) { + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + SemaRef.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo); + } + DeclarationNameInfo DNI = DeclarationNameInfo( + TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(), + TemplateId->TemplateNameLoc); + auto *CL = ConceptLoc::Create( + Context, NNS, TemplateId->TemplateKWLoc, DNI, + /*FoundDecl=*/nullptr, + /*NamedDecl=*/TL.getTypePtr()->getTypeConstraintConcept(), + ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo)); + 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 @@ -6846,15 +6846,23 @@ 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()) { + 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), + ASTTemplateArgumentListInfo::Create(SemaRef.Context, NewTemplateArgs)); + NewTL.setConceptLoc(CL); + } return Result; } 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 @@ -6806,19 +6806,25 @@ TL.setUnderlyingTInfo(GetTypeSourceInfo()); } +ConceptLoc *ASTRecordReader::readConceptLoc() { + if (!readBool()) { + return nullptr; + } + auto NNS = readNestedNameSpecifierLoc(); + auto TemplateKWLoc = readSourceLocation(); + auto ConceptNameLoc = readDeclarationNameInfo(); + auto FoundDecl = readDeclAs(); + auto NamedConcept = readDeclAs(); + auto *CL = ConceptLoc::Create( + getContext(), NNS, TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept, + (readBool() ? readASTTemplateArgumentListInfo() : nullptr)); + return CL; +} + 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())); + TL.setConceptLoc(Reader.readConceptLoc()); } 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 @@ -2620,15 +2620,10 @@ D->setDeclaredWithTypename(Record.readInt()); if (Record.readBool()) { - NestedNameSpecifierLoc NNS = Record.readNestedNameSpecifierLoc(); - DeclarationNameInfo DN = Record.readDeclarationNameInfo(); - ConceptDecl *NamedConcept = Record.readDeclAs(); - const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; - if (Record.readBool()) - ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); + auto *CL = Record.readConceptLoc(); Expr *ImmediatelyDeclaredConstraint = Record.readExpr(); - D->setTypeConstraint(NNS, DN, /*FoundDecl=*/nullptr, NamedConcept, - ArgsAsWritten, ImmediatelyDeclaredConstraint); + + 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,8 @@ 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(); E->SpecDecl = Record.readDeclAs(); - E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); + E->Loc = Record.readConceptLoc(); 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 @@ -469,20 +469,25 @@ Record.AddTypeSourceInfo(TL.getUnderlyingTInfo()); } +void ASTRecordWriter::AddConceptLoc(const ConceptLoc *CL) { + push_back(CL != nullptr); + if (!CL) + return; + AddNestedNameSpecifierLoc(CL->getNestedNameSpecifierLoc()); + AddSourceLocation(CL->getTemplateKWLoc()); + AddDeclarationNameInfo(CL->getConceptNameInfo()); + AddDeclRef(CL->getFoundDecl()); + AddDeclRef(CL->getNamedConcept()); + push_back(CL->getTemplateArgsAsWritten() != nullptr); + if (CL->getTemplateArgsAsWritten()) + AddASTTemplateArgumentListInfo(CL->getTemplateArgsAsWritten()); +} + void TypeLocWriter::VisitAutoTypeLoc(AutoTypeLoc TL) { 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.AddConceptLoc(TL.getConceptLoc()); } Record.push_back(TL.isDecltypeAuto()); if (TL.isDecltypeAuto()) diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1774,12 +1774,7 @@ const TypeConstraint *TC = D->getTypeConstraint(); Record.push_back(TC != nullptr); if (TC) { - Record.AddNestedNameSpecifierLoc(TC->getNestedNameSpecifierLoc()); - Record.AddDeclarationNameInfo(TC->getConceptNameInfo()); - Record.AddDeclRef(TC->getNamedConcept()); - Record.push_back(TC->getTemplateArgsAsWritten() != nullptr); - if (TC->getTemplateArgsAsWritten()) - Record.AddASTTemplateArgumentListInfo(TC->getTemplateArgsAsWritten()); + Record.AddConceptLoc(TC->getConceptLoc()); Record.AddStmt(TC->getImmediatelyDeclaredConstraint()); Record.push_back(D->isExpandedParameterPack()); if (D->isExpandedParameterPack()) diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -437,13 +437,8 @@ void ASTStmtWriter::VisitConceptSpecializationExpr( ConceptSpecializationExpr *E) { VisitExpr(E); - Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc()); - Record.AddSourceLocation(E->getTemplateKWLoc()); - Record.AddDeclarationNameInfo(E->getConceptNameInfo()); - Record.AddDeclRef(E->getNamedConcept()); - Record.AddDeclRef(E->getFoundDecl()); Record.AddDeclRef(E->getSpecializationDecl()); - Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten()); + Record.AddConceptLoc(E->getConceptLoc()); if (!E->isValueDependent()) addConstraintSatisfaction(Record, E->getSatisfaction()); 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,22 @@ ++ConceptRequirementsTraversed; return ExpectedLocationVisitor::TraverseConceptRequirement(R); } + bool TraverseConceptLoc(const ConceptLoc *CL) { + ++ConceptLocsTraversed; + return ExpectedLocationVisitor::TraverseConceptLoc(CL); + } + bool VisitConceptLoc(const ConceptLoc *CL) { + ++ConceptLocsVisited; + return true; + } bool shouldVisitImplicitCode() { return ShouldVisitImplicitCode; } int ConceptSpecializationExprsVisited = 0; int TypeConstraintsTraversed = 0; int ConceptRequirementsTraversed = 0; + int ConceptLocsTraversed = 0; + int ConceptLocsVisited = 0; bool ShouldVisitImplicitCode = false; }; @@ -50,6 +60,8 @@ 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); + EXPECT_EQ(1, Visitor.ConceptLocsVisited); Visitor = {}; // Don't visit implicit code now. EXPECT_TRUE(Visitor.runOver("template concept Fooable = true;\n" @@ -59,6 +71,8 @@ // generated immediately declared expression. EXPECT_EQ(0, Visitor.ConceptSpecializationExprsVisited); EXPECT_EQ(1, Visitor.TypeConstraintsTraversed); + EXPECT_EQ(1, Visitor.ConceptLocsTraversed); + EXPECT_EQ(1, Visitor.ConceptLocsVisited); Visitor = {}; EXPECT_TRUE(Visitor.runOver("template concept A = true;\n" @@ -70,6 +84,8 @@ "};", ConceptVisitor::Lang_CXX2a)); EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed); + EXPECT_EQ(1, Visitor.ConceptLocsTraversed); + EXPECT_EQ(1, Visitor.ConceptLocsVisited); } struct VisitDeclOnlyOnce : ExpectedLocationVisitor { @@ -86,6 +102,10 @@ ++AutoTypeLocVisited; return true; } + bool VisitConceptLoc(const ConceptLoc *) { + ++ConceptLocsVisited; + return true; + } bool TraverseVarDecl(VarDecl *V) { // The base traversal visits only the `TypeLoc`. @@ -99,6 +119,7 @@ int ConceptDeclsVisited = 0; int AutoTypeVisited = 0; int AutoTypeLocVisited = 0; + int ConceptLocsVisited = 0; }; TEST(RecursiveASTVisitor, ConceptDeclInAutoType) { @@ -111,6 +132,7 @@ EXPECT_EQ(1, Visitor.AutoTypeVisited); EXPECT_EQ(1, Visitor.AutoTypeLocVisited); EXPECT_EQ(1, Visitor.ConceptDeclsVisited); + EXPECT_EQ(1, Visitor.ConceptLocsVisited); } } // end anonymous namespace