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