ASTStructuralEquivalence.h 5.6 KB

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