Home | History | Annotate | Line # | Download | only in AST
      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 <queue>
     22 #include <utility>
     23 
     24 namespace clang {
     25 
     26 class ASTContext;
     27 class Decl;
     28 class DiagnosticBuilder;
     29 class QualType;
     30 class RecordDecl;
     31 class 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.
     36 enum class StructuralEquivalenceKind {
     37   Default,
     38   Minimal,
     39 };
     40 
     41 struct StructuralEquivalenceContext {
     42   /// AST contexts for which we are checking structural equivalence.
     43   ASTContext &FromCtx, &ToCtx;
     44 
     45   // Queue of from-to Decl pairs that are to be checked to determine the final
     46   // result of equivalence of a starting Decl pair.
     47   std::queue<std::pair<Decl *, Decl *>> DeclsToCheck;
     48 
     49   // Set of from-to Decl pairs that are already visited during the check
     50   // (are in or were once in \c DeclsToCheck) of a starting Decl pair.
     51   llvm::DenseSet<std::pair<Decl *, Decl *>> VisitedDecls;
     52 
     53   /// Declaration (from, to) pairs that are known not to be equivalent
     54   /// (which we have already complained about).
     55   llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls;
     56 
     57   StructuralEquivalenceKind EqKind;
     58 
     59   /// Whether we're being strict about the spelling of types when
     60   /// unifying two types.
     61   bool StrictTypeSpelling;
     62 
     63   /// Whether warn or error on tag type mismatches.
     64   bool ErrorOnTagTypeMismatch;
     65 
     66   /// Whether to complain about failures.
     67   bool Complain;
     68 
     69   /// \c true if the last diagnostic came from ToCtx.
     70   bool LastDiagFromC2 = false;
     71 
     72   StructuralEquivalenceContext(
     73       ASTContext &FromCtx, ASTContext &ToCtx,
     74       llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls,
     75       StructuralEquivalenceKind EqKind,
     76       bool StrictTypeSpelling = false, bool Complain = true,
     77       bool ErrorOnTagTypeMismatch = false)
     78       : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls),
     79         EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling),
     80         ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {}
     81 
     82   DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID);
     83   DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID);
     84 
     85   /// Determine whether the two declarations are structurally
     86   /// 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(Decl *D1, Decl *D2);
     92 
     93   /// Determine whether the two types are structurally equivalent.
     94   /// Implementation functions (all static functions in
     95   /// ASTStructuralEquivalence.cpp) must never call this function because that
     96   /// will wreak havoc the internal state (\c DeclsToCheck and
     97   /// \c VisitedDecls members) and can cause faulty equivalent results.
     98   bool IsEquivalent(QualType T1, QualType T2);
     99 
    100   /// Determine whether the two statements are structurally equivalent.
    101   /// Implementation functions (all static functions in
    102   /// ASTStructuralEquivalence.cpp) must never call this function because that
    103   /// will wreak havoc the internal state (\c DeclsToCheck and
    104   /// \c VisitedDecls members) and can cause faulty equivalent results.
    105   bool IsEquivalent(Stmt *S1, Stmt *S2);
    106 
    107   /// Find the index of the given anonymous struct/union within its
    108   /// context.
    109   ///
    110   /// \returns Returns the index of this anonymous struct/union in its context,
    111   /// including the next assigned index (if none of them match). Returns an
    112   /// empty option if the context is not a record, i.e.. if the anonymous
    113   /// struct/union is at namespace or block scope.
    114   ///
    115   /// FIXME: This is needed by ASTImporter and ASTStructureEquivalence. It
    116   /// probably makes more sense in some other common place then here.
    117   static llvm::Optional<unsigned>
    118   findUntaggedStructOrUnionIndex(RecordDecl *Anon);
    119 
    120   // If ErrorOnTagTypeMismatch is set, return the the error, otherwise get the
    121   // relevant warning for the input error diagnostic.
    122   unsigned getApplicableDiagnostic(unsigned ErrorDiagnostic);
    123 
    124 private:
    125   /// Finish checking all of the structural equivalences.
    126   ///
    127   /// \returns true if the equivalence check failed (non-equivalence detected),
    128   /// false if equivalence was detected.
    129   bool Finish();
    130 
    131   /// Check for common properties at Finish.
    132   /// \returns true if D1 and D2 may be equivalent,
    133   /// false if they are for sure not.
    134   bool CheckCommonEquivalence(Decl *D1, Decl *D2);
    135 
    136   /// Check for class dependent properties at Finish.
    137   /// \returns true if D1 and D2 may be equivalent,
    138   /// false if they are for sure not.
    139   bool CheckKindSpecificEquivalence(Decl *D1, Decl *D2);
    140 };
    141 
    142 } // namespace clang
    143 
    144 #endif // LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H
    145