From 5a5b38f4afaf4f203b96a11ba79890c7cd4cc4b8 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 12 Mar 2011 00:14:31 +0000 Subject: [PATCH] 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 . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127514 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaChecking.cpp | 21 ++++++++++++++++++++- test/Sema/conversion.c | 4 ++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 4cdbf5375e..ea14b4bbb1 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2753,6 +2753,13 @@ void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, << E->getType() << T << E->getSourceRange() << SourceRange(CContext); } +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag) { + S.Diag(E->getExprLoc(), diag) + << SourceType << T << E->getSourceRange() << SourceRange(CContext); +} + std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { if (!Range.Width) return "0"; @@ -2917,6 +2924,18 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } // Diagnose conversions between different enumeration types. + // In C, we pretend that the type of an EnumConstantDecl is its enumeration + // type, to give us better diagnostics. + QualType SourceType = E->getType(); + if (!S.getLangOptions().CPlusPlus) { + if (DeclRefExpr *DRE = dyn_cast(E)) + if (EnumConstantDecl *ECD = dyn_cast(DRE->getDecl())) { + EnumDecl *Enum = cast(ECD->getDeclContext()); + SourceType = S.Context.getTypeDeclType(Enum); + Source = S.Context.getCanonicalType(SourceType).getTypePtr(); + } + } + if (const EnumType *SourceEnum = Source->getAs()) if (const EnumType *TargetEnum = Target->getAs()) if ((SourceEnum->getDecl()->getIdentifier() || @@ -2927,7 +2946,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (isFromSystemMacro(S, CC)) return; - return DiagnoseImpCast(S, E, T, CC, + return DiagnoseImpCast(S, E, SourceType, T, CC, diag::warn_impcast_different_enum_types); } diff --git a/test/Sema/conversion.c b/test/Sema/conversion.c index 619d699325..1eaf7082d6 100644 --- a/test/Sema/conversion.c +++ b/test/Sema/conversion.c @@ -323,6 +323,10 @@ void test_8559831(enum E8559831b value_a, E8559831c value_c) { enum E8559831a a1 = value_a; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} a1 = value_a; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} + test_8559831_a(E8559831b_val); // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} + enum E8559831a a1a = E8559831b_val; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} + a1 = E8559831b_val; // expected-warning{{implicit conversion from enumeration type 'enum E8559831b' to different enumeration type 'enum E8559831a'}} + test_8559831_a(value_c); // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}} enum E8559831a a2 = value_c; // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}} a2 = value_c; // expected-warning{{implicit conversion from enumeration type 'E8559831c' to different enumeration type 'enum E8559831a'}} -- 2.40.0