/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/ODRDiagsEmitter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- ODRDiagsEmitter.cpp - Diagnostics for ODR mismatches ----*- 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 | | #include "clang/AST/ODRDiagsEmitter.h" |
10 | | #include "clang/AST/DeclFriend.h" |
11 | | #include "clang/AST/DeclTemplate.h" |
12 | | #include "clang/AST/ODRHash.h" |
13 | | #include "clang/Basic/DiagnosticAST.h" |
14 | | #include "clang/Basic/Module.h" |
15 | | |
16 | | using namespace clang; |
17 | | |
18 | 316 | static unsigned computeODRHash(QualType Ty) { |
19 | 316 | ODRHash Hasher; |
20 | 316 | Hasher.AddQualType(Ty); |
21 | 316 | return Hasher.CalculateHash(); |
22 | 316 | } |
23 | | |
24 | 40 | static unsigned computeODRHash(const Stmt *S) { |
25 | 40 | ODRHash Hasher; |
26 | 40 | Hasher.AddStmt(S); |
27 | 40 | return Hasher.CalculateHash(); |
28 | 40 | } |
29 | | |
30 | 923 | static unsigned computeODRHash(const Decl *D) { |
31 | 923 | assert(D); |
32 | 923 | ODRHash Hasher; |
33 | 923 | Hasher.AddSubDecl(D); |
34 | 923 | return Hasher.CalculateHash(); |
35 | 923 | } |
36 | | |
37 | 16 | static unsigned computeODRHash(const TemplateArgument &TA) { |
38 | 16 | ODRHash Hasher; |
39 | 16 | Hasher.AddTemplateArgument(TA); |
40 | 16 | return Hasher.CalculateHash(); |
41 | 16 | } |
42 | | |
43 | 922 | std::string ODRDiagsEmitter::getOwningModuleNameForDiagnostic(const Decl *D) { |
44 | | // If we know the owning module, use it. |
45 | 922 | if (Module *M = D->getImportedOwningModule()) |
46 | 865 | return M->getFullModuleName(); |
47 | | |
48 | | // Not from a module. |
49 | 57 | return {}; |
50 | 922 | } |
51 | | |
52 | | template <typename MethodT> |
53 | | static bool diagnoseSubMismatchMethodParameters(DiagnosticsEngine &Diags, |
54 | | const NamedDecl *FirstContainer, |
55 | | StringRef FirstModule, |
56 | | StringRef SecondModule, |
57 | | const MethodT *FirstMethod, |
58 | 46 | const MethodT *SecondMethod) { |
59 | 46 | enum DiagMethodType { |
60 | 46 | DiagMethod, |
61 | 46 | DiagConstructor, |
62 | 46 | DiagDestructor, |
63 | 46 | }; |
64 | 46 | auto GetDiagMethodType = [](const NamedDecl *D) { |
65 | 36 | if (isa<CXXConstructorDecl>(D)) |
66 | 2 | return DiagConstructor; |
67 | 34 | if (isa<CXXDestructorDecl>(D)) |
68 | 0 | return DiagDestructor; |
69 | 34 | return DiagMethod; |
70 | 34 | }; ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*)::'lambda'(clang::NamedDecl const*)::operator()(clang::NamedDecl const*) const Line | Count | Source | 64 | 24 | auto GetDiagMethodType = [](const NamedDecl *D) { | 65 | 24 | if (isa<CXXConstructorDecl>(D)) | 66 | 0 | return DiagConstructor; | 67 | 24 | if (isa<CXXDestructorDecl>(D)) | 68 | 0 | return DiagDestructor; | 69 | 24 | return DiagMethod; | 70 | 24 | }; |
ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*)::'lambda'(clang::NamedDecl const*)::operator()(clang::NamedDecl const*) const Line | Count | Source | 64 | 12 | auto GetDiagMethodType = [](const NamedDecl *D) { | 65 | 12 | if (isa<CXXConstructorDecl>(D)) | 66 | 2 | return DiagConstructor; | 67 | 10 | if (isa<CXXDestructorDecl>(D)) | 68 | 0 | return DiagDestructor; | 69 | 10 | return DiagMethod; | 70 | 10 | }; |
|
71 | | |
72 | 46 | enum ODRMethodParametersDifference { |
73 | 46 | NumberParameters, |
74 | 46 | ParameterType, |
75 | 46 | ParameterName, |
76 | 46 | }; |
77 | 46 | auto DiagError = [&Diags, &GetDiagMethodType, FirstContainer, FirstModule, |
78 | 46 | FirstMethod](ODRMethodParametersDifference DiffType) { |
79 | 18 | DeclarationName FirstName = FirstMethod->getDeclName(); |
80 | 18 | DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod); |
81 | 18 | return Diags.Report(FirstMethod->getLocation(), |
82 | 18 | diag::err_module_odr_violation_method_params) |
83 | 18 | << FirstContainer << FirstModule.empty() << FirstModule |
84 | 18 | << FirstMethod->getSourceRange() << DiffType << FirstMethodType |
85 | 18 | << FirstName; |
86 | 18 | }; ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*)::'lambda'(bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*)::ODRMethodParametersDifference)::operator()(bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*)::ODRMethodParametersDifference) const Line | Count | Source | 78 | 12 | FirstMethod](ODRMethodParametersDifference DiffType) { | 79 | 12 | DeclarationName FirstName = FirstMethod->getDeclName(); | 80 | 12 | DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod); | 81 | 12 | return Diags.Report(FirstMethod->getLocation(), | 82 | 12 | diag::err_module_odr_violation_method_params) | 83 | 12 | << FirstContainer << FirstModule.empty() << FirstModule | 84 | 12 | << FirstMethod->getSourceRange() << DiffType << FirstMethodType | 85 | 12 | << FirstName; | 86 | 12 | }; |
ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*)::'lambda'(bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*)::ODRMethodParametersDifference)::operator()(bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*)::ODRMethodParametersDifference) const Line | Count | Source | 78 | 6 | FirstMethod](ODRMethodParametersDifference DiffType) { | 79 | 6 | DeclarationName FirstName = FirstMethod->getDeclName(); | 80 | 6 | DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod); | 81 | 6 | return Diags.Report(FirstMethod->getLocation(), | 82 | 6 | diag::err_module_odr_violation_method_params) | 83 | 6 | << FirstContainer << FirstModule.empty() << FirstModule | 84 | 6 | << FirstMethod->getSourceRange() << DiffType << FirstMethodType | 85 | 6 | << FirstName; | 86 | 6 | }; |
|
87 | 46 | auto DiagNote = [&Diags, &GetDiagMethodType, SecondModule, |
88 | 46 | SecondMethod](ODRMethodParametersDifference DiffType) { |
89 | 18 | DeclarationName SecondName = SecondMethod->getDeclName(); |
90 | 18 | DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod); |
91 | 18 | return Diags.Report(SecondMethod->getLocation(), |
92 | 18 | diag::note_module_odr_violation_method_params) |
93 | 18 | << SecondModule.empty() << SecondModule |
94 | 18 | << SecondMethod->getSourceRange() << DiffType << SecondMethodType |
95 | 18 | << SecondName; |
96 | 18 | }; ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*)::'lambda0'(bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*)::ODRMethodParametersDifference)::operator()(bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*)::ODRMethodParametersDifference) const Line | Count | Source | 88 | 12 | SecondMethod](ODRMethodParametersDifference DiffType) { | 89 | 12 | DeclarationName SecondName = SecondMethod->getDeclName(); | 90 | 12 | DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod); | 91 | 12 | return Diags.Report(SecondMethod->getLocation(), | 92 | 12 | diag::note_module_odr_violation_method_params) | 93 | 12 | << SecondModule.empty() << SecondModule | 94 | 12 | << SecondMethod->getSourceRange() << DiffType << SecondMethodType | 95 | 12 | << SecondName; | 96 | 12 | }; |
ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*)::'lambda0'(bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*)::ODRMethodParametersDifference)::operator()(bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*)::ODRMethodParametersDifference) const Line | Count | Source | 88 | 6 | SecondMethod](ODRMethodParametersDifference DiffType) { | 89 | 6 | DeclarationName SecondName = SecondMethod->getDeclName(); | 90 | 6 | DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod); | 91 | 6 | return Diags.Report(SecondMethod->getLocation(), | 92 | 6 | diag::note_module_odr_violation_method_params) | 93 | 6 | << SecondModule.empty() << SecondModule | 94 | 6 | << SecondMethod->getSourceRange() << DiffType << SecondMethodType | 95 | 6 | << SecondName; | 96 | 6 | }; |
|
97 | | |
98 | 46 | const unsigned FirstNumParameters = FirstMethod->param_size(); |
99 | 46 | const unsigned SecondNumParameters = SecondMethod->param_size(); |
100 | 46 | if (FirstNumParameters != SecondNumParameters) { |
101 | 6 | DiagError(NumberParameters) << FirstNumParameters; |
102 | 6 | DiagNote(NumberParameters) << SecondNumParameters; |
103 | 6 | return true; |
104 | 6 | } |
105 | | |
106 | 44 | for (unsigned I = 0; 40 I < FirstNumParameters; ++I4 ) { |
107 | 16 | const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I); |
108 | 16 | const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I); |
109 | | |
110 | 16 | QualType FirstParamType = FirstParam->getType(); |
111 | 16 | QualType SecondParamType = SecondParam->getType(); |
112 | 16 | if (FirstParamType != SecondParamType && |
113 | 16 | computeODRHash(FirstParamType) != computeODRHash(SecondParamType)8 ) { |
114 | 7 | if (const DecayedType *ParamDecayedType = |
115 | 7 | FirstParamType->getAs<DecayedType>()) { |
116 | 1 | DiagError(ParameterType) << (I + 1) << FirstParamType << true |
117 | 1 | << ParamDecayedType->getOriginalType(); |
118 | 6 | } else { |
119 | 6 | DiagError(ParameterType) << (I + 1) << FirstParamType << false; |
120 | 6 | } |
121 | | |
122 | 7 | if (const DecayedType *ParamDecayedType = |
123 | 7 | SecondParamType->getAs<DecayedType>()) { |
124 | 1 | DiagNote(ParameterType) << (I + 1) << SecondParamType << true |
125 | 1 | << ParamDecayedType->getOriginalType(); |
126 | 6 | } else { |
127 | 6 | DiagNote(ParameterType) << (I + 1) << SecondParamType << false; |
128 | 6 | } |
129 | 7 | return true; |
130 | 7 | } |
131 | | |
132 | 9 | DeclarationName FirstParamName = FirstParam->getDeclName(); |
133 | 9 | DeclarationName SecondParamName = SecondParam->getDeclName(); |
134 | 9 | if (FirstParamName != SecondParamName) { |
135 | 5 | DiagError(ParameterName) << (I + 1) << FirstParamName; |
136 | 5 | DiagNote(ParameterName) << (I + 1) << SecondParamName; |
137 | 5 | return true; |
138 | 5 | } |
139 | 9 | } |
140 | | |
141 | 28 | return false; |
142 | 40 | } ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::ObjCMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::ObjCMethodDecl const*, clang::ObjCMethodDecl const*) Line | Count | Source | 58 | 20 | const MethodT *SecondMethod) { | 59 | 20 | enum DiagMethodType { | 60 | 20 | DiagMethod, | 61 | 20 | DiagConstructor, | 62 | 20 | DiagDestructor, | 63 | 20 | }; | 64 | 20 | auto GetDiagMethodType = [](const NamedDecl *D) { | 65 | 20 | if (isa<CXXConstructorDecl>(D)) | 66 | 20 | return DiagConstructor; | 67 | 20 | if (isa<CXXDestructorDecl>(D)) | 68 | 20 | return DiagDestructor; | 69 | 20 | return DiagMethod; | 70 | 20 | }; | 71 | | | 72 | 20 | enum ODRMethodParametersDifference { | 73 | 20 | NumberParameters, | 74 | 20 | ParameterType, | 75 | 20 | ParameterName, | 76 | 20 | }; | 77 | 20 | auto DiagError = [&Diags, &GetDiagMethodType, FirstContainer, FirstModule, | 78 | 20 | FirstMethod](ODRMethodParametersDifference DiffType) { | 79 | 20 | DeclarationName FirstName = FirstMethod->getDeclName(); | 80 | 20 | DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod); | 81 | 20 | return Diags.Report(FirstMethod->getLocation(), | 82 | 20 | diag::err_module_odr_violation_method_params) | 83 | 20 | << FirstContainer << FirstModule.empty() << FirstModule | 84 | 20 | << FirstMethod->getSourceRange() << DiffType << FirstMethodType | 85 | 20 | << FirstName; | 86 | 20 | }; | 87 | 20 | auto DiagNote = [&Diags, &GetDiagMethodType, SecondModule, | 88 | 20 | SecondMethod](ODRMethodParametersDifference DiffType) { | 89 | 20 | DeclarationName SecondName = SecondMethod->getDeclName(); | 90 | 20 | DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod); | 91 | 20 | return Diags.Report(SecondMethod->getLocation(), | 92 | 20 | diag::note_module_odr_violation_method_params) | 93 | 20 | << SecondModule.empty() << SecondModule | 94 | 20 | << SecondMethod->getSourceRange() << DiffType << SecondMethodType | 95 | 20 | << SecondName; | 96 | 20 | }; | 97 | | | 98 | 20 | const unsigned FirstNumParameters = FirstMethod->param_size(); | 99 | 20 | const unsigned SecondNumParameters = SecondMethod->param_size(); | 100 | 20 | if (FirstNumParameters != SecondNumParameters) { | 101 | 4 | DiagError(NumberParameters) << FirstNumParameters; | 102 | 4 | DiagNote(NumberParameters) << SecondNumParameters; | 103 | 4 | return true; | 104 | 4 | } | 105 | | | 106 | 16 | for (unsigned I = 0; I < FirstNumParameters; ++I0 ) { | 107 | 8 | const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I); | 108 | 8 | const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I); | 109 | | | 110 | 8 | QualType FirstParamType = FirstParam->getType(); | 111 | 8 | QualType SecondParamType = SecondParam->getType(); | 112 | 8 | if (FirstParamType != SecondParamType && | 113 | 8 | computeODRHash(FirstParamType) != computeODRHash(SecondParamType)4 ) { | 114 | 4 | if (const DecayedType *ParamDecayedType = | 115 | 4 | FirstParamType->getAs<DecayedType>()) { | 116 | 0 | DiagError(ParameterType) << (I + 1) << FirstParamType << true | 117 | 0 | << ParamDecayedType->getOriginalType(); | 118 | 4 | } else { | 119 | 4 | DiagError(ParameterType) << (I + 1) << FirstParamType << false; | 120 | 4 | } | 121 | | | 122 | 4 | if (const DecayedType *ParamDecayedType = | 123 | 4 | SecondParamType->getAs<DecayedType>()) { | 124 | 0 | DiagNote(ParameterType) << (I + 1) << SecondParamType << true | 125 | 0 | << ParamDecayedType->getOriginalType(); | 126 | 4 | } else { | 127 | 4 | DiagNote(ParameterType) << (I + 1) << SecondParamType << false; | 128 | 4 | } | 129 | 4 | return true; | 130 | 4 | } | 131 | | | 132 | 4 | DeclarationName FirstParamName = FirstParam->getDeclName(); | 133 | 4 | DeclarationName SecondParamName = SecondParam->getDeclName(); | 134 | 4 | if (FirstParamName != SecondParamName) { | 135 | 4 | DiagError(ParameterName) << (I + 1) << FirstParamName; | 136 | 4 | DiagNote(ParameterName) << (I + 1) << SecondParamName; | 137 | 4 | return true; | 138 | 4 | } | 139 | 4 | } | 140 | | | 141 | 8 | return false; | 142 | 16 | } |
ODRDiagsEmitter.cpp:bool diagnoseSubMismatchMethodParameters<clang::CXXMethodDecl>(clang::DiagnosticsEngine&, clang::NamedDecl const*, llvm::StringRef, llvm::StringRef, clang::CXXMethodDecl const*, clang::CXXMethodDecl const*) Line | Count | Source | 58 | 26 | const MethodT *SecondMethod) { | 59 | 26 | enum DiagMethodType { | 60 | 26 | DiagMethod, | 61 | 26 | DiagConstructor, | 62 | 26 | DiagDestructor, | 63 | 26 | }; | 64 | 26 | auto GetDiagMethodType = [](const NamedDecl *D) { | 65 | 26 | if (isa<CXXConstructorDecl>(D)) | 66 | 26 | return DiagConstructor; | 67 | 26 | if (isa<CXXDestructorDecl>(D)) | 68 | 26 | return DiagDestructor; | 69 | 26 | return DiagMethod; | 70 | 26 | }; | 71 | | | 72 | 26 | enum ODRMethodParametersDifference { | 73 | 26 | NumberParameters, | 74 | 26 | ParameterType, | 75 | 26 | ParameterName, | 76 | 26 | }; | 77 | 26 | auto DiagError = [&Diags, &GetDiagMethodType, FirstContainer, FirstModule, | 78 | 26 | FirstMethod](ODRMethodParametersDifference DiffType) { | 79 | 26 | DeclarationName FirstName = FirstMethod->getDeclName(); | 80 | 26 | DiagMethodType FirstMethodType = GetDiagMethodType(FirstMethod); | 81 | 26 | return Diags.Report(FirstMethod->getLocation(), | 82 | 26 | diag::err_module_odr_violation_method_params) | 83 | 26 | << FirstContainer << FirstModule.empty() << FirstModule | 84 | 26 | << FirstMethod->getSourceRange() << DiffType << FirstMethodType | 85 | 26 | << FirstName; | 86 | 26 | }; | 87 | 26 | auto DiagNote = [&Diags, &GetDiagMethodType, SecondModule, | 88 | 26 | SecondMethod](ODRMethodParametersDifference DiffType) { | 89 | 26 | DeclarationName SecondName = SecondMethod->getDeclName(); | 90 | 26 | DiagMethodType SecondMethodType = GetDiagMethodType(SecondMethod); | 91 | 26 | return Diags.Report(SecondMethod->getLocation(), | 92 | 26 | diag::note_module_odr_violation_method_params) | 93 | 26 | << SecondModule.empty() << SecondModule | 94 | 26 | << SecondMethod->getSourceRange() << DiffType << SecondMethodType | 95 | 26 | << SecondName; | 96 | 26 | }; | 97 | | | 98 | 26 | const unsigned FirstNumParameters = FirstMethod->param_size(); | 99 | 26 | const unsigned SecondNumParameters = SecondMethod->param_size(); | 100 | 26 | if (FirstNumParameters != SecondNumParameters) { | 101 | 2 | DiagError(NumberParameters) << FirstNumParameters; | 102 | 2 | DiagNote(NumberParameters) << SecondNumParameters; | 103 | 2 | return true; | 104 | 2 | } | 105 | | | 106 | 28 | for (unsigned I = 0; 24 I < FirstNumParameters; ++I4 ) { | 107 | 8 | const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I); | 108 | 8 | const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I); | 109 | | | 110 | 8 | QualType FirstParamType = FirstParam->getType(); | 111 | 8 | QualType SecondParamType = SecondParam->getType(); | 112 | 8 | if (FirstParamType != SecondParamType && | 113 | 8 | computeODRHash(FirstParamType) != computeODRHash(SecondParamType)4 ) { | 114 | 3 | if (const DecayedType *ParamDecayedType = | 115 | 3 | FirstParamType->getAs<DecayedType>()) { | 116 | 1 | DiagError(ParameterType) << (I + 1) << FirstParamType << true | 117 | 1 | << ParamDecayedType->getOriginalType(); | 118 | 2 | } else { | 119 | 2 | DiagError(ParameterType) << (I + 1) << FirstParamType << false; | 120 | 2 | } | 121 | | | 122 | 3 | if (const DecayedType *ParamDecayedType = | 123 | 3 | SecondParamType->getAs<DecayedType>()) { | 124 | 1 | DiagNote(ParameterType) << (I + 1) << SecondParamType << true | 125 | 1 | << ParamDecayedType->getOriginalType(); | 126 | 2 | } else { | 127 | 2 | DiagNote(ParameterType) << (I + 1) << SecondParamType << false; | 128 | 2 | } | 129 | 3 | return true; | 130 | 3 | } | 131 | | | 132 | 5 | DeclarationName FirstParamName = FirstParam->getDeclName(); | 133 | 5 | DeclarationName SecondParamName = SecondParam->getDeclName(); | 134 | 5 | if (FirstParamName != SecondParamName) { | 135 | 1 | DiagError(ParameterName) << (I + 1) << FirstParamName; | 136 | 1 | DiagNote(ParameterName) << (I + 1) << SecondParamName; | 137 | 1 | return true; | 138 | 1 | } | 139 | 5 | } | 140 | | | 141 | 20 | return false; | 142 | 24 | } |
|
143 | | |
144 | | bool ODRDiagsEmitter::diagnoseSubMismatchField( |
145 | | const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule, |
146 | 40 | const FieldDecl *FirstField, const FieldDecl *SecondField) const { |
147 | 40 | enum ODRFieldDifference { |
148 | 40 | FieldName, |
149 | 40 | FieldTypeName, |
150 | 40 | FieldSingleBitField, |
151 | 40 | FieldDifferentWidthBitField, |
152 | 40 | FieldSingleMutable, |
153 | 40 | FieldSingleInitializer, |
154 | 40 | FieldDifferentInitializers, |
155 | 40 | }; |
156 | | |
157 | 40 | auto DiagError = [FirstRecord, FirstField, FirstModule, |
158 | 40 | this](ODRFieldDifference DiffType) { |
159 | 36 | return Diag(FirstField->getLocation(), diag::err_module_odr_violation_field) |
160 | 36 | << FirstRecord << FirstModule.empty() << FirstModule |
161 | 36 | << FirstField->getSourceRange() << DiffType; |
162 | 36 | }; |
163 | 40 | auto DiagNote = [SecondField, SecondModule, |
164 | 40 | this](ODRFieldDifference DiffType) { |
165 | 36 | return Diag(SecondField->getLocation(), |
166 | 36 | diag::note_module_odr_violation_field) |
167 | 36 | << SecondModule.empty() << SecondModule << SecondField->getSourceRange() << DiffType; |
168 | 36 | }; |
169 | | |
170 | 40 | IdentifierInfo *FirstII = FirstField->getIdentifier(); |
171 | 40 | IdentifierInfo *SecondII = SecondField->getIdentifier(); |
172 | 40 | if (FirstII->getName() != SecondII->getName()) { |
173 | 7 | DiagError(FieldName) << FirstII; |
174 | 7 | DiagNote(FieldName) << SecondII; |
175 | 7 | return true; |
176 | 7 | } |
177 | | |
178 | 33 | QualType FirstType = FirstField->getType(); |
179 | 33 | QualType SecondType = SecondField->getType(); |
180 | 33 | if (computeODRHash(FirstType) != computeODRHash(SecondType)) { |
181 | 16 | DiagError(FieldTypeName) << FirstII << FirstType; |
182 | 16 | DiagNote(FieldTypeName) << SecondII << SecondType; |
183 | 16 | return true; |
184 | 16 | } |
185 | | |
186 | 17 | assert(Context.hasSameType(FirstField->getType(), SecondField->getType())); |
187 | 17 | (void)Context; |
188 | | |
189 | 17 | const bool IsFirstBitField = FirstField->isBitField(); |
190 | 17 | const bool IsSecondBitField = SecondField->isBitField(); |
191 | 17 | if (IsFirstBitField != IsSecondBitField) { |
192 | 3 | DiagError(FieldSingleBitField) << FirstII << IsFirstBitField; |
193 | 3 | DiagNote(FieldSingleBitField) << SecondII << IsSecondBitField; |
194 | 3 | return true; |
195 | 3 | } |
196 | | |
197 | 14 | if (IsFirstBitField && IsSecondBitField5 ) { |
198 | 5 | unsigned FirstBitWidthHash = computeODRHash(FirstField->getBitWidth()); |
199 | 5 | unsigned SecondBitWidthHash = computeODRHash(SecondField->getBitWidth()); |
200 | 5 | if (FirstBitWidthHash != SecondBitWidthHash) { |
201 | 4 | DiagError(FieldDifferentWidthBitField) |
202 | 4 | << FirstII << FirstField->getBitWidth()->getSourceRange(); |
203 | 4 | DiagNote(FieldDifferentWidthBitField) |
204 | 4 | << SecondII << SecondField->getBitWidth()->getSourceRange(); |
205 | 4 | return true; |
206 | 4 | } |
207 | 5 | } |
208 | | |
209 | 10 | if (!LangOpts.CPlusPlus) |
210 | 4 | return false; |
211 | | |
212 | 6 | const bool IsFirstMutable = FirstField->isMutable(); |
213 | 6 | const bool IsSecondMutable = SecondField->isMutable(); |
214 | 6 | if (IsFirstMutable != IsSecondMutable) { |
215 | 2 | DiagError(FieldSingleMutable) << FirstII << IsFirstMutable; |
216 | 2 | DiagNote(FieldSingleMutable) << SecondII << IsSecondMutable; |
217 | 2 | return true; |
218 | 2 | } |
219 | | |
220 | 4 | const Expr *FirstInitializer = FirstField->getInClassInitializer(); |
221 | 4 | const Expr *SecondInitializer = SecondField->getInClassInitializer(); |
222 | 4 | if ((!FirstInitializer && SecondInitializer1 ) || |
223 | 4 | (3 FirstInitializer3 && !SecondInitializer3 )) { |
224 | 1 | DiagError(FieldSingleInitializer) |
225 | 1 | << FirstII << (FirstInitializer != nullptr); |
226 | 1 | DiagNote(FieldSingleInitializer) |
227 | 1 | << SecondII << (SecondInitializer != nullptr); |
228 | 1 | return true; |
229 | 1 | } |
230 | | |
231 | 3 | if (FirstInitializer && SecondInitializer) { |
232 | 3 | unsigned FirstInitHash = computeODRHash(FirstInitializer); |
233 | 3 | unsigned SecondInitHash = computeODRHash(SecondInitializer); |
234 | 3 | if (FirstInitHash != SecondInitHash) { |
235 | 3 | DiagError(FieldDifferentInitializers) |
236 | 3 | << FirstII << FirstInitializer->getSourceRange(); |
237 | 3 | DiagNote(FieldDifferentInitializers) |
238 | 3 | << SecondII << SecondInitializer->getSourceRange(); |
239 | 3 | return true; |
240 | 3 | } |
241 | 3 | } |
242 | | |
243 | 0 | return false; |
244 | 3 | } |
245 | | |
246 | | bool ODRDiagsEmitter::diagnoseSubMismatchTypedef( |
247 | | const NamedDecl *FirstRecord, StringRef FirstModule, StringRef SecondModule, |
248 | | const TypedefNameDecl *FirstTD, const TypedefNameDecl *SecondTD, |
249 | 7 | bool IsTypeAlias) const { |
250 | 7 | enum ODRTypedefDifference { |
251 | 7 | TypedefName, |
252 | 7 | TypedefType, |
253 | 7 | }; |
254 | | |
255 | 7 | auto DiagError = [FirstRecord, FirstTD, FirstModule, |
256 | 7 | this](ODRTypedefDifference DiffType) { |
257 | 7 | return Diag(FirstTD->getLocation(), diag::err_module_odr_violation_typedef) |
258 | 7 | << FirstRecord << FirstModule.empty() << FirstModule |
259 | 7 | << FirstTD->getSourceRange() << DiffType; |
260 | 7 | }; |
261 | 7 | auto DiagNote = [SecondTD, SecondModule, |
262 | 7 | this](ODRTypedefDifference DiffType) { |
263 | 7 | return Diag(SecondTD->getLocation(), |
264 | 7 | diag::note_module_odr_violation_typedef) |
265 | 7 | << SecondModule << SecondTD->getSourceRange() << DiffType; |
266 | 7 | }; |
267 | | |
268 | 7 | DeclarationName FirstName = FirstTD->getDeclName(); |
269 | 7 | DeclarationName SecondName = SecondTD->getDeclName(); |
270 | 7 | if (FirstName != SecondName) { |
271 | 2 | DiagError(TypedefName) << IsTypeAlias << FirstName; |
272 | 2 | DiagNote(TypedefName) << IsTypeAlias << SecondName; |
273 | 2 | return true; |
274 | 2 | } |
275 | | |
276 | 5 | QualType FirstType = FirstTD->getUnderlyingType(); |
277 | 5 | QualType SecondType = SecondTD->getUnderlyingType(); |
278 | 5 | if (computeODRHash(FirstType) != computeODRHash(SecondType)) { |
279 | 5 | DiagError(TypedefType) << IsTypeAlias << FirstName << FirstType; |
280 | 5 | DiagNote(TypedefType) << IsTypeAlias << SecondName << SecondType; |
281 | 5 | return true; |
282 | 5 | } |
283 | 0 | return false; |
284 | 5 | } |
285 | | |
286 | | bool ODRDiagsEmitter::diagnoseSubMismatchVar(const NamedDecl *FirstRecord, |
287 | | StringRef FirstModule, |
288 | | StringRef SecondModule, |
289 | | const VarDecl *FirstVD, |
290 | 6 | const VarDecl *SecondVD) const { |
291 | 6 | enum ODRVarDifference { |
292 | 6 | VarName, |
293 | 6 | VarType, |
294 | 6 | VarSingleInitializer, |
295 | 6 | VarDifferentInitializer, |
296 | 6 | VarConstexpr, |
297 | 6 | }; |
298 | | |
299 | 6 | auto DiagError = [FirstRecord, FirstVD, FirstModule, |
300 | 6 | this](ODRVarDifference DiffType) { |
301 | 6 | return Diag(FirstVD->getLocation(), diag::err_module_odr_violation_variable) |
302 | 6 | << FirstRecord << FirstModule.empty() << FirstModule |
303 | 6 | << FirstVD->getSourceRange() << DiffType; |
304 | 6 | }; |
305 | 6 | auto DiagNote = [SecondVD, SecondModule, this](ODRVarDifference DiffType) { |
306 | 6 | return Diag(SecondVD->getLocation(), |
307 | 6 | diag::note_module_odr_violation_variable) |
308 | 6 | << SecondModule << SecondVD->getSourceRange() << DiffType; |
309 | 6 | }; |
310 | | |
311 | 6 | DeclarationName FirstName = FirstVD->getDeclName(); |
312 | 6 | DeclarationName SecondName = SecondVD->getDeclName(); |
313 | 6 | if (FirstName != SecondName) { |
314 | 1 | DiagError(VarName) << FirstName; |
315 | 1 | DiagNote(VarName) << SecondName; |
316 | 1 | return true; |
317 | 1 | } |
318 | | |
319 | 5 | QualType FirstType = FirstVD->getType(); |
320 | 5 | QualType SecondType = SecondVD->getType(); |
321 | 5 | if (computeODRHash(FirstType) != computeODRHash(SecondType)) { |
322 | 1 | DiagError(VarType) << FirstName << FirstType; |
323 | 1 | DiagNote(VarType) << SecondName << SecondType; |
324 | 1 | return true; |
325 | 1 | } |
326 | | |
327 | 4 | if (!LangOpts.CPlusPlus) |
328 | 0 | return false; |
329 | | |
330 | 4 | const Expr *FirstInit = FirstVD->getInit(); |
331 | 4 | const Expr *SecondInit = SecondVD->getInit(); |
332 | 4 | if ((FirstInit == nullptr) != (SecondInit == nullptr)) { |
333 | 1 | DiagError(VarSingleInitializer) |
334 | 1 | << FirstName << (FirstInit == nullptr) |
335 | 1 | << (FirstInit ? FirstInit->getSourceRange()0 : SourceRange()); |
336 | 1 | DiagNote(VarSingleInitializer) |
337 | 1 | << SecondName << (SecondInit == nullptr) |
338 | 1 | << (SecondInit ? SecondInit->getSourceRange() : SourceRange()0 ); |
339 | 1 | return true; |
340 | 1 | } |
341 | | |
342 | 3 | if (FirstInit && SecondInit && |
343 | 3 | computeODRHash(FirstInit) != computeODRHash(SecondInit)) { |
344 | 2 | DiagError(VarDifferentInitializer) |
345 | 2 | << FirstName << FirstInit->getSourceRange(); |
346 | 2 | DiagNote(VarDifferentInitializer) |
347 | 2 | << SecondName << SecondInit->getSourceRange(); |
348 | 2 | return true; |
349 | 2 | } |
350 | | |
351 | 1 | const bool FirstIsConstexpr = FirstVD->isConstexpr(); |
352 | 1 | const bool SecondIsConstexpr = SecondVD->isConstexpr(); |
353 | 1 | if (FirstIsConstexpr != SecondIsConstexpr) { |
354 | 1 | DiagError(VarConstexpr) << FirstName << FirstIsConstexpr; |
355 | 1 | DiagNote(VarConstexpr) << SecondName << SecondIsConstexpr; |
356 | 1 | return true; |
357 | 1 | } |
358 | 0 | return false; |
359 | 1 | } |
360 | | |
361 | | bool ODRDiagsEmitter::diagnoseSubMismatchProtocols( |
362 | | const ObjCProtocolList &FirstProtocols, |
363 | | const ObjCContainerDecl *FirstContainer, StringRef FirstModule, |
364 | | const ObjCProtocolList &SecondProtocols, |
365 | 97 | const ObjCContainerDecl *SecondContainer, StringRef SecondModule) const { |
366 | | // Keep in sync with err_module_odr_violation_referenced_protocols. |
367 | 97 | enum ODRReferencedProtocolDifference { |
368 | 97 | NumProtocols, |
369 | 97 | ProtocolType, |
370 | 97 | }; |
371 | 97 | auto DiagRefProtocolError = [FirstContainer, FirstModule, |
372 | 97 | this](SourceLocation Loc, SourceRange Range, |
373 | 97 | ODRReferencedProtocolDifference DiffType) { |
374 | 16 | return Diag(Loc, diag::err_module_odr_violation_referenced_protocols) |
375 | 16 | << FirstContainer << FirstModule.empty() << FirstModule << Range |
376 | 16 | << DiffType; |
377 | 16 | }; |
378 | 97 | auto DiagRefProtocolNote = [SecondModule, |
379 | 97 | this](SourceLocation Loc, SourceRange Range, |
380 | 97 | ODRReferencedProtocolDifference DiffType) { |
381 | 16 | return Diag(Loc, diag::note_module_odr_violation_referenced_protocols) |
382 | 16 | << SecondModule.empty() << SecondModule << Range << DiffType; |
383 | 16 | }; |
384 | 97 | auto GetProtoListSourceRange = [](const ObjCProtocolList &PL) { |
385 | 16 | if (PL.empty()) |
386 | 8 | return SourceRange(); |
387 | 8 | return SourceRange(*PL.loc_begin(), *std::prev(PL.loc_end())); |
388 | 16 | }; |
389 | | |
390 | 97 | if (FirstProtocols.size() != SecondProtocols.size()) { |
391 | 8 | DiagRefProtocolError(FirstContainer->getLocation(), |
392 | 8 | GetProtoListSourceRange(FirstProtocols), NumProtocols) |
393 | 8 | << FirstProtocols.size(); |
394 | 8 | DiagRefProtocolNote(SecondContainer->getLocation(), |
395 | 8 | GetProtoListSourceRange(SecondProtocols), NumProtocols) |
396 | 8 | << SecondProtocols.size(); |
397 | 8 | return true; |
398 | 8 | } |
399 | | |
400 | 89 | for (unsigned I = 0, E = FirstProtocols.size(); I != E; ++I0 ) { |
401 | 8 | const ObjCProtocolDecl *FirstProtocol = FirstProtocols[I]; |
402 | 8 | const ObjCProtocolDecl *SecondProtocol = SecondProtocols[I]; |
403 | 8 | DeclarationName FirstProtocolName = FirstProtocol->getDeclName(); |
404 | 8 | DeclarationName SecondProtocolName = SecondProtocol->getDeclName(); |
405 | 8 | if (FirstProtocolName != SecondProtocolName) { |
406 | 8 | SourceLocation FirstLoc = *(FirstProtocols.loc_begin() + I); |
407 | 8 | SourceLocation SecondLoc = *(SecondProtocols.loc_begin() + I); |
408 | 8 | SourceRange EmptyRange; |
409 | 8 | DiagRefProtocolError(FirstLoc, EmptyRange, ProtocolType) |
410 | 8 | << (I + 1) << FirstProtocolName; |
411 | 8 | DiagRefProtocolNote(SecondLoc, EmptyRange, ProtocolType) |
412 | 8 | << (I + 1) << SecondProtocolName; |
413 | 8 | return true; |
414 | 8 | } |
415 | 8 | } |
416 | | |
417 | 81 | return false; |
418 | 89 | } |
419 | | |
420 | | bool ODRDiagsEmitter::diagnoseSubMismatchObjCMethod( |
421 | | const NamedDecl *FirstObjCContainer, StringRef FirstModule, |
422 | | StringRef SecondModule, const ObjCMethodDecl *FirstMethod, |
423 | 30 | const ObjCMethodDecl *SecondMethod) const { |
424 | 30 | enum ODRMethodDifference { |
425 | 30 | ReturnType, |
426 | 30 | InstanceOrClass, |
427 | 30 | ControlLevel, // optional/required |
428 | 30 | DesignatedInitializer, |
429 | 30 | Directness, |
430 | 30 | Name, |
431 | 30 | }; |
432 | | |
433 | 30 | auto DiagError = [FirstObjCContainer, FirstModule, FirstMethod, |
434 | 30 | this](ODRMethodDifference DiffType) { |
435 | 18 | return Diag(FirstMethod->getLocation(), |
436 | 18 | diag::err_module_odr_violation_objc_method) |
437 | 18 | << FirstObjCContainer << FirstModule.empty() << FirstModule |
438 | 18 | << FirstMethod->getSourceRange() << DiffType; |
439 | 18 | }; |
440 | 30 | auto DiagNote = [SecondModule, SecondMethod, |
441 | 30 | this](ODRMethodDifference DiffType) { |
442 | 18 | return Diag(SecondMethod->getLocation(), |
443 | 18 | diag::note_module_odr_violation_objc_method) |
444 | 18 | << SecondModule.empty() << SecondModule |
445 | 18 | << SecondMethod->getSourceRange() << DiffType; |
446 | 18 | }; |
447 | | |
448 | 30 | if (computeODRHash(FirstMethod->getReturnType()) != |
449 | 30 | computeODRHash(SecondMethod->getReturnType())) { |
450 | 4 | DiagError(ReturnType) << FirstMethod << FirstMethod->getReturnType(); |
451 | 4 | DiagNote(ReturnType) << SecondMethod << SecondMethod->getReturnType(); |
452 | 4 | return true; |
453 | 4 | } |
454 | | |
455 | 26 | if (FirstMethod->isInstanceMethod() != SecondMethod->isInstanceMethod()) { |
456 | 4 | DiagError(InstanceOrClass) |
457 | 4 | << FirstMethod << FirstMethod->isInstanceMethod(); |
458 | 4 | DiagNote(InstanceOrClass) |
459 | 4 | << SecondMethod << SecondMethod->isInstanceMethod(); |
460 | 4 | return true; |
461 | 4 | } |
462 | 22 | if (FirstMethod->getImplementationControl() != |
463 | 22 | SecondMethod->getImplementationControl()) { |
464 | 2 | DiagError(ControlLevel) << FirstMethod->getImplementationControl(); |
465 | 2 | DiagNote(ControlLevel) << SecondMethod->getImplementationControl(); |
466 | 2 | return true; |
467 | 2 | } |
468 | 20 | if (FirstMethod->isThisDeclarationADesignatedInitializer() != |
469 | 20 | SecondMethod->isThisDeclarationADesignatedInitializer()) { |
470 | 0 | DiagError(DesignatedInitializer) |
471 | 0 | << FirstMethod |
472 | 0 | << FirstMethod->isThisDeclarationADesignatedInitializer(); |
473 | 0 | DiagNote(DesignatedInitializer) |
474 | 0 | << SecondMethod |
475 | 0 | << SecondMethod->isThisDeclarationADesignatedInitializer(); |
476 | 0 | return true; |
477 | 0 | } |
478 | 20 | if (FirstMethod->isDirectMethod() != SecondMethod->isDirectMethod()) { |
479 | 0 | DiagError(Directness) << FirstMethod << FirstMethod->isDirectMethod(); |
480 | 0 | DiagNote(Directness) << SecondMethod << SecondMethod->isDirectMethod(); |
481 | 0 | return true; |
482 | 0 | } |
483 | 20 | if (diagnoseSubMismatchMethodParameters(Diags, FirstObjCContainer, |
484 | 20 | FirstModule, SecondModule, |
485 | 20 | FirstMethod, SecondMethod)) |
486 | 12 | return true; |
487 | | |
488 | | // Check method name *after* looking at the parameters otherwise we get a |
489 | | // less ideal diagnostics: a ObjCMethodName mismatch given that selectors |
490 | | // for different parameters are likely to be different. |
491 | 8 | DeclarationName FirstName = FirstMethod->getDeclName(); |
492 | 8 | DeclarationName SecondName = SecondMethod->getDeclName(); |
493 | 8 | if (FirstName != SecondName) { |
494 | 8 | DiagError(Name) << FirstName; |
495 | 8 | DiagNote(Name) << SecondName; |
496 | 8 | return true; |
497 | 8 | } |
498 | | |
499 | 0 | return false; |
500 | 8 | } |
501 | | |
502 | | bool ODRDiagsEmitter::diagnoseSubMismatchObjCProperty( |
503 | | const NamedDecl *FirstObjCContainer, StringRef FirstModule, |
504 | | StringRef SecondModule, const ObjCPropertyDecl *FirstProp, |
505 | 24 | const ObjCPropertyDecl *SecondProp) const { |
506 | 24 | enum ODRPropertyDifference { |
507 | 24 | Name, |
508 | 24 | Type, |
509 | 24 | ControlLevel, // optional/required |
510 | 24 | Attribute, |
511 | 24 | }; |
512 | | |
513 | 24 | auto DiagError = [FirstObjCContainer, FirstModule, FirstProp, |
514 | 24 | this](SourceLocation Loc, ODRPropertyDifference DiffType) { |
515 | 24 | return Diag(Loc, diag::err_module_odr_violation_objc_property) |
516 | 24 | << FirstObjCContainer << FirstModule.empty() << FirstModule |
517 | 24 | << FirstProp->getSourceRange() << DiffType; |
518 | 24 | }; |
519 | 24 | auto DiagNote = [SecondModule, SecondProp, |
520 | 24 | this](SourceLocation Loc, ODRPropertyDifference DiffType) { |
521 | 24 | return Diag(Loc, diag::note_module_odr_violation_objc_property) |
522 | 24 | << SecondModule.empty() << SecondModule |
523 | 24 | << SecondProp->getSourceRange() << DiffType; |
524 | 24 | }; |
525 | | |
526 | 24 | IdentifierInfo *FirstII = FirstProp->getIdentifier(); |
527 | 24 | IdentifierInfo *SecondII = SecondProp->getIdentifier(); |
528 | 24 | if (FirstII->getName() != SecondII->getName()) { |
529 | 8 | DiagError(FirstProp->getLocation(), Name) << FirstII; |
530 | 8 | DiagNote(SecondProp->getLocation(), Name) << SecondII; |
531 | 8 | return true; |
532 | 8 | } |
533 | 16 | if (computeODRHash(FirstProp->getType()) != |
534 | 16 | computeODRHash(SecondProp->getType())) { |
535 | 4 | DiagError(FirstProp->getLocation(), Type) |
536 | 4 | << FirstII << FirstProp->getType(); |
537 | 4 | DiagNote(SecondProp->getLocation(), Type) |
538 | 4 | << SecondII << SecondProp->getType(); |
539 | 4 | return true; |
540 | 4 | } |
541 | 12 | if (FirstProp->getPropertyImplementation() != |
542 | 12 | SecondProp->getPropertyImplementation()) { |
543 | 0 | DiagError(FirstProp->getLocation(), ControlLevel) |
544 | 0 | << FirstProp->getPropertyImplementation(); |
545 | 0 | DiagNote(SecondProp->getLocation(), ControlLevel) |
546 | 0 | << SecondProp->getPropertyImplementation(); |
547 | 0 | return true; |
548 | 0 | } |
549 | | |
550 | | // Go over the property attributes and stop at the first mismatch. |
551 | 12 | unsigned FirstAttrs = (unsigned)FirstProp->getPropertyAttributes(); |
552 | 12 | unsigned SecondAttrs = (unsigned)SecondProp->getPropertyAttributes(); |
553 | 12 | if (FirstAttrs != SecondAttrs) { |
554 | 82 | for (unsigned I = 0; I < NumObjCPropertyAttrsBits; ++I70 ) { |
555 | 82 | unsigned CheckedAttr = (1 << I); |
556 | 82 | if ((FirstAttrs & CheckedAttr) == (SecondAttrs & CheckedAttr)) |
557 | 70 | continue; |
558 | | |
559 | 12 | bool IsFirstWritten = |
560 | 12 | (unsigned)FirstProp->getPropertyAttributesAsWritten() & CheckedAttr; |
561 | 12 | bool IsSecondWritten = |
562 | 12 | (unsigned)SecondProp->getPropertyAttributesAsWritten() & CheckedAttr; |
563 | 12 | DiagError(IsFirstWritten ? FirstProp->getLParenLoc()8 |
564 | 12 | : FirstProp->getLocation()4 , |
565 | 12 | Attribute) |
566 | 12 | << FirstII << (I + 1) << IsFirstWritten; |
567 | 12 | DiagNote(IsSecondWritten ? SecondProp->getLParenLoc()4 |
568 | 12 | : SecondProp->getLocation()8 , |
569 | 12 | Attribute) |
570 | 12 | << SecondII << (I + 1); |
571 | 12 | return true; |
572 | 82 | } |
573 | 12 | } |
574 | | |
575 | 0 | return false; |
576 | 12 | } |
577 | | |
578 | | ODRDiagsEmitter::DiffResult |
579 | | ODRDiagsEmitter::FindTypeDiffs(DeclHashes &FirstHashes, |
580 | 236 | DeclHashes &SecondHashes) { |
581 | 451 | auto DifferenceSelector = [](const Decl *D) { |
582 | 451 | assert(D && "valid Decl required"); |
583 | 451 | switch (D->getKind()) { |
584 | 0 | default: |
585 | 0 | return Other; |
586 | 77 | case Decl::AccessSpec: |
587 | 77 | switch (D->getAccess()) { |
588 | 39 | case AS_public: |
589 | 39 | return PublicSpecifer; |
590 | 37 | case AS_private: |
591 | 37 | return PrivateSpecifer; |
592 | 1 | case AS_protected: |
593 | 1 | return ProtectedSpecifer; |
594 | 0 | case AS_none: |
595 | 0 | break; |
596 | 77 | } |
597 | 0 | llvm_unreachable("Invalid access specifier"); |
598 | 7 | case Decl::StaticAssert: |
599 | 7 | return StaticAssert; |
600 | 68 | case Decl::Field: |
601 | 68 | return Field; |
602 | 66 | case Decl::CXXMethod: |
603 | 74 | case Decl::CXXConstructor: |
604 | 77 | case Decl::CXXDestructor: |
605 | 77 | return CXXMethod; |
606 | 11 | case Decl::TypeAlias: |
607 | 11 | return TypeAlias; |
608 | 5 | case Decl::Typedef: |
609 | 5 | return TypeDef; |
610 | 13 | case Decl::Var: |
611 | 13 | return Var; |
612 | 8 | case Decl::Friend: |
613 | 8 | return Friend; |
614 | 42 | case Decl::FunctionTemplate: |
615 | 42 | return FunctionTemplate; |
616 | 68 | case Decl::ObjCMethod: |
617 | 68 | return ObjCMethod; |
618 | 19 | case Decl::ObjCIvar: |
619 | 19 | return ObjCIvar; |
620 | 56 | case Decl::ObjCProperty: |
621 | 56 | return ObjCProperty; |
622 | 451 | } |
623 | 451 | }; |
624 | | |
625 | 236 | DiffResult DR; |
626 | 236 | auto FirstIt = FirstHashes.begin(); |
627 | 236 | auto SecondIt = SecondHashes.begin(); |
628 | 382 | while (FirstIt != FirstHashes.end() || SecondIt != SecondHashes.end()9 ) { |
629 | 382 | if (FirstIt != FirstHashes.end() && SecondIt != SecondHashes.end()373 && |
630 | 382 | FirstIt->second == SecondIt->second361 ) { |
631 | 146 | ++FirstIt; |
632 | 146 | ++SecondIt; |
633 | 146 | continue; |
634 | 146 | } |
635 | | |
636 | 236 | DR.FirstDecl = FirstIt == FirstHashes.end() ? nullptr9 : FirstIt->first227 ; |
637 | 236 | DR.SecondDecl = SecondIt == SecondHashes.end() ? nullptr12 : SecondIt->first224 ; |
638 | | |
639 | 236 | DR.FirstDiffType = |
640 | 236 | DR.FirstDecl ? DifferenceSelector(DR.FirstDecl)227 : EndOfClass9 ; |
641 | 236 | DR.SecondDiffType = |
642 | 236 | DR.SecondDecl ? DifferenceSelector(DR.SecondDecl)224 : EndOfClass12 ; |
643 | 236 | return DR; |
644 | 382 | } |
645 | 0 | return DR; |
646 | 236 | } |
647 | | |
648 | | void ODRDiagsEmitter::diagnoseSubMismatchUnexpected( |
649 | | DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule, |
650 | 0 | const NamedDecl *SecondRecord, StringRef SecondModule) const { |
651 | 0 | Diag(FirstRecord->getLocation(), |
652 | 0 | diag::err_module_odr_violation_different_definitions) |
653 | 0 | << FirstRecord << FirstModule.empty() << FirstModule; |
654 | |
|
655 | 0 | if (DR.FirstDecl) { |
656 | 0 | Diag(DR.FirstDecl->getLocation(), diag::note_first_module_difference) |
657 | 0 | << FirstRecord << DR.FirstDecl->getSourceRange(); |
658 | 0 | } |
659 | |
|
660 | 0 | Diag(SecondRecord->getLocation(), |
661 | 0 | diag::note_module_odr_violation_different_definitions) |
662 | 0 | << SecondModule; |
663 | |
|
664 | 0 | if (DR.SecondDecl) { |
665 | 0 | Diag(DR.SecondDecl->getLocation(), diag::note_second_module_difference) |
666 | 0 | << DR.SecondDecl->getSourceRange(); |
667 | 0 | } |
668 | 0 | } |
669 | | |
670 | | void ODRDiagsEmitter::diagnoseSubMismatchDifferentDeclKinds( |
671 | | DiffResult &DR, const NamedDecl *FirstRecord, StringRef FirstModule, |
672 | 64 | const NamedDecl *SecondRecord, StringRef SecondModule) const { |
673 | 64 | auto GetMismatchedDeclLoc = [](const NamedDecl *Container, |
674 | 128 | ODRMismatchDecl DiffType, const Decl *D) { |
675 | 128 | SourceLocation Loc; |
676 | 128 | SourceRange Range; |
677 | 128 | if (DiffType == EndOfClass) { |
678 | 21 | if (auto *Tag = dyn_cast<TagDecl>(Container)) |
679 | 2 | Loc = Tag->getBraceRange().getEnd(); |
680 | 19 | else if (auto *IF = dyn_cast<ObjCInterfaceDecl>(Container)) |
681 | 11 | Loc = IF->getAtEndRange().getBegin(); |
682 | 8 | else |
683 | 8 | Loc = Container->getEndLoc(); |
684 | 107 | } else { |
685 | 107 | Loc = D->getLocation(); |
686 | 107 | Range = D->getSourceRange(); |
687 | 107 | } |
688 | 128 | return std::make_pair(Loc, Range); |
689 | 128 | }; |
690 | | |
691 | 64 | auto FirstDiagInfo = |
692 | 64 | GetMismatchedDeclLoc(FirstRecord, DR.FirstDiffType, DR.FirstDecl); |
693 | 64 | Diag(FirstDiagInfo.first, diag::err_module_odr_violation_mismatch_decl) |
694 | 64 | << FirstRecord << FirstModule.empty() << FirstModule |
695 | 64 | << FirstDiagInfo.second << DR.FirstDiffType; |
696 | | |
697 | 64 | auto SecondDiagInfo = |
698 | 64 | GetMismatchedDeclLoc(SecondRecord, DR.SecondDiffType, DR.SecondDecl); |
699 | 64 | Diag(SecondDiagInfo.first, diag::note_module_odr_violation_mismatch_decl) |
700 | 64 | << SecondModule.empty() << SecondModule << SecondDiagInfo.second |
701 | 64 | << DR.SecondDiffType; |
702 | 64 | } |
703 | | |
704 | | bool ODRDiagsEmitter::diagnoseMismatch( |
705 | | const CXXRecordDecl *FirstRecord, const CXXRecordDecl *SecondRecord, |
706 | 164 | const struct CXXRecordDecl::DefinitionData *SecondDD) const { |
707 | | // Multiple different declarations got merged together; tell the user |
708 | | // where they came from. |
709 | 164 | if (FirstRecord == SecondRecord) |
710 | 0 | return false; |
711 | | |
712 | 164 | std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord); |
713 | 164 | std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord); |
714 | | |
715 | 164 | const struct CXXRecordDecl::DefinitionData *FirstDD = |
716 | 164 | FirstRecord->DefinitionData; |
717 | 164 | assert(FirstDD && SecondDD && "Definitions without DefinitionData"); |
718 | | |
719 | | // Diagnostics from DefinitionData are emitted here. |
720 | 164 | if (FirstDD != SecondDD) { |
721 | | // Keep in sync with err_module_odr_violation_definition_data. |
722 | 164 | enum ODRDefinitionDataDifference { |
723 | 164 | NumBases, |
724 | 164 | NumVBases, |
725 | 164 | BaseType, |
726 | 164 | BaseVirtual, |
727 | 164 | BaseAccess, |
728 | 164 | }; |
729 | 164 | auto DiagBaseError = [FirstRecord, &FirstModule, |
730 | 164 | this](SourceLocation Loc, SourceRange Range, |
731 | 164 | ODRDefinitionDataDifference DiffType) { |
732 | 10 | return Diag(Loc, diag::err_module_odr_violation_definition_data) |
733 | 10 | << FirstRecord << FirstModule.empty() << FirstModule << Range |
734 | 10 | << DiffType; |
735 | 10 | }; |
736 | 164 | auto DiagBaseNote = [&SecondModule, |
737 | 164 | this](SourceLocation Loc, SourceRange Range, |
738 | 164 | ODRDefinitionDataDifference DiffType) { |
739 | 10 | return Diag(Loc, diag::note_module_odr_violation_definition_data) |
740 | 10 | << SecondModule << Range << DiffType; |
741 | 10 | }; |
742 | 164 | auto GetSourceRange = [](const struct CXXRecordDecl::DefinitionData *DD) { |
743 | 10 | unsigned NumBases = DD->NumBases; |
744 | 10 | if (NumBases == 0) |
745 | 2 | return SourceRange(); |
746 | 8 | ArrayRef<CXXBaseSpecifier> bases = DD->bases(); |
747 | 8 | return SourceRange(bases[0].getBeginLoc(), |
748 | 8 | bases[NumBases - 1].getEndLoc()); |
749 | 10 | }; |
750 | | |
751 | 164 | unsigned FirstNumBases = FirstDD->NumBases; |
752 | 164 | unsigned FirstNumVBases = FirstDD->NumVBases; |
753 | 164 | unsigned SecondNumBases = SecondDD->NumBases; |
754 | 164 | unsigned SecondNumVBases = SecondDD->NumVBases; |
755 | 164 | if (FirstNumBases != SecondNumBases) { |
756 | 2 | DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD), |
757 | 2 | NumBases) |
758 | 2 | << FirstNumBases; |
759 | 2 | DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), |
760 | 2 | NumBases) |
761 | 2 | << SecondNumBases; |
762 | 2 | return true; |
763 | 2 | } |
764 | | |
765 | 162 | if (FirstNumVBases != SecondNumVBases) { |
766 | 3 | DiagBaseError(FirstRecord->getLocation(), GetSourceRange(FirstDD), |
767 | 3 | NumVBases) |
768 | 3 | << FirstNumVBases; |
769 | 3 | DiagBaseNote(SecondRecord->getLocation(), GetSourceRange(SecondDD), |
770 | 3 | NumVBases) |
771 | 3 | << SecondNumVBases; |
772 | 3 | return true; |
773 | 3 | } |
774 | | |
775 | 159 | ArrayRef<CXXBaseSpecifier> FirstBases = FirstDD->bases(); |
776 | 159 | ArrayRef<CXXBaseSpecifier> SecondBases = SecondDD->bases(); |
777 | 164 | for (unsigned I = 0; I < FirstNumBases; ++I5 ) { |
778 | 10 | const CXXBaseSpecifier FirstBase = FirstBases[I]; |
779 | 10 | const CXXBaseSpecifier SecondBase = SecondBases[I]; |
780 | 10 | if (computeODRHash(FirstBase.getType()) != |
781 | 10 | computeODRHash(SecondBase.getType())) { |
782 | 1 | DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(), |
783 | 1 | BaseType) |
784 | 1 | << (I + 1) << FirstBase.getType(); |
785 | 1 | DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(), |
786 | 1 | BaseType) |
787 | 1 | << (I + 1) << SecondBase.getType(); |
788 | 1 | return true; |
789 | 1 | } |
790 | | |
791 | 9 | if (FirstBase.isVirtual() != SecondBase.isVirtual()) { |
792 | 0 | DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(), |
793 | 0 | BaseVirtual) |
794 | 0 | << (I + 1) << FirstBase.isVirtual() << FirstBase.getType(); |
795 | 0 | DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(), |
796 | 0 | BaseVirtual) |
797 | 0 | << (I + 1) << SecondBase.isVirtual() << SecondBase.getType(); |
798 | 0 | return true; |
799 | 0 | } |
800 | | |
801 | 9 | if (FirstBase.getAccessSpecifierAsWritten() != |
802 | 9 | SecondBase.getAccessSpecifierAsWritten()) { |
803 | 4 | DiagBaseError(FirstRecord->getLocation(), FirstBase.getSourceRange(), |
804 | 4 | BaseAccess) |
805 | 4 | << (I + 1) << FirstBase.getType() |
806 | 4 | << (int)FirstBase.getAccessSpecifierAsWritten(); |
807 | 4 | DiagBaseNote(SecondRecord->getLocation(), SecondBase.getSourceRange(), |
808 | 4 | BaseAccess) |
809 | 4 | << (I + 1) << SecondBase.getType() |
810 | 4 | << (int)SecondBase.getAccessSpecifierAsWritten(); |
811 | 4 | return true; |
812 | 4 | } |
813 | 9 | } |
814 | 159 | } |
815 | | |
816 | 154 | const ClassTemplateDecl *FirstTemplate = |
817 | 154 | FirstRecord->getDescribedClassTemplate(); |
818 | 154 | const ClassTemplateDecl *SecondTemplate = |
819 | 154 | SecondRecord->getDescribedClassTemplate(); |
820 | | |
821 | 154 | assert(!FirstTemplate == !SecondTemplate && |
822 | 154 | "Both pointers should be null or non-null"); |
823 | | |
824 | 154 | if (FirstTemplate && SecondTemplate20 ) { |
825 | 20 | ArrayRef<const NamedDecl *> FirstTemplateParams = |
826 | 20 | FirstTemplate->getTemplateParameters()->asArray(); |
827 | 20 | ArrayRef<const NamedDecl *> SecondTemplateParams = |
828 | 20 | SecondTemplate->getTemplateParameters()->asArray(); |
829 | 20 | assert(FirstTemplateParams.size() == SecondTemplateParams.size() && |
830 | 20 | "Number of template parameters should be equal."); |
831 | 31 | for (auto Pair : llvm::zip(FirstTemplateParams, SecondTemplateParams))20 { |
832 | 31 | const NamedDecl *FirstDecl = std::get<0>(Pair); |
833 | 31 | const NamedDecl *SecondDecl = std::get<1>(Pair); |
834 | 31 | if (computeODRHash(FirstDecl) == computeODRHash(SecondDecl)) |
835 | 23 | continue; |
836 | | |
837 | 8 | assert(FirstDecl->getKind() == SecondDecl->getKind() && |
838 | 8 | "Parameter Decl's should be the same kind."); |
839 | | |
840 | 8 | enum ODRTemplateDifference { |
841 | 8 | ParamEmptyName, |
842 | 8 | ParamName, |
843 | 8 | ParamSingleDefaultArgument, |
844 | 8 | ParamDifferentDefaultArgument, |
845 | 8 | }; |
846 | | |
847 | 16 | auto hasDefaultArg = [](const NamedDecl *D) { |
848 | 16 | if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) |
849 | 8 | return TTP->hasDefaultArgument() && |
850 | 8 | !TTP->defaultArgumentWasInherited()3 ; |
851 | 8 | if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) |
852 | 6 | return NTTP->hasDefaultArgument() && |
853 | 6 | !NTTP->defaultArgumentWasInherited(); |
854 | 2 | auto *TTP = cast<TemplateTemplateParmDecl>(D); |
855 | 2 | return TTP->hasDefaultArgument() && !TTP->defaultArgumentWasInherited(); |
856 | 8 | }; |
857 | 8 | bool hasFirstArg = hasDefaultArg(FirstDecl); |
858 | 8 | bool hasSecondArg = hasDefaultArg(SecondDecl); |
859 | | |
860 | 8 | ODRTemplateDifference ErrDiffType; |
861 | 8 | ODRTemplateDifference NoteDiffType; |
862 | | |
863 | 8 | DeclarationName FirstName = FirstDecl->getDeclName(); |
864 | 8 | DeclarationName SecondName = SecondDecl->getDeclName(); |
865 | | |
866 | 8 | if (FirstName != SecondName) { |
867 | 2 | bool FirstNameEmpty = |
868 | 2 | FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo(); |
869 | 2 | bool SecondNameEmpty = |
870 | 2 | SecondName.isIdentifier() && !SecondName.getAsIdentifierInfo(); |
871 | 2 | ErrDiffType = FirstNameEmpty ? ParamEmptyName1 : ParamName1 ; |
872 | 2 | NoteDiffType = SecondNameEmpty ? ParamEmptyName0 : ParamName; |
873 | 6 | } else if (hasFirstArg == hasSecondArg) |
874 | 4 | ErrDiffType = NoteDiffType = ParamDifferentDefaultArgument; |
875 | 2 | else |
876 | 2 | ErrDiffType = NoteDiffType = ParamSingleDefaultArgument; |
877 | | |
878 | 8 | Diag(FirstDecl->getLocation(), |
879 | 8 | diag::err_module_odr_violation_template_parameter) |
880 | 8 | << FirstRecord << FirstModule.empty() << FirstModule |
881 | 8 | << FirstDecl->getSourceRange() << ErrDiffType << hasFirstArg |
882 | 8 | << FirstName; |
883 | 8 | Diag(SecondDecl->getLocation(), |
884 | 8 | diag::note_module_odr_violation_template_parameter) |
885 | 8 | << SecondModule << SecondDecl->getSourceRange() << NoteDiffType |
886 | 8 | << hasSecondArg << SecondName; |
887 | 8 | return true; |
888 | 8 | } |
889 | 20 | } |
890 | | |
891 | 146 | auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record, |
892 | 292 | const DeclContext *DC) { |
893 | 984 | for (const Decl *D : Record->decls()) { |
894 | 984 | if (!ODRHash::isSubDeclToBeProcessed(D, DC)) |
895 | 327 | continue; |
896 | 657 | Hashes.emplace_back(D, computeODRHash(D)); |
897 | 657 | } |
898 | 292 | }; |
899 | | |
900 | 146 | DeclHashes FirstHashes; |
901 | 146 | DeclHashes SecondHashes; |
902 | 146 | const DeclContext *DC = FirstRecord; |
903 | 146 | PopulateHashes(FirstHashes, FirstRecord, DC); |
904 | 146 | PopulateHashes(SecondHashes, SecondRecord, DC); |
905 | | |
906 | 146 | DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes); |
907 | 146 | ODRMismatchDecl FirstDiffType = DR.FirstDiffType; |
908 | 146 | ODRMismatchDecl SecondDiffType = DR.SecondDiffType; |
909 | 146 | const Decl *FirstDecl = DR.FirstDecl; |
910 | 146 | const Decl *SecondDecl = DR.SecondDecl; |
911 | | |
912 | 146 | if (FirstDiffType == Other || SecondDiffType == Other) { |
913 | 0 | diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord, |
914 | 0 | SecondModule); |
915 | 0 | return true; |
916 | 0 | } |
917 | | |
918 | 146 | if (FirstDiffType != SecondDiffType) { |
919 | 44 | diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule, |
920 | 44 | SecondRecord, SecondModule); |
921 | 44 | return true; |
922 | 44 | } |
923 | | |
924 | | // Used with err_module_odr_violation_record and |
925 | | // note_module_odr_violation_record |
926 | 102 | enum ODRCXXRecordDifference { |
927 | 102 | StaticAssertCondition, |
928 | 102 | StaticAssertMessage, |
929 | 102 | StaticAssertOnlyMessage, |
930 | 102 | MethodName, |
931 | 102 | MethodDeleted, |
932 | 102 | MethodDefaulted, |
933 | 102 | MethodVirtual, |
934 | 102 | MethodStatic, |
935 | 102 | MethodVolatile, |
936 | 102 | MethodConst, |
937 | 102 | MethodInline, |
938 | 102 | MethodParameterSingleDefaultArgument, |
939 | 102 | MethodParameterDifferentDefaultArgument, |
940 | 102 | MethodNoTemplateArguments, |
941 | 102 | MethodDifferentNumberTemplateArguments, |
942 | 102 | MethodDifferentTemplateArgument, |
943 | 102 | MethodSingleBody, |
944 | 102 | MethodDifferentBody, |
945 | 102 | FriendTypeFunction, |
946 | 102 | FriendType, |
947 | 102 | FriendFunction, |
948 | 102 | FunctionTemplateDifferentNumberParameters, |
949 | 102 | FunctionTemplateParameterDifferentKind, |
950 | 102 | FunctionTemplateParameterName, |
951 | 102 | FunctionTemplateParameterSingleDefaultArgument, |
952 | 102 | FunctionTemplateParameterDifferentDefaultArgument, |
953 | 102 | FunctionTemplateParameterDifferentType, |
954 | 102 | FunctionTemplatePackParameter, |
955 | 102 | }; |
956 | 102 | auto DiagError = [FirstRecord, &FirstModule, |
957 | 102 | this](SourceLocation Loc, SourceRange Range, |
958 | 102 | ODRCXXRecordDifference DiffType) { |
959 | 59 | return Diag(Loc, diag::err_module_odr_violation_record) |
960 | 59 | << FirstRecord << FirstModule.empty() << FirstModule << Range |
961 | 59 | << DiffType; |
962 | 59 | }; |
963 | 102 | auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range, |
964 | 102 | ODRCXXRecordDifference DiffType) { |
965 | 59 | return Diag(Loc, diag::note_module_odr_violation_record) |
966 | 59 | << SecondModule << Range << DiffType; |
967 | 59 | }; |
968 | | |
969 | 102 | assert(FirstDiffType == SecondDiffType); |
970 | 102 | switch (FirstDiffType) { |
971 | 0 | case Other: |
972 | 0 | case EndOfClass: |
973 | 0 | case PublicSpecifer: |
974 | 0 | case PrivateSpecifer: |
975 | 0 | case ProtectedSpecifer: |
976 | 0 | case ObjCMethod: |
977 | 0 | case ObjCIvar: |
978 | 0 | case ObjCProperty: |
979 | 0 | llvm_unreachable("Invalid diff type"); |
980 | |
|
981 | 3 | case StaticAssert: { |
982 | 3 | const StaticAssertDecl *FirstSA = cast<StaticAssertDecl>(FirstDecl); |
983 | 3 | const StaticAssertDecl *SecondSA = cast<StaticAssertDecl>(SecondDecl); |
984 | | |
985 | 3 | const Expr *FirstExpr = FirstSA->getAssertExpr(); |
986 | 3 | const Expr *SecondExpr = SecondSA->getAssertExpr(); |
987 | 3 | unsigned FirstODRHash = computeODRHash(FirstExpr); |
988 | 3 | unsigned SecondODRHash = computeODRHash(SecondExpr); |
989 | 3 | if (FirstODRHash != SecondODRHash) { |
990 | 1 | DiagError(FirstExpr->getBeginLoc(), FirstExpr->getSourceRange(), |
991 | 1 | StaticAssertCondition); |
992 | 1 | DiagNote(SecondExpr->getBeginLoc(), SecondExpr->getSourceRange(), |
993 | 1 | StaticAssertCondition); |
994 | 1 | return true; |
995 | 1 | } |
996 | | |
997 | 2 | const StringLiteral *FirstStr = FirstSA->getMessage(); |
998 | 2 | const StringLiteral *SecondStr = SecondSA->getMessage(); |
999 | 2 | assert((FirstStr || SecondStr) && "Both messages cannot be empty"); |
1000 | 2 | if ((FirstStr && !SecondStr1 ) || (!FirstStr && SecondStr1 )) { |
1001 | 1 | SourceLocation FirstLoc, SecondLoc; |
1002 | 1 | SourceRange FirstRange, SecondRange; |
1003 | 1 | if (FirstStr) { |
1004 | 0 | FirstLoc = FirstStr->getBeginLoc(); |
1005 | 0 | FirstRange = FirstStr->getSourceRange(); |
1006 | 1 | } else { |
1007 | 1 | FirstLoc = FirstSA->getBeginLoc(); |
1008 | 1 | FirstRange = FirstSA->getSourceRange(); |
1009 | 1 | } |
1010 | 1 | if (SecondStr) { |
1011 | 1 | SecondLoc = SecondStr->getBeginLoc(); |
1012 | 1 | SecondRange = SecondStr->getSourceRange(); |
1013 | 1 | } else { |
1014 | 0 | SecondLoc = SecondSA->getBeginLoc(); |
1015 | 0 | SecondRange = SecondSA->getSourceRange(); |
1016 | 0 | } |
1017 | 1 | DiagError(FirstLoc, FirstRange, StaticAssertOnlyMessage) |
1018 | 1 | << (FirstStr == nullptr); |
1019 | 1 | DiagNote(SecondLoc, SecondRange, StaticAssertOnlyMessage) |
1020 | 1 | << (SecondStr == nullptr); |
1021 | 1 | return true; |
1022 | 1 | } |
1023 | | |
1024 | 1 | if (FirstStr && SecondStr && |
1025 | 1 | FirstStr->getString() != SecondStr->getString()) { |
1026 | 1 | DiagError(FirstStr->getBeginLoc(), FirstStr->getSourceRange(), |
1027 | 1 | StaticAssertMessage); |
1028 | 1 | DiagNote(SecondStr->getBeginLoc(), SecondStr->getSourceRange(), |
1029 | 1 | StaticAssertMessage); |
1030 | 1 | return true; |
1031 | 1 | } |
1032 | 0 | break; |
1033 | 1 | } |
1034 | | |
1035 | 24 | case Field: { |
1036 | 24 | if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule, |
1037 | 24 | cast<FieldDecl>(FirstDecl), |
1038 | 24 | cast<FieldDecl>(SecondDecl))) |
1039 | 24 | return true; |
1040 | 0 | break; |
1041 | 24 | } |
1042 | | |
1043 | 38 | case CXXMethod: { |
1044 | 38 | enum { |
1045 | 38 | DiagMethod, |
1046 | 38 | DiagConstructor, |
1047 | 38 | DiagDestructor, |
1048 | 38 | } FirstMethodType, |
1049 | 38 | SecondMethodType; |
1050 | 76 | auto GetMethodTypeForDiagnostics = [](const CXXMethodDecl *D) { |
1051 | 76 | if (isa<CXXConstructorDecl>(D)) |
1052 | 8 | return DiagConstructor; |
1053 | 68 | if (isa<CXXDestructorDecl>(D)) |
1054 | 3 | return DiagDestructor; |
1055 | 65 | return DiagMethod; |
1056 | 68 | }; |
1057 | 38 | const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl); |
1058 | 38 | const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl); |
1059 | 38 | FirstMethodType = GetMethodTypeForDiagnostics(FirstMethod); |
1060 | 38 | SecondMethodType = GetMethodTypeForDiagnostics(SecondMethod); |
1061 | 38 | DeclarationName FirstName = FirstMethod->getDeclName(); |
1062 | 38 | DeclarationName SecondName = SecondMethod->getDeclName(); |
1063 | 38 | auto DiagMethodError = [&DiagError, FirstMethod, FirstMethodType, |
1064 | 38 | FirstName](ODRCXXRecordDifference DiffType) { |
1065 | 32 | return DiagError(FirstMethod->getLocation(), |
1066 | 32 | FirstMethod->getSourceRange(), DiffType) |
1067 | 32 | << FirstMethodType << FirstName; |
1068 | 32 | }; |
1069 | 38 | auto DiagMethodNote = [&DiagNote, SecondMethod, SecondMethodType, |
1070 | 38 | SecondName](ODRCXXRecordDifference DiffType) { |
1071 | 32 | return DiagNote(SecondMethod->getLocation(), |
1072 | 32 | SecondMethod->getSourceRange(), DiffType) |
1073 | 32 | << SecondMethodType << SecondName; |
1074 | 32 | }; |
1075 | | |
1076 | 38 | if (FirstMethodType != SecondMethodType || FirstName != SecondName36 ) { |
1077 | 3 | DiagMethodError(MethodName); |
1078 | 3 | DiagMethodNote(MethodName); |
1079 | 3 | return true; |
1080 | 3 | } |
1081 | | |
1082 | 35 | const bool FirstDeleted = FirstMethod->isDeletedAsWritten(); |
1083 | 35 | const bool SecondDeleted = SecondMethod->isDeletedAsWritten(); |
1084 | 35 | if (FirstDeleted != SecondDeleted) { |
1085 | 1 | DiagMethodError(MethodDeleted) << FirstDeleted; |
1086 | 1 | DiagMethodNote(MethodDeleted) << SecondDeleted; |
1087 | 1 | return true; |
1088 | 1 | } |
1089 | | |
1090 | 34 | const bool FirstDefaulted = FirstMethod->isExplicitlyDefaulted(); |
1091 | 34 | const bool SecondDefaulted = SecondMethod->isExplicitlyDefaulted(); |
1092 | 34 | if (FirstDefaulted != SecondDefaulted) { |
1093 | 1 | DiagMethodError(MethodDefaulted) << FirstDefaulted; |
1094 | 1 | DiagMethodNote(MethodDefaulted) << SecondDefaulted; |
1095 | 1 | return true; |
1096 | 1 | } |
1097 | | |
1098 | 33 | const bool FirstVirtual = FirstMethod->isVirtualAsWritten(); |
1099 | 33 | const bool SecondVirtual = SecondMethod->isVirtualAsWritten(); |
1100 | 33 | const bool FirstPure = FirstMethod->isPure(); |
1101 | 33 | const bool SecondPure = SecondMethod->isPure(); |
1102 | 33 | if ((FirstVirtual || SecondVirtual32 ) && |
1103 | 33 | (3 FirstVirtual != SecondVirtual3 || FirstPure != SecondPure1 )) { |
1104 | 3 | DiagMethodError(MethodVirtual) << FirstPure << FirstVirtual; |
1105 | 3 | DiagMethodNote(MethodVirtual) << SecondPure << SecondVirtual; |
1106 | 3 | return true; |
1107 | 3 | } |
1108 | | |
1109 | | // CXXMethodDecl::isStatic uses the canonical Decl. With Decl merging, |
1110 | | // FirstDecl is the canonical Decl of SecondDecl, so the storage |
1111 | | // class needs to be checked instead. |
1112 | 30 | StorageClass FirstStorage = FirstMethod->getStorageClass(); |
1113 | 30 | StorageClass SecondStorage = SecondMethod->getStorageClass(); |
1114 | 30 | const bool FirstStatic = FirstStorage == SC_Static; |
1115 | 30 | const bool SecondStatic = SecondStorage == SC_Static; |
1116 | 30 | if (FirstStatic != SecondStatic) { |
1117 | 1 | DiagMethodError(MethodStatic) << FirstStatic; |
1118 | 1 | DiagMethodNote(MethodStatic) << SecondStatic; |
1119 | 1 | return true; |
1120 | 1 | } |
1121 | | |
1122 | 29 | const bool FirstVolatile = FirstMethod->isVolatile(); |
1123 | 29 | const bool SecondVolatile = SecondMethod->isVolatile(); |
1124 | 29 | if (FirstVolatile != SecondVolatile) { |
1125 | 1 | DiagMethodError(MethodVolatile) << FirstVolatile; |
1126 | 1 | DiagMethodNote(MethodVolatile) << SecondVolatile; |
1127 | 1 | return true; |
1128 | 1 | } |
1129 | | |
1130 | 28 | const bool FirstConst = FirstMethod->isConst(); |
1131 | 28 | const bool SecondConst = SecondMethod->isConst(); |
1132 | 28 | if (FirstConst != SecondConst) { |
1133 | 1 | DiagMethodError(MethodConst) << FirstConst; |
1134 | 1 | DiagMethodNote(MethodConst) << SecondConst; |
1135 | 1 | return true; |
1136 | 1 | } |
1137 | | |
1138 | 27 | const bool FirstInline = FirstMethod->isInlineSpecified(); |
1139 | 27 | const bool SecondInline = SecondMethod->isInlineSpecified(); |
1140 | 27 | if (FirstInline != SecondInline) { |
1141 | 1 | DiagMethodError(MethodInline) << FirstInline; |
1142 | 1 | DiagMethodNote(MethodInline) << SecondInline; |
1143 | 1 | return true; |
1144 | 1 | } |
1145 | | |
1146 | 26 | if (diagnoseSubMismatchMethodParameters(Diags, FirstRecord, |
1147 | 26 | FirstModule, SecondModule, |
1148 | 26 | FirstMethod, SecondMethod)) |
1149 | 6 | return true; |
1150 | | |
1151 | 20 | for (unsigned I = 0, N = FirstMethod->param_size(); I < N; ++I0 ) { |
1152 | 4 | const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I); |
1153 | 4 | const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I); |
1154 | | |
1155 | 4 | const Expr *FirstInit = FirstParam->getInit(); |
1156 | 4 | const Expr *SecondInit = SecondParam->getInit(); |
1157 | 4 | if ((FirstInit == nullptr) != (SecondInit == nullptr)) { |
1158 | 1 | DiagMethodError(MethodParameterSingleDefaultArgument) |
1159 | 1 | << (I + 1) << (FirstInit == nullptr) |
1160 | 1 | << (FirstInit ? FirstInit->getSourceRange() : SourceRange()0 ); |
1161 | 1 | DiagMethodNote(MethodParameterSingleDefaultArgument) |
1162 | 1 | << (I + 1) << (SecondInit == nullptr) |
1163 | 1 | << (SecondInit ? SecondInit->getSourceRange()0 : SourceRange()); |
1164 | 1 | return true; |
1165 | 1 | } |
1166 | | |
1167 | 3 | if (FirstInit && SecondInit && |
1168 | 3 | computeODRHash(FirstInit) != computeODRHash(SecondInit)) { |
1169 | 3 | DiagMethodError(MethodParameterDifferentDefaultArgument) |
1170 | 3 | << (I + 1) << FirstInit->getSourceRange(); |
1171 | 3 | DiagMethodNote(MethodParameterDifferentDefaultArgument) |
1172 | 3 | << (I + 1) << SecondInit->getSourceRange(); |
1173 | 3 | return true; |
1174 | 3 | } |
1175 | 3 | } |
1176 | | |
1177 | 16 | const TemplateArgumentList *FirstTemplateArgs = |
1178 | 16 | FirstMethod->getTemplateSpecializationArgs(); |
1179 | 16 | const TemplateArgumentList *SecondTemplateArgs = |
1180 | 16 | SecondMethod->getTemplateSpecializationArgs(); |
1181 | | |
1182 | 16 | if ((FirstTemplateArgs && !SecondTemplateArgs8 ) || |
1183 | 16 | (!FirstTemplateArgs && SecondTemplateArgs8 )) { |
1184 | 1 | DiagMethodError(MethodNoTemplateArguments) |
1185 | 1 | << (FirstTemplateArgs != nullptr); |
1186 | 1 | DiagMethodNote(MethodNoTemplateArguments) |
1187 | 1 | << (SecondTemplateArgs != nullptr); |
1188 | 1 | return true; |
1189 | 1 | } |
1190 | | |
1191 | 15 | if (FirstTemplateArgs && SecondTemplateArgs8 ) { |
1192 | | // Remove pack expansions from argument list. |
1193 | 16 | auto ExpandTemplateArgumentList = [](const TemplateArgumentList *TAL) { |
1194 | 16 | llvm::SmallVector<const TemplateArgument *, 8> ExpandedList; |
1195 | 23 | for (const TemplateArgument &TA : TAL->asArray()) { |
1196 | 23 | if (TA.getKind() != TemplateArgument::Pack) { |
1197 | 19 | ExpandedList.push_back(&TA); |
1198 | 19 | continue; |
1199 | 19 | } |
1200 | 4 | llvm::append_range(ExpandedList, |
1201 | 4 | llvm::make_pointer_range(TA.getPackAsArray())); |
1202 | 4 | } |
1203 | 16 | return ExpandedList; |
1204 | 16 | }; |
1205 | 8 | llvm::SmallVector<const TemplateArgument *, 8> FirstExpandedList = |
1206 | 8 | ExpandTemplateArgumentList(FirstTemplateArgs); |
1207 | 8 | llvm::SmallVector<const TemplateArgument *, 8> SecondExpandedList = |
1208 | 8 | ExpandTemplateArgumentList(SecondTemplateArgs); |
1209 | | |
1210 | 8 | if (FirstExpandedList.size() != SecondExpandedList.size()) { |
1211 | 2 | DiagMethodError(MethodDifferentNumberTemplateArguments) |
1212 | 2 | << (unsigned)FirstExpandedList.size(); |
1213 | 2 | DiagMethodNote(MethodDifferentNumberTemplateArguments) |
1214 | 2 | << (unsigned)SecondExpandedList.size(); |
1215 | 2 | return true; |
1216 | 2 | } |
1217 | | |
1218 | 7 | for (unsigned i = 0, e = FirstExpandedList.size(); 6 i != e; ++i1 ) { |
1219 | 7 | const TemplateArgument &FirstTA = *FirstExpandedList[i], |
1220 | 7 | &SecondTA = *SecondExpandedList[i]; |
1221 | 7 | if (computeODRHash(FirstTA) == computeODRHash(SecondTA)) |
1222 | 1 | continue; |
1223 | | |
1224 | 6 | DiagMethodError(MethodDifferentTemplateArgument) << FirstTA << i + 1; |
1225 | 6 | DiagMethodNote(MethodDifferentTemplateArgument) << SecondTA << i + 1; |
1226 | 6 | return true; |
1227 | 7 | } |
1228 | 6 | } |
1229 | | |
1230 | | // Compute the hash of the method as if it has no body. |
1231 | 14 | auto ComputeCXXMethodODRHash = [](const CXXMethodDecl *D) 7 { |
1232 | 14 | ODRHash Hasher; |
1233 | 14 | Hasher.AddFunctionDecl(D, true /*SkipBody*/); |
1234 | 14 | return Hasher.CalculateHash(); |
1235 | 14 | }; |
1236 | | |
1237 | | // Compare the hash generated to the hash stored. A difference means |
1238 | | // that a body was present in the original source. Due to merging, |
1239 | | // the standard way of detecting a body will not work. |
1240 | 7 | const bool HasFirstBody = |
1241 | 7 | ComputeCXXMethodODRHash(FirstMethod) != FirstMethod->getODRHash(); |
1242 | 7 | const bool HasSecondBody = |
1243 | 7 | ComputeCXXMethodODRHash(SecondMethod) != SecondMethod->getODRHash(); |
1244 | | |
1245 | 7 | if (HasFirstBody != HasSecondBody) { |
1246 | 6 | DiagMethodError(MethodSingleBody) << HasFirstBody; |
1247 | 6 | DiagMethodNote(MethodSingleBody) << HasSecondBody; |
1248 | 6 | return true; |
1249 | 6 | } |
1250 | | |
1251 | 1 | if (HasFirstBody && HasSecondBody) { |
1252 | 1 | DiagMethodError(MethodDifferentBody); |
1253 | 1 | DiagMethodNote(MethodDifferentBody); |
1254 | 1 | return true; |
1255 | 1 | } |
1256 | | |
1257 | 0 | break; |
1258 | 1 | } |
1259 | | |
1260 | 5 | case TypeAlias: |
1261 | 7 | case TypeDef: { |
1262 | 7 | if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule, |
1263 | 7 | cast<TypedefNameDecl>(FirstDecl), |
1264 | 7 | cast<TypedefNameDecl>(SecondDecl), |
1265 | 7 | FirstDiffType == TypeAlias)) |
1266 | 7 | return true; |
1267 | 0 | break; |
1268 | 7 | } |
1269 | 6 | case Var: { |
1270 | 6 | if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule, |
1271 | 6 | cast<VarDecl>(FirstDecl), |
1272 | 6 | cast<VarDecl>(SecondDecl))) |
1273 | 6 | return true; |
1274 | 0 | break; |
1275 | 6 | } |
1276 | 4 | case Friend: { |
1277 | 4 | const FriendDecl *FirstFriend = cast<FriendDecl>(FirstDecl); |
1278 | 4 | const FriendDecl *SecondFriend = cast<FriendDecl>(SecondDecl); |
1279 | | |
1280 | 4 | const NamedDecl *FirstND = FirstFriend->getFriendDecl(); |
1281 | 4 | const NamedDecl *SecondND = SecondFriend->getFriendDecl(); |
1282 | | |
1283 | 4 | TypeSourceInfo *FirstTSI = FirstFriend->getFriendType(); |
1284 | 4 | TypeSourceInfo *SecondTSI = SecondFriend->getFriendType(); |
1285 | | |
1286 | 4 | if (FirstND && SecondND2 ) { |
1287 | 1 | DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(), |
1288 | 1 | FriendFunction) |
1289 | 1 | << FirstND; |
1290 | 1 | DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(), |
1291 | 1 | FriendFunction) |
1292 | 1 | << SecondND; |
1293 | 1 | return true; |
1294 | 1 | } |
1295 | | |
1296 | 3 | if (FirstTSI && SecondTSI2 ) { |
1297 | 2 | QualType FirstFriendType = FirstTSI->getType(); |
1298 | 2 | QualType SecondFriendType = SecondTSI->getType(); |
1299 | 2 | assert(computeODRHash(FirstFriendType) != |
1300 | 2 | computeODRHash(SecondFriendType)); |
1301 | 2 | DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(), |
1302 | 2 | FriendType) |
1303 | 2 | << FirstFriendType; |
1304 | 2 | DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(), |
1305 | 2 | FriendType) |
1306 | 2 | << SecondFriendType; |
1307 | 2 | return true; |
1308 | 2 | } |
1309 | | |
1310 | 1 | DiagError(FirstFriend->getFriendLoc(), FirstFriend->getSourceRange(), |
1311 | 1 | FriendTypeFunction) |
1312 | 1 | << (FirstTSI == nullptr); |
1313 | 1 | DiagNote(SecondFriend->getFriendLoc(), SecondFriend->getSourceRange(), |
1314 | 1 | FriendTypeFunction) |
1315 | 1 | << (SecondTSI == nullptr); |
1316 | 1 | return true; |
1317 | 3 | } |
1318 | 20 | case FunctionTemplate: { |
1319 | 20 | const FunctionTemplateDecl *FirstTemplate = |
1320 | 20 | cast<FunctionTemplateDecl>(FirstDecl); |
1321 | 20 | const FunctionTemplateDecl *SecondTemplate = |
1322 | 20 | cast<FunctionTemplateDecl>(SecondDecl); |
1323 | | |
1324 | 20 | TemplateParameterList *FirstTPL = FirstTemplate->getTemplateParameters(); |
1325 | 20 | TemplateParameterList *SecondTPL = SecondTemplate->getTemplateParameters(); |
1326 | | |
1327 | 20 | auto DiagTemplateError = [&DiagError, |
1328 | 20 | FirstTemplate](ODRCXXRecordDifference DiffType) { |
1329 | 20 | return DiagError(FirstTemplate->getLocation(), |
1330 | 20 | FirstTemplate->getSourceRange(), DiffType) |
1331 | 20 | << FirstTemplate; |
1332 | 20 | }; |
1333 | 20 | auto DiagTemplateNote = [&DiagNote, |
1334 | 20 | SecondTemplate](ODRCXXRecordDifference DiffType) { |
1335 | 20 | return DiagNote(SecondTemplate->getLocation(), |
1336 | 20 | SecondTemplate->getSourceRange(), DiffType) |
1337 | 20 | << SecondTemplate; |
1338 | 20 | }; |
1339 | | |
1340 | 20 | if (FirstTPL->size() != SecondTPL->size()) { |
1341 | 1 | DiagTemplateError(FunctionTemplateDifferentNumberParameters) |
1342 | 1 | << FirstTPL->size(); |
1343 | 1 | DiagTemplateNote(FunctionTemplateDifferentNumberParameters) |
1344 | 1 | << SecondTPL->size(); |
1345 | 1 | return true; |
1346 | 1 | } |
1347 | | |
1348 | 19 | for (unsigned i = 0, e = FirstTPL->size(); i != e; ++i0 ) { |
1349 | 19 | NamedDecl *FirstParam = FirstTPL->getParam(i); |
1350 | 19 | NamedDecl *SecondParam = SecondTPL->getParam(i); |
1351 | | |
1352 | 19 | if (FirstParam->getKind() != SecondParam->getKind()) { |
1353 | 3 | enum { |
1354 | 3 | TemplateTypeParameter, |
1355 | 3 | NonTypeTemplateParameter, |
1356 | 3 | TemplateTemplateParameter, |
1357 | 3 | }; |
1358 | 6 | auto GetParamType = [](NamedDecl *D) { |
1359 | 6 | switch (D->getKind()) { |
1360 | 0 | default: |
1361 | 0 | llvm_unreachable("Unexpected template parameter type"); |
1362 | 2 | case Decl::TemplateTypeParm: |
1363 | 2 | return TemplateTypeParameter; |
1364 | 2 | case Decl::NonTypeTemplateParm: |
1365 | 2 | return NonTypeTemplateParameter; |
1366 | 2 | case Decl::TemplateTemplateParm: |
1367 | 2 | return TemplateTemplateParameter; |
1368 | 6 | } |
1369 | 6 | }; |
1370 | | |
1371 | 3 | DiagTemplateError(FunctionTemplateParameterDifferentKind) |
1372 | 3 | << (i + 1) << GetParamType(FirstParam); |
1373 | 3 | DiagTemplateNote(FunctionTemplateParameterDifferentKind) |
1374 | 3 | << (i + 1) << GetParamType(SecondParam); |
1375 | 3 | return true; |
1376 | 3 | } |
1377 | | |
1378 | 16 | if (FirstParam->getName() != SecondParam->getName()) { |
1379 | 2 | DiagTemplateError(FunctionTemplateParameterName) |
1380 | 2 | << (i + 1) << (bool)FirstParam->getIdentifier() << FirstParam; |
1381 | 2 | DiagTemplateNote(FunctionTemplateParameterName) |
1382 | 2 | << (i + 1) << (bool)SecondParam->getIdentifier() << SecondParam; |
1383 | 2 | return true; |
1384 | 2 | } |
1385 | | |
1386 | 14 | if (isa<TemplateTypeParmDecl>(FirstParam) && |
1387 | 14 | isa<TemplateTypeParmDecl>(SecondParam)6 ) { |
1388 | 6 | TemplateTypeParmDecl *FirstTTPD = |
1389 | 6 | cast<TemplateTypeParmDecl>(FirstParam); |
1390 | 6 | TemplateTypeParmDecl *SecondTTPD = |
1391 | 6 | cast<TemplateTypeParmDecl>(SecondParam); |
1392 | 6 | bool HasFirstDefaultArgument = |
1393 | 6 | FirstTTPD->hasDefaultArgument() && |
1394 | 6 | !FirstTTPD->defaultArgumentWasInherited()3 ; |
1395 | 6 | bool HasSecondDefaultArgument = |
1396 | 6 | SecondTTPD->hasDefaultArgument() && |
1397 | 6 | !SecondTTPD->defaultArgumentWasInherited()5 ; |
1398 | 6 | if (HasFirstDefaultArgument != HasSecondDefaultArgument) { |
1399 | 3 | DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument) |
1400 | 3 | << (i + 1) << HasFirstDefaultArgument; |
1401 | 3 | DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument) |
1402 | 3 | << (i + 1) << HasSecondDefaultArgument; |
1403 | 3 | return true; |
1404 | 3 | } |
1405 | | |
1406 | 3 | if (HasFirstDefaultArgument && HasSecondDefaultArgument2 ) { |
1407 | 2 | QualType FirstType = FirstTTPD->getDefaultArgument(); |
1408 | 2 | QualType SecondType = SecondTTPD->getDefaultArgument(); |
1409 | 2 | if (computeODRHash(FirstType) != computeODRHash(SecondType)) { |
1410 | 2 | DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument) |
1411 | 2 | << (i + 1) << FirstType; |
1412 | 2 | DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument) |
1413 | 2 | << (i + 1) << SecondType; |
1414 | 2 | return true; |
1415 | 2 | } |
1416 | 2 | } |
1417 | | |
1418 | 1 | if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) { |
1419 | 1 | DiagTemplateError(FunctionTemplatePackParameter) |
1420 | 1 | << (i + 1) << FirstTTPD->isParameterPack(); |
1421 | 1 | DiagTemplateNote(FunctionTemplatePackParameter) |
1422 | 1 | << (i + 1) << SecondTTPD->isParameterPack(); |
1423 | 1 | return true; |
1424 | 1 | } |
1425 | 1 | } |
1426 | | |
1427 | 8 | if (isa<TemplateTemplateParmDecl>(FirstParam) && |
1428 | 8 | isa<TemplateTemplateParmDecl>(SecondParam)4 ) { |
1429 | 4 | TemplateTemplateParmDecl *FirstTTPD = |
1430 | 4 | cast<TemplateTemplateParmDecl>(FirstParam); |
1431 | 4 | TemplateTemplateParmDecl *SecondTTPD = |
1432 | 4 | cast<TemplateTemplateParmDecl>(SecondParam); |
1433 | | |
1434 | 4 | TemplateParameterList *FirstTPL = FirstTTPD->getTemplateParameters(); |
1435 | 4 | TemplateParameterList *SecondTPL = SecondTTPD->getTemplateParameters(); |
1436 | | |
1437 | 4 | auto ComputeTemplateParameterListODRHash = |
1438 | 8 | [](const TemplateParameterList *TPL) { |
1439 | 8 | assert(TPL); |
1440 | 8 | ODRHash Hasher; |
1441 | 8 | Hasher.AddTemplateParameterList(TPL); |
1442 | 8 | return Hasher.CalculateHash(); |
1443 | 8 | }; |
1444 | | |
1445 | 4 | if (ComputeTemplateParameterListODRHash(FirstTPL) != |
1446 | 4 | ComputeTemplateParameterListODRHash(SecondTPL)) { |
1447 | 1 | DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1); |
1448 | 1 | DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1); |
1449 | 1 | return true; |
1450 | 1 | } |
1451 | | |
1452 | 3 | bool HasFirstDefaultArgument = |
1453 | 3 | FirstTTPD->hasDefaultArgument() && |
1454 | 3 | !FirstTTPD->defaultArgumentWasInherited()1 ; |
1455 | 3 | bool HasSecondDefaultArgument = |
1456 | 3 | SecondTTPD->hasDefaultArgument() && |
1457 | 3 | !SecondTTPD->defaultArgumentWasInherited()2 ; |
1458 | 3 | if (HasFirstDefaultArgument != HasSecondDefaultArgument) { |
1459 | 1 | DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument) |
1460 | 1 | << (i + 1) << HasFirstDefaultArgument; |
1461 | 1 | DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument) |
1462 | 1 | << (i + 1) << HasSecondDefaultArgument; |
1463 | 1 | return true; |
1464 | 1 | } |
1465 | | |
1466 | 2 | if (HasFirstDefaultArgument && HasSecondDefaultArgument1 ) { |
1467 | 1 | TemplateArgument FirstTA = |
1468 | 1 | FirstTTPD->getDefaultArgument().getArgument(); |
1469 | 1 | TemplateArgument SecondTA = |
1470 | 1 | SecondTTPD->getDefaultArgument().getArgument(); |
1471 | 1 | if (computeODRHash(FirstTA) != computeODRHash(SecondTA)) { |
1472 | 1 | DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument) |
1473 | 1 | << (i + 1) << FirstTA; |
1474 | 1 | DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument) |
1475 | 1 | << (i + 1) << SecondTA; |
1476 | 1 | return true; |
1477 | 1 | } |
1478 | 1 | } |
1479 | | |
1480 | 1 | if (FirstTTPD->isParameterPack() != SecondTTPD->isParameterPack()) { |
1481 | 1 | DiagTemplateError(FunctionTemplatePackParameter) |
1482 | 1 | << (i + 1) << FirstTTPD->isParameterPack(); |
1483 | 1 | DiagTemplateNote(FunctionTemplatePackParameter) |
1484 | 1 | << (i + 1) << SecondTTPD->isParameterPack(); |
1485 | 1 | return true; |
1486 | 1 | } |
1487 | 1 | } |
1488 | | |
1489 | 4 | if (isa<NonTypeTemplateParmDecl>(FirstParam) && |
1490 | 4 | isa<NonTypeTemplateParmDecl>(SecondParam)) { |
1491 | 4 | NonTypeTemplateParmDecl *FirstNTTPD = |
1492 | 4 | cast<NonTypeTemplateParmDecl>(FirstParam); |
1493 | 4 | NonTypeTemplateParmDecl *SecondNTTPD = |
1494 | 4 | cast<NonTypeTemplateParmDecl>(SecondParam); |
1495 | | |
1496 | 4 | QualType FirstType = FirstNTTPD->getType(); |
1497 | 4 | QualType SecondType = SecondNTTPD->getType(); |
1498 | 4 | if (computeODRHash(FirstType) != computeODRHash(SecondType)) { |
1499 | 1 | DiagTemplateError(FunctionTemplateParameterDifferentType) << (i + 1); |
1500 | 1 | DiagTemplateNote(FunctionTemplateParameterDifferentType) << (i + 1); |
1501 | 1 | return true; |
1502 | 1 | } |
1503 | | |
1504 | 3 | bool HasFirstDefaultArgument = |
1505 | 3 | FirstNTTPD->hasDefaultArgument() && |
1506 | 3 | !FirstNTTPD->defaultArgumentWasInherited()2 ; |
1507 | 3 | bool HasSecondDefaultArgument = |
1508 | 3 | SecondNTTPD->hasDefaultArgument() && |
1509 | 3 | !SecondNTTPD->defaultArgumentWasInherited()2 ; |
1510 | 3 | if (HasFirstDefaultArgument != HasSecondDefaultArgument) { |
1511 | 1 | DiagTemplateError(FunctionTemplateParameterSingleDefaultArgument) |
1512 | 1 | << (i + 1) << HasFirstDefaultArgument; |
1513 | 1 | DiagTemplateNote(FunctionTemplateParameterSingleDefaultArgument) |
1514 | 1 | << (i + 1) << HasSecondDefaultArgument; |
1515 | 1 | return true; |
1516 | 1 | } |
1517 | | |
1518 | 2 | if (HasFirstDefaultArgument && HasSecondDefaultArgument1 ) { |
1519 | 1 | Expr *FirstDefaultArgument = FirstNTTPD->getDefaultArgument(); |
1520 | 1 | Expr *SecondDefaultArgument = SecondNTTPD->getDefaultArgument(); |
1521 | 1 | if (computeODRHash(FirstDefaultArgument) != |
1522 | 1 | computeODRHash(SecondDefaultArgument)) { |
1523 | 1 | DiagTemplateError(FunctionTemplateParameterDifferentDefaultArgument) |
1524 | 1 | << (i + 1) << FirstDefaultArgument; |
1525 | 1 | DiagTemplateNote(FunctionTemplateParameterDifferentDefaultArgument) |
1526 | 1 | << (i + 1) << SecondDefaultArgument; |
1527 | 1 | return true; |
1528 | 1 | } |
1529 | 1 | } |
1530 | | |
1531 | 1 | if (FirstNTTPD->isParameterPack() != SecondNTTPD->isParameterPack()) { |
1532 | 1 | DiagTemplateError(FunctionTemplatePackParameter) |
1533 | 1 | << (i + 1) << FirstNTTPD->isParameterPack(); |
1534 | 1 | DiagTemplateNote(FunctionTemplatePackParameter) |
1535 | 1 | << (i + 1) << SecondNTTPD->isParameterPack(); |
1536 | 1 | return true; |
1537 | 1 | } |
1538 | 1 | } |
1539 | 4 | } |
1540 | 0 | break; |
1541 | 19 | } |
1542 | 102 | } |
1543 | | |
1544 | 0 | Diag(FirstDecl->getLocation(), |
1545 | 0 | diag::err_module_odr_violation_mismatch_decl_unknown) |
1546 | 0 | << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType |
1547 | 0 | << FirstDecl->getSourceRange(); |
1548 | 0 | Diag(SecondDecl->getLocation(), |
1549 | 0 | diag::note_module_odr_violation_mismatch_decl_unknown) |
1550 | 0 | << SecondModule.empty() << SecondModule << FirstDiffType |
1551 | 0 | << SecondDecl->getSourceRange(); |
1552 | 0 | return true; |
1553 | 102 | } |
1554 | | |
1555 | | bool ODRDiagsEmitter::diagnoseMismatch(const RecordDecl *FirstRecord, |
1556 | 9 | const RecordDecl *SecondRecord) const { |
1557 | 9 | if (FirstRecord == SecondRecord) |
1558 | 0 | return false; |
1559 | | |
1560 | 9 | std::string FirstModule = getOwningModuleNameForDiagnostic(FirstRecord); |
1561 | 9 | std::string SecondModule = getOwningModuleNameForDiagnostic(SecondRecord); |
1562 | | |
1563 | 9 | auto PopulateHashes = [](DeclHashes &Hashes, const RecordDecl *Record, |
1564 | 18 | const DeclContext *DC) { |
1565 | 21 | for (const Decl *D : Record->decls()) { |
1566 | 21 | if (!ODRHash::isSubDeclToBeProcessed(D, DC)) |
1567 | 0 | continue; |
1568 | 21 | Hashes.emplace_back(D, computeODRHash(D)); |
1569 | 21 | } |
1570 | 18 | }; |
1571 | | |
1572 | 9 | DeclHashes FirstHashes; |
1573 | 9 | DeclHashes SecondHashes; |
1574 | 9 | const DeclContext *DC = FirstRecord; |
1575 | 9 | PopulateHashes(FirstHashes, FirstRecord, DC); |
1576 | 9 | PopulateHashes(SecondHashes, SecondRecord, DC); |
1577 | | |
1578 | 9 | DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes); |
1579 | 9 | ODRMismatchDecl FirstDiffType = DR.FirstDiffType; |
1580 | 9 | ODRMismatchDecl SecondDiffType = DR.SecondDiffType; |
1581 | 9 | const Decl *FirstDecl = DR.FirstDecl; |
1582 | 9 | const Decl *SecondDecl = DR.SecondDecl; |
1583 | | |
1584 | 9 | if (FirstDiffType == Other || SecondDiffType == Other) { |
1585 | 0 | diagnoseSubMismatchUnexpected(DR, FirstRecord, FirstModule, SecondRecord, |
1586 | 0 | SecondModule); |
1587 | 0 | return true; |
1588 | 0 | } |
1589 | | |
1590 | 9 | if (FirstDiffType != SecondDiffType) { |
1591 | 1 | diagnoseSubMismatchDifferentDeclKinds(DR, FirstRecord, FirstModule, |
1592 | 1 | SecondRecord, SecondModule); |
1593 | 1 | return true; |
1594 | 1 | } |
1595 | | |
1596 | 8 | assert(FirstDiffType == SecondDiffType); |
1597 | 8 | switch (FirstDiffType) { |
1598 | | // Already handled. |
1599 | 0 | case EndOfClass: |
1600 | 0 | case Other: |
1601 | | // C++ only, invalid in this context. |
1602 | 0 | case PublicSpecifer: |
1603 | 0 | case PrivateSpecifer: |
1604 | 0 | case ProtectedSpecifer: |
1605 | 0 | case StaticAssert: |
1606 | 0 | case CXXMethod: |
1607 | 0 | case TypeAlias: |
1608 | 0 | case Friend: |
1609 | 0 | case FunctionTemplate: |
1610 | | // Cannot be contained by RecordDecl, invalid in this context. |
1611 | 0 | case ObjCMethod: |
1612 | 0 | case ObjCIvar: |
1613 | 0 | case ObjCProperty: |
1614 | 0 | llvm_unreachable("Invalid diff type"); |
1615 | |
|
1616 | 8 | case Field: { |
1617 | 8 | if (diagnoseSubMismatchField(FirstRecord, FirstModule, SecondModule, |
1618 | 8 | cast<FieldDecl>(FirstDecl), |
1619 | 8 | cast<FieldDecl>(SecondDecl))) |
1620 | 8 | return true; |
1621 | 0 | break; |
1622 | 8 | } |
1623 | 0 | case TypeDef: { |
1624 | 0 | if (diagnoseSubMismatchTypedef(FirstRecord, FirstModule, SecondModule, |
1625 | 0 | cast<TypedefNameDecl>(FirstDecl), |
1626 | 0 | cast<TypedefNameDecl>(SecondDecl), |
1627 | 0 | /*IsTypeAlias=*/false)) |
1628 | 0 | return true; |
1629 | 0 | break; |
1630 | 0 | } |
1631 | 0 | case Var: { |
1632 | 0 | if (diagnoseSubMismatchVar(FirstRecord, FirstModule, SecondModule, |
1633 | 0 | cast<VarDecl>(FirstDecl), |
1634 | 0 | cast<VarDecl>(SecondDecl))) |
1635 | 0 | return true; |
1636 | 0 | break; |
1637 | 0 | } |
1638 | 8 | } |
1639 | | |
1640 | 0 | Diag(FirstDecl->getLocation(), |
1641 | 0 | diag::err_module_odr_violation_mismatch_decl_unknown) |
1642 | 0 | << FirstRecord << FirstModule.empty() << FirstModule << FirstDiffType |
1643 | 0 | << FirstDecl->getSourceRange(); |
1644 | 0 | Diag(SecondDecl->getLocation(), |
1645 | 0 | diag::note_module_odr_violation_mismatch_decl_unknown) |
1646 | 0 | << SecondModule.empty() << SecondModule << FirstDiffType |
1647 | 0 | << SecondDecl->getSourceRange(); |
1648 | 0 | return true; |
1649 | 8 | } |
1650 | | |
1651 | | bool ODRDiagsEmitter::diagnoseMismatch( |
1652 | | const FunctionDecl *FirstFunction, |
1653 | 40 | const FunctionDecl *SecondFunction) const { |
1654 | 40 | if (FirstFunction == SecondFunction) |
1655 | 0 | return false; |
1656 | | |
1657 | | // Keep in sync with select options in err_module_odr_violation_function. |
1658 | 40 | enum ODRFunctionDifference { |
1659 | 40 | ReturnType, |
1660 | 40 | ParameterName, |
1661 | 40 | ParameterType, |
1662 | 40 | ParameterSingleDefaultArgument, |
1663 | 40 | ParameterDifferentDefaultArgument, |
1664 | 40 | FunctionBody, |
1665 | 40 | }; |
1666 | | |
1667 | 40 | std::string FirstModule = getOwningModuleNameForDiagnostic(FirstFunction); |
1668 | 40 | std::string SecondModule = getOwningModuleNameForDiagnostic(SecondFunction); |
1669 | | |
1670 | 40 | auto DiagError = [FirstFunction, &FirstModule, |
1671 | 40 | this](SourceLocation Loc, SourceRange Range, |
1672 | 40 | ODRFunctionDifference DiffType) { |
1673 | 40 | return Diag(Loc, diag::err_module_odr_violation_function) |
1674 | 40 | << FirstFunction << FirstModule.empty() << FirstModule << Range |
1675 | 40 | << DiffType; |
1676 | 40 | }; |
1677 | 40 | auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range, |
1678 | 40 | ODRFunctionDifference DiffType) { |
1679 | 40 | return Diag(Loc, diag::note_module_odr_violation_function) |
1680 | 40 | << SecondModule << Range << DiffType; |
1681 | 40 | }; |
1682 | | |
1683 | 40 | if (computeODRHash(FirstFunction->getReturnType()) != |
1684 | 40 | computeODRHash(SecondFunction->getReturnType())) { |
1685 | 1 | DiagError(FirstFunction->getReturnTypeSourceRange().getBegin(), |
1686 | 1 | FirstFunction->getReturnTypeSourceRange(), ReturnType) |
1687 | 1 | << FirstFunction->getReturnType(); |
1688 | 1 | DiagNote(SecondFunction->getReturnTypeSourceRange().getBegin(), |
1689 | 1 | SecondFunction->getReturnTypeSourceRange(), ReturnType) |
1690 | 1 | << SecondFunction->getReturnType(); |
1691 | 1 | return true; |
1692 | 1 | } |
1693 | | |
1694 | 39 | assert(FirstFunction->param_size() == SecondFunction->param_size() && |
1695 | 39 | "Merged functions with different number of parameters"); |
1696 | | |
1697 | 39 | size_t ParamSize = FirstFunction->param_size(); |
1698 | 41 | for (unsigned I = 0; I < ParamSize; ++I2 ) { |
1699 | 8 | const ParmVarDecl *FirstParam = FirstFunction->getParamDecl(I); |
1700 | 8 | const ParmVarDecl *SecondParam = SecondFunction->getParamDecl(I); |
1701 | | |
1702 | 8 | assert(Context.hasSameType(FirstParam->getType(), SecondParam->getType()) && |
1703 | 8 | "Merged function has different parameter types."); |
1704 | | |
1705 | 8 | if (FirstParam->getDeclName() != SecondParam->getDeclName()) { |
1706 | 2 | DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), |
1707 | 2 | ParameterName) |
1708 | 2 | << I + 1 << FirstParam->getDeclName(); |
1709 | 2 | DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), |
1710 | 2 | ParameterName) |
1711 | 2 | << I + 1 << SecondParam->getDeclName(); |
1712 | 2 | return true; |
1713 | 6 | }; |
1714 | | |
1715 | 6 | QualType FirstParamType = FirstParam->getType(); |
1716 | 6 | QualType SecondParamType = SecondParam->getType(); |
1717 | 6 | if (FirstParamType != SecondParamType && |
1718 | 6 | computeODRHash(FirstParamType) != computeODRHash(SecondParamType)2 ) { |
1719 | 2 | if (const DecayedType *ParamDecayedType = |
1720 | 2 | FirstParamType->getAs<DecayedType>()) { |
1721 | 1 | DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), |
1722 | 1 | ParameterType) |
1723 | 1 | << (I + 1) << FirstParamType << true |
1724 | 1 | << ParamDecayedType->getOriginalType(); |
1725 | 1 | } else { |
1726 | 1 | DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), |
1727 | 1 | ParameterType) |
1728 | 1 | << (I + 1) << FirstParamType << false; |
1729 | 1 | } |
1730 | | |
1731 | 2 | if (const DecayedType *ParamDecayedType = |
1732 | 2 | SecondParamType->getAs<DecayedType>()) { |
1733 | 1 | DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), |
1734 | 1 | ParameterType) |
1735 | 1 | << (I + 1) << SecondParamType << true |
1736 | 1 | << ParamDecayedType->getOriginalType(); |
1737 | 1 | } else { |
1738 | 1 | DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), |
1739 | 1 | ParameterType) |
1740 | 1 | << (I + 1) << SecondParamType << false; |
1741 | 1 | } |
1742 | 2 | return true; |
1743 | 2 | } |
1744 | | |
1745 | | // Note, these calls can trigger deserialization. |
1746 | 4 | const Expr *FirstInit = FirstParam->getInit(); |
1747 | 4 | const Expr *SecondInit = SecondParam->getInit(); |
1748 | 4 | if ((FirstInit == nullptr) != (SecondInit == nullptr)) { |
1749 | 1 | DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), |
1750 | 1 | ParameterSingleDefaultArgument) |
1751 | 1 | << (I + 1) << (FirstInit == nullptr) |
1752 | 1 | << (FirstInit ? FirstInit->getSourceRange() : SourceRange()0 ); |
1753 | 1 | DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), |
1754 | 1 | ParameterSingleDefaultArgument) |
1755 | 1 | << (I + 1) << (SecondInit == nullptr) |
1756 | 1 | << (SecondInit ? SecondInit->getSourceRange()0 : SourceRange()); |
1757 | 1 | return true; |
1758 | 1 | } |
1759 | | |
1760 | 3 | if (FirstInit && SecondInit1 && |
1761 | 3 | computeODRHash(FirstInit) != computeODRHash(SecondInit)1 ) { |
1762 | 1 | DiagError(FirstParam->getLocation(), FirstParam->getSourceRange(), |
1763 | 1 | ParameterDifferentDefaultArgument) |
1764 | 1 | << (I + 1) << FirstInit->getSourceRange(); |
1765 | 1 | DiagNote(SecondParam->getLocation(), SecondParam->getSourceRange(), |
1766 | 1 | ParameterDifferentDefaultArgument) |
1767 | 1 | << (I + 1) << SecondInit->getSourceRange(); |
1768 | 1 | return true; |
1769 | 1 | } |
1770 | | |
1771 | 2 | assert(computeODRHash(FirstParam) == computeODRHash(SecondParam) && |
1772 | 2 | "Undiagnosed parameter difference."); |
1773 | 2 | } |
1774 | | |
1775 | | // If no error has been generated before now, assume the problem is in |
1776 | | // the body and generate a message. |
1777 | 33 | DiagError(FirstFunction->getLocation(), FirstFunction->getSourceRange(), |
1778 | 33 | FunctionBody); |
1779 | 33 | DiagNote(SecondFunction->getLocation(), SecondFunction->getSourceRange(), |
1780 | 33 | FunctionBody); |
1781 | 33 | return true; |
1782 | 39 | } |
1783 | | |
1784 | | bool ODRDiagsEmitter::diagnoseMismatch(const EnumDecl *FirstEnum, |
1785 | 13 | const EnumDecl *SecondEnum) const { |
1786 | 13 | if (FirstEnum == SecondEnum) |
1787 | 0 | return false; |
1788 | | |
1789 | | // Keep in sync with select options in err_module_odr_violation_enum. |
1790 | 13 | enum ODREnumDifference { |
1791 | 13 | SingleScopedEnum, |
1792 | 13 | EnumTagKeywordMismatch, |
1793 | 13 | SingleSpecifiedType, |
1794 | 13 | DifferentSpecifiedTypes, |
1795 | 13 | DifferentNumberEnumConstants, |
1796 | 13 | EnumConstantName, |
1797 | 13 | EnumConstantSingleInitializer, |
1798 | 13 | EnumConstantDifferentInitializer, |
1799 | 13 | }; |
1800 | | |
1801 | 13 | std::string FirstModule = getOwningModuleNameForDiagnostic(FirstEnum); |
1802 | 13 | std::string SecondModule = getOwningModuleNameForDiagnostic(SecondEnum); |
1803 | | |
1804 | 13 | auto DiagError = [FirstEnum, &FirstModule, this](const auto *DiagAnchor, |
1805 | 13 | ODREnumDifference DiffType) { |
1806 | 13 | return Diag(DiagAnchor->getLocation(), diag::err_module_odr_violation_enum) |
1807 | 13 | << FirstEnum << FirstModule.empty() << FirstModule |
1808 | 13 | << DiagAnchor->getSourceRange() << DiffType; |
1809 | 13 | }; ODRDiagsEmitter.cpp:auto clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::$_0::operator()<clang::EnumDecl>(clang::EnumDecl const*, clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::ODREnumDifference) const Line | Count | Source | 1805 | 9 | ODREnumDifference DiffType) { | 1806 | 9 | return Diag(DiagAnchor->getLocation(), diag::err_module_odr_violation_enum) | 1807 | 9 | << FirstEnum << FirstModule.empty() << FirstModule | 1808 | 9 | << DiagAnchor->getSourceRange() << DiffType; | 1809 | 9 | }; |
ODRDiagsEmitter.cpp:auto clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::$_0::operator()<clang::EnumConstantDecl>(clang::EnumConstantDecl const*, clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::ODREnumDifference) const Line | Count | Source | 1805 | 4 | ODREnumDifference DiffType) { | 1806 | 4 | return Diag(DiagAnchor->getLocation(), diag::err_module_odr_violation_enum) | 1807 | 4 | << FirstEnum << FirstModule.empty() << FirstModule | 1808 | 4 | << DiagAnchor->getSourceRange() << DiffType; | 1809 | 4 | }; |
|
1810 | 13 | auto DiagNote = [&SecondModule, this](const auto *DiagAnchor, |
1811 | 13 | ODREnumDifference DiffType) { |
1812 | 13 | return Diag(DiagAnchor->getLocation(), diag::note_module_odr_violation_enum) |
1813 | 13 | << SecondModule << DiagAnchor->getSourceRange() << DiffType; |
1814 | 13 | }; ODRDiagsEmitter.cpp:auto clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::$_1::operator()<clang::EnumDecl>(clang::EnumDecl const*, clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::ODREnumDifference) const Line | Count | Source | 1811 | 9 | ODREnumDifference DiffType) { | 1812 | 9 | return Diag(DiagAnchor->getLocation(), diag::note_module_odr_violation_enum) | 1813 | 9 | << SecondModule << DiagAnchor->getSourceRange() << DiffType; | 1814 | 9 | }; |
ODRDiagsEmitter.cpp:auto clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::$_1::operator()<clang::EnumConstantDecl>(clang::EnumConstantDecl const*, clang::ODRDiagsEmitter::diagnoseMismatch(clang::EnumDecl const*, clang::EnumDecl const*) const::ODREnumDifference) const Line | Count | Source | 1811 | 4 | ODREnumDifference DiffType) { | 1812 | 4 | return Diag(DiagAnchor->getLocation(), diag::note_module_odr_violation_enum) | 1813 | 4 | << SecondModule << DiagAnchor->getSourceRange() << DiffType; | 1814 | 4 | }; |
|
1815 | | |
1816 | 13 | if (FirstEnum->isScoped() != SecondEnum->isScoped()) { |
1817 | 2 | DiagError(FirstEnum, SingleScopedEnum) << FirstEnum->isScoped(); |
1818 | 2 | DiagNote(SecondEnum, SingleScopedEnum) << SecondEnum->isScoped(); |
1819 | 2 | return true; |
1820 | 2 | } |
1821 | | |
1822 | 11 | if (FirstEnum->isScoped() && SecondEnum->isScoped()4 ) { |
1823 | 4 | if (FirstEnum->isScopedUsingClassTag() != |
1824 | 4 | SecondEnum->isScopedUsingClassTag()) { |
1825 | 2 | DiagError(FirstEnum, EnumTagKeywordMismatch) |
1826 | 2 | << FirstEnum->isScopedUsingClassTag(); |
1827 | 2 | DiagNote(SecondEnum, EnumTagKeywordMismatch) |
1828 | 2 | << SecondEnum->isScopedUsingClassTag(); |
1829 | 2 | return true; |
1830 | 2 | } |
1831 | 4 | } |
1832 | | |
1833 | 9 | QualType FirstUnderlyingType = |
1834 | 9 | FirstEnum->getIntegerTypeSourceInfo() |
1835 | 9 | ? FirstEnum->getIntegerTypeSourceInfo()->getType()2 |
1836 | 9 | : QualType()7 ; |
1837 | 9 | QualType SecondUnderlyingType = |
1838 | 9 | SecondEnum->getIntegerTypeSourceInfo() |
1839 | 9 | ? SecondEnum->getIntegerTypeSourceInfo()->getType()2 |
1840 | 9 | : QualType()7 ; |
1841 | 9 | if (FirstUnderlyingType.isNull() != SecondUnderlyingType.isNull()) { |
1842 | 2 | DiagError(FirstEnum, SingleSpecifiedType) << !FirstUnderlyingType.isNull(); |
1843 | 2 | DiagNote(SecondEnum, SingleSpecifiedType) << !SecondUnderlyingType.isNull(); |
1844 | 2 | return true; |
1845 | 2 | } |
1846 | | |
1847 | 7 | if (!FirstUnderlyingType.isNull() && !SecondUnderlyingType.isNull()1 ) { |
1848 | 1 | if (computeODRHash(FirstUnderlyingType) != |
1849 | 1 | computeODRHash(SecondUnderlyingType)) { |
1850 | 1 | DiagError(FirstEnum, DifferentSpecifiedTypes) << FirstUnderlyingType; |
1851 | 1 | DiagNote(SecondEnum, DifferentSpecifiedTypes) << SecondUnderlyingType; |
1852 | 1 | return true; |
1853 | 1 | } |
1854 | 1 | } |
1855 | | |
1856 | | // Compare enum constants. |
1857 | 6 | using DeclHashes = |
1858 | 6 | llvm::SmallVector<std::pair<const EnumConstantDecl *, unsigned>, 4>; |
1859 | 12 | auto PopulateHashes = [FirstEnum](DeclHashes &Hashes, const EnumDecl *Enum) { |
1860 | 16 | for (const Decl *D : Enum->decls()) { |
1861 | | // Due to decl merging, the first EnumDecl is the parent of |
1862 | | // Decls in both records. |
1863 | 16 | if (!ODRHash::isSubDeclToBeProcessed(D, FirstEnum)) |
1864 | 0 | continue; |
1865 | 16 | assert(isa<EnumConstantDecl>(D) && "Unexpected Decl kind"); |
1866 | 16 | Hashes.emplace_back(cast<EnumConstantDecl>(D), computeODRHash(D)); |
1867 | 16 | } |
1868 | 12 | }; |
1869 | 6 | DeclHashes FirstHashes; |
1870 | 6 | PopulateHashes(FirstHashes, FirstEnum); |
1871 | 6 | DeclHashes SecondHashes; |
1872 | 6 | PopulateHashes(SecondHashes, SecondEnum); |
1873 | | |
1874 | 6 | if (FirstHashes.size() != SecondHashes.size()) { |
1875 | 2 | DiagError(FirstEnum, DifferentNumberEnumConstants) |
1876 | 2 | << (int)FirstHashes.size(); |
1877 | 2 | DiagNote(SecondEnum, DifferentNumberEnumConstants) |
1878 | 2 | << (int)SecondHashes.size(); |
1879 | 2 | return true; |
1880 | 2 | } |
1881 | | |
1882 | 5 | for (unsigned I = 0, N = FirstHashes.size(); 4 I < N; ++I1 ) { |
1883 | 5 | if (FirstHashes[I].second == SecondHashes[I].second) |
1884 | 1 | continue; |
1885 | 4 | const EnumConstantDecl *FirstConstant = FirstHashes[I].first; |
1886 | 4 | const EnumConstantDecl *SecondConstant = SecondHashes[I].first; |
1887 | | |
1888 | 4 | if (FirstConstant->getDeclName() != SecondConstant->getDeclName()) { |
1889 | 1 | DiagError(FirstConstant, EnumConstantName) << I + 1 << FirstConstant; |
1890 | 1 | DiagNote(SecondConstant, EnumConstantName) << I + 1 << SecondConstant; |
1891 | 1 | return true; |
1892 | 1 | } |
1893 | | |
1894 | 3 | const Expr *FirstInit = FirstConstant->getInitExpr(); |
1895 | 3 | const Expr *SecondInit = SecondConstant->getInitExpr(); |
1896 | 3 | if (!FirstInit && !SecondInit1 ) |
1897 | 0 | continue; |
1898 | | |
1899 | 3 | if (!FirstInit || !SecondInit2 ) { |
1900 | 2 | DiagError(FirstConstant, EnumConstantSingleInitializer) |
1901 | 2 | << I + 1 << FirstConstant << (FirstInit != nullptr); |
1902 | 2 | DiagNote(SecondConstant, EnumConstantSingleInitializer) |
1903 | 2 | << I + 1 << SecondConstant << (SecondInit != nullptr); |
1904 | 2 | return true; |
1905 | 2 | } |
1906 | | |
1907 | 1 | if (computeODRHash(FirstInit) != computeODRHash(SecondInit)) { |
1908 | 1 | DiagError(FirstConstant, EnumConstantDifferentInitializer) |
1909 | 1 | << I + 1 << FirstConstant; |
1910 | 1 | DiagNote(SecondConstant, EnumConstantDifferentInitializer) |
1911 | 1 | << I + 1 << SecondConstant; |
1912 | 1 | return true; |
1913 | 1 | } |
1914 | 1 | } |
1915 | 0 | return false; |
1916 | 4 | } |
1917 | | |
1918 | | bool ODRDiagsEmitter::diagnoseMismatch( |
1919 | | const ObjCInterfaceDecl *FirstID, const ObjCInterfaceDecl *SecondID, |
1920 | 60 | const struct ObjCInterfaceDecl::DefinitionData *SecondDD) const { |
1921 | | // Multiple different declarations got merged together; tell the user |
1922 | | // where they came from. |
1923 | 60 | if (FirstID == SecondID) |
1924 | 0 | return false; |
1925 | | |
1926 | 60 | std::string FirstModule = getOwningModuleNameForDiagnostic(FirstID); |
1927 | 60 | std::string SecondModule = getOwningModuleNameForDiagnostic(SecondID); |
1928 | | |
1929 | | // Keep in sync with err_module_odr_violation_objc_interface. |
1930 | 60 | enum ODRInterfaceDifference { |
1931 | 60 | SuperClassType, |
1932 | 60 | IVarAccess, |
1933 | 60 | }; |
1934 | | |
1935 | 60 | auto DiagError = [FirstID, &FirstModule, |
1936 | 60 | this](SourceLocation Loc, SourceRange Range, |
1937 | 60 | ODRInterfaceDifference DiffType) { |
1938 | 11 | return Diag(Loc, diag::err_module_odr_violation_objc_interface) |
1939 | 11 | << FirstID << FirstModule.empty() << FirstModule << Range |
1940 | 11 | << DiffType; |
1941 | 11 | }; |
1942 | 60 | auto DiagNote = [&SecondModule, this](SourceLocation Loc, SourceRange Range, |
1943 | 60 | ODRInterfaceDifference DiffType) { |
1944 | 11 | return Diag(Loc, diag::note_module_odr_violation_objc_interface) |
1945 | 11 | << SecondModule.empty() << SecondModule << Range << DiffType; |
1946 | 11 | }; |
1947 | | |
1948 | 60 | const struct ObjCInterfaceDecl::DefinitionData *FirstDD = &FirstID->data(); |
1949 | 60 | assert(FirstDD && SecondDD && "Definitions without DefinitionData"); |
1950 | 60 | if (FirstDD != SecondDD) { |
1951 | | // Check for matching super class. |
1952 | 60 | auto GetSuperClassSourceRange = [](const TypeSourceInfo *SuperInfo, |
1953 | 60 | const ObjCInterfaceDecl *ID) { |
1954 | 14 | if (!SuperInfo) |
1955 | 5 | return ID->getSourceRange(); |
1956 | 9 | TypeLoc Loc = SuperInfo->getTypeLoc(); |
1957 | 9 | return SourceRange(Loc.getBeginLoc(), Loc.getEndLoc()); |
1958 | 14 | }; |
1959 | | |
1960 | 60 | ObjCInterfaceDecl *FirstSuperClass = FirstID->getSuperClass(); |
1961 | 60 | ObjCInterfaceDecl *SecondSuperClass = nullptr; |
1962 | 60 | const TypeSourceInfo *FirstSuperInfo = FirstID->getSuperClassTInfo(); |
1963 | 60 | const TypeSourceInfo *SecondSuperInfo = SecondDD->SuperClassTInfo; |
1964 | 60 | if (SecondSuperInfo) |
1965 | 58 | SecondSuperClass = |
1966 | 58 | SecondSuperInfo->getType()->castAs<ObjCObjectType>()->getInterface(); |
1967 | | |
1968 | 60 | if ((FirstSuperClass && SecondSuperClass57 && |
1969 | 60 | FirstSuperClass->getODRHash() != SecondSuperClass->getODRHash()55 ) || |
1970 | 60 | (58 FirstSuperClass58 && !SecondSuperClass55 ) || |
1971 | 60 | (56 !FirstSuperClass56 && SecondSuperClass3 )) { |
1972 | 7 | QualType FirstType; |
1973 | 7 | if (FirstSuperInfo) |
1974 | 4 | FirstType = FirstSuperInfo->getType(); |
1975 | | |
1976 | 7 | DiagError(FirstID->getLocation(), |
1977 | 7 | GetSuperClassSourceRange(FirstSuperInfo, FirstID), |
1978 | 7 | SuperClassType) |
1979 | 7 | << (bool)FirstSuperInfo << FirstType; |
1980 | | |
1981 | 7 | QualType SecondType; |
1982 | 7 | if (SecondSuperInfo) |
1983 | 5 | SecondType = SecondSuperInfo->getType(); |
1984 | | |
1985 | 7 | DiagNote(SecondID->getLocation(), |
1986 | 7 | GetSuperClassSourceRange(SecondSuperInfo, SecondID), |
1987 | 7 | SuperClassType) |
1988 | 7 | << (bool)SecondSuperInfo << SecondType; |
1989 | 7 | return true; |
1990 | 7 | } |
1991 | | |
1992 | | // Check both interfaces reference the same protocols. |
1993 | 53 | auto &FirstProtos = FirstID->getReferencedProtocols(); |
1994 | 53 | auto &SecondProtos = SecondDD->ReferencedProtocols; |
1995 | 53 | if (diagnoseSubMismatchProtocols(FirstProtos, FirstID, FirstModule, |
1996 | 53 | SecondProtos, SecondID, SecondModule)) |
1997 | 8 | return true; |
1998 | 53 | } |
1999 | | |
2000 | 45 | auto PopulateHashes = [](DeclHashes &Hashes, const ObjCInterfaceDecl *ID, |
2001 | 90 | const DeclContext *DC) { |
2002 | 151 | for (auto *D : ID->decls()) { |
2003 | 151 | if (!ODRHash::isSubDeclToBeProcessed(D, DC)) |
2004 | 60 | continue; |
2005 | 91 | Hashes.emplace_back(D, computeODRHash(D)); |
2006 | 91 | } |
2007 | 90 | }; |
2008 | | |
2009 | 45 | DeclHashes FirstHashes; |
2010 | 45 | DeclHashes SecondHashes; |
2011 | | // Use definition as DeclContext because definitions are merged when |
2012 | | // DeclContexts are merged and separate when DeclContexts are separate. |
2013 | 45 | PopulateHashes(FirstHashes, FirstID, FirstID->getDefinition()); |
2014 | 45 | PopulateHashes(SecondHashes, SecondID, SecondID->getDefinition()); |
2015 | | |
2016 | 45 | DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes); |
2017 | 45 | ODRMismatchDecl FirstDiffType = DR.FirstDiffType; |
2018 | 45 | ODRMismatchDecl SecondDiffType = DR.SecondDiffType; |
2019 | 45 | const Decl *FirstDecl = DR.FirstDecl; |
2020 | 45 | const Decl *SecondDecl = DR.SecondDecl; |
2021 | | |
2022 | 45 | if (FirstDiffType == Other || SecondDiffType == Other) { |
2023 | 0 | diagnoseSubMismatchUnexpected(DR, FirstID, FirstModule, SecondID, |
2024 | 0 | SecondModule); |
2025 | 0 | return true; |
2026 | 0 | } |
2027 | | |
2028 | 45 | if (FirstDiffType != SecondDiffType) { |
2029 | 11 | diagnoseSubMismatchDifferentDeclKinds(DR, FirstID, FirstModule, SecondID, |
2030 | 11 | SecondModule); |
2031 | 11 | return true; |
2032 | 11 | } |
2033 | | |
2034 | 34 | assert(FirstDiffType == SecondDiffType); |
2035 | 34 | switch (FirstDiffType) { |
2036 | | // Already handled. |
2037 | 0 | case EndOfClass: |
2038 | 0 | case Other: |
2039 | | // Cannot be contained by ObjCInterfaceDecl, invalid in this context. |
2040 | 0 | case Field: |
2041 | 0 | case TypeDef: |
2042 | 0 | case Var: |
2043 | | // C++ only, invalid in this context. |
2044 | 0 | case PublicSpecifer: |
2045 | 0 | case PrivateSpecifer: |
2046 | 0 | case ProtectedSpecifer: |
2047 | 0 | case StaticAssert: |
2048 | 0 | case CXXMethod: |
2049 | 0 | case TypeAlias: |
2050 | 0 | case Friend: |
2051 | 0 | case FunctionTemplate: |
2052 | 0 | llvm_unreachable("Invalid diff type"); |
2053 | |
|
2054 | 14 | case ObjCMethod: { |
2055 | 14 | if (diagnoseSubMismatchObjCMethod(FirstID, FirstModule, SecondModule, |
2056 | 14 | cast<ObjCMethodDecl>(FirstDecl), |
2057 | 14 | cast<ObjCMethodDecl>(SecondDecl))) |
2058 | 14 | return true; |
2059 | 0 | break; |
2060 | 14 | } |
2061 | 8 | case ObjCIvar: { |
2062 | 8 | if (diagnoseSubMismatchField(FirstID, FirstModule, SecondModule, |
2063 | 8 | cast<FieldDecl>(FirstDecl), |
2064 | 8 | cast<FieldDecl>(SecondDecl))) |
2065 | 4 | return true; |
2066 | | |
2067 | | // Check if the access match. |
2068 | 4 | const ObjCIvarDecl *FirstIvar = cast<ObjCIvarDecl>(FirstDecl); |
2069 | 4 | const ObjCIvarDecl *SecondIvar = cast<ObjCIvarDecl>(SecondDecl); |
2070 | 4 | if (FirstIvar->getCanonicalAccessControl() != |
2071 | 4 | SecondIvar->getCanonicalAccessControl()) { |
2072 | 4 | DiagError(FirstIvar->getLocation(), FirstIvar->getSourceRange(), |
2073 | 4 | IVarAccess) |
2074 | 4 | << FirstIvar->getName() |
2075 | 4 | << (int)FirstIvar->getCanonicalAccessControl(); |
2076 | 4 | DiagNote(SecondIvar->getLocation(), SecondIvar->getSourceRange(), |
2077 | 4 | IVarAccess) |
2078 | 4 | << SecondIvar->getName() |
2079 | 4 | << (int)SecondIvar->getCanonicalAccessControl(); |
2080 | 4 | return true; |
2081 | 4 | } |
2082 | 0 | break; |
2083 | 4 | } |
2084 | 12 | case ObjCProperty: { |
2085 | 12 | if (diagnoseSubMismatchObjCProperty(FirstID, FirstModule, SecondModule, |
2086 | 12 | cast<ObjCPropertyDecl>(FirstDecl), |
2087 | 12 | cast<ObjCPropertyDecl>(SecondDecl))) |
2088 | 12 | return true; |
2089 | 0 | break; |
2090 | 12 | } |
2091 | 34 | } |
2092 | | |
2093 | 0 | Diag(FirstDecl->getLocation(), |
2094 | 0 | diag::err_module_odr_violation_mismatch_decl_unknown) |
2095 | 0 | << FirstID << FirstModule.empty() << FirstModule << FirstDiffType |
2096 | 0 | << FirstDecl->getSourceRange(); |
2097 | 0 | Diag(SecondDecl->getLocation(), |
2098 | 0 | diag::note_module_odr_violation_mismatch_decl_unknown) |
2099 | 0 | << SecondModule << FirstDiffType << SecondDecl->getSourceRange(); |
2100 | 0 | return true; |
2101 | 34 | } |
2102 | | |
2103 | | bool ODRDiagsEmitter::diagnoseMismatch( |
2104 | | const ObjCProtocolDecl *FirstProtocol, |
2105 | | const ObjCProtocolDecl *SecondProtocol, |
2106 | 44 | const struct ObjCProtocolDecl::DefinitionData *SecondDD) const { |
2107 | 44 | if (FirstProtocol == SecondProtocol) |
2108 | 0 | return false; |
2109 | | |
2110 | 44 | std::string FirstModule = getOwningModuleNameForDiagnostic(FirstProtocol); |
2111 | 44 | std::string SecondModule = getOwningModuleNameForDiagnostic(SecondProtocol); |
2112 | | |
2113 | 44 | const ObjCProtocolDecl::DefinitionData *FirstDD = &FirstProtocol->data(); |
2114 | 44 | assert(FirstDD && SecondDD && "Definitions without DefinitionData"); |
2115 | | // Diagnostics from ObjCProtocol DefinitionData are emitted here. |
2116 | 44 | if (FirstDD != SecondDD) { |
2117 | | // Check both protocols reference the same protocols. |
2118 | 44 | const ObjCProtocolList &FirstProtocols = |
2119 | 44 | FirstProtocol->getReferencedProtocols(); |
2120 | 44 | const ObjCProtocolList &SecondProtocols = SecondDD->ReferencedProtocols; |
2121 | 44 | if (diagnoseSubMismatchProtocols(FirstProtocols, FirstProtocol, FirstModule, |
2122 | 44 | SecondProtocols, SecondProtocol, |
2123 | 44 | SecondModule)) |
2124 | 8 | return true; |
2125 | 44 | } |
2126 | | |
2127 | 36 | auto PopulateHashes = [](DeclHashes &Hashes, const ObjCProtocolDecl *ID, |
2128 | 72 | const DeclContext *DC) { |
2129 | 134 | for (const Decl *D : ID->decls()) { |
2130 | 134 | if (!ODRHash::isSubDeclToBeProcessed(D, DC)) |
2131 | 62 | continue; |
2132 | 72 | Hashes.emplace_back(D, computeODRHash(D)); |
2133 | 72 | } |
2134 | 72 | }; |
2135 | | |
2136 | 36 | DeclHashes FirstHashes; |
2137 | 36 | DeclHashes SecondHashes; |
2138 | | // Use definition as DeclContext because definitions are merged when |
2139 | | // DeclContexts are merged and separate when DeclContexts are separate. |
2140 | 36 | PopulateHashes(FirstHashes, FirstProtocol, FirstProtocol->getDefinition()); |
2141 | 36 | PopulateHashes(SecondHashes, SecondProtocol, SecondProtocol->getDefinition()); |
2142 | | |
2143 | 36 | DiffResult DR = FindTypeDiffs(FirstHashes, SecondHashes); |
2144 | 36 | ODRMismatchDecl FirstDiffType = DR.FirstDiffType; |
2145 | 36 | ODRMismatchDecl SecondDiffType = DR.SecondDiffType; |
2146 | 36 | const Decl *FirstDecl = DR.FirstDecl; |
2147 | 36 | const Decl *SecondDecl = DR.SecondDecl; |
2148 | | |
2149 | 36 | if (FirstDiffType == Other || SecondDiffType == Other) { |
2150 | 0 | diagnoseSubMismatchUnexpected(DR, FirstProtocol, FirstModule, |
2151 | 0 | SecondProtocol, SecondModule); |
2152 | 0 | return true; |
2153 | 0 | } |
2154 | | |
2155 | 36 | if (FirstDiffType != SecondDiffType) { |
2156 | 8 | diagnoseSubMismatchDifferentDeclKinds(DR, FirstProtocol, FirstModule, |
2157 | 8 | SecondProtocol, SecondModule); |
2158 | 8 | return true; |
2159 | 8 | } |
2160 | | |
2161 | 28 | assert(FirstDiffType == SecondDiffType); |
2162 | 28 | switch (FirstDiffType) { |
2163 | | // Already handled. |
2164 | 0 | case EndOfClass: |
2165 | 0 | case Other: |
2166 | | // Cannot be contained by ObjCProtocolDecl, invalid in this context. |
2167 | 0 | case Field: |
2168 | 0 | case TypeDef: |
2169 | 0 | case Var: |
2170 | 0 | case ObjCIvar: |
2171 | | // C++ only, invalid in this context. |
2172 | 0 | case PublicSpecifer: |
2173 | 0 | case PrivateSpecifer: |
2174 | 0 | case ProtectedSpecifer: |
2175 | 0 | case StaticAssert: |
2176 | 0 | case CXXMethod: |
2177 | 0 | case TypeAlias: |
2178 | 0 | case Friend: |
2179 | 0 | case FunctionTemplate: |
2180 | 0 | llvm_unreachable("Invalid diff type"); |
2181 | 16 | case ObjCMethod: { |
2182 | 16 | if (diagnoseSubMismatchObjCMethod(FirstProtocol, FirstModule, SecondModule, |
2183 | 16 | cast<ObjCMethodDecl>(FirstDecl), |
2184 | 16 | cast<ObjCMethodDecl>(SecondDecl))) |
2185 | 16 | return true; |
2186 | 0 | break; |
2187 | 16 | } |
2188 | 12 | case ObjCProperty: { |
2189 | 12 | if (diagnoseSubMismatchObjCProperty(FirstProtocol, FirstModule, |
2190 | 12 | SecondModule, |
2191 | 12 | cast<ObjCPropertyDecl>(FirstDecl), |
2192 | 12 | cast<ObjCPropertyDecl>(SecondDecl))) |
2193 | 12 | return true; |
2194 | 0 | break; |
2195 | 12 | } |
2196 | 28 | } |
2197 | | |
2198 | 0 | Diag(FirstDecl->getLocation(), |
2199 | 0 | diag::err_module_odr_violation_mismatch_decl_unknown) |
2200 | 0 | << FirstProtocol << FirstModule.empty() << FirstModule << FirstDiffType |
2201 | 0 | << FirstDecl->getSourceRange(); |
2202 | 0 | Diag(SecondDecl->getLocation(), |
2203 | 0 | diag::note_module_odr_violation_mismatch_decl_unknown) |
2204 | 0 | << SecondModule.empty() << SecondModule << FirstDiffType |
2205 | 0 | << SecondDecl->getSourceRange(); |
2206 | 0 | return true; |
2207 | 28 | } |