[cfe-commits] r39601 - in /cfe/cfe/trunk: Sema/Sema.h Sema/SemaExpr.cpp Sema/SemaStmt.cpp clang.xcodeproj/project.pbxproj

Steve Naroff snaroff at apple.com
Wed Jul 11 09:46:07 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:46:07 2007
New Revision: 39601

URL: http://llvm.org/viewvc/llvm-project?rev=39601&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:

The following code illustrates a bug in the semantic analysis for assignments:

int func() {
  int *P;
  char *x;
  P = x; // type of this assignment expression should be "int *", NOT "char *".
}

While the type checking/diagnostics are correct, the type of the assignment
expression is incorrect (which shows up during code gen).  With the fix,
the llvm code looks correct...

[dylan:~/llvm/tools/clang] admin% ../../Debug/bin/clang cast.c -emit-llvm
cast.c:4:5: warning: incompatible pointer types assigning 'char *' to 'int *'
  P = x; // type of assignment expression is "int *", NOT "char *".
  ~ ^ ~
; ModuleID = 'foo'

define i32 @func() {
entry:
        %P = alloca i32*                ; <i32**> [#uses=1]
        %x = alloca i8*         ; <i8**> [#uses=1]
        %allocapt = bitcast i32 undef to i32            ; <i32> [#uses=0]
        %tmp = load i8** %x             ; <i8*> [#uses=1]
        %conv = bitcast i8* %tmp to i32*                ; <i32*> [#uses=1]
        store i32* %conv, i32** %P
        ret i32 undef
}

Even though the fix was simple, I decided to rename/refactor the surrounding code
to make a clearer distinction between constraint checking and conversion.

- Renamed AssignmentConversionResult -> AssignmentCheckResult.
- Renamed UsualAssignmentConversions -> CheckAssignmentConstraints.
- Changed the return type of CheckAssignmentConstraints and CheckPointerTypesForAssignment
from QualType -> AssignmentCheckResult. These routines no longer take a reference to the result (obviously).
- Changed CheckAssignmentOperands to return the correct type (with spec annotations).

Modified:
    cfe/cfe/trunk/Sema/Sema.h
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/Sema/SemaStmt.cpp
    cfe/cfe/trunk/clang.xcodeproj/project.pbxproj

Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39601&r1=39600&r2=39601&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:46:07 2007
@@ -273,7 +273,7 @@
   // or array, this routine simply returns the input type (unmodified).
   QualType DefaultFunctionArrayConversion(QualType t);
   
-  enum AssignmentConversionResult {
+  enum AssignmentCheckResult {
     Compatible,
     Incompatible,
     PointerFromInt, 
@@ -281,14 +281,13 @@
     IncompatiblePointer,
     CompatiblePointerDiscardsQualifiers
   };
-  // UsualAssignmentConversions - conversions for assignment, argument passing, 
+  // CheckAssignmentConstraints - conversions for assignment, argument passing, 
   // variable initialization, and function return values. Currently used by 
-  // CheckAssignmentOperands, ParseCallExpr, and ParseReturnStmt. 
-  QualType UsualAssignmentConversions(QualType lhs, QualType rhs, // C99 6.5.16
-                                      AssignmentConversionResult &r);
-  // Helper function for UsualAssignmentConversions (C99 6.5.16.1p1)
-  QualType CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType,
-                                          AssignmentConversionResult &r);
+  // CheckAssignmentOperands, ParseCallExpr, and ParseReturnStmt.  C99 6.5.16.
+  AssignmentCheckResult CheckAssignmentConstraints(QualType lhs, QualType rhs);
+  // Helper function for CheckAssignmentConstraints (C99 6.5.16.1p1)
+  AssignmentCheckResult CheckPointerTypesForAssignment(QualType lhsType, 
+                                                       QualType rhsType);
   
   /// the following "Check" methods will return a valid/converted QualType
   /// or a null QualType (indicating an error diagnostic was issued).

Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39601&r1=39600&r2=39601&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:46:07 2007
@@ -415,9 +415,9 @@
       
       if (lhsType == rhsType) // common case, fast path...
         continue;
-      AssignmentConversionResult result;
-      UsualAssignmentConversions(lhsType, rhsType, result);
-
+        
+      AssignmentCheckResult result = CheckAssignmentConstraints(lhsType,
+                                                                rhsType);
       SourceLocation l = argExpr->getLocStart();
 
       // decode the result (notice that AST's are still created for extensions).
@@ -634,9 +634,8 @@
 // routine is it effectively iqnores the qualifiers on the top level pointee.
 // This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3].
 // FIXME: add a couple examples in this comment.
-QualType Sema::CheckPointerTypesForAssignment(QualType lhsType, 
-                                              QualType rhsType,
-                                              AssignmentConversionResult &r) {
+Sema::AssignmentCheckResult 
+Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
   QualType lhptee, rhptee;
   
   // get the "pointed to" type (ignoring qualifiers at the top level)
@@ -647,6 +646,8 @@
   lhptee = lhptee.getCanonicalType();
   rhptee = rhptee.getCanonicalType();
 
+  AssignmentCheckResult r = Compatible;
+  
   // C99 6.5.16.1p1: This following citation is common to constraints 
   // 3 & 4 (below). ...and the type *pointed to* by the left has all the 
   // qualifiers of the type *pointed to* by the right; 
@@ -668,10 +669,10 @@
   else if (!Type::typesAreCompatible(lhptee.getUnqualifiedType(), 
                                      rhptee.getUnqualifiedType()))
     r = IncompatiblePointer; // this "trumps" PointerAssignDiscardsQualifiers
-  return rhsType;
+  return r;
 }
 
-/// UsualAssignmentConversions (C99 6.5.16) - This routine currently 
+/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently 
 /// has code to accommodate several GCC extensions when type checking 
 /// pointers. Here are some objectionable examples that GCC considers warnings:
 ///
@@ -688,44 +689,37 @@
 /// C99 spec dictates. 
 /// Note: the warning above turn into errors when -pedantic-errors is enabled. 
 ///
-QualType Sema::UsualAssignmentConversions(QualType lhsType, QualType rhsType,
-                                          AssignmentConversionResult &r) {
+Sema::AssignmentCheckResult
+Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
   // This check seems unnatural, however it is necessary to insure the proper
   // conversion of functions/arrays. If the conversion were done for all
   // DeclExpr's (created by ParseIdentifierExpr), it would mess up the unary
   // expressions that surpress this implicit conversion (&, sizeof).
   rhsType = DefaultFunctionArrayConversion(rhsType);
     
-  r = Compatible;
   if (lhsType->isArithmeticType() && rhsType->isArithmeticType())
-    return lhsType;
+    return Compatible;
   else if (lhsType->isPointerType()) {
-    if (rhsType->isIntegerType()) {
-      r = PointerFromInt;
-      return rhsType;
-    }
+    if (rhsType->isIntegerType())
+      return PointerFromInt;
+      
     if (rhsType->isPointerType())
-      return CheckPointerTypesForAssignment(lhsType, rhsType, r);
+      return CheckPointerTypesForAssignment(lhsType, rhsType);
   } else if (rhsType->isPointerType()) {
-    if (lhsType->isIntegerType()) {
-      // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
-      if (lhsType != Context.BoolTy)
-        r = IntFromPointer;
-      return rhsType;
-    }
+    // C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
+    if ((lhsType->isIntegerType()) && (lhsType != Context.BoolTy))
+      return IntFromPointer;
+
     if (lhsType->isPointerType()) 
-      return CheckPointerTypesForAssignment(lhsType, rhsType, r);
+      return CheckPointerTypesForAssignment(lhsType, rhsType);
   } else if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
     if (Type::tagTypesAreCompatible(lhsType, rhsType))
-      return rhsType;
+      return Compatible;
   } else if (lhsType->isReferenceType() || rhsType->isReferenceType()) {
     if (Type::referenceTypesAreCompatible(lhsType, rhsType))
-      // C++ 5.17p1: ...the type of the assignment exression is that of its left
-      // operand.
-      return lhsType;
+      return Compatible;
   }
-  r = Incompatible;
-  return QualType();
+  return Incompatible;
 }
 
 inline void Sema::InvalidOperands(SourceLocation loc, Expr *lex, Expr *rex) {
@@ -898,8 +892,7 @@
   if (lhsType == rhsType) // common case, fast path...
     return lhsType;
   
-  AssignmentConversionResult result;
-  QualType resType = UsualAssignmentConversions(lhsType, rhsType, result);
+  AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
 
   // decode the result (notice that extensions still return a type).
   switch (result) {
@@ -935,7 +928,13 @@
          lex->getSourceRange(), rex->getSourceRange());
     break;
   }
-  return hadError ? QualType() : resType;
+  // C99 6.5.16p3: The type of an assignment expression is the type of the
+  // left operand unless the left operand has qualified type, in which case
+  // it is the unqualified version of the type of the left operand. 
+  // C99 6.5.16.1p2: In simple assignment, the value of the right operand
+  // is converted to the type of the assignment expression (above).
+  // C++ 5.17p1: the type of the assignment expression is that of its left oprdu.
+  return hadError ? QualType() : lhsType.getUnqualifiedType();
 }
 
 inline QualType Sema::CheckCommaOperands( // C99 6.5.17

Modified: cfe/cfe/trunk/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaStmt.cpp?rev=39601&r1=39600&r2=39601&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaStmt.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaStmt.cpp Wed Jul 11 11:46:07 2007
@@ -241,8 +241,7 @@
   // C99 6.8.6.4p3(136): The return statement is not an assignment. The 
   // overlap restriction of subclause 6.5.16.1 does not apply to the case of 
   // function return.  
-  AssignmentConversionResult result;
-  QualType resType = UsualAssignmentConversions(lhsType, rhsType, result);
+  AssignmentCheckResult result = CheckAssignmentConstraints(lhsType, rhsType);
   bool hadError = false;
   
   // decode the result (notice that extensions still return a type).

Modified: cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=39601&r1=39600&r2=39601&view=diff

==============================================================================
--- cfe/cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/cfe/trunk/clang.xcodeproj/project.pbxproj Wed Jul 11 11:46:07 2007
@@ -10,6 +10,8 @@
 		1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A30A9E80B93A4C800201A91 /* ExprCXX.h */; };
 		1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
 		1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
+		84916BE50C161E580080778F /* Attr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84916BE40C161E580080778F /* Attr.cpp */; };
+		84916BE70C161E800080778F /* Attr.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 84916BE60C161E800080778F /* Attr.h */; };
 		DE01DA490B12ADA300AC22CE /* PPCallbacks.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE01DA480B12ADA300AC22CE /* PPCallbacks.h */; };
 		DE06756C0C051CFE00EBBFD8 /* ParseExprCXX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */; };
 		DE06B73E0A8307640050E87E /* LangOptions.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE06B73D0A8307640050E87E /* LangOptions.h */; };
@@ -106,6 +108,23 @@
 		DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
 /* End PBXBuildFile section */
 
+/* Begin PBXBuildStyle section */
+		84916C3B0C1736920080778F /* Development */ = {
+			isa = PBXBuildStyle;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+			};
+			name = Development;
+		};
+		84916C3C0C1736920080778F /* Deployment */ = {
+			isa = PBXBuildStyle;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+			};
+			name = Deployment;
+		};
+/* End PBXBuildStyle section */
+
 /* Begin PBXCopyFilesBuildPhase section */
 		8DD76F690486A84900D96B5E /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
@@ -160,6 +179,7 @@
 				DE928B200C0565B000231DA4 /* ModuleBuilder.h in CopyFiles */,
 				DE928B7D0C0A615100231DA4 /* CodeGenModule.h in CopyFiles */,
 				DE928B810C0A615B00231DA4 /* CodeGenFunction.h in CopyFiles */,
+				84916BE70C161E800080778F /* Attr.h in CopyFiles */,
 			);
 			runOnlyForDeploymentPostprocessing = 1;
 		};
@@ -169,6 +189,8 @@
 		1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = "<group>"; };
 		1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
 		1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
+		84916BE40C161E580080778F /* Attr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Attr.cpp; path = AST/Attr.cpp; sourceTree = "<group>"; };
+		84916BE60C161E800080778F /* Attr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = Attr.h; path = include/clang/AST/Attr.h; sourceTree = "<group>"; };
 		8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
 		DE01DA480B12ADA300AC22CE /* PPCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCallbacks.h; sourceTree = "<group>"; };
 		DE06756B0C051CFE00EBBFD8 /* ParseExprCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParseExprCXX.cpp; path = Parse/ParseExprCXX.cpp; sourceTree = "<group>"; };
@@ -432,6 +454,8 @@
 				DED677C80B6C854100AAD4A3 /* Builtins.cpp */,
 				DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */,
 				DE0FCB330A9C21F100248FD5 /* Expr.cpp */,
+				84916BE60C161E800080778F /* Attr.h */,
+				84916BE40C161E580080778F /* Attr.cpp */,
 				DE3452400AEF1A2D00DBC861 /* Stmt.cpp */,
 				DE75EDF00B06880E0020CF81 /* Type.cpp */,
 				DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */,
@@ -547,6 +571,12 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+			buildSettings = {
+			};
+			buildStyles = (
+				84916C3B0C1736920080778F /* Development */,
+				84916C3C0C1736920080778F /* Deployment */,
+			);
 			hasScannedForEncodings = 1;
 			mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
 			projectDirPath = "";
@@ -611,6 +641,7 @@
 				DE4772FA0C10EAE5002239E8 /* CGStmt.cpp in Sources */,
 				DE4772FC0C10EAEC002239E8 /* CGExpr.cpp in Sources */,
 				DE4264FC0C113592005A861D /* CGDecl.cpp in Sources */,
+				84916BE50C161E580080778F /* Attr.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};





More information about the cfe-commits mailing list