[ODRHash] Finish FieldDecl support by handling mutable and initializers.

https://reviews.llvm.org/rL296170

llvm-svn: 296198
This commit is contained in:
Richard Trieu 2017-02-24 23:35:37 +00:00
parent 0d67b10a3c
commit 8d543e2741
4 changed files with 109 additions and 3 deletions

View File

@ -136,7 +136,10 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
"field %4|"
"field %4 with type %5|"
"%select{non-|}5bitfield %4|"
"bitfield %4 with one width expression}3">;
"bitfield %4 with one width expression|"
"%select{non-|}5mutable field %4|"
"field %4 with %select{no|an}5 initalizer|"
"field %4 with an initializer}3">;
def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"%select{"
@ -146,7 +149,10 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"field %2|"
"field %2 with type %3|"
"%select{non-|}3bitfield %2|"
"bitfield %2 with different width expression}1">;
"bitfield %2 with different width expression|"
"%select{non-|}3mutable field %2|"
"field %2 with %select{no|an}3 initializer|"
"field %2 with a different initializer}1">;
def warn_module_uses_date_time : Warning<
"%select{precompiled header|module}0 uses __DATE__ or __TIME__">,

View File

@ -190,6 +190,9 @@ public:
if (IsBitfield) {
AddStmt(D->getBitWidth());
}
Hash.AddBoolean(D->isMutable());
AddStmt(D->getInClassInitializer());
}
};

View File

@ -9064,7 +9064,10 @@ void ASTReader::diagnoseOdrViolations() {
FieldName,
FieldTypeName,
FieldSingleBitField,
FieldDifferentWidthBitField
FieldDifferentWidthBitField,
FieldSingleMutable,
FieldSingleInitializer,
FieldDifferentInitializers,
};
// These lambdas have the common portions of the ODR diagnostics. This
@ -9239,6 +9242,50 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
const bool IsFirstMutable = FirstField->isMutable();
const bool IsSecondMutable = SecondField->isMutable();
if (IsFirstMutable != IsSecondMutable) {
ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(),
FieldSingleMutable)
<< FirstII << IsFirstMutable;
ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(),
FieldSingleMutable)
<< SecondII << IsSecondMutable;
Diagnosed = true;
break;
}
const Expr *FirstInitializer = FirstField->getInClassInitializer();
const Expr *SecondInitializer = SecondField->getInClassInitializer();
if ((!FirstInitializer && SecondInitializer) ||
(FirstInitializer && !SecondInitializer)) {
ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(),
FieldSingleInitializer)
<< FirstII << (FirstInitializer != nullptr);
ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(),
FieldSingleInitializer)
<< SecondII << (SecondInitializer != nullptr);
Diagnosed = true;
break;
}
if (FirstInitializer && SecondInitializer) {
unsigned FirstInitHash = ComputeODRHash(FirstInitializer);
unsigned SecondInitHash = ComputeODRHash(SecondInitializer);
if (FirstInitHash != SecondInitHash) {
ODRDiagError(FirstField->getLocation(),
FirstField->getSourceRange(),
FieldDifferentInitializers)
<< FirstII << FirstInitializer->getSourceRange();
ODRDiagNote(SecondField->getLocation(),
SecondField->getSourceRange(),
FieldDifferentInitializers)
<< SecondII << SecondInitializer->getSourceRange();
Diagnosed = true;
break;
}
}
break;
}
}

View File

@ -233,6 +233,48 @@ S8 s8;
// expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}}
#endif
#if defined(FIRST)
struct S9 {
mutable int x;
};
#elif defined(SECOND)
struct S9 {
int x;
};
#else
S9 s9;
// expected-error@second.h:* {{'Field::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found non-mutable field 'x'}}
// expected-note@first.h:* {{but in 'FirstModule' found mutable field 'x'}}
#endif
#if defined(FIRST)
struct S10 {
unsigned x = 5;
};
#elif defined(SECOND)
struct S10 {
unsigned x;
};
#else
S10 s10;
// expected-error@second.h:* {{'Field::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with no initalizer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with an initializer}}
#endif
#if defined(FIRST)
struct S11 {
unsigned x = 5;
};
#elif defined(SECOND)
struct S11 {
unsigned x = 7;
};
#else
S11 s11;
// expected-error@second.h:* {{'Field::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'x' with an initializer}}
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with a different initializer}}
#endif
} // namespace Field
// Naive parsing of AST can lead to cycles in processing. Ensure
@ -280,6 +322,8 @@ struct S {
unsigned a : 1;
unsigned b : 2*2 + 5/2;
mutable int c = sizeof(x + y);
};
#elif defined(SECOND)
typedef int INT;
@ -298,6 +342,8 @@ struct S {
unsigned a : 1;
unsigned b : 2 * 2 + 5 / 2;
mutable int c = sizeof(x + y);
};
#else
S s;
@ -321,6 +367,8 @@ struct T {
unsigned a : 1;
unsigned b : 2 * 2 + 5 / 2;
mutable int c = sizeof(x + y);
private:
};
#elif defined(SECOND)
@ -341,6 +389,8 @@ struct T {
unsigned a : 1;
unsigned b : 2 * 2 + 5 / 2;
mutable int c = sizeof(x + y);
public:
};
#else