[cfe-commits] r39501 - in /cfe/cfe/trunk: AST/Expr.cpp Sema/Sema.h Sema/SemaExpr.cpp Sema/SemaStmt.cpp clang.xcodeproj/project.pbxproj include/clang/AST/Decl.h include/clang/AST/Expr.h include/clang/AST/Type.h include/clang/Basic/DiagnosticKinds.def

Steve Naroff snaroff at apple.com
Wed Jul 11 09:45:02 PDT 2007


Author: snaroff
Date: Wed Jul 11 11:45:02 2007
New Revision: 39501

URL: http://llvm.org/viewvc/llvm-project?rev=39501&view=rev
Log:
Bug #:
Submitted by:
Reviewed by:
- Added type checking to Sema::ParseReturnStmt (still under construction).
- Improved Expr::isLvalue() and Expr::isModifiableLvalue() to return more
info. Used the info in Sema::CheckAssignmentOperands() to produce more
descriptive diagnostics. Added FIXME to other clients of isLvalue()/etc.
- Added a SourceLocation slot to MemberExpr...changed the implementation
of getSourceRange().
- Added getResultType() helper to FunctionDecl.
- Changed many Diag calls to use the SourceRange support (now that it's
a big hit...we better milk it:-).

Modified:
    cfe/cfe/trunk/AST/Expr.cpp
    cfe/cfe/trunk/Sema/Sema.h
    cfe/cfe/trunk/Sema/SemaExpr.cpp
    cfe/cfe/trunk/Sema/SemaStmt.cpp
    cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
    cfe/cfe/trunk/include/clang/AST/Decl.h
    cfe/cfe/trunk/include/clang/AST/Expr.h
    cfe/cfe/trunk/include/clang/AST/Type.h
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Expr.cpp?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:45:02 2007
@@ -133,31 +133,35 @@
 ///  - *e, the type of e cannot be a function type
 ///  - string-constant
 ///
-bool Expr::isLvalue() {
+Expr::isLvalueResult Expr::isLvalue() {
   // first, check the type (C99 6.3.2.1)
-  if (!TR->isObjectType())
-    return false;
+  if (isa<FunctionType>(TR.getCanonicalType())) // from isObjectType()
+    return LV_NotObjectType;
   if (TR->isIncompleteType() && TR->isVoidType())
-    return false;
+    return LV_IncompleteVoidType;
   
   // the type looks fine, now check the expression
   switch (getStmtClass()) {
   case StringLiteralClass: // C99 6.5.1p4
-    return true;
   case ArraySubscriptExprClass: // C99 6.5.3p4 (e1[e2] == (*((e1)+(e2))))
-    return true;
+    return LV_Valid;
   case DeclRefExprClass: // C99 6.5.1p2
-    return isa<VarDecl>(cast<DeclRefExpr>(this)->getDecl());
+    if (isa<VarDecl>(cast<DeclRefExpr>(this)->getDecl()))
+      return LV_Valid;
+    break;
   case MemberExprClass: // C99 6.5.2.3p4
     const MemberExpr *m = cast<MemberExpr>(this);
-    return m->isArrow() ? true : m->getBase()->isLvalue();
+    return m->isArrow() ? LV_Valid : m->getBase()->isLvalue();
   case UnaryOperatorClass: // C99 6.5.3p4
-    return cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref;
+    if (cast<UnaryOperator>(this)->getOpcode() == UnaryOperator::Deref)
+      return LV_Valid;
+    break;
   case ParenExprClass: // C99 6.5.1p5
     return cast<ParenExpr>(this)->getSubExpr()->isLvalue();
-  default: 
-    return false;
+  default:
+    break;
   }
+  return LV_InvalidExpression;
 }
 
 /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
@@ -165,19 +169,27 @@
 /// if it is a structure or union, does not have any member (including, 
 /// recursively, any member or element of all contained aggregates or unions)
 /// with a const-qualified type.
-bool Expr::isModifiableLvalue() {
-  if (!isLvalue())
-    return false;
-  
+Expr::isModifiableLvalueResult Expr::isModifiableLvalue() {
+  isLvalueResult lvalResult = isLvalue();
+    
+  switch (lvalResult) {
+    case LV_Valid: break;
+    case LV_NotObjectType: return MLV_NotObjectType;
+    case LV_IncompleteVoidType: return MLV_IncompleteVoidType;
+    case LV_InvalidExpression: return MLV_InvalidExpression;
+  }
   if (TR.isConstQualified())
-    return false;
+    return MLV_ConstQualified;
   if (TR->isArrayType())
-    return false;
+    return MLV_ArrayType;
   if (TR->isIncompleteType())
-    return false;
-  if (const RecordType *r = dyn_cast<RecordType>(TR.getCanonicalType()))
-    return r->isModifiableLvalue();
-  return true;    
+    return MLV_IncompleteType;
+    
+  if (const RecordType *r = dyn_cast<RecordType>(TR.getCanonicalType())) {
+    if (r->hasConstFields()) 
+      return MLV_ConstQualified;
+  }
+  return MLV_Valid;    
 }
 
 /// isConstantExpr - this recursive routine will test if an expression is

Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:45:02 2007
@@ -292,7 +292,7 @@
     Expr *cond, Expr *lhs, Expr *rhs, SourceLocation questionLoc);
   
   /// type checking unary operators (subroutines of ParseUnaryOp).
-  // C99 6.5.3.1, 6.5.3.2, 6.5.3.4
+  /// C99 6.5.3.1, 6.5.3.2, 6.5.3.4
   QualType CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc);   
   QualType CheckAddressOfOperand(Expr *op, SourceLocation OpLoc);
   QualType CheckIndirectionOperand(Expr *op, SourceLocation OpLoc);

Modified: cfe/cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaExpr.cpp?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaExpr.cpp Wed Jul 11 11:45:02 2007
@@ -352,7 +352,8 @@
   if (!MemberDecl)
     return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName());
     
-  return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
+  return new MemberExpr((Expr*)Base, OpKind == tok::arrow, 
+                        MemberDecl, MemberLoc);
 }
 
 /// ParseCallExpr - Handle a call to Fn with the specified array of arguments.
@@ -835,15 +836,32 @@
   QualType lhsType = lex->getType();
   QualType rhsType = compoundType.isNull() ? rex->getType() : compoundType;
   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, lex->getSourceRange());
-    hadError = true;
-  } else if (!lex->isModifiableLvalue()) { // C99 6.5.16p2
-    Diag(loc, diag::err_typecheck_assign_non_lvalue, lex->getSourceRange());
-    return QualType(); // no need to continue checking...
+  Expr::isModifiableLvalueResult mlval = lex->isModifiableLvalue(); 
+
+  switch (mlval) { // C99 6.5.16p2
+    case Expr::MLV_Valid: 
+      break;
+    case Expr::MLV_ConstQualified:
+      Diag(loc, diag::err_typecheck_assign_const, lex->getSourceRange());
+      hadError = true;
+      break;
+    case Expr::MLV_ArrayType: 
+      Diag(loc, diag::err_typecheck_array_not_modifiable_lvalue,
+           lhsType.getAsString(), lex->getSourceRange());
+      return QualType(); 
+    case Expr::MLV_NotObjectType: 
+      Diag(loc, diag::err_typecheck_non_object_not_modifiable_lvalue,
+           lhsType.getAsString(), lex->getSourceRange());
+      return QualType();
+    case Expr::MLV_InvalidExpression:
+      Diag(loc, diag::err_typecheck_expression_not_modifiable_lvalue,
+           lex->getSourceRange());
+      return QualType();
+    case Expr::MLV_IncompleteType:
+    case Expr::MLV_IncompleteVoidType:
+      Diag(loc, diag::err_typecheck_incomplete_type_not_modifiable_lvalue,
+           lhsType.getAsString(), lex->getSourceRange());
+      return QualType();
   }
   if (lhsType == rhsType) // common case, fast path...
     return lhsType;
@@ -864,16 +882,22 @@
   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);
+      Diag(loc, diag::ext_typecheck_assign_pointer_from_int,
+           lex->getSourceRange(), rex->getSourceRange());
     break;
   case IntFromPointer:
-    Diag(loc, diag::ext_typecheck_assign_int_from_pointer);
+    Diag(loc, diag::ext_typecheck_assign_int_from_pointer,
+         lex->getSourceRange(), rex->getSourceRange());
     break;
   case IncompatiblePointer:
-    Diag(loc, diag::ext_typecheck_assign_incompatible_pointer);
+    Diag(loc, diag::ext_typecheck_assign_incompatible_pointer,
+         lhsType.getAsString(), rhsType.getAsString(),
+         lex->getSourceRange(), rex->getSourceRange());
     break;
   case CompatiblePointerDiscardsQualifiers:
-    Diag(loc, diag::ext_typecheck_assign_discards_qualifiers);
+    Diag(loc, diag::ext_typecheck_assign_discards_qualifiers,
+         lhsType.getAsString(), rhsType.getAsString(),
+         lex->getSourceRange(), rex->getSourceRange());
     break;
   }
   return hadError ? QualType() : resType;
@@ -903,7 +927,9 @@
   }
   // At this point, we know we have a real or pointer type. Now make sure
   // the operand is a modifiable lvalue.
-  if (!op->isModifiableLvalue()) {
+  Expr::isModifiableLvalueResult mlval = op->isModifiableLvalue();
+  if (mlval != Expr::MLV_Valid) {
+    // FIXME: emit a more precise diagnostic...
     Diag(OpLoc, diag::err_typecheck_invalid_lvalue_incr_decr,
          op->getSourceRange());
     return QualType();
@@ -941,11 +967,12 @@
 /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
 QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
   Decl *dcl = getPrimaryDeclaration(op);
+  Expr::isLvalueResult lval = op->isLvalue();
   
-  if (!op->isLvalue()) { // C99 6.5.3.2p1
+  if (lval != Expr::LV_Valid) { // C99 6.5.3.2p1
     if (dcl && isa<FunctionDecl>(dcl)) // allow function designators
       ;  
-    else {
+    else { // FIXME: emit more specific diag...
       Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof, 
            op->getSourceRange());
       return QualType();
@@ -973,6 +1000,7 @@
   
   assert(!qType.isNull() && "no type for * expression");
 
+  // FIXME: need to check if the pointee is an incomplete type. Find spec ref.
   if (PointerType *PT = dyn_cast<PointerType>(qType.getCanonicalType()))
     return PT->getPointeeType();
   Diag(OpLoc, diag::err_typecheck_indirection_expr, qType.getAsString(),

Modified: cfe/cfe/trunk/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaStmt.cpp?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaStmt.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaStmt.cpp Wed Jul 11 11:45:02 2007
@@ -122,6 +122,54 @@
 
 Action::StmtResult
 Sema::ParseReturnStmt(SourceLocation ReturnLoc, ExprTy *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.
+  QualType lhsType = CurFunctionDecl->getResultType();
+
+  if (!RetValExp)
+    return new ReturnStmt((Expr*)RetValExp);
+    
+  // C99 6.8.6.4p1
+  if (lhsType->isVoidType()) {
+    // a void function may not return a value
+    // non-void function "voidFunc" should return a value
+  }
+
+  QualType rhsType = ((Expr *)RetValExp)->getType();
+
+  if (lhsType == rhsType) // common case, fast path...
+    return new ReturnStmt((Expr*)RetValExp);
+  
+  AssignmentConversionResult result;
+  QualType resType = UsualAssignmentConversions(lhsType, rhsType, result);
+  bool hadError = false;
+  
+  // decode the result (notice that extensions still return a type).
+  switch (result) {
+  case Compatible:
+    break;
+  case Incompatible:
+    Diag(ReturnLoc, diag::err_typecheck_return_incompatible, 
+         lhsType.getAsString(), rhsType.getAsString(),
+         ((Expr *)RetValExp)->getSourceRange());
+    hadError = true;
+    break;
+  case PointerFromInt:
+    // check for null pointer constant (C99 6.3.2.3p3)
+    if (!((Expr *)RetValExp)->isNullPointerConstant())
+      Diag(ReturnLoc, diag::ext_typecheck_return_pointer_from_int);
+    break;
+  case IntFromPointer:
+    Diag(ReturnLoc, diag::ext_typecheck_return_int_from_pointer);
+    break;
+  case IncompatiblePointer:
+    Diag(ReturnLoc, diag::ext_typecheck_return_incompatible_pointer);
+    break;
+  case CompatiblePointerDiscardsQualifiers:
+    Diag(ReturnLoc, diag::ext_typecheck_return_discards_qualifiers);
+    break;
+  }
   return new ReturnStmt((Expr*)RetValExp);
 }
 

Modified: cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/cfe/trunk/clang.xcodeproj/project.pbxproj Wed Jul 11 11:45:02 2007
@@ -100,6 +100,23 @@
 		DED7D9E50A5257F6003AD0FB /* ScratchBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DED7D9E40A5257F6003AD0FB /* ScratchBuffer.cpp */; };
 /* End PBXBuildFile section */
 
+/* Begin PBXBuildStyle section */
+		84FCE23B0C08F6EF00F0C622 /* Development */ = {
+			isa = PBXBuildStyle;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+			};
+			name = Development;
+		};
+		84FCE23C0C08F6EF00F0C622 /* Deployment */ = {
+			isa = PBXBuildStyle;
+			buildSettings = {
+				COPY_PHASE_STRIP = YES;
+			};
+			name = Deployment;
+		};
+/* End PBXBuildStyle section */
+
 /* Begin PBXCopyFilesBuildPhase section */
 		8DD76F690486A84900D96B5E /* CopyFiles */ = {
 			isa = PBXCopyFilesBuildPhase;
@@ -528,10 +545,15 @@
 		08FB7793FE84155DC02AAC07 /* Project object */ = {
 			isa = PBXProject;
 			buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+			buildSettings = {
+			};
+			buildStyles = (
+				84FCE23B0C08F6EF00F0C622 /* Development */,
+				84FCE23C0C08F6EF00F0C622 /* Deployment */,
+			);
 			hasScannedForEncodings = 1;
 			mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
 			projectDirPath = "";
-			projectRoot = "";
 			targets = (
 				8DD76F620486A84900D96B5E /* clang */,
 			);

Modified: cfe/cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Decl.h?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Decl.h Wed Jul 11 11:45:02 2007
@@ -210,6 +210,9 @@
   }
   void setParams(VarDecl **NewParamInfo, unsigned NumParams);
 
+  QualType getResultType() { 
+    return cast<FunctionType>(getType())->getResultType();
+  }
   StorageClass getStorageClass() const { return SClass; }
     
   // Implement isa/cast/dyncast/etc.

Modified: cfe/cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Expr.h?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Expr.h Wed Jul 11 11:45:02 2007
@@ -53,14 +53,29 @@
   ///  - *e, the type of e cannot be a function type
   ///  - string-constant
   ///
-  bool isLvalue();
+  enum isLvalueResult {
+    LV_Valid,
+    LV_NotObjectType,
+    LV_IncompleteVoidType,
+    LV_InvalidExpression
+  };
+  isLvalueResult isLvalue();
   
   /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type,
   /// does not have an incomplete type, does not have a const-qualified type,
   /// and if it is a structure or union, does not have any member (including, 
   /// recursively, any member or element of all contained aggregates or unions)
   /// with a const-qualified type.
-  bool isModifiableLvalue();
+  enum isModifiableLvalueResult {
+    MLV_Valid,
+    MLV_NotObjectType,
+    MLV_IncompleteVoidType,
+    MLV_InvalidExpression,
+    MLV_IncompleteType,
+    MLV_ConstQualified,
+    MLV_ArrayType
+  };
+  isModifiableLvalueResult isModifiableLvalue();
   
   bool isNullPointerConstant() const;
 
@@ -354,18 +369,18 @@
 class MemberExpr : public Expr {
   Expr *Base;
   FieldDecl *MemberDecl;
+  SourceLocation MemberLoc;
   bool IsArrow;      // True if this is "X->F", false if this is "X.F".
 public:
-  MemberExpr(Expr *base, bool isarrow, FieldDecl *memberdecl) 
+  MemberExpr(Expr *base, bool isarrow, FieldDecl *memberdecl, SourceLocation l) 
     : Expr(MemberExprClass, memberdecl->getType()),
-      Base(base), MemberDecl(memberdecl), IsArrow(isarrow) {}
+      Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow) {}
   
   Expr *getBase() const { return Base; }
   FieldDecl *getMemberDecl() const { return MemberDecl; }
   bool isArrow() const { return IsArrow; }
   virtual SourceRange getSourceRange() const {
-    return SourceRange(getBase()->getLocStart(),
-                       getMemberDecl()->getLocation());
+    return SourceRange(getBase()->getLocStart(), MemberLoc);
   }
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 

Modified: cfe/cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/AST/Type.h?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Type.h Wed Jul 11 11:45:02 2007
@@ -519,7 +519,7 @@
   // FIXME: This predicate is a helper to QualType/Type. It needs to 
   // recursively check all fields for const-ness. If any field is declared
   // const, it needs to return false. 
-  bool isModifiableLvalue() const { return true; } 
+  bool hasConstFields() const { return false; } 
   
   static bool classof(const Type *T);
   static bool classof(const RecordType *) { return true; }

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39501&r1=39500&r2=39501&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:45:02 2007
@@ -546,13 +546,13 @@
 DIAG(err_typecheck_unary_expr, ERROR,
      "invalid argument type to unary expression '%0'")
 DIAG(err_typecheck_indirection_expr, ERROR,
-     "indirection requires a pointer ('%0' operand invalid)")
+     "indirection requires a pointer operand ('%0' invalid)")
 DIAG(err_typecheck_invalid_operands, ERROR,
      "invalid operands to binary expression ('%0' and '%1')")
 DIAG(ext_typecheck_comparison_of_pointer_integer, EXTENSION,
      "comparison between pointer and integer")
 DIAG(err_typecheck_assign_const, ERROR,
-     "assignment of read-only variable")
+     "read-only variable is not assignable")
 DIAG(err_typecheck_assign_incompatible, ERROR,
      "incompatible types in assignment ('%0' and '%1')")
 DIAG(ext_typecheck_assign_int_from_pointer, EXTENSION,
@@ -560,11 +560,17 @@
 DIAG(ext_typecheck_assign_pointer_from_int, EXTENSION,
      "assignment makes pointer from integer without a cast")
 DIAG(ext_typecheck_assign_incompatible_pointer, EXTENSION,
-     "assignment from incompatible pointer type")
+     "assignment from incompatible pointer type ('%0' and '%1')")
 DIAG(ext_typecheck_assign_discards_qualifiers, EXTENSION,
-     "assignment discards qualifiers from pointer target type")
-DIAG(err_typecheck_assign_non_lvalue, ERROR,
-     "invalid lvalue in assignment")
+     "assignment discards qualifiers from pointer target type ('%0' and '%1')")
+DIAG(err_typecheck_array_not_modifiable_lvalue, ERROR,
+     "array type '%0' is not assignable")
+DIAG(err_typecheck_non_object_not_modifiable_lvalue, ERROR,
+     "non-object type '%0' is not assignable")
+DIAG(err_typecheck_expression_not_modifiable_lvalue, ERROR,
+     "expression is not assignable")
+DIAG(err_typecheck_incomplete_type_not_modifiable_lvalue, ERROR,
+     "incomplete type '%0' is not assignable")
 DIAG(err_typecheck_call_too_few_args, ERROR,
      "too few arguments to function")
 DIAG(err_typecheck_call_too_many_args, ERROR,
@@ -579,6 +585,16 @@
      "passing argument %0 from incompatible pointer type")
 DIAG(ext_typecheck_passing_discards_qualifiers, EXTENSION,
      "passing argument %0 discards qualifiers from pointer target type")
+DIAG(err_typecheck_return_incompatible, ERROR,
+     "incompatible types in return ('%0' and '%1')")
+DIAG(ext_typecheck_return_int_from_pointer, EXTENSION,
+     "return makes integer from pointer without a cast")
+DIAG(ext_typecheck_return_pointer_from_int, EXTENSION,
+     "return makes pointer from integer without a cast")
+DIAG(ext_typecheck_return_incompatible_pointer, EXTENSION,
+     "return from incompatible pointer type")
+DIAG(ext_typecheck_return_discards_qualifiers, EXTENSION,
+     "return discards qualifiers from pointer target type")
 DIAG(err_typecheck_cond_expect_scalar, ERROR,
      "used type '%0' where arithmetic or pointer type is required")
 DIAG(err_typecheck_cond_incompatible_operands, ERROR,





More information about the cfe-commits mailing list