[cfe-commits] r109751 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/Sema/SemaDecl.cpp test/Sema/knr-def-call.c

Douglas Gregor dgregor at apple.com
Thu Jul 29 08:18:02 PDT 2010


Author: dgregor
Date: Thu Jul 29 10:18:02 2010
New Revision: 109751

URL: http://llvm.org/viewvc/llvm-project?rev=109751&view=rev
Log:
Allow a looser form of compatibility checking (which ignores
qualifiers) when checking a K&R function definition against a previous
prototype. Fixes <rdar://problem/8193107>.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/knr-def-call.c

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=109751&r1=109750&r2=109751&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Jul 29 10:18:02 2010
@@ -1215,7 +1215,8 @@
   //===--------------------------------------------------------------------===//
 
   /// Compatibility predicates used to check assignment expressions.
-  bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
+  bool typesAreCompatible(QualType T1, QualType T2, 
+                          bool CompareUnqualified = false); // C99 6.2.7p1
 
   bool typesAreBlockPointerCompatible(QualType, QualType); 
 
@@ -1247,8 +1248,10 @@
                                    const ObjCObjectPointerType *RHSOPT);
   
   // Functions for calculating composite types
-  QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false);
-  QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false);
+  QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false,
+                      bool Unqualified = false);
+  QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
+                              bool Unqualified = false);
   
   QualType mergeObjCGCQualifiers(QualType, QualType);
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=109751&r1=109750&r2=109751&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Jul 29 10:18:02 2010
@@ -4539,11 +4539,12 @@
 /// both shall have the identically qualified version of a compatible type.
 /// C99 6.2.7p1: Two types have compatible types if their types are the
 /// same. See 6.7.[2,3,5] for additional rules.
-bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS) {
+bool ASTContext::typesAreCompatible(QualType LHS, QualType RHS,
+                                    bool CompareUnqualified) {
   if (getLangOptions().CPlusPlus)
     return hasSameType(LHS, RHS);
   
-  return !mergeTypes(LHS, RHS).isNull();
+  return !mergeTypes(LHS, RHS, false, CompareUnqualified).isNull();
 }
 
 bool ASTContext::typesAreBlockPointerCompatible(QualType LHS, QualType RHS) {
@@ -4551,7 +4552,8 @@
 }
 
 QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, 
-                                        bool OfBlockPointer) {
+                                        bool OfBlockPointer,
+                                        bool Unqualified) {
   const FunctionType *lbase = lhs->getAs<FunctionType>();
   const FunctionType *rbase = rhs->getAs<FunctionType>();
   const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase);
@@ -4562,13 +4564,26 @@
   // Check return type
   QualType retType;
   if (OfBlockPointer)
-    retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true);
+    retType = mergeTypes(rbase->getResultType(), lbase->getResultType(), true,
+                         Unqualified);
   else
-   retType = mergeTypes(lbase->getResultType(), rbase->getResultType());
+   retType = mergeTypes(lbase->getResultType(), rbase->getResultType(),
+                        false, Unqualified);
   if (retType.isNull()) return QualType();
-  if (getCanonicalType(retType) != getCanonicalType(lbase->getResultType()))
+  
+  if (Unqualified)
+    retType = retType.getUnqualifiedType();
+
+  CanQualType LRetType = getCanonicalType(lbase->getResultType());
+  CanQualType RRetType = getCanonicalType(rbase->getResultType());
+  if (Unqualified) {
+    LRetType = LRetType.getUnqualifiedType();
+    RRetType = RRetType.getUnqualifiedType();
+  }
+  
+  if (getCanonicalType(retType) != LRetType)
     allLTypes = false;
-  if (getCanonicalType(retType) != getCanonicalType(rbase->getResultType()))
+  if (getCanonicalType(retType) != RRetType)
     allRTypes = false;
   // FIXME: double check this
   // FIXME: should we error if lbase->getRegParmAttr() != 0 &&
@@ -4613,9 +4628,19 @@
     for (unsigned i = 0; i < lproto_nargs; i++) {
       QualType largtype = lproto->getArgType(i).getUnqualifiedType();
       QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
-      QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer);
+      QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer,
+                                    Unqualified);
       if (argtype.isNull()) return QualType();
+      
+      if (Unqualified)
+        argtype = argtype.getUnqualifiedType();
+      
       types.push_back(argtype);
+      if (Unqualified) {
+        largtype = largtype.getUnqualifiedType();
+        rargtype = rargtype.getUnqualifiedType();
+      }
+      
       if (getCanonicalType(argtype) != getCanonicalType(largtype))
         allLTypes = false;
       if (getCanonicalType(argtype) != getCanonicalType(rargtype))
@@ -4671,7 +4696,8 @@
 }
 
 QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, 
-                                bool OfBlockPointer) {
+                                bool OfBlockPointer,
+                                bool Unqualified) {
   // C++ [expr]: If an expression initially has the type "reference to T", the
   // type is adjusted to "T" prior to any further analysis, the expression
   // designates the object or function denoted by the reference, and the
@@ -4679,6 +4705,11 @@
   // the expression is a function call (possibly inside parentheses).
   assert(!LHS->getAs<ReferenceType>() && "LHS is a reference type?");
   assert(!RHS->getAs<ReferenceType>() && "RHS is a reference type?");
+
+  if (Unqualified) {
+    LHS = LHS.getUnqualifiedType();
+    RHS = RHS.getUnqualifiedType();
+  }
   
   QualType LHSCan = getCanonicalType(LHS),
            RHSCan = getCanonicalType(RHS);
@@ -4790,7 +4821,12 @@
     // Merge two pointer types, while trying to preserve typedef info
     QualType LHSPointee = LHS->getAs<PointerType>()->getPointeeType();
     QualType RHSPointee = RHS->getAs<PointerType>()->getPointeeType();
-    QualType ResultType = mergeTypes(LHSPointee, RHSPointee);
+    if (Unqualified) {
+      LHSPointee = LHSPointee.getUnqualifiedType();
+      RHSPointee = RHSPointee.getUnqualifiedType();
+    }
+    QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false, 
+                                     Unqualified);
     if (ResultType.isNull()) return QualType();
     if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
       return LHS;
@@ -4803,7 +4839,12 @@
     // Merge two block pointer types, while trying to preserve typedef info
     QualType LHSPointee = LHS->getAs<BlockPointerType>()->getPointeeType();
     QualType RHSPointee = RHS->getAs<BlockPointerType>()->getPointeeType();
-    QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer);
+    if (Unqualified) {
+      LHSPointee = LHSPointee.getUnqualifiedType();
+      RHSPointee = RHSPointee.getUnqualifiedType();
+    }
+    QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer,
+                                     Unqualified);
     if (ResultType.isNull()) return QualType();
     if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType))
       return LHS;
@@ -4820,7 +4861,12 @@
 
     QualType LHSElem = getAsArrayType(LHS)->getElementType();
     QualType RHSElem = getAsArrayType(RHS)->getElementType();
-    QualType ResultType = mergeTypes(LHSElem, RHSElem);
+    if (Unqualified) {
+      LHSElem = LHSElem.getUnqualifiedType();
+      RHSElem = RHSElem.getUnqualifiedType();
+    }
+    
+    QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified);
     if (ResultType.isNull()) return QualType();
     if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType))
       return LHS;
@@ -4854,7 +4900,7 @@
                                   ArrayType::ArraySizeModifier(), 0);
   }
   case Type::FunctionNoProto:
-    return mergeFunctionTypes(LHS, RHS, OfBlockPointer);
+    return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified);
   case Type::Record:
   case Type::Enum:
     return QualType();

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=109751&r1=109750&r2=109751&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jul 29 10:18:02 2010
@@ -1246,7 +1246,8 @@
                                      NewProto->getArgType(Idx))) {
         ArgTypes.push_back(NewParm->getType());
       } else if (Context.typesAreCompatible(OldParm->getType(),
-                                            NewParm->getType())) {
+                                            NewParm->getType(),
+                                            /*CompareUnqualified=*/true)) {
         GNUCompatibleParamWarning Warn
           = { OldParm, NewParm, NewProto->getArgType(Idx) };
         Warnings.push_back(Warn);
@@ -1261,8 +1262,9 @@
              diag::ext_param_promoted_not_compatible_with_prototype)
           << Warnings[Warn].PromotedType
           << Warnings[Warn].OldParm->getType();
-        Diag(Warnings[Warn].OldParm->getLocation(),
-             diag::note_previous_declaration);
+        if (Warnings[Warn].OldParm->getLocation().isValid())
+          Diag(Warnings[Warn].OldParm->getLocation(),
+               diag::note_previous_declaration);
       }
 
       New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0],

Modified: cfe/trunk/test/Sema/knr-def-call.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/knr-def-call.c?rev=109751&r1=109750&r2=109751&view=diff
==============================================================================
--- cfe/trunk/test/Sema/knr-def-call.c (original)
+++ cfe/trunk/test/Sema/knr-def-call.c Thu Jul 29 10:18:02 2010
@@ -16,3 +16,14 @@
 
 typedef void (*f3)(void);
 f3 t3(int b) { return b? f0 : f1; } // okay
+
+// <rdar://problem/8193107>
+void f4() {
+    char *rindex();
+}
+
+char *rindex(s, c)
+     register char *s, c; // expected-warning{{promoted type 'char *' of K&R function parameter is not compatible with the parameter type 'char const *' declared in a previous prototype}}
+{
+  return 0;
+}





More information about the cfe-commits mailing list