]> granicus.if.org Git - clang/commitdiff
Fix Sema::ParseCallExpr()...it wasn't doing the default array/function promotions...
authorSteve Naroff <snaroff@apple.com>
Tue, 24 Jul 2007 21:46:40 +0000 (21:46 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 24 Jul 2007 21:46:40 +0000 (21:46 +0000)
This resulted in the following errors when compiling promote_types_in_proto.c test...

[dylan:~/llvm/tools/clang] admin% ../../Debug/bin/clang test/Parser/promote_types_in_proto.c
test/Parser/promote_types_in_proto.c:7:24: error: incompatible types passing 'char *[]' to function expecting 'char *const []'
        arrayPromotion(argv);
        ~~~~~~~~~~~~~~ ^~~~
test/Parser/promote_types_in_proto.c:8:27: error: incompatible types passing 'void (char *const [])' to function expecting 'void (char *const [])'
        functionPromotion(arrayPromotion);
        ~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~
2 diagnostics generated.

When fixing this, noticed that both ParseCallExpr() and ParseReturnStmt() were prematurely comparing types for
equivalence. This is incorrect (since the expr. promotions haven't been done yet). To fix this, I moved the
check "down" to Sema::CheckAssignmentConstraints().

I also converted Type::isArrayType() to the modern API (since I needed it). Still more Type predicates to
convert.

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

AST/Type.cpp
Sema/SemaExpr.cpp
Sema/SemaStmt.cpp
clang.xcodeproj/project.pbxproj
include/clang/AST/Type.h
test/Parser/promote_types_in_proto.c [new file with mode: 0644]

index 4e415e4ab6c96c5d9d71e47af586202b89c0eaec..b09d3afa63a2a7a3f2bf30767447efe6d41e0169 100644 (file)
@@ -84,8 +84,16 @@ const ReferenceType *Type::isReferenceType() const {
   return 0;
 }
 
-bool Type::isArrayType() const {
-  return isa<ArrayType>(CanonicalType);
+const ArrayType *Type::isArrayType() const {
+  // If this is directly a reference type, return it.
+  if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
+    return ATy;
+  
+  // If this is a typedef for an array type, strip the typedef off without
+  // losing all typedef information.
+  if (isa<ArrayType>(CanonicalType))
+    return cast<ArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
+  return 0;
 }
 
 bool Type::isStructureType() const {
index 7e0b6412761e62e5b9f92ee7ddc463e8a5c835d9..abc3ce3f7a75e954db59caaa15d4b5d676d97cb3 100644 (file)
@@ -433,10 +433,15 @@ ParseCallExpr(ExprTy *fn, SourceLocation LParenLoc,
       
       QualType lhsType = proto->getArgType(i);
       QualType rhsType = argExpr->getType();
-      
-      if (lhsType == rhsType) // common case, fast path...
-        continue;
+
+      // C99 6.7.5.3p7
+      if (const ArrayType *ary = lhsType->isArrayType())
+        lhsType = Context.getPointerType(ary->getElementType());
         
+      // C99 6.7.5.3p8
+      if (lhsType->isFunctionType())
+        lhsType = Context.getPointerType(lhsType);
+
       AssignmentCheckResult result = CheckSingleAssignmentConstraints(lhsType,
                                                                       argExpr);
       SourceLocation l = argExpr->getLocStart();
@@ -638,7 +643,7 @@ void Sema::DefaultFunctionArrayConversion(Expr *&e) {
   }
   if (t->isFunctionType())
     promoteExprToType(e, Context.getPointerType(t));
-  else if (const ArrayType *ary = dyn_cast<ArrayType>(t.getCanonicalType()))
+  else if (const ArrayType *ary = t->isArrayType())
     promoteExprToType(e, Context.getPointerType(ary->getElementType()));
 }
 
@@ -793,6 +798,9 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
 ///
 Sema::AssignmentCheckResult
 Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
+  if (lhsType == rhsType) // common case, fast path...
+    return Compatible;
+
   if (lhsType->isArithmeticType() && rhsType->isArithmeticType()) {
     if (lhsType->isVectorType() || rhsType->isVectorType()) {
       if (lhsType.getCanonicalType() != rhsType.getCanonicalType())
@@ -1066,9 +1074,6 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
            lhsType.getAsString(), lex->getSourceRange());
       return QualType();
   }
-  if (lhsType == rhsType) // common case, fast path...
-    return lhsType;
-  
   AssignmentCheckResult result;
   
   if (compoundType.isNull())
index f19737e30a967211c9bfd37e0fd23f6b49e5c115..f9e2c0a21a293490c221d5fb20ffe5b9127c3132 100644 (file)
@@ -318,9 +318,6 @@ Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *rex) {
   // we have a non-void function with an expression, continue checking
   QualType rhsType = RetValExp->getType();
 
-  if (lhsType == rhsType) // common case, fast path...
-    return new ReturnStmt(RetValExp);
-
   // 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.  
index ff84ac7c23151c701bc56bf555be41593b7f68f5..bb772fa1827bfe2c9e25f8e9a3c44b87b16d0846 100644 (file)
                1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
                84D9A8870C1A57E100AC7ABC /* AttributeList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AttributeList.cpp; path = Parse/AttributeList.cpp; sourceTree = "<group>"; };
                84D9A88B0C1A581300AC7ABC /* AttributeList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AttributeList.h; path = clang/Parse/AttributeList.h; sourceTree = "<group>"; };
-               8DD76F6C0486A84900D96B5E /* clang */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = "compiled.mach-o.executable"; path = clang; sourceTree = BUILT_PRODUCTS_DIR; };
+               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>"; };
                DE06B73D0A8307640050E87E /* LangOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LangOptions.h; sourceTree = "<group>"; };
index 29472b4fe8e157bd2ca68a6ad0e4c48c899397dc..0f4770860c91fc0c417ffbf431bfeb8b30aa7977 100644 (file)
@@ -35,6 +35,7 @@ namespace clang {
   class PointerType;
   class ReferenceType;
   class VectorType;
+  class ArrayType;
   
 /// QualType - For efficiency, we don't store CVR-qualified types as nodes on
 /// their own: instead each reference to a type stores the qualifiers.  This
@@ -237,7 +238,7 @@ public:
   bool isDerivedType() const;
   const PointerType *isPointerType() const;
   const ReferenceType *isReferenceType() const;
-  bool isArrayType() const;
+  const ArrayType *isArrayType() const;
   bool isStructureType() const;   
   bool isUnionType() const;
   
diff --git a/test/Parser/promote_types_in_proto.c b/test/Parser/promote_types_in_proto.c
new file mode 100644 (file)
index 0000000..40617a2
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN: clang %s
+void functionPromotion(void f(char *const []));
+void arrayPromotion(char * const argv[]);
+
+int whatever(int argc, char *argv[])
+{
+        arrayPromotion(argv);
+        functionPromotion(arrayPromotion);
+}