[ODRHash] Add basic support for CXXRecordDecl

llvm-svn: 296521
This commit is contained in:
Richard Trieu 2017-02-28 21:24:38 +00:00
parent 4d263f6f18
commit 48143749f8
4 changed files with 79 additions and 4 deletions
clang
include/clang/Basic
lib
AST
Serialization
test/Modules

View File

@ -121,10 +121,10 @@ def err_module_odr_violation_mismatch_decl : Error<
"%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|field}3">;
"protected access specifier|static assert|field|method}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|field}1">;
"protected access specifier|static assert|field|method}1">;
def err_module_odr_violation_mismatch_decl_diff : Error<
"%q0 has different definitions in different modules; first difference is "
@ -139,7 +139,8 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
"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">;
"field %4 with an initializer|"
"method %4}3">;
def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"%select{"
@ -152,7 +153,8 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"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">;
"field %2 with a different initializer|"
"method %2}1">;
def warn_module_uses_date_time : Warning<
"%select{precompiled header|module}0 uses __DATE__ or __TIME__">,

View File

@ -194,6 +194,14 @@ public:
Inherited::VisitFieldDecl(D);
}
void VisitFunctionDecl(const FunctionDecl *D) {
Inherited::VisitFunctionDecl(D);
}
void VisitCXXMethodDecl(const CXXMethodDecl *D) {
Inherited::VisitCXXMethodDecl(D);
}
};
// Only allow a small portion of Decl's to be processed. Remove this once
@ -206,6 +214,7 @@ bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
default:
return false;
case Decl::AccessSpec:
case Decl::CXXMethod:
case Decl::Field:
case Decl::StaticAssert:
return true;

View File

@ -8957,6 +8957,7 @@ void ASTReader::diagnoseOdrViolations() {
ProtectedSpecifer,
StaticAssert,
Field,
CXXMethod,
Other
} FirstDiffType = Other,
SecondDiffType = Other;
@ -8982,6 +8983,8 @@ void ASTReader::diagnoseOdrViolations() {
return StaticAssert;
case Decl::Field:
return Field;
case Decl::CXXMethod:
return CXXMethod;
}
};
@ -9068,6 +9071,7 @@ void ASTReader::diagnoseOdrViolations() {
FieldSingleMutable,
FieldSingleInitializer,
FieldDifferentInitializers,
MethodName,
};
// These lambdas have the common portions of the ODR diagnostics. This
@ -9288,6 +9292,25 @@ void ASTReader::diagnoseOdrViolations() {
break;
}
case CXXMethod: {
const CXXMethodDecl *FirstMethod = cast<CXXMethodDecl>(FirstDecl);
const CXXMethodDecl *SecondMethod = cast<CXXMethodDecl>(SecondDecl);
IdentifierInfo *FirstII = FirstMethod->getIdentifier();
IdentifierInfo *SecondII = SecondMethod->getIdentifier();
if (FirstII->getName() != SecondII->getName()) {
ODRDiagError(FirstMethod->getLocation(),
FirstMethod->getSourceRange(), MethodName)
<< FirstII;
ODRDiagNote(SecondMethod->getLocation(),
SecondMethod->getSourceRange(), MethodName)
<< SecondII;
Diagnosed = true;
break;
}
break;
}
}
if (Diagnosed == true)

View File

@ -277,6 +277,39 @@ S11 s11;
} // namespace Field
namespace Method {
#if defined(FIRST)
struct S1 {
void A() {}
};
#elif defined(SECOND)
struct S1 {
private:
void A() {}
};
#else
S1 s1;
// expected-error@second.h:* {{'Method::S1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}}
// expected-note@first.h:* {{but in 'FirstModule' found method}}
#endif
#if defined(FIRST)
struct S2 {
void A() {}
void B() {}
};
#elif defined(SECOND)
struct S2 {
void B() {}
void A() {}
};
#else
S2 s2;
// expected-error@second.h:* {{'Method::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'B'}}
// expected-note@first.h:* {{but in 'FirstModule' found method 'A'}}
#endif
} // namespace Method
// 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 {
@ -324,6 +357,8 @@ struct S {
unsigned b : 2*2 + 5/2;
mutable int c = sizeof(x + y);
void method() {}
};
#elif defined(SECOND)
typedef int INT;
@ -344,6 +379,8 @@ struct S {
unsigned b : 2 * 2 + 5 / 2;
mutable int c = sizeof(x + y);
void method() {}
};
#else
S s;
@ -369,6 +406,8 @@ struct T {
mutable int c = sizeof(x + y);
void method() {}
private:
};
#elif defined(SECOND)
@ -391,6 +430,8 @@ struct T {
mutable int c = sizeof(x + y);
void method() {}
public:
};
#else