Index: include/clang/AST/ASTTypeTraits.h =================================================================== --- include/clang/AST/ASTTypeTraits.h +++ include/clang/AST/ASTTypeTraits.h @@ -296,6 +296,10 @@ NNSLB.getOpaqueData()); } + if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) + return TemplateArgumentLess(getUnchecked(), + Other.getUnchecked()); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() < Other.getMemoizationData(); } @@ -316,6 +320,10 @@ return getUnchecked() == Other.getUnchecked(); + if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) + return getUnchecked().structurallyEquals( + Other.getUnchecked()); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() == Other.getMemoizationData(); } @@ -428,6 +436,9 @@ } }; + static bool TemplateArgumentLess(const TemplateArgument &LHS, + const TemplateArgument &RHS); + ASTNodeKind NodeKind; /// \brief Stores the data of the node. Index: lib/AST/ASTTypeTraits.cpp =================================================================== --- lib/AST/ASTTypeTraits.cpp +++ lib/AST/ASTTypeTraits.cpp @@ -150,5 +150,54 @@ return SourceRange(); } +bool DynTypedNode::TemplateArgumentLess(const TemplateArgument &LHS, + const TemplateArgument &RHS) { + if (LHS.getKind() != RHS.getKind()) return LHS.getKind() < RHS.getKind(); + + switch (LHS.getKind()) { + case TemplateArgument::Null: + return false; + + case TemplateArgument::Type: + return LHS.getAsType().getAsOpaquePtr() < + RHS.getAsType().getAsOpaquePtr(); + + case TemplateArgument::Expression: + return LHS.getAsExpr() < RHS.getAsExpr(); + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + return LHS.getAsTemplateOrTemplatePattern().getAsVoidPointer() < + RHS.getAsTemplateOrTemplatePattern().getAsVoidPointer(); + + case TemplateArgument::NullPtr: + return LHS.getNullPtrType().getAsOpaquePtr() < + RHS.getNullPtrType().getAsOpaquePtr(); + + case TemplateArgument::Pack: { + if (LHS.pack_size() != RHS.pack_size()) + return LHS.pack_size() < RHS.pack_size(); + auto PackA = LHS.getPackAsArray(); + auto PackB = RHS.getPackAsArray(); + for (unsigned I = 0, E = PackA.size(); I != E; ++I) + if (!PackA[I].structurallyEquals(PackB[I])) + return TemplateArgumentLess(PackA[I], PackB[I]); + return false; + } + + case TemplateArgument::Declaration: + return (LHS.getAsDecl() ? LHS.getAsDecl()->getCanonicalDecl() : nullptr) < + (RHS.getAsDecl() ? RHS.getAsDecl()->getCanonicalDecl() : nullptr); + + case TemplateArgument::Integral: + return std::make_pair(LHS.getIntegralType().getAsOpaquePtr(), + LHS.getAsIntegral()) < + std::make_pair(RHS.getIntegralType().getAsOpaquePtr(), + RHS.getAsIntegral()); + + } + llvm_unreachable("Unsupported or invalid TemplateArgument kind"); +} + } // end namespace ast_type_traits } // end namespace clang Index: unittests/AST/ASTTypeTraitsTest.cpp =================================================================== --- unittests/AST/ASTTypeTraitsTest.cpp +++ unittests/AST/ASTTypeTraitsTest.cpp @@ -180,5 +180,65 @@ EXPECT_FALSE(Node < Node); } +TEST(DynTypedNode, TemplateArgumentNull) { + TemplateArgument T; + DynTypedNode Node = DynTypedNode::create(T); + EXPECT_TRUE(Node == Node); + EXPECT_FALSE(Node < Node); +} + +TEST(DynTypedNode, TemplateArgumentQualType) { + QualType QT; + TemplateArgument T(QT); + DynTypedNode Node = DynTypedNode::create(T); + EXPECT_TRUE(Node == Node); + EXPECT_FALSE(Node < Node); +} + +TEST(DynTypedNode, TemplateArgumentNullPtr) { + QualType QT; + TemplateArgument T(QT, true); + DynTypedNode Node = DynTypedNode::create(T); + EXPECT_TRUE(Node == Node); + EXPECT_FALSE(Node < Node); +} + +TEST(DynTypedNode, TemplateArgumentExpr) { + BuiltinType Void(BuiltinType::Void); + QualType QT(&Void, 0); + NoInitExpr E(QT); + TemplateArgument T(&E); + DynTypedNode Node = DynTypedNode::create(T); + EXPECT_TRUE(Node == Node); + EXPECT_FALSE(Node < Node); +} + +TEST(DynTypedNode, TemplateArgumentTemplate) { + TemplateName TN; + TemplateArgument T(TN); + DynTypedNode Node = DynTypedNode::create(T); + EXPECT_TRUE(Node == Node); + EXPECT_FALSE(Node < Node); +} + +TEST(DynTypedNode, TemplateArgumentTemplateExpansion) { + TemplateName TN; + TemplateArgument T(TN, llvm::Optional(0u)); + DynTypedNode Node = DynTypedNode::create(T); + EXPECT_TRUE(Node == Node); + EXPECT_FALSE(Node < Node); +} + +TEST(DynTypedNode, TemplateArgumentPack) { + TemplateArgument TP[1]; + TemplateArgument T(TP); + DynTypedNode Node = DynTypedNode::create(T); + EXPECT_TRUE(Node == Node); + EXPECT_FALSE(Node < Node); +} + +// FIXME: Figure out how to test TemplateArgument of the Declaration and +// Integral kinds. + } // namespace ast_type_traits } // namespace clang