summaryrefslogtreecommitdiffstats
path: root/clang/AST/SemaExpr.cpp
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-05-11 04:00:31 +0000
committerSteve Naroff <snaroff@apple.com>2007-05-11 04:00:31 +0000
commit1f4d72724e5d61dfeee5c36018fb353f3d8e2c3f (patch)
treeb67d2f9fcda77d3e68a11e9ad2da195f11f55d7e /clang/AST/SemaExpr.cpp
parentb8c289df7a385a2e6f0916286d67291d1f6d4ba7 (diff)
downloadbcm5719-llvm-1f4d72724e5d61dfeee5c36018fb353f3d8e2c3f.tar.gz
bcm5719-llvm-1f4d72724e5d61dfeee5c36018fb353f3d8e2c3f.zip
Bug #:
Submitted by: Reviewed by: - Enhanced UsualAssignmentConversions() to properly handle type qualifiers on pointers. - Added helper function Sema::pointerTypeQualifiersAlign(). - Noticed several errors improperly named "ext_" (fixed). - Combined structureTypesAreCompatible/unionTypesAreCompatible into tagTypesAreCompatible. - Renamed Type::getCanonicalType() to Type::getCanonicalTypeInternal(). It will never confuse/bite me again:-) - Added a couple extension diagnostics for discarded type qualifiers. llvm-svn: 39439
Diffstat (limited to 'clang/AST/SemaExpr.cpp')
-rw-r--r--clang/AST/SemaExpr.cpp93
1 files changed, 65 insertions, 28 deletions
diff --git a/clang/AST/SemaExpr.cpp b/clang/AST/SemaExpr.cpp
index 1eb8f1c0750..7bed03575bf 100644
--- a/clang/AST/SemaExpr.cpp
+++ b/clang/AST/SemaExpr.cpp
@@ -317,10 +317,10 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
unsigned NumArgsToCheck = NumArgsInCall;
if (NumArgsInCall < NumArgsInProto)
- Diag(LParenLoc, diag::ext_typecheck_call_too_few_args);
+ Diag(LParenLoc, diag::err_typecheck_call_too_few_args);
else if (NumArgsInCall > NumArgsInProto) {
if (!proto->isVariadic())
- Diag(LParenLoc, diag::ext_typecheck_call_too_many_args);
+ Diag(LParenLoc, diag::err_typecheck_call_too_many_args);
NumArgsToCheck = NumArgsInProto;
}
// Continue to check argument types (even if we have too few/many args).
@@ -353,6 +353,9 @@ ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
case IncompatiblePointer:
Diag(l, diag::ext_typecheck_passing_incompatible_pointer, utostr(i+1));
break;
+ case CompatiblePointerDiscardsQualifiers:
+ Diag(l, diag::ext_typecheck_passing_discards_qualifiers, utostr(i+1));
+ break;
case Incompatible:
return Diag(l, diag::err_typecheck_passing_incompatible, utostr(i+1));
}
@@ -449,6 +452,39 @@ QualType Sema::UsualArithmeticConversions(QualType t1, QualType t2) {
return Context.maxIntegerType(lhs, rhs);
}
+// C99 6.5.16.1p1: both operands are pointers to qualified or
+// unqualified versions of compatible types, and the type *pointed to* by
+// the left has all the qualifiers of the type *pointed to* by the right;
+bool Sema::pointerTypeQualifiersAlign(QualType lhsType, QualType rhsType) {
+ QualType lPointee, rPointee;
+
+ // get the "pointed to" type (ignoring qualifiers at the top level)
+ lPointee = cast<PointerType>(lhsType.getCanonicalType())->getPointeeType();
+ rPointee = cast<PointerType>(rhsType.getCanonicalType())->getPointeeType();
+
+ // make sure we operate on the canonical type
+ lPointee = lPointee.getCanonicalType();
+ rPointee = rPointee.getCanonicalType();
+
+ while (!rPointee.isNull() && !lPointee.isNull()) {
+ unsigned rightQuals = rPointee.getQualifiers();
+ if (rightQuals && (rightQuals != lPointee.getQualifiers()))
+ return false;
+
+ // if necessary, continue checking pointees...
+ if (const PointerType *rPtr = dyn_cast<PointerType>(rPointee))
+ rPointee = rPtr->getPointeeType().getCanonicalType();
+ else
+ rPointee = QualType();
+
+ if (const PointerType *lPtr = dyn_cast<PointerType>(lPointee))
+ lPointee = lPtr->getPointeeType().getCanonicalType();
+ else
+ rPointee = QualType();
+ }
+ return true;
+}
+
/// UsualAssignmentConversions (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:
@@ -483,9 +519,11 @@ QualType Sema::UsualAssignmentConversions(QualType lhsType, QualType rhsType,
r = PointerFromInt;
return rhsType;
}
- // FIXME: make sure the qualifier are matching
if (rhsType->isPointerType()) {
- if (!Type::pointerTypesAreCompatible(lhsType, rhsType))
+ if (Type::pointerTypesAreCompatible(lhsType, rhsType)) {
+ if (!pointerTypeQualifiersAlign(lhsType, rhsType))
+ r = CompatiblePointerDiscardsQualifiers;
+ } else
r = IncompatiblePointer;
return rhsType;
}
@@ -496,21 +534,18 @@ QualType Sema::UsualAssignmentConversions(QualType lhsType, QualType rhsType,
r = IntFromPointer;
return rhsType;
}
- // - both operands are pointers to qualified or unqualified versions of
- // compatible types, and the type pointed to by the left has *all* the
- // qualifiers of the type pointed to by the right;
if (lhsType->isPointerType()) {
- if (!Type::pointerTypesAreCompatible(lhsType, rhsType))
+ if (Type::pointerTypesAreCompatible(lhsType, rhsType)) {
+ if (!pointerTypeQualifiersAlign(lhsType, rhsType))
+ r = CompatiblePointerDiscardsQualifiers;
+ } else
r = IncompatiblePointer;
return rhsType;
}
- } else if (lhsType->isStructureType() && rhsType->isStructureType()) {
- if (Type::structureTypesAreCompatible(lhsType, rhsType))
+ } else if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
+ if (Type::tagTypesAreCompatible(lhsType, rhsType))
return rhsType;
- } else if (lhsType->isUnionType() && rhsType->isUnionType()) {
- if (Type::unionTypesAreCompatible(lhsType, rhsType))
- return rhsType;
- }
+ }
r = Incompatible;
return QualType();
}
@@ -644,18 +679,16 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
{
QualType lhsType = lex->getType();
QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType;
-
- // FIXME: consider hacking isModifiableLvalue to return an enum that
- // communicates why the expression/type wasn't a modifiableLvalue.
+ bool hadError = false;
// this check is done first to give a more precise diagnostic.
+ // isModifiableLvalue() will also check for "const".
if (lhsType.isConstQualified()) {
Diag(loc, diag::err_typecheck_assign_const);
- return QualType();
- }
- if (!lex->isModifiableLvalue()) { // this includes checking for "const"
- Diag(loc, diag::ext_typecheck_assign_non_lvalue);
- return QualType();
+ hadError = true;
+ } else if (!lex->isModifiableLvalue()) { // C99 6.5.16p2
+ Diag(loc, diag::err_typecheck_assign_non_lvalue);
+ return QualType(); // no need to continue checking...
}
if (lhsType == rhsType) // common case, fast path...
return lhsType;
@@ -666,23 +699,27 @@ inline QualType Sema::CheckAssignmentOperands( // C99 6.5.16.1
// decode the result (notice that extensions still return a type).
switch (result) {
case Compatible:
- return resType;
+ break;
case Incompatible:
Diag(loc, diag::err_typecheck_assign_incompatible);
- return QualType();
+ hadError = true;
+ break;
case PointerFromInt:
// check for null pointer constant (C99 6.3.2.3p3)
if (compoundType.isNull() && !rex->isNullPointerConstant())
Diag(loc, diag::ext_typecheck_assign_pointer_from_int);
- return resType;
+ break;
case IntFromPointer:
Diag(loc, diag::ext_typecheck_assign_int_from_pointer);
- return resType;
+ break;
case IncompatiblePointer:
Diag(loc, diag::ext_typecheck_assign_incompatible_pointer);
- return resType;
+ break;
+ case CompatiblePointerDiscardsQualifiers:
+ Diag(loc, diag::ext_typecheck_assign_discards_qualifiers);
+ break;
}
- assert(0 && "should never get here");
+ return hadError ? QualType() : resType;
}
inline QualType Sema::CheckCommaOperands( // C99 6.5.17
OpenPOWER on IntegriCloud