Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 5a5b38f

Browse files
committed
When we're determining whether to complain about a conversion from one
enumeration type to another in C, classify enumeration constants as if they had the type of their enclosing enumeration. Fixes <rdar://problem/9116337>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127514 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent c29ea8f commit 5a5b38f

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

lib/Sema/SemaChecking.cpp

+20-1
Original file line numberDiff line numberDiff line change
@@ -2753,6 +2753,13 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext,
27532753
<< E->getType() << T << E->getSourceRange() << SourceRange(CContext);
27542754
}
27552755

2756+
/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion.
2757+
void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T,
2758+
SourceLocation CContext, unsigned diag) {
2759+
S.Diag(E->getExprLoc(), diag)
2760+
<< SourceType << T << E->getSourceRange() << SourceRange(CContext);
2761+
}
2762+
27562763
std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) {
27572764
if (!Range.Width) return "0";
27582765

@@ -2917,6 +2924,18 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
29172924
}
29182925

29192926
// Diagnose conversions between different enumeration types.
2927+
// In C, we pretend that the type of an EnumConstantDecl is its enumeration
2928+
// type, to give us better diagnostics.
2929+
QualType SourceType = E->getType();
2930+
if (!S.getLangOptions().CPlusPlus) {
2931+
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
2932+
if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
2933+
EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext());
2934+
SourceType = S.Context.getTypeDeclType(Enum);
2935+
Source = S.Context.getCanonicalType(SourceType).getTypePtr();
2936+
}
2937+
}
2938+
29202939
if (const EnumType *SourceEnum = Source->getAs<EnumType>())
29212940
if (const EnumType *TargetEnum = Target->getAs<EnumType>())
29222941
if ((SourceEnum->getDecl()->getIdentifier() ||
@@ -2927,7 +2946,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
29272946
if (isFromSystemMacro(S, CC))
29282947
return;
29292948

2930-
return DiagnoseImpCast(S, E, T, CC,
2949+
return DiagnoseImpCast(S, E, SourceType, T, CC,
29312950
diag::warn_impcast_different_enum_types);
29322951
}
29332952

test/Sema/conversion.c

+4
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ void test_8559831(enum E8559831b value_a, E8559831c value_c) {
323323
enum E8559831a a1 = value_a; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}}
324324
a1 = value_a; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}}
325325

326+
test_8559831_a(E8559831b_val); // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}}
327+
enum E8559831a a1a = E8559831b_val; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}}
328+
a1 = E8559831b_val; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}}
329+
326330
test_8559831_a(value_c); // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}}
327331
enum E8559831a a2 = value_c; // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}}
328332
a2 = value_c; // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}}

0 commit comments

Comments
 (0)