reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
//===- ASTStructuralEquivalence.h -------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the StructuralEquivalenceContext class which checks for
//  structural equivalence between types.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
#define LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H

#include "clang/AST/DeclBase.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Optional.h"
#include <queue>
#include <utility>

namespace clang {

class ASTContext;
class Decl;
class DiagnosticBuilder;
class QualType;
class RecordDecl;
class SourceLocation;

/// \brief Whether to perform a normal or minimal equivalence check.
/// In case of `Minimal`, we do not perform a recursive check of decls with
/// external storage.
enum class StructuralEquivalenceKind {
  Default,
  Minimal,
};

struct StructuralEquivalenceContext {
  /// AST contexts for which we are checking structural equivalence.
  ASTContext &FromCtx, &ToCtx;

  // Queue of from-to Decl pairs that are to be checked to determine the final
  // result of equivalence of a starting Decl pair.
  std::queue<std::pair<Decl *, Decl *>> DeclsToCheck;

  // Set of from-to Decl pairs that are already visited during the check
  // (are in or were once in \c DeclsToCheck) of a starting Decl pair.
  llvm::DenseSet<std::pair<Decl *, Decl *>> VisitedDecls;

  /// Declaration (from, to) pairs that are known not to be equivalent
  /// (which we have already complained about).
  llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls;

  StructuralEquivalenceKind EqKind;

  /// Whether we're being strict about the spelling of types when
  /// unifying two types.
  bool StrictTypeSpelling;

  /// Whether warn or error on tag type mismatches.
  bool ErrorOnTagTypeMismatch;

  /// Whether to complain about failures.
  bool Complain;

  /// \c true if the last diagnostic came from ToCtx.
  bool LastDiagFromC2 = false;

  StructuralEquivalenceContext(
      ASTContext &FromCtx, ASTContext &ToCtx,
      llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls,
      StructuralEquivalenceKind EqKind,
      bool StrictTypeSpelling = false, bool Complain = true,
      bool ErrorOnTagTypeMismatch = false)
      : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls),
        EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling),
        ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {}

  DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID);
  DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID);

  /// Determine whether the two declarations are structurally
  /// equivalent.
  /// Implementation functions (all static functions in
  /// ASTStructuralEquivalence.cpp) must never call this function because that
  /// will wreak havoc the internal state (\c DeclsToCheck and
  /// \c VisitedDecls members) and can cause faulty equivalent results.
  bool IsEquivalent(Decl *D1, Decl *D2);

  /// Determine whether the two types are structurally equivalent.
  /// Implementation functions (all static functions in
  /// ASTStructuralEquivalence.cpp) must never call this function because that
  /// will wreak havoc the internal state (\c DeclsToCheck and
  /// \c VisitedDecls members) and can cause faulty equivalent results.
  bool IsEquivalent(QualType T1, QualType T2);

  /// Find the index of the given anonymous struct/union within its
  /// context.
  ///
  /// \returns Returns the index of this anonymous struct/union in its context,
  /// including the next assigned index (if none of them match). Returns an
  /// empty option if the context is not a record, i.e.. if the anonymous
  /// struct/union is at namespace or block scope.
  ///
  /// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
  /// probably makes more sense in some other common place then here.
  static llvm::Optional<unsigned>
  findUntaggedStructOrUnionIndex(RecordDecl *Anon);

  // If ErrorOnTagTypeMismatch is set, return the the error, otherwise get the
  // relevant warning for the input error diagnostic.
  unsigned getApplicableDiagnostic(unsigned ErrorDiagnostic);

private:
  /// Finish checking all of the structural equivalences.
  ///
  /// \returns true if the equivalence check failed (non-equivalence detected),
  /// false if equivalence was detected.
  bool Finish();

  /// Check for common properties at Finish.
  /// \returns true if D1 and D2 may be equivalent,
  /// false if they are for sure not.
  bool CheckCommonEquivalence(Decl *D1, Decl *D2);

  /// Check for class dependent properties at Finish.
  /// \returns true if D1 and D2 may be equivalent,
  /// false if they are for sure not.
  bool CheckKindSpecificEquivalence(Decl *D1, Decl *D2);
};

} // namespace clang

#endif // LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H