aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ASTStructuralEquivalence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ASTStructuralEquivalence.cpp')
-rw-r--r--clang/lib/AST/ASTStructuralEquivalence.cpp159
1 files changed, 103 insertions, 56 deletions
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index d80fc3ce7292..ba7dfc35edf2 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -84,13 +84,12 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
+#include <optional>
#include <utility>
using namespace clang;
@@ -103,6 +102,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const TemplateArgument &Arg1,
const TemplateArgument &Arg2);
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ const TemplateArgumentLoc &Arg1,
+ const TemplateArgumentLoc &Arg2);
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
NestedNameSpecifier *NNS1,
NestedNameSpecifier *NNS2);
static bool IsStructurallyEquivalent(const IdentifierInfo *Name1,
@@ -238,8 +240,8 @@ class StmtComparer {
const GenericSelectionExpr *E2) {
for (auto Pair : zip_longest(E1->getAssocTypeSourceInfos(),
E2->getAssocTypeSourceInfos())) {
- Optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
- Optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
+ std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
+ std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
// Skip this case if there are a different number of associated types.
if (!Child1 || !Child2)
return false;
@@ -289,8 +291,14 @@ class StmtComparer {
bool IsStmtEquivalent(const SubstNonTypeTemplateParmExpr *E1,
const SubstNonTypeTemplateParmExpr *E2) {
- return IsStructurallyEquivalent(Context, E1->getParameter(),
- E2->getParameter());
+ if (!IsStructurallyEquivalent(Context, E1->getAssociatedDecl(),
+ E2->getAssociatedDecl()))
+ return false;
+ if (E1->getIndex() != E2->getIndex())
+ return false;
+ if (E1->getPackIndex() != E2->getPackIndex())
+ return false;
+ return true;
}
bool IsStmtEquivalent(const SubstNonTypeTemplateParmPackExpr *E1,
@@ -304,8 +312,8 @@ class StmtComparer {
return false;
for (auto Pair : zip_longest(E1->getArgs(), E2->getArgs())) {
- Optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
- Optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
+ std::optional<TypeSourceInfo *> Child1 = std::get<0>(Pair);
+ std::optional<TypeSourceInfo *> Child2 = std::get<1>(Pair);
// Different number of args.
if (!Child1 || !Child2)
return false;
@@ -334,6 +342,30 @@ class StmtComparer {
return true;
}
+ bool IsStmtEquivalent(const OverloadExpr *E1, const OverloadExpr *E2) {
+ if (!IsStructurallyEquivalent(Context, E1->getName(), E2->getName()))
+ return false;
+
+ if (static_cast<bool>(E1->getQualifier()) !=
+ static_cast<bool>(E2->getQualifier()))
+ return false;
+ if (E1->getQualifier() &&
+ !IsStructurallyEquivalent(Context, E1->getQualifier(),
+ E2->getQualifier()))
+ return false;
+
+ if (E1->getNumTemplateArgs() != E2->getNumTemplateArgs())
+ return false;
+ const TemplateArgumentLoc *Args1 = E1->getTemplateArgs();
+ const TemplateArgumentLoc *Args2 = E2->getTemplateArgs();
+ for (unsigned int ArgI = 0, ArgN = E1->getNumTemplateArgs(); ArgI < ArgN;
+ ++ArgI)
+ if (!IsStructurallyEquivalent(Context, Args1[ArgI], Args2[ArgI]))
+ return false;
+
+ return true;
+ }
+
/// End point of the traversal chain.
bool TraverseStmt(const Stmt *S1, const Stmt *S2) { return true; }
@@ -394,8 +426,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
// Iterate over the children of both statements and also compare them.
for (auto Pair : zip_longest(S1->children(), S2->children())) {
- Optional<const Stmt *> Child1 = std::get<0>(Pair);
- Optional<const Stmt *> Child2 = std::get<1>(Pair);
+ std::optional<const Stmt *> Child1 = std::get<0>(Pair);
+ std::optional<const Stmt *> Child2 = std::get<1>(Pair);
// One of the statements has a different amount of children than the other,
// so the statements can't be equivalent.
if (!Child1 || !Child2)
@@ -510,8 +542,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
*P2 = N2.getAsSubstTemplateTemplateParmPack();
return IsStructurallyEquivalent(Context, P1->getArgumentPack(),
P2->getArgumentPack()) &&
- IsStructurallyEquivalent(Context, P1->getParameterPack(),
- P2->getParameterPack());
+ IsStructurallyEquivalent(Context, P1->getAssociatedDecl(),
+ P2->getAssociatedDecl()) &&
+ P1->getIndex() == P2->getIndex();
}
case TemplateName::Template:
@@ -526,6 +559,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return true;
}
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ ArrayRef<TemplateArgument> Args1,
+ ArrayRef<TemplateArgument> Args2);
+
/// Determine whether two template arguments are equivalent.
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
const TemplateArgument &Arg1,
@@ -568,18 +605,32 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
Arg2.getAsExpr());
case TemplateArgument::Pack:
- if (Arg1.pack_size() != Arg2.pack_size())
- return false;
+ return IsStructurallyEquivalent(Context, Arg1.pack_elements(),
+ Arg2.pack_elements());
+ }
- for (unsigned I = 0, N = Arg1.pack_size(); I != N; ++I)
- if (!IsStructurallyEquivalent(Context, Arg1.pack_begin()[I],
- Arg2.pack_begin()[I]))
- return false;
+ llvm_unreachable("Invalid template argument kind");
+}
- return true;
+/// Determine structural equivalence of two template argument lists.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ ArrayRef<TemplateArgument> Args1,
+ ArrayRef<TemplateArgument> Args2) {
+ if (Args1.size() != Args2.size())
+ return false;
+ for (unsigned I = 0, N = Args1.size(); I != N; ++I) {
+ if (!IsStructurallyEquivalent(Context, Args1[I], Args2[I]))
+ return false;
}
+ return true;
+}
- llvm_unreachable("Invalid template argument kind");
+/// Determine whether two template argument locations are equivalent.
+static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
+ const TemplateArgumentLoc &Arg1,
+ const TemplateArgumentLoc &Arg2) {
+ return IsStructurallyEquivalent(Context, Arg1.getArgument(),
+ Arg2.getArgument());
}
/// Determine structural equivalence for the common part of array
@@ -900,7 +951,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
return false;
// Fall through to check the bits common with FunctionNoProtoType.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
}
case Type::FunctionNoProto: {
@@ -957,11 +1008,17 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!IsStructurallyEquivalent(Context, cast<UsingType>(T1)->getFoundDecl(),
cast<UsingType>(T2)->getFoundDecl()))
return false;
+ if (!IsStructurallyEquivalent(Context,
+ cast<UsingType>(T1)->getUnderlyingType(),
+ cast<UsingType>(T2)->getUnderlyingType()))
+ return false;
break;
case Type::Typedef:
if (!IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->getDecl(),
- cast<TypedefType>(T2)->getDecl()))
+ cast<TypedefType>(T2)->getDecl()) ||
+ !IsStructurallyEquivalent(Context, cast<TypedefType>(T1)->desugar(),
+ cast<TypedefType>(T2)->desugar()))
return false;
break;
@@ -974,8 +1031,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::TypeOf:
if (!IsStructurallyEquivalent(Context,
- cast<TypeOfType>(T1)->getUnderlyingType(),
- cast<TypeOfType>(T2)->getUnderlyingType()))
+ cast<TypeOfType>(T1)->getUnmodifiedType(),
+ cast<TypeOfType>(T2)->getUnmodifiedType()))
return false;
break;
@@ -1005,16 +1062,10 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (Auto1->getTypeConstraintConcept() !=
Auto2->getTypeConstraintConcept())
return false;
- ArrayRef<TemplateArgument> Auto1Args =
- Auto1->getTypeConstraintArguments();
- ArrayRef<TemplateArgument> Auto2Args =
- Auto2->getTypeConstraintArguments();
- if (Auto1Args.size() != Auto2Args.size())
+ if (!IsStructurallyEquivalent(Context,
+ Auto1->getTypeConstraintArguments(),
+ Auto2->getTypeConstraintArguments()))
return false;
- for (unsigned I = 0, N = Auto1Args.size(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context, Auto1Args[I], Auto2Args[I]))
- return false;
- }
}
break;
}
@@ -1055,22 +1106,26 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
case Type::SubstTemplateTypeParm: {
const auto *Subst1 = cast<SubstTemplateTypeParmType>(T1);
const auto *Subst2 = cast<SubstTemplateTypeParmType>(T2);
- if (!IsStructurallyEquivalent(Context,
- QualType(Subst1->getReplacedParameter(), 0),
- QualType(Subst2->getReplacedParameter(), 0)))
- return false;
if (!IsStructurallyEquivalent(Context, Subst1->getReplacementType(),
Subst2->getReplacementType()))
return false;
+ if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
+ Subst2->getAssociatedDecl()))
+ return false;
+ if (Subst1->getIndex() != Subst2->getIndex())
+ return false;
+ if (Subst1->getPackIndex() != Subst2->getPackIndex())
+ return false;
break;
}
case Type::SubstTemplateTypeParmPack: {
const auto *Subst1 = cast<SubstTemplateTypeParmPackType>(T1);
const auto *Subst2 = cast<SubstTemplateTypeParmPackType>(T2);
- if (!IsStructurallyEquivalent(Context,
- QualType(Subst1->getReplacedParameter(), 0),
- QualType(Subst2->getReplacedParameter(), 0)))
+ if (!IsStructurallyEquivalent(Context, Subst1->getAssociatedDecl(),
+ Subst2->getAssociatedDecl()))
+ return false;
+ if (Subst1->getIndex() != Subst2->getIndex())
return false;
if (!IsStructurallyEquivalent(Context, Subst1->getArgumentPack(),
Subst2->getArgumentPack()))
@@ -1084,13 +1139,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!IsStructurallyEquivalent(Context, Spec1->getTemplateName(),
Spec2->getTemplateName()))
return false;
- if (Spec1->getNumArgs() != Spec2->getNumArgs())
+ if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
+ Spec2->template_arguments()))
return false;
- for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context, Spec1->getArg(I),
- Spec2->getArg(I)))
- return false;
- }
break;
}
@@ -1141,13 +1192,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!IsStructurallyEquivalent(Spec1->getIdentifier(),
Spec2->getIdentifier()))
return false;
- if (Spec1->getNumArgs() != Spec2->getNumArgs())
+ if (!IsStructurallyEquivalent(Context, Spec1->template_arguments(),
+ Spec2->template_arguments()))
return false;
- for (unsigned I = 0, N = Spec1->getNumArgs(); I != N; ++I) {
- if (!IsStructurallyEquivalent(Context, Spec1->getArg(I),
- Spec2->getArg(I)))
- return false;
- }
break;
}
@@ -1434,9 +1481,9 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
if (!D1->getDeclName() && !D2->getDeclName()) {
// If both anonymous structs/unions are in a record context, make sure
// they occur in the same location in the context records.
- if (Optional<unsigned> Index1 =
+ if (std::optional<unsigned> Index1 =
StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(D1)) {
- if (Optional<unsigned> Index2 =
+ if (std::optional<unsigned> Index2 =
StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(
D2)) {
if (*Index1 != *Index2)
@@ -2108,14 +2155,14 @@ DiagnosticBuilder StructuralEquivalenceContext::Diag2(SourceLocation Loc,
return ToCtx.getDiagnostics().Report(Loc, DiagID);
}
-Optional<unsigned>
+std::optional<unsigned>
StructuralEquivalenceContext::findUntaggedStructOrUnionIndex(RecordDecl *Anon) {
ASTContext &Context = Anon->getASTContext();
QualType AnonTy = Context.getRecordType(Anon);
const auto *Owner = dyn_cast<RecordDecl>(Anon->getDeclContext());
if (!Owner)
- return None;
+ return std::nullopt;
unsigned Index = 0;
for (const auto *D : Owner->noload_decls()) {