Skip to content

Commit

Permalink
[ODRHash] Add diagnostic messages for typedef and type alias.
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@305238 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Weverything committed Jun 12, 2017
1 parent 7021b25 commit 7b936e3
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 5 deletions.
16 changes: 11 additions & 5 deletions include/clang/Basic/DiagnosticSerializationKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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|method}3">;
"protected access specifier|static assert|field|method|type alias|typedef}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|method}1">;
"protected access specifier|static assert|field|method|type alias|typedef}1">;

def err_module_odr_violation_mismatch_decl_diff : Error<
"%q0 has different definitions in different modules; first difference is "
Expand All @@ -149,7 +149,9 @@ def err_module_odr_violation_mismatch_decl_diff : Error<
"method %4 is %select{not inline|inline}5|"
"method %4 that has %5 parameter%s5|"
"method %4 with %ordinal5 parameter of type %6%select{| decayed from %8}7|"
"method %4 with %ordinal5 parameter named %6}3">;
"method %4 with %ordinal5 parameter named %6|"
"%select{typedef|type alias}4 name %5|"
"%select{typedef|type alias}4 %5 with underlying type %6}3">;

def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"%select{"
Expand All @@ -172,15 +174,19 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found "
"method %2 is %select{not inline|inline}3|"
"method %2 that has %3 parameter%s3|"
"method %2 with %ordinal3 parameter of type %4%select{| decayed from %6}5|"
"method %2 with %ordinal3 parameter named %4}1">;
"method %2 with %ordinal3 parameter named %4|"
"%select{typedef|type alias}2 name %3|"
"%select{typedef|type alias}2 %3 with different underlying type %4}1">;

def err_module_odr_violation_mismatch_decl_unknown : Error<
"%q0 %select{with definition in module '%2'|defined here}1 has different "
"definitions in different modules; first difference is this "
"%select{||||static assert|field|method|unexpected decl}3">;
"%select{||||static assert|field|method|type alias|typedef|"
"unexpected decl}3">;
def note_module_odr_violation_mismatch_decl_unknown : Note<
"but in '%0' found "
"%select{||||different static assert|different field|different method|"
"different type alias|different typedef|"
"another unexpected decl}1">;

def warn_duplicate_module_file_extension : Warning<
Expand Down
41 changes: 41 additions & 0 deletions lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9242,6 +9242,7 @@ void ASTReader::diagnoseOdrViolations() {

// Used with err_module_odr_violation_mismatch_decl and
// note_module_odr_violation_mismatch_decl
// This list should be the same Decl's as in ODRHash::isWhiteListedDecl
enum {
EndOfClass,
PublicSpecifer,
Expand All @@ -9250,6 +9251,8 @@ void ASTReader::diagnoseOdrViolations() {
StaticAssert,
Field,
CXXMethod,
TypeAlias,
TypeDef,
Other
} FirstDiffType = Other,
SecondDiffType = Other;
Expand Down Expand Up @@ -9277,6 +9280,10 @@ void ASTReader::diagnoseOdrViolations() {
return Field;
case Decl::CXXMethod:
return CXXMethod;
case Decl::TypeAlias:
return TypeAlias;
case Decl::Typedef:
return TypeDef;
}
};

Expand Down Expand Up @@ -9373,6 +9380,8 @@ void ASTReader::diagnoseOdrViolations() {
MethodNumberParameters,
MethodParameterType,
MethodParameterName,
TypedefName,
TypedefType,
};

// These lambdas have the common portions of the ODR diagnostics. This
Expand Down Expand Up @@ -9748,6 +9757,38 @@ void ASTReader::diagnoseOdrViolations() {

break;
}
case TypeAlias:
case TypeDef: {
TypedefNameDecl *FirstTD = cast<TypedefNameDecl>(FirstDecl);
TypedefNameDecl *SecondTD = cast<TypedefNameDecl>(SecondDecl);
auto FirstName = FirstTD->getDeclName();
auto SecondName = SecondTD->getDeclName();
if (FirstName != SecondName) {
ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(),
TypedefName)
<< (FirstDiffType == TypeAlias) << FirstName;
ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(),
TypedefName)
<< (FirstDiffType == TypeAlias) << SecondName;
Diagnosed = true;
break;
}

QualType FirstType = FirstTD->getUnderlyingType();
QualType SecondType = SecondTD->getUnderlyingType();
if (ComputeQualTypeODRHash(FirstType) !=
ComputeQualTypeODRHash(SecondType)) {
ODRDiagError(FirstTD->getLocation(), FirstTD->getSourceRange(),
TypedefType)
<< (FirstDiffType == TypeAlias) << FirstName << FirstType;
ODRDiagNote(SecondTD->getLocation(), SecondTD->getSourceRange(),
TypedefType)
<< (FirstDiffType == TypeAlias) << SecondName << SecondType;
Diagnosed = true;
break;
}
break;
}
}

if (Diagnosed == true)
Expand Down
102 changes: 102 additions & 0 deletions test/Modules/odr_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,57 @@ S3 s3;
// [email protected]:* {{'TypeDef::S3::a' from module 'FirstModule' is not present in definition of 'TypeDef::S3' in module 'SecondModule'}}
// [email protected]:* {{declaration of 'a' does not match}}
#endif

#if defined(FIRST)
struct S4 {
typedef int a;
typedef int b;
};
#elif defined(SECOND)
struct S4 {
typedef int b;
typedef int a;
};
#else
S4 s4;
// [email protected]:* {{'TypeDef::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef name 'b'}}
// [email protected]:* {{but in 'FirstModule' found typedef name 'a'}}
#endif

#if defined(FIRST)
struct S5 {
typedef int a;
typedef int b;
int x;
};
#elif defined(SECOND)
struct S5 {
int x;
typedef int b;
typedef int a;
};
#else
S5 s5;
// [email protected]:* {{'TypeDef::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
// [email protected]:* {{but in 'FirstModule' found typedef}}
#endif

#if defined(FIRST)
typedef float F;
struct S6 {
typedef int a;
typedef F b;
};
#elif defined(SECOND)
struct S6 {
typedef int a;
typedef float b;
};
#else
S6 s6;
// [email protected]:* {{'TypeDef::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found typedef 'b' with underlying type 'float'}}
// [email protected]:* {{but in 'FirstModule' found typedef 'b' with different underlying type 'TypeDef::F' (aka 'float')}}
#endif
} // namespace TypeDef

namespace Using {
Expand Down Expand Up @@ -632,6 +683,57 @@ S3 s3;
// [email protected]:* {{'Using::S3::a' from module 'FirstModule' is not present in definition of 'Using::S3' in module 'SecondModule'}}
// [email protected]:* {{declaration of 'a' does not match}}
#endif

#if defined(FIRST)
struct S4 {
using a = int;
using b = int;
};
#elif defined(SECOND)
struct S4 {
using b = int;
using a = int;
};
#else
S4 s4;
// [email protected]:* {{'Using::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias name 'b'}}
// [email protected]:* {{but in 'FirstModule' found type alias name 'a'}}
#endif

#if defined(FIRST)
struct S5 {
using a = int;
using b = int;
int x;
};
#elif defined(SECOND)
struct S5 {
int x;
using b = int;
using a = int;
};
#else
S5 s5;
// [email protected]:* {{'Using::S5' has different definitions in different modules; first difference is definition in module 'SecondModule' found field}}
// [email protected]:* {{but in 'FirstModule' found type alias}}
#endif

#if defined(FIRST)
typedef float F;
struct S6 {
using a = int;
using b = F;
};
#elif defined(SECOND)
struct S6 {
using a = int;
using b = float;
};
#else
S6 s6;
// [email protected]:* {{'Using::S6' has different definitions in different modules; first difference is definition in module 'SecondModule' found type alias 'b' with underlying type 'float'}}
// [email protected]:* {{but in 'FirstModule' found type alias 'b' with different underlying type 'Using::F' (aka 'float')}}
#endif
} // namespace Using

namespace RecordType {
Expand Down

0 comments on commit 7b936e3

Please sign in to comment.