]> granicus.if.org Git - clang/commitdiff
When we're determining whether to complain about a conversion from one
authorDouglas Gregor <dgregor@apple.com>
Sat, 12 Mar 2011 00:14:31 +0000 (00:14 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 12 Mar 2011 00:14:31 +0000 (00:14 +0000)
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

lib/Sema/SemaChecking.cpp
test/Sema/conversion.c

index 4cdbf5375e6f059bad678e158e10df38c7a9c2cb..ea14b4bbb1e8ee1d1fe1c9f455e5ab1d0a651976 100644 (file)
@@ -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<DeclRefExpr>(E))
+      if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
+        EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext());
+        SourceType = S.Context.getTypeDeclType(Enum);
+        Source = S.Context.getCanonicalType(SourceType).getTypePtr();
+      }
+  }
+  
   if (const EnumType *SourceEnum = Source->getAs<EnumType>())
     if (const EnumType *TargetEnum = Target->getAs<EnumType>())
       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);
       }
   
index 619d6993251f3101edde17208620b559081188c6..1eaf7082d67e75797e237a3499b16bd3b54b79f9 100644 (file)
@@ -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'}}