Clang Project

clang_source_code/include/clang/AST/ASTStructuralEquivalence.h
1//===- ASTStructuralEquivalence.h -------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file defines the StructuralEquivalenceContext class which checks for
10//  structural equivalence between types.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
15#define LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
16
17#include "clang/AST/DeclBase.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/DenseSet.h"
20#include "llvm/ADT/Optional.h"
21#include <deque>
22#include <utility>
23
24namespace clang {
25
26class ASTContext;
27class Decl;
28class DiagnosticBuilder;
29class QualType;
30class RecordDecl;
31class SourceLocation;
32
33/// \brief Whether to perform a normal or minimal equivalence check.
34/// In case of `Minimal`, we do not perform a recursive check of decls with
35/// external storage.
36enum class StructuralEquivalenceKind {
37  Default,
38  Minimal,
39};
40
41struct StructuralEquivalenceContext {
42  /// AST contexts for which we are checking structural equivalence.
43  ASTContext &FromCtx, &ToCtx;
44
45  /// The set of "tentative" equivalences between two canonical
46  /// declarations, mapping from a declaration in the first context to the
47  /// declaration in the second context that we believe to be equivalent.
48  llvm::DenseMap<Decl *, Decl *> TentativeEquivalences;
49
50  /// Queue of declarations in the first context whose equivalence
51  /// with a declaration in the second context still needs to be verified.
52  std::deque<Decl *> DeclsToCheck;
53
54  /// Declaration (from, to) pairs that are known not to be equivalent
55  /// (which we have already complained about).
56  llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls;
57
58  StructuralEquivalenceKind EqKind;
59
60  /// Whether we're being strict about the spelling of types when
61  /// unifying two types.
62  bool StrictTypeSpelling;
63
64  /// Whether warn or error on tag type mismatches.
65  bool ErrorOnTagTypeMismatch;
66
67  /// Whether to complain about failures.
68  bool Complain;
69
70  /// \c true if the last diagnostic came from ToCtx.
71  bool LastDiagFromC2 = false;
72
73  StructuralEquivalenceContext(
74      ASTContext &FromCtxASTContext &ToCtx,
75      llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls,
76      StructuralEquivalenceKind EqKind,
77      bool StrictTypeSpelling = falsebool Complain = true,
78      bool ErrorOnTagTypeMismatch = false)
79      : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls),
80        EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling),
81        ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {}
82
83  DiagnosticBuilder Diag1(SourceLocation Locunsigned DiagID);
84  DiagnosticBuilder Diag2(SourceLocation Locunsigned DiagID);
85
86  /// Determine whether the two declarations are structurally
87  /// equivalent.
88  /// Implementation functions (all static functions in
89  /// ASTStructuralEquivalence.cpp) must never call this function because that
90  /// will wreak havoc the internal state (\c DeclsToCheck and
91  /// \c TentativeEquivalences members) and can cause faulty equivalent results.
92  bool IsEquivalent(Decl *D1Decl *D2);
93
94  /// Determine whether the two types are structurally equivalent.
95  /// Implementation functions (all static functions in
96  /// ASTStructuralEquivalence.cpp) must never call this function because that
97  /// will wreak havoc the internal state (\c DeclsToCheck and
98  /// \c TentativeEquivalences members) and can cause faulty equivalent results.
99  bool IsEquivalent(QualType T1QualType T2);
100
101  /// Find the index of the given anonymous struct/union within its
102  /// context.
103  ///
104  /// \returns Returns the index of this anonymous struct/union in its context,
105  /// including the next assigned index (if none of them match). Returns an
106  /// empty option if the context is not a record, i.e.. if the anonymous
107  /// struct/union is at namespace or block scope.
108  ///
109  /// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
110  /// probably makes more sense in some other common place then here.
111  static llvm::Optional<unsigned>
112  findUntaggedStructOrUnionIndex(RecordDecl *Anon);
113
114private:
115  /// Finish checking all of the structural equivalences.
116  ///
117  /// \returns true if the equivalence check failed (non-equivalence detected),
118  /// false if equivalence was detected.
119  bool Finish();
120
121  /// Check for common properties at Finish.
122  /// \returns true if D1 and D2 may be equivalent,
123  /// false if they are for sure not.
124  bool CheckCommonEquivalence(Decl *D1Decl *D2);
125
126  /// Check for class dependent properties at Finish.
127  /// \returns true if D1 and D2 may be equivalent,
128  /// false if they are for sure not.
129  bool CheckKindSpecificEquivalence(Decl *D1Decl *D2);
130};
131
132// namespace clang
133
134#endif // LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
135
clang::StructuralEquivalenceContext::FromCtx
clang::StructuralEquivalenceContext::ToCtx
clang::StructuralEquivalenceContext::TentativeEquivalences
clang::StructuralEquivalenceContext::DeclsToCheck
clang::StructuralEquivalenceContext::NonEquivalentDecls
clang::StructuralEquivalenceContext::EqKind
clang::StructuralEquivalenceContext::StrictTypeSpelling
clang::StructuralEquivalenceContext::ErrorOnTagTypeMismatch
clang::StructuralEquivalenceContext::Complain
clang::StructuralEquivalenceContext::LastDiagFromC2
clang::StructuralEquivalenceContext::Diag1
clang::StructuralEquivalenceContext::Diag2
clang::StructuralEquivalenceContext::IsEquivalent
clang::StructuralEquivalenceContext::IsEquivalent
clang::StructuralEquivalenceContext::findUntaggedStructOrUnionIndex
clang::StructuralEquivalenceContext::Finish
clang::StructuralEquivalenceContext::CheckCommonEquivalence
clang::StructuralEquivalenceContext::CheckKindSpecificEquivalence