massberg updated this revision to Diff 554743.
massberg marked 7 inline comments as done.
massberg added a comment.
Fixed remaining nits. Thanks for the reviews and comments everyone!
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D155858/new/
https://reviews.llvm.org/D155858
Files:
clang/include/clang/AST/ASTConcept.h
clang/include/clang/AST/DeclTemplate.h
clang/include/clang/AST/ExprConcepts.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/TypeLoc.h
clang/include/clang/Serialization/ASTRecordReader.h
clang/include/clang/Serialization/ASTRecordWriter.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/DeclTemplate.cpp
clang/lib/AST/ExprConcepts.cpp
clang/lib/AST/TypeLoc.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/lib/Sema/SemaType.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/unittests/AST/SourceLocationTest.cpp
clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
Index: clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
===================================================================
--- clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
+++ clang/unittests/Tooling/RecursiveASTVisitorTests/Concept.cpp
@@ -29,12 +29,22 @@
++ConceptRequirementsTraversed;
return ExpectedLocationVisitor::TraverseConceptRequirement(R);
}
+ bool TraverseConceptReference(ConceptReference *CR) {
+ ++ConceptReferencesTraversed;
+ return ExpectedLocationVisitor::TraverseConceptReference(CR);
+ }
+ bool VisitConceptReference(ConceptReference *CR) {
+ ++ConceptReferencesVisited;
+ return true;
+ }
bool shouldVisitImplicitCode() { return ShouldVisitImplicitCode; }
int ConceptSpecializationExprsVisited = 0;
int TypeConstraintsTraversed = 0;
int ConceptRequirementsTraversed = 0;
+ int ConceptReferencesTraversed = 0;
+ int ConceptReferencesVisited = 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.ConceptReferencesTraversed);
+ EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
Visitor = {}; // Don't visit implicit code now.
EXPECT_TRUE(Visitor.runOver("template <typename T> 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.ConceptReferencesTraversed);
+ EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
Visitor = {};
EXPECT_TRUE(Visitor.runOver("template <class T> concept A = true;\n"
@@ -70,6 +84,8 @@
"};",
ConceptVisitor::Lang_CXX2a));
EXPECT_EQ(3, Visitor.ConceptRequirementsTraversed);
+ EXPECT_EQ(1, Visitor.ConceptReferencesTraversed);
+ EXPECT_EQ(1, Visitor.ConceptReferencesVisited);
}
struct VisitDeclOnlyOnce : ExpectedLocationVisitor<VisitDeclOnlyOnce> {
@@ -86,6 +102,10 @@
++AutoTypeLocVisited;
return true;
}
+ bool VisitConceptReference(ConceptReference *) {
+ ++ConceptReferencesVisited;
+ 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 ConceptReferencesVisited = 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.ConceptReferencesVisited);
}
} // end anonymous namespace
Index: clang/unittests/AST/SourceLocationTest.cpp
===================================================================
--- clang/unittests/AST/SourceLocationTest.cpp
+++ clang/unittests/AST/SourceLocationTest.cpp
@@ -16,7 +16,11 @@
//===----------------------------------------------------------------------===//
#include "MatchVerifier.h"
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTFwd.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprConcepts.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
@@ -370,10 +374,10 @@
TEST(CompoundLiteralExpr, ParensCompoundVectorLiteralRange) {
RangeVerifier<CompoundLiteralExpr> Verifier;
Verifier.expectRange(2, 20, 2, 31);
- EXPECT_TRUE(Verifier.match(
- "typedef int int2 __attribute__((ext_vector_type(2)));\n"
- "constant int2 i2 = (int2)(1, 2);",
- compoundLiteralExpr(), Lang_OpenCL));
+ EXPECT_TRUE(
+ Verifier.match("typedef int int2 __attribute__((ext_vector_type(2)));\n"
+ "constant int2 i2 = (int2)(1, 2);",
+ compoundLiteralExpr(), Lang_OpenCL));
}
TEST(InitListExpr, VectorLiteralListBraceRange) {
@@ -1000,4 +1004,129 @@
ASSERT_EQ(SM.getFileOffset(TL.getStarLoc()), Example.point("star"));
}
+class AutoTypeLocConceptReferenceRangeVerifier
+ : public RangeVerifier<AutoTypeLoc> {
+protected:
+ SourceRange getRange(const AutoTypeLoc &Node) override {
+ if (const ConceptReference *ConceptRef = Node.getConceptReference()) {
+ return ConceptRef->getSourceRange();
+ }
+ return SourceRange();
+ }
+};
+
+TEST(LocationVerifier, AutoTypeLocConceptReference) {
+ AutoTypeLocConceptReferenceRangeVerifier Verifier;
+
+ const char *Code =
+ R"cpp(template <typename T> concept CCC = true;
+CCC auto abc();
+)cpp";
+ Verifier.expectRange(2, 1, 2, 1);
+ EXPECT_TRUE(Verifier.match(Code, typeLoc(loc(autoType())), Lang_CXX20));
+
+ const char *Code2 =
+ R"cpp(template <typename T, int> concept CCC = true;
+CCC<10> auto abc();
+)cpp";
+ Verifier.expectRange(2, 1, 2, 7);
+ EXPECT_TRUE(Verifier.match(Code2, typeLoc(loc(autoType())), Lang_CXX20));
+
+ const char *Code3 =
+ R"cpp(namespace NS {
+ template <typename T, int> concept CCC = true;
+}
+NS::CCC<10> auto abc();
+)cpp";
+ Verifier.expectRange(4, 1, 4, 11);
+ EXPECT_TRUE(Verifier.match(Code3, typeLoc(loc(autoType())), Lang_CXX20));
+
+ const char *Code4 =
+ R"cpp(template <typename T> concept CCC = true;
+CCC<> auto abc();
+)cpp";
+ Verifier.expectRange(2, 1, 2, 5);
+ EXPECT_TRUE(Verifier.match(Code4, typeLoc(loc(autoType())), Lang_CXX20));
+}
+
+class TemplateTypeParmDeclConceptReferenceRangeVerifier
+ : public RangeVerifier<TemplateTypeParmDecl> {
+protected:
+ SourceRange getRange(const TemplateTypeParmDecl &Node) override {
+ if (const TypeConstraint *TC = Node.getTypeConstraint()) {
+ if (const ConceptReference *ConceptRef = TC->getConceptReference()) {
+ return ConceptRef->getSourceRange();
+ }
+ }
+ return SourceRange();
+ }
+};
+
+TEST(LocationVerifier, TemplateTypeParmDeclConceptReference) {
+ TemplateTypeParmDeclConceptReferenceRangeVerifier Verifier;
+
+ const char *Code =
+ R"cpp(template <typename S> concept CCC = true;
+template <CCC T> void print(T object);
+)cpp";
+ Verifier.expectRange(2, 11, 2, 11);
+ EXPECT_TRUE(Verifier.match(Code, templateTypeParmDecl(), Lang_CXX20));
+
+ const char *Code2 =
+ R"cpp(template <typename S, typename T> concept CCC = true;
+template <CCC<int> T> void print(T object);
+)cpp";
+ Verifier.expectRange(2, 11, 2, 18);
+ EXPECT_TRUE(Verifier.match(Code2, templateTypeParmDecl(), Lang_CXX20));
+
+ const char *Code3 =
+ R"cpp(namespace X {
+ template <typename S, typename T> concept CCC = true;
+}
+template <X::CCC<int> T> void print(T object);
+)cpp";
+ Verifier.expectRange(4, 11, 4, 21);
+ EXPECT_TRUE(Verifier.match(Code3, templateTypeParmDecl(), Lang_CXX20));
+}
+
+class ConceptSpecializationExprConceptReferenceRangeVerifier
+ : public RangeVerifier<VarTemplateDecl> {
+protected:
+ SourceRange getRange(const VarTemplateDecl &Node) override {
+ assert(Node.hasAssociatedConstraints());
+ SmallVector<const Expr *, 3> ACs;
+ Node.getAssociatedConstraints(ACs);
+ for (const Expr *Constraint : ACs) {
+ if (const ConceptSpecializationExpr *CSConstraint =
+ dyn_cast<ConceptSpecializationExpr>(Constraint)) {
+ return CSConstraint->getConceptReference()->getSourceRange();
+ }
+ }
+ return SourceRange();
+ }
+};
+
+const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
+ varTemplateDecl;
+
+TEST(LocationVerifier, ConceptSpecializationExprConceptReference) {
+ ConceptSpecializationExprConceptReferenceRangeVerifier Verifier;
+
+ const char *Code =
+ R"cpp(template <int X> concept CCC = true;
+template <int X> requires CCC<X> int z = X;
+)cpp";
+ Verifier.expectRange(2, 27, 2, 32);
+ EXPECT_TRUE(Verifier.match(Code, varTemplateDecl(hasName("z")), Lang_CXX20));
+
+ const char *Code2 =
+ R"cpp(namespace NS {
+template <int X> concept CCC = true;
+}
+template <int X> requires NS::CCC<X> int z = X;
+)cpp";
+ Verifier.expectRange(4, 27, 4, 36);
+ EXPECT_TRUE(Verifier.match(Code2, varTemplateDecl(hasName("z")), Lang_CXX20));
+}
+
} // end namespace
Index: clang/lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterStmt.cpp
+++ clang/lib/Serialization/ASTWriterStmt.cpp
@@ -11,15 +11,16 @@
///
//===----------------------------------------------------------------------===//
-#include "clang/AST/ExprOpenMP.h"
-#include "clang/Serialization/ASTRecordWriter.h"
-#include "clang/Sema/DeclSpec.h"
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Lex/Token.h"
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Serialization/ASTRecordWriter.h"
#include "llvm/Bitstream/BitstreamWriter.h"
using namespace clang;
@@ -437,13 +438,11 @@
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());
+ const ConceptReference *CR = E->getConceptReference();
+ Record.push_back(CR != nullptr);
+ if (CR)
+ Record.AddConceptReference(CR);
if (!E->isValueDependent())
addConstraintSatisfaction(Record, E->getSatisfaction());
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1774,12 +1774,10 @@
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());
+ auto *CR = TC->getConceptReference();
+ Record.push_back(CR != nullptr);
+ if (CR)
+ Record.AddConceptReference(CR);
Record.AddStmt(TC->getImmediatelyDeclaredConstraint());
Record.push_back(D->isExpandedParameterPack());
if (D->isExpandedParameterPack())
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -469,21 +469,24 @@
Record.AddTypeSourceInfo(TL.getUnderlyingTInfo());
}
+void ASTRecordWriter::AddConceptReference(const ConceptReference *CR) {
+ assert(CR);
+ AddNestedNameSpecifierLoc(CR->getNestedNameSpecifierLoc());
+ AddSourceLocation(CR->getTemplateKWLoc());
+ AddDeclarationNameInfo(CR->getConceptNameInfo());
+ AddDeclRef(CR->getFoundDecl());
+ AddDeclRef(CR->getNamedConcept());
+ push_back(CR->getTemplateArgsAsWritten() != nullptr);
+ if (CR->getTemplateArgsAsWritten())
+ AddASTTemplateArgumentListInfo(CR->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));
- }
+ auto *CR = TL.getConceptReference();
+ Record.push_back(TL.isConstrained() && CR);
+ if (TL.isConstrained() && CR)
+ Record.AddConceptReference(CR);
Record.push_back(TL.isDecltypeAuto());
if (TL.isDecltypeAuto())
addSourceLocation(TL.getRParenLoc());
Index: clang/lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderStmt.cpp
+++ clang/lib/Serialization/ASTReaderStmt.cpp
@@ -795,13 +795,9 @@
void ASTStmtReader::VisitConceptSpecializationExpr(
ConceptSpecializationExpr *E) {
VisitExpr(E);
- E->NestedNameSpec = Record.readNestedNameSpecifierLoc();
- E->TemplateKWLoc = Record.readSourceLocation();
- E->ConceptName = Record.readDeclarationNameInfo();
- E->NamedConcept = readDeclAs<ConceptDecl>();
- E->FoundDecl = Record.readDeclAs<NamedDecl>();
E->SpecDecl = Record.readDeclAs<ImplicitConceptSpecializationDecl>();
- E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
+ if (Record.readBool())
+ E->ConceptRef = Record.readConceptReference();
E->Satisfaction = E->isValueDependent() ? nullptr :
ASTConstraintSatisfaction::Create(Record.getContext(),
readConstraintSatisfaction(Record));
Index: clang/lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderDecl.cpp
+++ clang/lib/Serialization/ASTReaderDecl.cpp
@@ -13,6 +13,7 @@
#include "ASTCommon.h"
#include "ASTReaderInternals.h"
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/Attr.h"
@@ -2633,15 +2634,12 @@
D->setDeclaredWithTypename(Record.readInt());
if (Record.readBool()) {
- NestedNameSpecifierLoc NNS = Record.readNestedNameSpecifierLoc();
- DeclarationNameInfo DN = Record.readDeclarationNameInfo();
- ConceptDecl *NamedConcept = Record.readDeclAs<ConceptDecl>();
- const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
+ ConceptReference *CR = nullptr;
if (Record.readBool())
- ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
+ CR = Record.readConceptReference();
Expr *ImmediatelyDeclaredConstraint = Record.readExpr();
- D->setTypeConstraint(NNS, DN, /*FoundDecl=*/nullptr, NamedConcept,
- ArgsAsWritten, ImmediatelyDeclaredConstraint);
+
+ D->setTypeConstraint(CR, ImmediatelyDeclaredConstraint);
if ((D->ExpandedParameterPack = Record.readInt()))
D->NumExpanded = Record.readInt();
}
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -6841,20 +6841,22 @@
TL.setUnderlyingTInfo(GetTypeSourceInfo());
}
+ConceptReference *ASTRecordReader::readConceptReference() {
+ auto NNS = readNestedNameSpecifierLoc();
+ auto TemplateKWLoc = readSourceLocation();
+ auto ConceptNameLoc = readDeclarationNameInfo();
+ auto FoundDecl = readDeclAs<NamedDecl>();
+ auto NamedConcept = readDeclAs<ConceptDecl>();
+ auto *CR = ConceptReference::Create(
+ getContext(), NNS, TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept,
+ (readBool() ? readASTTemplateArgumentListInfo() : nullptr));
+ return CR;
+}
+
void TypeLocReader::VisitAutoTypeLoc(AutoTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
- if (Reader.readBool()) {
- TL.setNestedNameSpecifierLoc(ReadNestedNameSpecifierLoc());
- TL.setTemplateKWLoc(readSourceLocation());
- TL.setConceptNameLoc(readSourceLocation());
- TL.setFoundDecl(Reader.readDeclAs<NamedDecl>());
- 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()));
- }
+ if (Reader.readBool())
+ TL.setConceptReference(Reader.readConceptReference());
if (Reader.readBool())
TL.setRParenLoc(readSourceLocation());
}
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -6822,16 +6822,16 @@
TemplateArgumentListInfo NewTemplateArgs;
NestedNameSpecifierLoc NewNestedNameSpec;
if (T->isConstrained()) {
+ assert(TL.getConceptReference());
NewCD = cast_or_null<ConceptDecl>(getDerived().TransformDecl(
TL.getConceptNameLoc(), T->getTypeConstraintConcept()));
NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc());
NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc());
typedef TemplateArgumentLocContainerIterator<AutoTypeLoc> ArgIterator;
- if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0),
- ArgIterator(TL,
- TL.getNumArgs()),
- NewTemplateArgs))
+ if (getDerived().TransformTemplateArguments(
+ ArgIterator(TL, 0), ArgIterator(TL, TL.getNumArgs()),
+ NewTemplateArgs))
return QualType();
if (TL.getNestedNameSpecifierLoc()) {
@@ -6859,15 +6859,19 @@
AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(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(
+ TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(),
+ TL.getConceptNameLoc(),
+ TL.getTypePtr()->getTypeConstraintConcept()->getDeclName());
+ auto *CR = ConceptReference::Create(
+ SemaRef.Context, NewNestedNameSpec, TL.getTemplateKWLoc(), DNI,
+ TL.getFoundDecl(), TL.getTypePtr()->getTypeConstraintConcept(),
+ ASTTemplateArgumentListInfo::Create(SemaRef.Context, NewTemplateArgs));
+ NewTL.setConceptReference(CR);
+ }
return Result;
}
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -6304,24 +6304,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 *CR = ConceptReference::Create(
+ Context, NNS, TemplateId->TemplateKWLoc, DNI,
+ /*FoundDecl=*/nullptr,
+ /*NamedDecl=*/TL.getTypePtr()->getTypeConstraintConcept(),
+ ASTTemplateArgumentListInfo::Create(Context, TemplateArgsInfo));
+ TL.setConceptReference(CR);
}
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ 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->getConceptReference(),
+ TC->getImmediatelyDeclaredConstraint());
+ return false;
}
TemplateArgumentListInfo InstArgs;
Index: clang/lib/Sema/SemaTemplate.cpp
===================================================================
--- clang/lib/Sema/SemaTemplate.cpp
+++ 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 = ConceptReference::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 = ConceptReference::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,
Index: clang/lib/AST/TypeLoc.cpp
===================================================================
--- clang/lib/AST/TypeLoc.cpp
+++ clang/lib/AST/TypeLoc.cpp
@@ -11,9 +11,10 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/TypeLoc.h"
-#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/ASTConcept.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
@@ -621,25 +622,43 @@
}
}
-DeclarationNameInfo AutoTypeLoc::getConceptNameInfo() const {
- return DeclarationNameInfo(getNamedConcept()->getDeclName(),
- getLocalData()->ConceptNameLoc);
+// Builds a ConceptReference where all locations point at the same token,
+// for use in trivial TypeSourceInfo for constrained AutoType
+static ConceptReference *createTrivialConceptReference(ASTContext &Context,
+ SourceLocation Loc,
+ const AutoType *AT) {
+ DeclarationNameInfo DNI =
+ DeclarationNameInfo(AT->getTypeConstraintConcept()->getDeclName(), Loc,
+ AT->getTypeConstraintConcept()->getDeclName());
+ unsigned size = AT->getTypeConstraintArguments().size();
+ TemplateArgumentLocInfo *TALI = new TemplateArgumentLocInfo[size];
+ TemplateSpecializationTypeLoc::initializeArgLocs(
+ Context, AT->getTypeConstraintArguments(), TALI, Loc);
+ TemplateArgumentListInfo TAListI;
+ for (unsigned i = 0; i < size; ++i) {
+ TAListI.addArgument(
+ TemplateArgumentLoc(AT->getTypeConstraintArguments()[i],
+ TALI[i])); // TemplateArgumentLocInfo()
+ }
+
+ auto *ConceptRef = ConceptReference::Create(
+ Context, NestedNameSpecifierLoc{}, Loc, DNI, nullptr,
+ AT->getTypeConstraintConcept(),
+ ASTTemplateArgumentListInfo::Create(Context, TAListI));
+ delete[] TALI;
+ return ConceptRef;
}
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);
+ setConceptReference(nullptr);
+ if (getTypePtr()->isConstrained()) {
+ setConceptReference(
+ createTrivialConceptReference(Context, Loc, getTypePtr()));
+ }
}
-
namespace {
class GetContainedAutoTypeLocVisitor :
Index: clang/lib/AST/ExprConcepts.cpp
===================================================================
--- clang/lib/AST/ExprConcepts.cpp
+++ 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, ConceptReference *Loc,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction)
: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
- ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
- NamedConcept, ArgsAsWritten),
- SpecDecl(SpecDecl),
+ ConceptRef(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, ConceptReference *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, ConceptReference *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),
+ ConceptRef(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, ConceptReference *Loc,
+ ImplicitConceptSpecializationDecl *SpecDecl,
+ const ConstraintSatisfaction *Satisfaction,
+ bool Dependent,
+ bool ContainsUnexpandedParameterPack) {
+ return new (C)
+ ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,
+ ContainsUnexpandedParameterPack);
}
const TypeConstraint *
Index: clang/lib/AST/DeclTemplate.cpp
===================================================================
--- clang/lib/AST/DeclTemplate.cpp
+++ clang/lib/AST/DeclTemplate.cpp
@@ -697,17 +697,15 @@
return getTypeForDecl()->castAs<TemplateTypeParmType>()->isParameterPack();
}
-void TemplateTypeParmDecl::setTypeConstraint(NestedNameSpecifierLoc NNS,
- DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, ConceptDecl *CD,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
- Expr *ImmediatelyDeclaredConstraint) {
+void TemplateTypeParmDecl::setTypeConstraint(
+ ConceptReference *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>()) TypeConstraint(NNS, NameInfo,
- FoundDecl, CD, ArgsAsWritten, ImmediatelyDeclaredConstraint);
+ new (getTrailingObjects<TypeConstraint>())
+ TypeConstraint(Loc, ImmediatelyDeclaredConstraint);
TypeConstraintInitialized = true;
}
@@ -1554,7 +1552,8 @@
createBuiltinTemplateParameterList(C, DC, BTK)),
BTK(BTK) {}
-void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const {
+void ConceptReference::print(llvm::raw_ostream &OS,
+ const PrintingPolicy &Policy) const {
if (NestedNameSpec)
NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy);
ConceptName.printName(OS, Policy);
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -1009,6 +1009,33 @@
*ToRBracketLocOrErr);
}
+template <>
+Expected<ConceptReference *> ASTNodeImporter::import(ConceptReference *From) {
+ Error Err = Error::success();
+ auto ToNNS = importChecked(Err, From->getNestedNameSpecifierLoc());
+ auto ToTemplateKWLoc = importChecked(Err, From->getTemplateKWLoc());
+ auto ToConceptNameLoc =
+ importChecked(Err, From->getConceptNameInfo().getLoc());
+ auto ToConceptName = importChecked(Err, From->getConceptNameInfo().getName());
+ auto ToFoundDecl = importChecked(Err, From->getFoundDecl());
+ auto ToNamedConcept = importChecked(Err, From->getNamedConcept());
+ if (Err)
+ return std::move(Err);
+ TemplateArgumentListInfo ToTAInfo;
+ const auto *ASTTemplateArgs = From->getTemplateArgsAsWritten();
+ if (ASTTemplateArgs)
+ if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo))
+ return std::move(Err);
+ auto *ConceptRef = ConceptReference::Create(
+ Importer.getToContext(), ToNNS, ToTemplateKWLoc,
+ DeclarationNameInfo(ToConceptName, ToConceptNameLoc), ToFoundDecl,
+ ToNamedConcept,
+ ASTTemplateArgs ? ASTTemplateArgumentListInfo::Create(
+ Importer.getToContext(), ToTAInfo)
+ : nullptr);
+ return ConceptRef;
+}
+
template <>
Expected<LambdaCapture> ASTNodeImporter::import(const LambdaCapture &From) {
ValueDecl *Var = nullptr;
@@ -5688,28 +5715,12 @@
if (const TypeConstraint *TC = D->getTypeConstraint()) {
Error Err = Error::success();
- auto ToNNS = importChecked(Err, TC->getNestedNameSpecifierLoc());
- auto ToName = importChecked(Err, TC->getConceptNameInfo().getName());
- auto ToNameLoc = importChecked(Err, TC->getConceptNameInfo().getLoc());
- auto ToFoundDecl = importChecked(Err, TC->getFoundDecl());
- auto ToNamedConcept = importChecked(Err, TC->getNamedConcept());
+ auto ToConceptRef = importChecked(Err, TC->getConceptReference());
auto ToIDC = importChecked(Err, TC->getImmediatelyDeclaredConstraint());
if (Err)
return std::move(Err);
- TemplateArgumentListInfo ToTAInfo;
- const auto *ASTTemplateArgs = TC->getTemplateArgsAsWritten();
- if (ASTTemplateArgs)
- 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);
+ ToD->setTypeConstraint(ToConceptRef, ToIDC);
}
if (D->hasDefaultArgument()) {
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -6345,11 +6345,14 @@
auto *NCY = YTC->getNamedConcept();
if (!NCX || !NCY || !isSameEntity(NCX, NCY))
return false;
- if (XTC->hasExplicitTemplateArgs() != YTC->hasExplicitTemplateArgs())
+ if (XTC->getConceptReference()->hasExplicitTemplateArgs() !=
+ YTC->getConceptReference()->hasExplicitTemplateArgs())
return false;
- if (XTC->hasExplicitTemplateArgs())
- if (XTC->getTemplateArgsAsWritten()->NumTemplateArgs !=
- YTC->getTemplateArgsAsWritten()->NumTemplateArgs)
+ if (XTC->getConceptReference()->hasExplicitTemplateArgs())
+ if (XTC->getConceptReference()
+ ->getTemplateArgsAsWritten()
+ ->NumTemplateArgs !=
+ YTC->getConceptReference()->getTemplateArgsAsWritten()->NumTemplateArgs)
return false;
// Compare slowly by profiling.
Index: clang/include/clang/Serialization/ASTRecordWriter.h
===================================================================
--- clang/include/clang/Serialization/ASTRecordWriter.h
+++ clang/include/clang/Serialization/ASTRecordWriter.h
@@ -222,6 +222,9 @@
void AddASTTemplateArgumentListInfo(
const ASTTemplateArgumentListInfo *ASTTemplArgList);
+ // Emits a concept reference.
+ void AddConceptReference(const ConceptReference *CR);
+
/// Emit a reference to a declaration.
void AddDeclRef(const Decl *D) {
return Writer->AddDeclRef(D, *Record);
Index: clang/include/clang/Serialization/ASTRecordReader.h
===================================================================
--- clang/include/clang/Serialization/ASTRecordReader.h
+++ clang/include/clang/Serialization/ASTRecordReader.h
@@ -158,6 +158,9 @@
const ASTTemplateArgumentListInfo*
readASTTemplateArgumentListInfo();
+ // Reads a concept reference from the given record.
+ ConceptReference *readConceptReference();
+
/// Reads a declarator info from the given record, advancing Idx.
TypeSourceInfo *readTypeSourceInfo();
Index: clang/include/clang/AST/TypeLoc.h
===================================================================
--- clang/include/clang/AST/TypeLoc.h
+++ 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,17 +2105,10 @@
DeducedType> {};
struct AutoTypeLocInfo : TypeSpecLocInfo {
- NestedNameSpecifierLoc NestedNameSpec;
- SourceLocation TemplateKWLoc;
- SourceLocation ConceptNameLoc;
- NamedDecl *FoundDecl = nullptr;
- SourceLocation LAngleLoc;
- SourceLocation RAngleLoc;
-
// For decltype(auto).
SourceLocation RParenLoc;
- // Followed by a TemplateArgumentLocInfo[]
+ ConceptReference *CR = nullptr;
};
class AutoTypeLoc
@@ -2135,79 +2129,77 @@
return getTypePtr()->isConstrained();
}
- const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
- return getLocalData()->NestedNameSpec;
- }
+ void setConceptReference(ConceptReference *CR) { getLocalData()->CR = CR; }
- void setNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
- getLocalData()->NestedNameSpec = NNS;
- }
+ ConceptReference *getConceptReference() const { return getLocalData()->CR; }
- SourceLocation getTemplateKWLoc() const {
- return getLocalData()->TemplateKWLoc;
+ // FIXME: Several of the following functions can be removed. Instead the
+ // caller can directly work with the ConceptReference.
+ const NestedNameSpecifierLoc getNestedNameSpecifierLoc() const {
+ if (const auto *CR = getConceptReference())
+ return CR->getNestedNameSpecifierLoc();
+ return NestedNameSpecifierLoc();
}
- void setTemplateKWLoc(SourceLocation Loc) {
- getLocalData()->TemplateKWLoc = Loc;
+ SourceLocation getTemplateKWLoc() const {
+ if (const auto *CR = getConceptReference())
+ return CR->getTemplateKWLoc();
+ return SourceLocation();
}
SourceLocation getConceptNameLoc() const {
- return getLocalData()->ConceptNameLoc;
- }
-
- void setConceptNameLoc(SourceLocation Loc) {
- getLocalData()->ConceptNameLoc = Loc;
+ if (const auto *CR = getConceptReference())
+ return CR->getConceptNameLoc();
+ return SourceLocation();
}
NamedDecl *getFoundDecl() const {
- return getLocalData()->FoundDecl;
- }
-
- void setFoundDecl(NamedDecl *D) {
- getLocalData()->FoundDecl = D;
+ if (const auto *CR = getConceptReference())
+ return CR->getFoundDecl();
+ return nullptr;
}
ConceptDecl *getNamedConcept() const {
- return getTypePtr()->getTypeConstraintConcept();
+ if (const auto *CR = getConceptReference())
+ return CR->getNamedConcept();
+ return nullptr;
}
- DeclarationNameInfo getConceptNameInfo() const;
+ DeclarationNameInfo getConceptNameInfo() const {
+ return getConceptReference()->getConceptNameInfo();
+ }
bool hasExplicitTemplateArgs() const {
- return getLocalData()->LAngleLoc.isValid();
+ return (getConceptReference() &&
+ getConceptReference()->getTemplateArgsAsWritten() &&
+ getConceptReference()
+ ->getTemplateArgsAsWritten()
+ ->getLAngleLoc()
+ .isValid());
}
SourceLocation getLAngleLoc() const {
- return this->getLocalData()->LAngleLoc;
- }
-
- void setLAngleLoc(SourceLocation Loc) {
- this->getLocalData()->LAngleLoc = Loc;
+ if (const auto *CR = getConceptReference())
+ if (const auto *TAAW = CR->getTemplateArgsAsWritten())
+ return TAAW->getLAngleLoc();
+ return SourceLocation();
}
SourceLocation getRAngleLoc() const {
- return this->getLocalData()->RAngleLoc;
- }
-
- void setRAngleLoc(SourceLocation Loc) {
- this->getLocalData()->RAngleLoc = Loc;
+ if (const auto *CR = getConceptReference())
+ if (const auto *TAAW = CR->getTemplateArgsAsWritten())
+ return TAAW->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 {
- return TemplateArgumentLoc(getTypePtr()->getTypeConstraintArguments()[i],
- getArgLocInfo(i));
+ const auto *CR = getConceptReference();
+ assert(CR && "No ConceptReference");
+ return CR->getTemplateArgsAsWritten()->getTemplateArgs()[i];
}
SourceRange getLocalSourceRange() const {
@@ -2227,19 +2219,6 @@
}
void initializeLocal(ASTContext &Context, SourceLocation Loc);
-
- unsigned getExtraLocalDataSize() const {
- return getNumArgs() * sizeof(TemplateArgumentLocInfo);
- }
-
- unsigned getExtraLocalDataAlignment() const {
- return alignof(TemplateArgumentLocInfo);
- }
-
-private:
- TemplateArgumentLocInfo *getArgInfos() const {
- return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
- }
};
class DeducedTemplateSpecializationTypeLoc
Index: clang/include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- clang/include/clang/AST/RecursiveASTVisitor.h
+++ 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 TraverseConceptReference(ConceptReference *CR);
+
+ // Visit concept reference.
+ bool VisitConceptReference(ConceptReference *CR) { 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 <typename T>
@@ -507,7 +511,7 @@
bool RecursiveASTVisitor<Derived>::TraverseTypeConstraint(
const TypeConstraint *C) {
if (!getDerived().shouldVisitImplicitCode()) {
- TRY_TO(TraverseConceptReferenceHelper(*C));
+ TRY_TO(TraverseConceptReference(C->getConceptReference()));
return true;
}
if (Expr *IDC = C->getImmediatelyDeclaredConstraint()) {
@@ -517,7 +521,7 @@
// 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(TraverseConceptReference(C->getConceptReference()));
}
return true;
}
@@ -540,18 +544,6 @@
llvm_unreachable("unexpected case");
}
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::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 <typename Derived>
bool RecursiveASTVisitor<Derived>::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(TraverseConceptReference(TL.getConceptReference()));
}
})
@@ -2522,6 +2511,22 @@
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseConceptReference(
+ ConceptReference *CR) {
+ if (!getDerived().shouldTraversePostOrder())
+ TRY_TO(VisitConceptReference(CR));
+ TRY_TO(TraverseNestedNameSpecifierLoc(CR->getNestedNameSpecifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(CR->getConceptNameInfo()));
+ if (CR->hasExplicitTemplateArgs())
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ CR->getTemplateArgsAsWritten()->getTemplateArgs(),
+ CR->getTemplateArgsAsWritten()->NumTemplateArgs));
+ if (getDerived().shouldTraversePostOrder())
+ TRY_TO(VisitConceptReference(CR));
+ 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
@@ -2903,8 +2908,9 @@
}
})
-DEF_TRAVERSE_STMT(ConceptSpecializationExpr,
- { TRY_TO(TraverseConceptReferenceHelper(*S)); })
+DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {
+ TRY_TO(TraverseConceptReference(S->getConceptReference()));
+})
DEF_TRAVERSE_STMT(RequiresExpr, {
TRY_TO(TraverseDecl(S->getBody()));
Index: clang/include/clang/AST/ExprConcepts.h
===================================================================
--- clang/include/clang/AST/ExprConcepts.h
+++ clang/include/clang/AST/ExprConcepts.h
@@ -38,14 +38,13 @@
///
/// 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;
-public:
- using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
+private:
+ ConceptReference *ConceptRef;
-protected:
/// \brief The Implicit Concept Specialization Decl, which holds the template
/// arguments for this specialization.
ImplicitConceptSpecializationDecl *SpecDecl;
@@ -55,16 +54,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, ConceptReference *ConceptRef,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction);
- ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction,
bool Dependent,
@@ -73,16 +67,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, ConceptReference *ConceptRef,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction);
static ConceptSpecializationExpr *
- Create(const ASTContext &C, ConceptDecl *NamedConcept,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ Create(const ASTContext &C, ConceptReference *ConceptRef,
ImplicitConceptSpecializationDecl *SpecDecl,
const ConstraintSatisfaction *Satisfaction, bool Dependent,
bool ContainsUnexpandedParameterPack);
@@ -91,6 +81,37 @@
return SpecDecl->getTemplateArguments();
}
+ ConceptReference *getConceptReference() const { return ConceptRef; }
+
+ ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); }
+
+ // FIXME: Several of the following functions can be removed. Instead the
+ // caller can directly work with the ConceptReference.
+ bool hasExplicitTemplateArgs() const {
+ return ConceptRef->hasExplicitTemplateArgs();
+ }
+
+ SourceLocation getConceptNameLoc() const {
+ return ConceptRef->getConceptNameLoc();
+ }
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+ return ConceptRef->getTemplateArgsAsWritten();
+ }
+
+ const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
+ return ConceptRef->getNestedNameSpecifierLoc();
+ }
+
+ SourceLocation getTemplateKWLoc() const {
+ return ConceptRef->getTemplateKWLoc();
+ }
+
+ NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); }
+
+ const DeclarationNameInfo &getConceptNameInfo() const {
+ return ConceptRef->getConceptNameInfo();
+ }
+
const ImplicitConceptSpecializationDecl *getSpecializationDecl() const {
assert(SpecDecl && "Template Argument Decl not initialized");
return SpecDecl;
@@ -119,17 +140,15 @@
}
SourceLocation getBeginLoc() const LLVM_READONLY {
- if (auto QualifierLoc = getNestedNameSpecifierLoc())
- return QualifierLoc.getBeginLoc();
- return ConceptName.getBeginLoc();
+ return ConceptRef->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 ConceptRef->getEndLoc();
+ }
+
+ SourceLocation getExprLoc() const LLVM_READONLY {
+ return ConceptRef->getLocation();
}
// Iterators
Index: clang/include/clang/AST/DeclTemplate.h
===================================================================
--- clang/include/clang/AST/DeclTemplate.h
+++ clang/include/clang/AST/DeclTemplate.h
@@ -1373,10 +1373,7 @@
nullptr;
}
- void setTypeConstraint(NestedNameSpecifierLoc NNS,
- DeclarationNameInfo NameInfo, NamedDecl *FoundDecl,
- ConceptDecl *CD,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ void setTypeConstraint(ConceptReference *CR,
Expr *ImmediatelyDeclaredConstraint);
/// Determine whether this template parameter has a type-constraint.
Index: clang/include/clang/AST/ASTConcept.h
===================================================================
--- clang/include/clang/AST/ASTConcept.h
+++ 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,10 +109,18 @@
Rebuild(const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction);
};
-/// \brief Common data class for constructs that reference concepts with
-/// template arguments.
+/// A reference to a concept and its template args, as it appears in the code.
+///
+/// Examples:
+/// template <int X> requires is_even<X> int half = X/2;
+/// ~~~~~~~~~~ (in ConceptSpecializationExpr)
+///
+/// std::input_iterator auto I = Container.begin();
+/// ~~~~~~~~~~~~~~~~~~~ (in AutoTypeLoc)
+///
+/// template <std::derives_from<Expr> T> void dump();
+/// ~~~~~~~~~~~~~~~~~~~~~~~ (in TemplateTypeParmDecl)
class ConceptReference {
-protected:
// \brief The optional nested name specifier used when naming the concept.
NestedNameSpecifierLoc NestedNameSpec;
@@ -134,7 +144,6 @@
/// concept.
const ASTTemplateArgumentListInfo *ArgsAsWritten;
-public:
ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
ConceptDecl *NamedConcept,
@@ -143,8 +152,15 @@
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {}
- ConceptReference()
- : FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {}
+public:
+ static ConceptReference *
+ Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
+ SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten) {
+ return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo,
+ FoundDecl, NamedConcept, ArgsAsWritten);
+ }
const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
return NestedNameSpec;
@@ -158,6 +174,26 @@
SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
+ SourceLocation getLocation() const { return getConceptNameLoc(); }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY {
+ // Note that if the qualifier is null the template KW must also be null.
+ if (auto QualifierLoc = getNestedNameSpecifierLoc())
+ return QualifierLoc.getBeginLoc();
+ return getConceptNameInfo().getBeginLoc();
+ }
+
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getTemplateArgsAsWritten() &&
+ getTemplateArgsAsWritten()->getRAngleLoc().isValid()
+ ? getTemplateArgsAsWritten()->getRAngleLoc()
+ : getConceptNameInfo().getEndLoc();
+ }
+
+ SourceRange getSourceRange() const LLVM_READONLY {
+ return SourceRange(getBeginLoc(), getEndLoc());
+ }
+
NamedDecl *getFoundDecl() const {
return FoundDecl;
}
@@ -175,22 +211,30 @@
bool hasExplicitTemplateArgs() const {
return ArgsAsWritten != nullptr;
}
+
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
};
-class TypeConstraint : public ConceptReference {
+/// Models the abbreviated syntax to constrain a template type parameter:
+/// template <convertible_to<string> T> void print(T object);
+/// ~~~~~~~~~~~~~~~~~~~~~~
+/// Semantically, this adds an "immediately-declared constraint" with extra arg:
+/// requires convertible_to<T, string>
+///
+/// In the C++ grammar, a type-constraint is also used for auto types:
+/// convertible_to<string> auto X = ...;
+/// We do *not* model these as TypeConstraints, but AutoType(Loc) directly.
+class TypeConstraint {
/// \brief The immediately-declared constraint expression introduced by this
/// type-constraint.
Expr *ImmediatelyDeclaredConstraint = nullptr;
+ ConceptReference *ConceptRef;
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(ConceptReference *ConceptRef,
+ Expr *ImmediatelyDeclaredConstraint)
+ : ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint),
+ ConceptRef(ConceptRef) {}
/// \brief Get the immediately-declared constraint expression introduced by
/// this type-constraint, that is - the constraint expression that is added to
@@ -199,7 +243,41 @@
return ImmediatelyDeclaredConstraint;
}
- void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const;
+ ConceptReference *getConceptReference() const { return ConceptRef; }
+
+ // FIXME: Instead of using these concept related functions the callers should
+ // directly work with the corresponding ConceptReference.
+ ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); }
+
+ SourceLocation getConceptNameLoc() const {
+ return ConceptRef->getConceptNameLoc();
+ }
+
+ bool hasExplicitTemplateArgs() const {
+ return ConceptRef->hasExplicitTemplateArgs();
+ }
+
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+ return ConceptRef->getTemplateArgsAsWritten();
+ }
+
+ SourceLocation getTemplateKWLoc() const {
+ return ConceptRef->getTemplateKWLoc();
+ }
+
+ NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); }
+
+ const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
+ return ConceptRef->getNestedNameSpecifierLoc();
+ }
+
+ const DeclarationNameInfo &getConceptNameInfo() const {
+ return ConceptRef->getConceptNameInfo();
+ }
+
+ void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const {
+ ConceptRef->print(OS, Policy);
+ }
};
} // clang
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits