]> granicus.if.org Git - clang/commitdiff
Add Type::getAsBuiltinType() and Type::builtinTypesAreCompatible().
authorSteve Naroff <snaroff@apple.com>
Mon, 27 Aug 2007 04:08:11 +0000 (04:08 +0000)
committerSteve Naroff <snaroff@apple.com>
Mon, 27 Aug 2007 04:08:11 +0000 (04:08 +0000)
Modified Type::typesAreCompatible() to use the above.

This fixes the following bug submitted by Keith Bauer (thanks!).

int equal(char *a, const char *b)
{
    return a == b;
}

Also tweaked Sema::CheckCompareOperands() to ignore the qualifiers when
comparing two pointer types (though it doesn't relate directly to this bug).

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

AST/Type.cpp
Sema/SemaExpr.cpp
include/clang/AST/Type.h
test/Sema/compare.c
test/Sema/unused-expr.c

index 65ba90a75d9c69b038a7f6efbe74891492ef1425..f4c5aa748f2cfd1460012696357dc5453c07d181 100644 (file)
@@ -75,6 +75,18 @@ bool Type::isComplexType() const {
   return isa<ComplexType>(CanonicalType);
 }
 
+const BuiltinType *Type::getAsBuiltinType() const {
+  // If this is directly a builtin type, return it.
+  if (const BuiltinType *BTy = dyn_cast<BuiltinType>(this))
+    return BTy;
+  
+  // If this is a typedef for a builtin type, strip the typedef off without
+  // losing all typedef information.
+  if (isa<BuiltinType>(CanonicalType))
+    return cast<BuiltinType>(cast<TypedefType>(this)->LookThroughTypedefs());
+  return 0;
+}
+
 const FunctionType *Type::getAsFunctionType() const {
   // If this is directly a function type, return it.
   if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
@@ -204,6 +216,12 @@ const OCUVectorType *Type::getAsOCUVectorType() const {
   return 0;
 }
 
+bool Type::builtinTypesAreCompatible(QualType lhs, QualType rhs) {
+  const BuiltinType *lBuiltin = lhs->getAsBuiltinType();
+  const BuiltinType *rBuiltin = rhs->getAsBuiltinType();
+  
+  return lBuiltin->getKind() == rBuiltin->getKind();
+}
 
 // C99 6.2.7p1: If both are complete types, then the following additional
 // requirements apply...FIXME (handle compatibility across source files).
@@ -334,7 +352,7 @@ bool Type::typesAreCompatible(QualType lhs, QualType rhs) {
     case Type::Tagged: // handle structures, unions
       return tagTypesAreCompatible(lcanon, rcanon);
     case Type::Builtin:
-      return false
+      return builtinTypesAreCompatible(lcanon, rcanon)
     default:
       assert(0 && "unexpected type");
   }
index cc9a64f7268a14571d289be696cdfa3c3aa063b3..9033ee917fc3b4265d87ada10c31ca7797557ce1 100644 (file)
@@ -1109,9 +1109,10 @@ inline QualType Sema::CheckCompareOperands( // C99 6.5.8
   // All of the following pointer related warnings are GCC extensions, except
   // when handling null pointer constants. One day, we can consider making them
   // errors (when -pedantic-errors is enabled).
-  if (lType->isPointerType() && rType->isPointerType()) {
+  if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
     if (!LHSIsNull && !RHSIsNull &&
-        !Type::pointerTypesAreCompatible(lType, rType)) {
+        !Type::pointerTypesAreCompatible(lType.getUnqualifiedType(),
+                                         rType.getUnqualifiedType())) {
       Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
            lType.getAsString(), rType.getAsString(),
            lex->getSourceRange(), rex->getSourceRange());
index de5e48ee2ccdb81b70c64d8f01c732fcaf624ccf..9c72b050c5efb63e4c2f1a0661bc915ef8b313a1 100644 (file)
@@ -41,6 +41,7 @@ namespace clang {
   class TagType;
   class FunctionType;
   class OCUVectorType;
+  class BuiltinType;
   
 /// 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
@@ -262,6 +263,7 @@ public:
   // Type Checking Functions: Check to see if this type is structurally the
   // specified type, ignoring typedefs, and return a pointer to the best type
   // we can.
+  const BuiltinType *getAsBuiltinType() const;   
   const FunctionType *getAsFunctionType() const;   
   const PointerType *getAsPointerType() const;
   const ReferenceType *getAsReferenceType() const;
@@ -297,6 +299,7 @@ public:
   static bool referenceTypesAreCompatible(QualType, QualType); // C++ 5.17p6
   static bool functionTypesAreCompatible(QualType, QualType); // C99 6.7.5.3p15
   static bool arrayTypesAreCompatible(QualType, QualType); // C99 6.7.5.2p6
+  static bool builtinTypesAreCompatible(QualType, QualType);
 private:  
   QualType getCanonicalTypeInternal() const { return CanonicalType; }
   friend class QualType;
index 0aeeb30d735975b7a00cd2d87644177aa2a6ad32..d4e29e8674fa3707a21ef2d23f46ef16963b260e 100644 (file)
@@ -6,3 +6,7 @@ int test(char *C) { // nothing here should warn.
   return C != 0;
 }
 
+int equal(char *a, const char *b)
+{
+    return a == b;
+}
index 323df3496424110413931def53a4fc19bdeedb61..da3a21fcdd7f815a0ae3f364e9ac13b92b94b9b8 100644 (file)
@@ -5,8 +5,7 @@ int foo(int X, int Y);
 void bar(volatile int *VP, int *P, int A,
          _Complex double C, volatile _Complex double VC) {
   
-  VP == P;             // expected-warning {{expression result unused}} \
-                          expected-warning {{comparison}}
+  VP == P;             // expected-warning {{expression result unused}}
   (void)A;
   (void)foo(1,2);      // no warning.