Skip to content

Commit 0255227

Browse files
committed
[ODRHash] Add support for array and decayed types, and parameter names and types.
llvm-svn: 301989
1 parent d919115 commit 0255227

File tree

4 files changed

+346
-33
lines changed

4 files changed

+346
-33
lines changed

clang/include/clang/Basic/DiagnosticSerializationKinds.td

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
146146
"method %4 is %select{not static|static}5|"
147147
"method %4 is %select{not volatile|volatile}5|"
148148
"method %4 is %select{not const|const}5|"
149-
"method %4 is %select{not inline|inline}5}3">;
149+
"method %4 is %select{not inline|inline}5|"
150+
"method %4 that has %5 parameter%s5|"
151+
"method %4 with %ordinal5 parameter of type %6%select{| decayed from %8}7|"
152+
"method %4 with %ordinal5 parameter named %6}3">;
150153

151154
def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
152155
"%select{"
@@ -166,7 +169,10 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
166169
"method %2 is %select{not static|static}3|"
167170
"method %2 is %select{not volatile|volatile}3|"
168171
"method %2 is %select{not const|const}3|"
169-
"method %2 is %select{not inline|inline}3}1">;
172+
"method %2 is %select{not inline|inline}3|"
173+
"method %2 that has %3 parameter%s3|"
174+
"method %2 with %ordinal3 parameter of type %4%select{| decayed from %6}5|"
175+
"method %2 with %ordinal3 parameter named %4}1">;
170176

171177
def warn_module_uses_date_time : Warning<
172178
"%select{precompiled header|module}0 uses __DATE__ or __TIME__">,

clang/lib/AST/ODRHash.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,11 @@ class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {
169169
Inherited::VisitValueDecl(D);
170170
}
171171

172+
void VisitParmVarDecl(const ParmVarDecl *D) {
173+
// TODO: Handle default arguments.
174+
Inherited::VisitParmVarDecl(D);
175+
}
176+
172177
void VisitAccessSpecDecl(const AccessSpecDecl *D) {
173178
ID.AddInteger(D->getAccess());
174179
Inherited::VisitAccessSpecDecl(D);
@@ -202,6 +207,12 @@ class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {
202207
Hash.AddBoolean(D->isPure());
203208
Hash.AddBoolean(D->isDeletedAsWritten());
204209

210+
ID.AddInteger(D->param_size());
211+
212+
for (auto *Param : D->parameters()) {
213+
Hash.AddSubDecl(Param);
214+
}
215+
205216
Inherited::VisitFunctionDecl(D);
206217
}
207218

@@ -256,6 +267,11 @@ void ODRHash::AddSubDecl(const Decl *D) {
256267
void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
257268
assert(Record && Record->hasDefinition() &&
258269
"Expected non-null record to be a definition.");
270+
271+
if (isa<ClassTemplateSpecializationDecl>(Record)) {
272+
return;
273+
}
274+
259275
AddDecl(Record);
260276

261277
// Filter out sub-Decls which will not be processed in order to get an
@@ -315,18 +331,84 @@ class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
315331
}
316332
}
317333

334+
void AddQualType(QualType T) {
335+
Hash.AddQualType(T);
336+
}
337+
338+
void VisitQualifiers(Qualifiers Quals) {
339+
ID.AddInteger(Quals.getAsOpaqueValue());
340+
}
341+
318342
void Visit(const Type *T) {
319343
ID.AddInteger(T->getTypeClass());
320344
Inherited::Visit(T);
321345
}
322346

323347
void VisitType(const Type *T) {}
324348

349+
void VisitAdjustedType(const AdjustedType *T) {
350+
AddQualType(T->getOriginalType());
351+
AddQualType(T->getAdjustedType());
352+
VisitType(T);
353+
}
354+
355+
void VisitDecayedType(const DecayedType *T) {
356+
AddQualType(T->getDecayedType());
357+
AddQualType(T->getPointeeType());
358+
VisitAdjustedType(T);
359+
}
360+
361+
void VisitArrayType(const ArrayType *T) {
362+
AddQualType(T->getElementType());
363+
ID.AddInteger(T->getSizeModifier());
364+
VisitQualifiers(T->getIndexTypeQualifiers());
365+
VisitType(T);
366+
}
367+
void VisitConstantArrayType(const ConstantArrayType *T) {
368+
T->getSize().Profile(ID);
369+
VisitArrayType(T);
370+
}
371+
372+
void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
373+
AddStmt(T->getSizeExpr());
374+
VisitArrayType(T);
375+
}
376+
377+
void VisitIncompleteArrayType(const IncompleteArrayType *T) {
378+
VisitArrayType(T);
379+
}
380+
381+
void VisitVariableArrayType(const VariableArrayType *T) {
382+
AddStmt(T->getSizeExpr());
383+
VisitArrayType(T);
384+
}
385+
325386
void VisitBuiltinType(const BuiltinType *T) {
326387
ID.AddInteger(T->getKind());
327388
VisitType(T);
328389
}
329390

391+
void VisitFunctionType(const FunctionType *T) {
392+
AddQualType(T->getReturnType());
393+
T->getExtInfo().Profile(ID);
394+
Hash.AddBoolean(T->isConst());
395+
Hash.AddBoolean(T->isVolatile());
396+
Hash.AddBoolean(T->isRestrict());
397+
VisitType(T);
398+
}
399+
400+
void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
401+
VisitFunctionType(T);
402+
}
403+
404+
void VisitFunctionProtoType(const FunctionProtoType *T) {
405+
ID.AddInteger(T->getNumParams());
406+
for (auto ParamType : T->getParamTypes())
407+
AddQualType(ParamType);
408+
409+
VisitFunctionType(T);
410+
}
411+
330412
void VisitTypedefType(const TypedefType *T) {
331413
AddDecl(T->getDecl());
332414
Hash.AddQualType(T->getDecl()->getUnderlyingType());

clang/lib/Serialization/ASTReader.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9316,6 +9316,9 @@ void ASTReader::diagnoseOdrViolations() {
93169316
MethodVolatile,
93179317
MethodConst,
93189318
MethodInline,
9319+
MethodNumberParameters,
9320+
MethodParameterType,
9321+
MethodParameterName,
93199322
};
93209323

93219324
// These lambdas have the common portions of the ODR diagnostics. This
@@ -9346,6 +9349,12 @@ void ASTReader::diagnoseOdrViolations() {
93469349
return Hash.CalculateHash();
93479350
};
93489351

9352+
auto ComputeQualTypeODRHash = [&Hash](QualType Ty) {
9353+
Hash.clear();
9354+
Hash.AddQualType(Ty);
9355+
return Hash.CalculateHash();
9356+
};
9357+
93499358
switch (FirstDiffType) {
93509359
case Other:
93519360
case EndOfClass:
@@ -9640,6 +9649,76 @@ void ASTReader::diagnoseOdrViolations() {
96409649
break;
96419650
}
96429651

9652+
const unsigned FirstNumParameters = FirstMethod->param_size();
9653+
const unsigned SecondNumParameters = SecondMethod->param_size();
9654+
if (FirstNumParameters != SecondNumParameters) {
9655+
ODRDiagError(FirstMethod->getLocation(),
9656+
FirstMethod->getSourceRange(), MethodNumberParameters)
9657+
<< FirstName << FirstNumParameters;
9658+
ODRDiagNote(SecondMethod->getLocation(),
9659+
SecondMethod->getSourceRange(), MethodNumberParameters)
9660+
<< SecondName << SecondNumParameters;
9661+
Diagnosed = true;
9662+
break;
9663+
}
9664+
9665+
// Need this status boolean to know when break out of the switch.
9666+
bool ParameterMismatch = false;
9667+
for (unsigned I = 0; I < FirstNumParameters; ++I) {
9668+
const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);
9669+
const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);
9670+
9671+
QualType FirstParamType = FirstParam->getType();
9672+
QualType SecondParamType = SecondParam->getType();
9673+
if (FirstParamType != SecondParamType &&
9674+
ComputeQualTypeODRHash(FirstParamType) !=
9675+
ComputeQualTypeODRHash(SecondParamType)) {
9676+
if (const DecayedType *ParamDecayedType =
9677+
FirstParamType->getAs<DecayedType>()) {
9678+
ODRDiagError(FirstMethod->getLocation(),
9679+
FirstMethod->getSourceRange(), MethodParameterType)
9680+
<< FirstName << (I + 1) << FirstParamType << true
9681+
<< ParamDecayedType->getOriginalType();
9682+
} else {
9683+
ODRDiagError(FirstMethod->getLocation(),
9684+
FirstMethod->getSourceRange(), MethodParameterType)
9685+
<< FirstName << (I + 1) << FirstParamType << false;
9686+
}
9687+
9688+
if (const DecayedType *ParamDecayedType =
9689+
SecondParamType->getAs<DecayedType>()) {
9690+
ODRDiagNote(SecondMethod->getLocation(),
9691+
SecondMethod->getSourceRange(), MethodParameterType)
9692+
<< SecondName << (I + 1) << SecondParamType << true
9693+
<< ParamDecayedType->getOriginalType();
9694+
} else {
9695+
ODRDiagNote(SecondMethod->getLocation(),
9696+
SecondMethod->getSourceRange(), MethodParameterType)
9697+
<< SecondName << (I + 1) << SecondParamType << false;
9698+
}
9699+
ParameterMismatch = true;
9700+
break;
9701+
}
9702+
9703+
DeclarationName FirstParamName = FirstParam->getDeclName();
9704+
DeclarationName SecondParamName = SecondParam->getDeclName();
9705+
if (FirstParamName != SecondParamName) {
9706+
ODRDiagError(FirstMethod->getLocation(),
9707+
FirstMethod->getSourceRange(), MethodParameterName)
9708+
<< FirstName << (I + 1) << FirstParamName;
9709+
ODRDiagNote(SecondMethod->getLocation(),
9710+
SecondMethod->getSourceRange(), MethodParameterName)
9711+
<< SecondName << (I + 1) << SecondParamName;
9712+
ParameterMismatch = true;
9713+
break;
9714+
}
9715+
}
9716+
9717+
if (ParameterMismatch) {
9718+
Diagnosed = true;
9719+
break;
9720+
}
9721+
96439722
break;
96449723
}
96459724
}

0 commit comments

Comments
 (0)