forked from OSchip/llvm-project
Add Type::getAsBuiltinType() and Type::builtinTypesAreCompatible().
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). llvm-svn: 41476
This commit is contained in:
parent
fc6ffa2513
commit
808eb8fe88
|
@ -75,6 +75,18 @@ bool Type::isComplexType() const {
|
||||||
return isa<ComplexType>(CanonicalType);
|
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 {
|
const FunctionType *Type::getAsFunctionType() const {
|
||||||
// If this is directly a function type, return it.
|
// If this is directly a function type, return it.
|
||||||
if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
|
if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
|
||||||
|
@ -204,6 +216,12 @@ const OCUVectorType *Type::getAsOCUVectorType() const {
|
||||||
return 0;
|
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
|
// C99 6.2.7p1: If both are complete types, then the following additional
|
||||||
// requirements apply...FIXME (handle compatibility across source files).
|
// 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
|
case Type::Tagged: // handle structures, unions
|
||||||
return tagTypesAreCompatible(lcanon, rcanon);
|
return tagTypesAreCompatible(lcanon, rcanon);
|
||||||
case Type::Builtin:
|
case Type::Builtin:
|
||||||
return false;
|
return builtinTypesAreCompatible(lcanon, rcanon);
|
||||||
default:
|
default:
|
||||||
assert(0 && "unexpected type");
|
assert(0 && "unexpected type");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1109,9 +1109,10 @@ inline QualType Sema::CheckCompareOperands( // C99 6.5.8
|
||||||
// All of the following pointer related warnings are GCC extensions, except
|
// All of the following pointer related warnings are GCC extensions, except
|
||||||
// when handling null pointer constants. One day, we can consider making them
|
// when handling null pointer constants. One day, we can consider making them
|
||||||
// errors (when -pedantic-errors is enabled).
|
// errors (when -pedantic-errors is enabled).
|
||||||
if (lType->isPointerType() && rType->isPointerType()) {
|
if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2
|
||||||
if (!LHSIsNull && !RHSIsNull &&
|
if (!LHSIsNull && !RHSIsNull &&
|
||||||
!Type::pointerTypesAreCompatible(lType, rType)) {
|
!Type::pointerTypesAreCompatible(lType.getUnqualifiedType(),
|
||||||
|
rType.getUnqualifiedType())) {
|
||||||
Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
|
Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
|
||||||
lType.getAsString(), rType.getAsString(),
|
lType.getAsString(), rType.getAsString(),
|
||||||
lex->getSourceRange(), rex->getSourceRange());
|
lex->getSourceRange(), rex->getSourceRange());
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace clang {
|
||||||
class TagType;
|
class TagType;
|
||||||
class FunctionType;
|
class FunctionType;
|
||||||
class OCUVectorType;
|
class OCUVectorType;
|
||||||
|
class BuiltinType;
|
||||||
|
|
||||||
/// QualType - For efficiency, we don't store CVR-qualified types as nodes on
|
/// 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
|
/// 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
|
// Type Checking Functions: Check to see if this type is structurally the
|
||||||
// specified type, ignoring typedefs, and return a pointer to the best type
|
// specified type, ignoring typedefs, and return a pointer to the best type
|
||||||
// we can.
|
// we can.
|
||||||
|
const BuiltinType *getAsBuiltinType() const;
|
||||||
const FunctionType *getAsFunctionType() const;
|
const FunctionType *getAsFunctionType() const;
|
||||||
const PointerType *getAsPointerType() const;
|
const PointerType *getAsPointerType() const;
|
||||||
const ReferenceType *getAsReferenceType() const;
|
const ReferenceType *getAsReferenceType() const;
|
||||||
|
@ -297,6 +299,7 @@ public:
|
||||||
static bool referenceTypesAreCompatible(QualType, QualType); // C++ 5.17p6
|
static bool referenceTypesAreCompatible(QualType, QualType); // C++ 5.17p6
|
||||||
static bool functionTypesAreCompatible(QualType, QualType); // C99 6.7.5.3p15
|
static bool functionTypesAreCompatible(QualType, QualType); // C99 6.7.5.3p15
|
||||||
static bool arrayTypesAreCompatible(QualType, QualType); // C99 6.7.5.2p6
|
static bool arrayTypesAreCompatible(QualType, QualType); // C99 6.7.5.2p6
|
||||||
|
static bool builtinTypesAreCompatible(QualType, QualType);
|
||||||
private:
|
private:
|
||||||
QualType getCanonicalTypeInternal() const { return CanonicalType; }
|
QualType getCanonicalTypeInternal() const { return CanonicalType; }
|
||||||
friend class QualType;
|
friend class QualType;
|
||||||
|
|
|
@ -6,3 +6,7 @@ int test(char *C) { // nothing here should warn.
|
||||||
return C != 0;
|
return C != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int equal(char *a, const char *b)
|
||||||
|
{
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ int foo(int X, int Y);
|
||||||
void bar(volatile int *VP, int *P, int A,
|
void bar(volatile int *VP, int *P, int A,
|
||||||
_Complex double C, volatile _Complex double VC) {
|
_Complex double C, volatile _Complex double VC) {
|
||||||
|
|
||||||
VP == P; // expected-warning {{expression result unused}} \
|
VP == P; // expected-warning {{expression result unused}}
|
||||||
expected-warning {{comparison}}
|
|
||||||
(void)A;
|
(void)A;
|
||||||
(void)foo(1,2); // no warning.
|
(void)foo(1,2); // no warning.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue