"%q0 has different definitions in different modules; first difference is "
"%select{definition in module '%2'|defined here}1 found "
"%select{end of class|public access specifier|private access specifier|"
- "protected access specifier|static assert}3">;
+ "protected access specifier|static assert|field}3">;
def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found "
"%select{end of class|public access specifier|private access specifier|"
- "protected access specifier|static assert}1">;
+ "protected access specifier|static assert|field}1">;
def err_module_odr_violation_mismatch_decl_diff : Error<
"%q0 has different definitions in different modules; first difference is "
"%select{"
"static assert with condition|"
"static assert with message|"
- "static assert with %select{|no }4message}3">;
+ "static assert with %select{|no }4message|"
+ "field %4}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}1">;
+ "static assert with %select{|no }2message|"
+ "field %2}1">;
def warn_module_uses_date_time : Warning<
"%select{precompiled header|module}0 uses __DATE__ or __TIME__">,
assert(S && "Expecting non-null pointer.");
S->ProcessODRHash(ID, *this);
}
-void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {}
+
+void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
+ assert(II && "Expecting non-null pointer.");
+ ID.AddString(II->getName());
+}
+
void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {}
void ODRHash::AddTemplateName(TemplateName Name) {}
void ODRHash::AddDeclarationName(DeclarationName Name) {}
}
}
+ void AddIdentifierInfo(const IdentifierInfo *II) {
+ Hash.AddBoolean(II);
+ if (II) {
+ Hash.AddIdentifierInfo(II);
+ }
+ }
+
void Visit(const Decl *D) {
ID.AddInteger(D->getKind());
Inherited::Visit(D);
}
+ void VisitNamedDecl(const NamedDecl *D) {
+ AddIdentifierInfo(D->getIdentifier());
+ Inherited::VisitNamedDecl(D);
+ }
+
void VisitAccessSpecDecl(const AccessSpecDecl *D) {
ID.AddInteger(D->getAccess());
Inherited::VisitAccessSpecDecl(D);
Inherited::VisitStaticAssertDecl(D);
}
+
+ void VisitFieldDecl(const FieldDecl *D) {
+ Inherited::VisitFieldDecl(D);
+ }
};
// Only allow a small portion of Decl's to be processed. Remove this once
default:
return false;
case Decl::AccessSpec:
+ case Decl::Field:
case Decl::StaticAssert:
return true;
}
PrivateSpecifer,
ProtectedSpecifer,
StaticAssert,
+ Field,
Other
} FirstDiffType = Other,
SecondDiffType = Other;
llvm_unreachable("Invalid access specifier");
case Decl::StaticAssert:
return StaticAssert;
+ case Decl::Field:
+ return Field;
}
};
StaticAssertCondition,
StaticAssertMessage,
StaticAssertOnlyMessage,
+ FieldName,
};
// These lambdas have the common portions of the ODR diagnostics. This
}
break;
}
+ case Field: {
+ FieldDecl *FirstField = cast<FieldDecl>(FirstDecl);
+ FieldDecl *SecondField = cast<FieldDecl>(SecondDecl);
+ IdentifierInfo *FirstII = FirstField->getIdentifier();
+ IdentifierInfo *SecondII = SecondField->getIdentifier();
+ if (FirstII->getName() != SecondII->getName()) {
+ ODRDiagError(FirstField->getLocation(), FirstField->getSourceRange(),
+ FieldName)
+ << FirstII;
+ ODRDiagNote(SecondField->getLocation(), SecondField->getSourceRange(),
+ FieldName)
+ << SecondII;
+
+ Diagnosed = true;
+ break;
+ }
+ break;
+ }
}
if (Diagnosed == true)
#endif
}
+namespace Field {
+#if defined(FIRST)
+struct S1 {
+ int x;
+ private:
+ int y;
+};
+#elif defined(SECOND)
+struct S1 {
+ int x;
+ int y;
+};
+#else
+S1 s1;
+// expected-error@second.h:* {{'Field::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
+// expected-note@first.h:* {{but in 'FirstModule' found private access specifier}}
+#endif
+
+#if defined(FIRST)
+struct S2 {
+ int x;
+ int y;
+};
+#elif defined(SECOND)
+struct S2 {
+ int y;
+ int x;
+};
+#else
+S2 s2;
+// expected-error@second.h:* {{'Field::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found field 'y'}}
+// expected-note@first.h:* {{but in 'FirstModule' found field 'x'}}
+#endif
+} // namespace Field
+
// Naive parsing of AST can lead to cycles in processing. Ensure
// self-references don't trigger an endless cycles of AST node processing.
namespace SelfReference {
static_assert(1 == 1, "Message");
static_assert(2 == 2);
+
+ int x;
+ double y;
};
#elif defined(SECOND)
struct S {
static_assert(1 == 1, "Message");
static_assert(2 == 2);
+
+ int x;
+ double y;
};
#else
S s;
static_assert(1 == 1, "Message");
static_assert(2 == 2);
+ int x;
+ double y;
+
private:
};
#elif defined(SECOND)
static_assert(1 == 1, "Message");
static_assert(2 == 2);
+ int x;
+ double y;
+
public:
};
#else