Skip to content

Commit

Permalink
[ODRHash] Add handling of bitfields
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D21675

llvm-svn: 296170
  • Loading branch information
Weverything committed Feb 24, 2017
1 parent 68ea9aa commit 93772fc
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 2 deletions.
10 changes: 8 additions & 2 deletions clang/include/clang/Basic/DiagnosticSerializationKinds.td
Expand Up @@ -133,14 +133,20 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
"static assert with condition|"
"static assert with message|"
"static assert with %select{|no }4message|"
"field %4|field %4 with type %5}3">;
"field %4|"
"field %4 with type %5|"
"%select{non-|}5bitfield %4|"
"bitfield %4 with one width expression}3">;

def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"%select{"
"static assert with different condition|"
"static assert with different message|"
"static assert with %select{|no }2message|"
"field %2|field %2 with type %3}1">;
"field %2|"
"field %2 with type %3|"
"%select{non-|}3bitfield %2|"
"bitfield %2 with different width expression}1">;

def warn_module_uses_date_time : Warning<
"%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/ODRHash.cpp
Expand Up @@ -183,6 +183,13 @@ class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {

void VisitFieldDecl(const FieldDecl *D) {
Inherited::VisitFieldDecl(D);

const bool IsBitfield = D->isBitField();
Hash.AddBoolean(IsBitfield);

if (IsBitfield) {
AddStmt(D->getBitWidth());
}
}
};

Expand Down
26 changes: 26 additions & 0 deletions clang/lib/Serialization/ASTReader.cpp
Expand Up @@ -9063,6 +9063,8 @@ void ASTReader::diagnoseOdrViolations() {
StaticAssertOnlyMessage,
FieldName,
FieldTypeName,
FieldSingleBitField,
FieldDifferentWidthBitField
};

// These lambdas have the common portions of the ODR diagnostics. This
Expand Down Expand Up @@ -9213,6 +9215,30 @@ void ASTReader::diagnoseOdrViolations() {
}
}

const bool IsFirstBitField = FirstField->isBitField();
const bool IsSecondBitField = SecondField->isBitField();
if (IsFirstBitField != IsSecondBitField) {
ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(),
FieldSingleBitField)
<< FirstII << IsFirstBitField;
ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(),
FieldSingleBitField)
<< SecondII << IsSecondBitField;
Diagnosed = true;
break;
}

if (IsFirstBitField && IsSecondBitField) {
ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(),
FieldDifferentWidthBitField)
<< FirstII << FirstField->getBitWidth()->getSourceRange();
ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(),
FieldDifferentWidthBitField)
<< SecondII << SecondField->getBitWidth()->getSourceRange();
Diagnosed = true;
break;
}

break;
}
}
Expand Down
53 changes: 53 additions & 0 deletions clang/test/Modules/odr_hash.cpp
Expand Up @@ -191,6 +191,47 @@ S5 s5;
// expected-note@first.h:* {{but in 'FirstModule' found field 'x' with type 'A' (aka 'int')}}
#endif

#if defined(FIRST)
struct S6 {
unsigned x;
};
#elif defined(SECOND)
struct S6 {
unsigned x : 1;
};
#else
S6 s6;
// expected-error@second.h:* {{'Field::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x'}}
// expected-note@first.h:* {{but in 'FirstModule' found non-bitfield 'x'}}
#endif

#if defined(FIRST)
struct S7 {
unsigned x : 2;
};
#elif defined(SECOND)
struct S7 {
unsigned x : 1;
};
#else
S7 s7;
// expected-error@second.h:* {{'Field::S7' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x' with one width expression}}
// expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}}
#endif

#if defined(FIRST)
struct S8 {
unsigned x : 2;
};
#elif defined(SECOND)
struct S8 {
unsigned x : 1 + 1;
};
#else
S8 s8;
// expected-error@second.h:* {{'Field::S8' has different definitions in different modules; first difference is definition in module 'SecondModule' found bitfield 'x' with one width expression}}
// expected-note@first.h:* {{but in 'FirstModule' found bitfield 'x' with different width expression}}
#endif

} // namespace Field

Expand Down Expand Up @@ -236,6 +277,9 @@ struct S {
double y;

INT z;

unsigned a : 1;
unsigned b : 2*2 + 5/2;
};
#elif defined(SECOND)
typedef int INT;
Expand All @@ -251,6 +295,9 @@ struct S {
double y;

INT z;

unsigned a : 1;
unsigned b : 2 * 2 + 5 / 2;
};
#else
S s;
Expand All @@ -271,6 +318,9 @@ struct T {

INT z;

unsigned a : 1;
unsigned b : 2 * 2 + 5 / 2;

private:
};
#elif defined(SECOND)
Expand All @@ -288,6 +338,9 @@ struct T {

INT z;

unsigned a : 1;
unsigned b : 2 * 2 + 5 / 2;

public:
};
#else
Expand Down

0 comments on commit 93772fc

Please sign in to comment.