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