]> granicus.if.org Git - clang/commitdiff
Fix a couple bugs in aggregate cast processing: 1) fix precedecence
authorChris Lattner <sabre@nondot.org>
Fri, 25 Jul 2008 22:06:10 +0000 (22:06 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 25 Jul 2008 22:06:10 +0000 (22:06 +0000)
problem with &&/||.  2) use canonical types for comparison instead
of raw types. 3) emit an ext-warn for a gnu extension.

Also simplify the code to make it less nested.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54068 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp

index 27e4027e68ac91b1f6977518f42ce4d0e7a70b9e..80953da56c594945edec13ade11e4f9747319f62 100644 (file)
@@ -1122,33 +1122,34 @@ ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
 
   // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
   // type needs to be scalar.
-  if (!castType->isVoidType()) {  // Cast to void allows any expr type.
-    if (!castType->isScalarType() && !castType->isVectorType()) {
-      // GCC struct/union extension.
-      if (castType == castExpr->getType() &&
-          castType->isStructureType() || castType->isUnionType()) {
-        Diag(LParenLoc, diag::ext_typecheck_cast_nonscalar,
-             SourceRange(LParenLoc, RParenLoc));
-        return new CastExpr(castType, castExpr, LParenLoc);
-      } else
-        return Diag(LParenLoc, diag::err_typecheck_cond_expect_scalar, 
-                    castType.getAsString(), SourceRange(LParenLoc, RParenLoc));
-    }
-    if (!castExpr->getType()->isScalarType() && 
-        !castExpr->getType()->isVectorType())
-      return Diag(castExpr->getLocStart(), 
-                  diag::err_typecheck_expect_scalar_operand, 
-                  castExpr->getType().getAsString(),castExpr->getSourceRange());
-
-    if (castExpr->getType()->isVectorType()) {
-      if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc), 
-                          castExpr->getType(), castType))
-        return true;
-    } else if (castType->isVectorType()) {
-      if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc), 
-                          castType, castExpr->getType()))
-        return true;
+  if (castType->isVoidType()) {
+    // Cast to void allows any expr type.
+  } else if (!castType->isScalarType() && !castType->isVectorType()) {
+    // GCC struct/union extension: allow cast to self.
+    if (Context.getCanonicalType(castType) !=
+        Context.getCanonicalType(castExpr->getType()) ||
+        (!castType->isStructureType() && !castType->isUnionType())) {
+      // Reject any other conversions to non-scalar types.
+      return Diag(LParenLoc, diag::err_typecheck_cond_expect_scalar, 
+                  castType.getAsString(), castExpr->getSourceRange());
     }
+      
+    // accept this, but emit an ext-warn.
+    Diag(LParenLoc, diag::ext_typecheck_cast_nonscalar, 
+         castType.getAsString(), castExpr->getSourceRange());
+  } else if (!castExpr->getType()->isScalarType() && 
+             !castExpr->getType()->isVectorType()) {
+    return Diag(castExpr->getLocStart(), 
+                diag::err_typecheck_expect_scalar_operand, 
+                castExpr->getType().getAsString(),castExpr->getSourceRange());
+  } else if (castExpr->getType()->isVectorType()) {
+    if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc), 
+                        castExpr->getType(), castType))
+      return true;
+  } else if (castType->isVectorType()) {
+    if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc), 
+                        castType, castExpr->getType()))
+      return true;
   }
   return new CastExpr(castType, castExpr, LParenLoc);
 }