瀏覽代碼

HPCC-10977 Add warning categories to the parser

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 11 年之前
父節點
當前提交
29b0e3b271

+ 3 - 4
ecl/hql/hqlerror.cpp

@@ -42,9 +42,8 @@ ErrorSeverity queryDefaultSeverity(WarnErrorCategory category)
         return SeverityFatal;
     if (category == CategoryInformation)
         return SeverityInfo;
-//MORE: Should the following be enabled?
-//    if (category == CategoryMistake)
-//        return SeverityError;
+    if (category == CategoryMistake)
+        return SeverityError;
     return SeverityWarning;
 }
 
@@ -61,7 +60,7 @@ WarnErrorCategory getCategory(const char * category)
     if (strieq(category, "efficiency"))
         return CategoryEfficiency;
     if (strieq(category, "fold"))
-        CategoryFolding;
+        return CategoryFolding;
     if (strieq(category, "future"))
         return CategoryFuture;
     if (strieq(category, "ignored"))

+ 9 - 8
ecl/hql/hqlgram.hpp

@@ -564,26 +564,27 @@ public:
     IHqlExpression * nextEnumValue();
 
 // Error handling
-    void doReportWarning(int warnNo, const char *msg, const char *filename, int lineno, int column, int pos);
+    void doReportWarning(WarnErrorCategory category, int warnNo, const char *msg, const char *filename, int lineno, int column, int pos);
     void reportError(int errNo, const attribute& a, const char* format, ...) __attribute__((format(printf, 4, 5)));
     void reportError(int errNo, const ECLlocation & pos, const char* format, ...) __attribute__((format(printf, 4, 5)));
-    void reportMacroExpansionPosition(int errNo, HqlLex * lexer, bool isError);
+    void reportMacroExpansionPosition(IECLError * warning, HqlLex * lexer);
     void reportErrorUnexpectedX(const attribute & errpos, IAtom * unexpected);
 
     // Don't use overloading: va_list is the same as char*!!
     void reportErrorVa(int errNo, const ECLlocation & a, const char* format, va_list args);
     void reportError(int errNo, const char *msg, int lineno, int column, int position=0);
-    void reportWarning(int warnNo, const ECLlocation & pos, const char* format, ...) __attribute__((format(printf, 4, 5)));
-    void reportWarning(ErrorSeverity severity, int warnNo, const ECLlocation & pos, const char* format, ...) __attribute__((format(printf, 5, 6)));
-    void reportWarningVa(int errNo, const attribute& a, const char* format, va_list args);
-    void reportWarning(int warnNo, const char *msg, int lineno, int column);
+    void reportWarning(WarnErrorCategory category, int warnNo, const ECLlocation & pos, const char* format, ...) __attribute__((format(printf, 5,6)));
+    void reportWarning(WarnErrorCategory category, ErrorSeverity severity, int warnNo, const ECLlocation & pos, const char* format, ...) __attribute__((format(printf, 6, 7)));
+    void reportWarningVa(WarnErrorCategory category, int errNo, const attribute& a, const char* format, va_list args);
+    void reportWarning(WarnErrorCategory category, int warnNo, const char *msg, int lineno, int column);
     void addResult(IHqlExpression *query, const attribute& errpos);
 
     // interface IErrorReceiver
     virtual void reportError(int errNo, const char *msg, const char *filename=NULL, int lineno=0, int column=0, int pos=0);
     virtual void report(IECLError * error);
     virtual IECLError * mapError(IECLError * error);
-    virtual void reportWarning(int warnNo, const char *msg, const char *filename=NULL, int lineno=0, int column=0, int pos=0);
+
+    void reportWarning(WarnErrorCategory category, int warnNo, const char *msg, const char *filename=NULL, int lineno=0, int column=0, int pos=0);
     virtual size32_t errCount();
     virtual size32_t warnCount();
     
@@ -1100,7 +1101,7 @@ class HqlLex
 
         IHqlExpression *lookupSymbol(IIdAtom * name, const attribute& errpos);
         void reportError(const YYSTYPE & returnToken, int errNo, const char *format, ...) __attribute__((format(printf, 4, 5)));
-        void reportWarning(const YYSTYPE & returnToken, int warnNo, const char *format, ...) __attribute__((format(printf, 4, 5)));
+        void reportWarning(WarnErrorCategory category, const YYSTYPE & returnToken, int warnNo, const char *format, ...) __attribute__((format(printf, 5, 6)));
 
         void beginNestedHash(unsigned kind) { hashendKinds.append(kind); hashendFlags.append(0); }
         void endNestedHash() { hashendKinds.pop(); hashendFlags.pop(); }

+ 14 - 14
ecl/hql/hqlgram.y

@@ -668,7 +668,7 @@ importItem
     | importSelectorList AS '*'
                         {
                             if (queryLegacyImportSemantics())
-                                parser->reportWarning(ERR_DEPRECATED, $1.pos, "IMPORT <module> AS * is deprecated, use IMPORT * FROM <module>");
+                                parser->reportWarning(CategoryDeprecated, ERR_DEPRECATED, $1.pos, "IMPORT <module> AS * is deprecated, use IMPORT * FROM <module>");
                             else
                                 parser->reportError(ERR_DEPRECATED, $1.pos, "IMPORT <module> AS * is deprecated, use IMPORT * FROM <module>");
                             parser->processImportAll($1);
@@ -1459,7 +1459,7 @@ metaCommandWithNoSemicolon
     : setMetaCommand
                         {
                             //These are really treated like actions now, this is here for backward compatibility
-                            parser->reportWarning(ERR_DEPRECATED, $1.pos, "#command with no trailing semicolon is deprecated");
+                            parser->reportWarning(CategoryDeprecated, ERR_DEPRECATED, $1.pos, "#command with no trailing semicolon is deprecated");
                             parser->addResult($1.getExpr(), $1);
                             $$.clear();
                         }
@@ -2480,7 +2480,7 @@ actionStmt
                         {
                             parser->normalizeExpression($3);
                             // change error to warning.
-                            parser->reportWarning(WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
+                            parser->reportWarning(CategoryUnusual, WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
                             HqlExprArray list;
                             parser->endList(list);
                             ::Release($3.getExpr());
@@ -3867,7 +3867,7 @@ attriblist
 attrib
     : knownOrUnknownId EQ UNKNOWN_ID        
                         {
-                            parser->reportWarning(WRN_OBSOLETED_SYNTAX,$1.pos,"Syntax obsoleted; use alternative: id = '<string constant>'");
+                            parser->reportWarning(CategoryDeprecated, SeverityError, WRN_OBSOLETED_SYNTAX,$1.pos,"Syntax obsoleted; use alternative: id = '<string constant>'");
                             $$.setExpr(createAttribute($1.getId()->lower(), createConstant(*$3.getId())));
                         }
     | knownOrUnknownId EQ expr %prec reduceAttrib
@@ -5626,7 +5626,7 @@ primexpr1
                             parser->normalizeExpression($3);
                             parser->normalizeExpression($6);
                             // change error to warning.
-                            parser->reportWarning(WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
+                            parser->reportWarning(CategoryUnusual, WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
                             HqlExprArray args;
                             parser->endList(args);
                             ::Release($3.getExpr());
@@ -6081,7 +6081,7 @@ primexpr1
                         }
     | COUNT             {
                             $$.setExpr(parser->getActiveCounter($1));
-                            parser->reportWarning(SeverityError, ERR_COUNTER_NOT_COUNT, $1.pos, "Use of COUNT instead of COUNTER is deprecated");
+                            parser->reportWarning(CategoryDeprecated, SeverityError, ERR_COUNTER_NOT_COUNT, $1.pos, "Use of COUNT instead of COUNTER is deprecated");
                         }
     | COUNTER               {
                             $$.setExpr(parser->getActiveCounter($1));
@@ -6419,7 +6419,7 @@ primexpr1
     | EXISTS '(' expressionList ')'
                         {
                             if (parser->isSingleValuedExpressionList($3))
-                                parser->reportWarning(WRN_SILLY_EXISTS,$1.pos,"EXISTS() on a scalar expression is always true, was this intended?");
+                                parser->reportWarning(CategoryMistake, WRN_SILLY_EXISTS,$1.pos,"EXISTS() on a scalar expression is always true, was this intended?");
 
                             OwnedHqlExpr list = parser->createListFromExpressionList($3);
                             $$.setExpr(createValue(no_existslist, makeBoolType(), LINK(list)));
@@ -7397,7 +7397,7 @@ simpleDictionary
                         {
                             parser->normalizeExpression($3, type_scalar, false);
                             // change error to warning.
-                            parser->reportWarning(WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
+                            parser->reportWarning(CategoryUnusual, WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
                             HqlExprArray list;
                             parser->endList(list);
                             $3.release();
@@ -7647,7 +7647,7 @@ simpleDataSet
                             
                             IHqlExpression * limit = $5.getExpr();
                             if (limit->queryValue() && limit->queryValue()->getIntValue() == 0)
-                                parser->reportWarning(WRN_CHOOSEN_ALL,$1.pos,"Use CHOOSEN(dataset, ALL) to remove implicit choosen.  CHOOSEN(dataset, 0) now returns no records.");
+                                parser->reportWarning(CategoryUnusual, WRN_CHOOSEN_ALL,$1.pos,"Use CHOOSEN(dataset, ALL) to remove implicit choosen.  CHOOSEN(dataset, 0) now returns no records.");
                             $$.setExpr(createDataset(no_choosen, $3.getExpr(), createComma(limit, $6.getExpr())), $1);
                             parser->attachPendingWarnings($$);
                         }
@@ -7859,7 +7859,7 @@ simpleDataSet
                             HqlExprArray sortItems;
                             parser->endList(sortItems);
                             if (!queryAttribute(sortedAtom, sortItems))
-                                parser->reportWarning(WRN_MERGE_RECOMMEND_SORTED, $1.pos, "MERGE without an explicit SORTED() attribute is deprecated");
+                                parser->reportWarning(CategoryDeprecated, WRN_MERGE_RECOMMEND_SORTED, $1.pos, "MERGE without an explicit SORTED() attribute is deprecated");
 
                             IHqlExpression * ds = $3.getExpr();
                             parser->expandSortedAsList(sortItems);
@@ -8108,7 +8108,7 @@ simpleDataSet
                             OwnedHqlExpr newSorted;
                             if (!sorted)
                             {
-                                parser->reportWarning(WRN_MERGE_RECOMMEND_SORTED, $1.pos, "MERGE without an explicit SORTED() attribute is deprecated");
+                                parser->reportWarning(CategoryDeprecated, WRN_MERGE_RECOMMEND_SORTED, $1.pos, "MERGE without an explicit SORTED() attribute is deprecated");
                                 OwnedHqlExpr order = getExistingSortOrder(ds, isLocal, true);
                                 HqlExprArray sorts;
                                 if (order)
@@ -8352,7 +8352,7 @@ simpleDataSet
                             {
                                 parser->checkGrouping($7, dataset,record,grouping);
                                 if (dataset->getOperator() == no_group && isGrouped(dataset))
-                                    parser->reportWarning(WRN_GROUPINGIGNORED, $3.pos, "Grouping of table input will have no effect, was this intended?");
+                                    parser->reportWarning(CategoryIgnored, WRN_GROUPINGIGNORED, $3.pos, "Grouping of table input will have no effect, was this intended?");
                             }
 
                             HqlExprArray args;
@@ -8858,7 +8858,7 @@ simpleDataSet
                         {
                             parser->normalizeExpression($3, type_scalar, false);
                             // change error to warning.
-                            parser->reportWarning(WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
+                            parser->reportWarning(CategoryUnusual, WRN_CASENOCONDITION, $1.pos, "CASE does not have any conditions");
                             HqlExprArray list;
                             parser->endList(list);
                             $3.release();
@@ -12272,7 +12272,7 @@ featureValueList
 featureModifiers
     : '{' featureValueList '}'
                         {
-                            parser->reportWarning(WRN_FEATURE_NOT_REPEAT, $1.pos, "Curly brackets are not used for repeats - they are reserved for future functionality");
+                            parser->reportWarning(CategorySyntax, SeverityError, WRN_FEATURE_NOT_REPEAT, $1.pos, "Curly brackets are not used for repeats - they are reserved for future functionality");
                             $$.setExpr($2.getExpr());
                         }
     ;

+ 70 - 82
ecl/hql/hqlgram2.cpp

@@ -176,9 +176,6 @@ protected:
 };
 
 
-/* This enables warning on a assignall which tries to reassign a field. */
-//#define _WARN_ON_ASSIGNALL
-
 void attribute::annotateExprWithLocation()
 {
     if ((atr_type==t_expr) && expr && !queryLocation(expr))
@@ -964,7 +961,7 @@ IHqlExpression * HqlGram::processUserAggregate(const attribute & mainPos, attrib
     OwnedHqlExpr grouping = itemsAttr ? processSortList(*itemsAttr, no_aggregate, dataset, sortItems, NULL, &attrs) : NULL;
 
     if (grouping && (dataset->getOperator() == no_group) && isGrouped(dataset))
-        reportWarning(WRN_GROUPINGIGNORED, dsAttr.pos, "Grouping of aggregate input will have no effect, was this intended?");
+        reportWarning(CategoryIgnored, WRN_GROUPINGIGNORED, dsAttr.pos, "Grouping of aggregate input will have no effect, was this intended?");
 
     HqlExprArray args;
     args.append(*LINK(dataset));
@@ -1744,11 +1741,8 @@ void HqlGram::addAssignall(IHqlExpression *tgt, IHqlExpression *src, const attri
     assignall = assignall->closeExpr();
     if (assignall->numChildren() > firstAssign) 
         curTransform->addOperand(assignall);
-    else // empty assignall.
-    {
-        //reportWarning(WRN_TRANX_EMPTYASSIGNALL, errpos.pos, "Assignment has no effect; ignored");
+    else
         assignall->Release();
-    }
 }
 
 
@@ -1865,13 +1859,6 @@ void HqlGram::doAddAssignCompound(IHqlExpression * assignall, IHqlExpression * t
                     else
                         doAddAssignment(assignall,LINK(lhs),LINK(rhs),errpos);
                 }
-                else
-                {
-    #ifdef _WARN_ON_ASSIGNALL
-                    StringBuffer fldName;
-                    reportWarning(WRN_TRANX_HASASSIGNEDVALUE, errpos.pos, "A value for \"%s\" has already been specified", getFldName(lhs,fldName).str());
-    #endif
-                }   
             }
         }
     }
@@ -2056,7 +2043,7 @@ void HqlGram::doCheckAssignedNormalizeTransform(HqlExprArray * assigns, IHqlExpr
                         //Not very nice - only ok in some situations....
                         if (cur->hasAttribute(virtualAtom))
                         {
-                            reportWarning(ERR_TRANS_NOVALUE4FIELD, errpos.pos, "Transform does not supply a value for field \"%s\"", fldName.str());
+                            reportWarning(CategorySyntax, ERR_TRANS_NOVALUE4FIELD, errpos.pos, "Transform does not supply a value for field \"%s\"", fldName.str());
                             OwnedHqlExpr null = createNullExpr(cur);
                             if (assigns)
                                 assigns->append(*createAssign(LINK(targetSelected), LINK(null)));
@@ -2254,7 +2241,7 @@ void HqlGram::addFields(const attribute &errpos, IHqlExpression *e, IHqlExpressi
         if (match)
         {
             if (!clone)
-                reportWarning(ERR_REC_DUPFIELD, errpos.pos, "A field called %s is already defined in this record",id->str());
+                reportWarning(CategorySyntax, ERR_REC_DUPFIELD, errpos.pos, "A field called %s is already defined in this record",id->str());
             continue;
         }
 
@@ -2386,7 +2373,7 @@ void HqlGram::addField(const attribute &errpos, IIdAtom * name, ITypeInfo *_type
                     canNotAssignTypeError(fieldType,defvalueType,errpos);
                 IValue * constValue = defaultValue->queryValue();
                 if (constValue && (constValue->rangeCompare(expectedType) > 0))
-                    reportWarning(ERR_TYPE_INCOMPATIBLE, errpos.pos, "%s", "Default value too large");
+                    reportWarning(CategorySyntax, ERR_TYPE_INCOMPATIBLE, errpos.pos, "%s", "Default value too large");
                 if (expectedType->getTypeCode() != type_row)
                 {
                     HqlExprArray allAttrs;
@@ -2414,7 +2401,7 @@ void HqlGram::addField(const attribute &errpos, IIdAtom * name, ITypeInfo *_type
     case type_decimal:
         if (fieldType->getSize() == UNKNOWN_LENGTH)
         {
-            reportWarning(ERR_BAD_FIELD_TYPE, errpos.pos, "Fields of unknown length decimal not currently supported");
+            reportWarning(CategorySyntax, ERR_BAD_FIELD_TYPE, errpos.pos, "Fields of unknown length decimal not currently supported");
             fieldType.setown(makeDecimalType(MAX_DECIMAL_DIGITS, MAX_DECIMAL_PRECISION, fieldType->isSigned()));
         }
         break;
@@ -2448,7 +2435,7 @@ void HqlGram::addField(const attribute &errpos, IIdAtom * name, ITypeInfo *_type
     }
 
     if ((fieldType->getSize() != UNKNOWN_LENGTH) && (fieldType->getSize() > MAX_SENSIBLE_FIELD_LENGTH))
-        reportError(ERR_BAD_FIELD_SIZE, errpos, "Field %s is too large", name->str());
+        reportWarning(CategoryEfficiency, SeverityError, ERR_BAD_FIELD_SIZE, errpos.pos, "Field %s is too large", name->str());
 
     OwnedHqlExpr newField = createField(name, fieldType.getClear(), value.getClear(), attrs);
     OwnedHqlExpr annotated = createLocationAnnotation(LINK(newField), errpos.pos);
@@ -3517,7 +3504,7 @@ void HqlGram::checkMaxCompatible(IHqlExpression * sortOrder, IHqlExpression * va
 void HqlGram::checkSvcAttrNoValue(IHqlExpression* attr, const attribute& errpos)
 {
     if (attr->numChildren()>0)
-        reportWarning(WRN_SVC_ATTRNEEDNOVALUE, errpos.pos,"Service attribute '%s' requires no value; ignored",attr->queryName()->str());
+        reportWarning(CategorySyntax, WRN_SVC_ATTRNEEDNOVALUE, errpos.pos,"Service attribute '%s' requires no value; ignored",attr->queryName()->str());
 }
 
 void cleanupService(IHqlScope*& serviceScope)
@@ -3634,7 +3621,7 @@ IHqlExpression* HqlGram::checkServiceDef(IHqlScope* serviceScope,IIdAtom * name,
 
                 /* should be really an error */
                 if (invalid)
-                    reportWarning(ERR_SVC_INVALIDINCLUDE,errpos.pos,"Invalid include: can not be empty");
+                    reportWarning(CategorySyntax, ERR_SVC_INVALIDINCLUDE,errpos.pos, "Invalid include: can not be empty");
             }
             else if (name == eclrtlAtom)
             {
@@ -3668,7 +3655,7 @@ IHqlExpression* HqlGram::checkServiceDef(IHqlScope* serviceScope,IIdAtom * name,
                 //backward compatibility
             }
             else // unsupported
-                reportWarning(WRN_SVC_UNSUPPORTED_ATTR, errpos.pos, "Unsupported service attribute: '%s'; ignored", name->str());
+                reportWarning(CategorySyntax,WRN_SVC_UNSUPPORTED_ATTR, errpos.pos, "Unsupported service attribute: '%s'; ignored", name->str());
         }
 
         // check attribute conflicts
@@ -3677,7 +3664,7 @@ IHqlExpression* HqlGram::checkServiceDef(IHqlScope* serviceScope,IIdAtom * name,
         if (cApi)   apiAttrs++;
         if (bcdApi) apiAttrs++;
         if (apiAttrs>1)
-            reportWarning(ERR_SVC_ATTRCONFLICTS, errpos.pos, "Attributes eclrtl, bcd, c are conflict: only 1 can be used at a time");
+            reportWarning(CategorySyntax, ERR_SVC_ATTRCONFLICTS, errpos.pos, "Attributes eclrtl, bcd, c are conflict: only 1 can be used at a time");
     }
 
     if (!hasEntrypoint)
@@ -3799,7 +3786,7 @@ bool HqlGram::checkAlienTypeDef(IHqlScope* scope, const attribute& errpos)
             else
             {
                 if (phyLen)
-                    reportWarning(WRN_USRTYPE_EXTRAPHYLEN,errpos.pos,"physicalLength not needed since the type size is known");
+                    reportWarning(CategoryIgnored, WRN_USRTYPE_EXTRAPHYLEN,errpos.pos,"physicalLength not needed since the type size is known");
             }
         }
 
@@ -3865,19 +3852,19 @@ ITypeInfo * HqlGram::checkStringIndex(attribute & strAttr, attribute & idxAttr)
     if (info.knownStart() && (startIndex < 1 || ((strSize != UNKNOWN_LENGTH) && startIndex > strSize)))
     {
         if (startIndex<1)
-            reportWarning(ERR_SUBSTR_INVALIDRANGE, idxAttr.pos,"Invalid substring range: start index %d must >= 1", startIndex);
+            reportWarning(CategoryIndex, ERR_SUBSTR_INVALIDRANGE, idxAttr.pos,"Invalid substring range: start index %d must >= 1", startIndex);
         else  /* assert: strSize != UNKNOWN_LENGTH */
-            reportWarning(ERR_SUBSTR_INVALIDRANGE, idxAttr.pos,"Invalid substring range: index %d out of bound: 1..%d", startIndex, strSize);
+            reportWarning(CategoryIndex, ERR_SUBSTR_INVALIDRANGE, idxAttr.pos,"Invalid substring range: index %d out of bound: 1..%d", startIndex, strSize);
     }
     else if (info.knownEnd() && (endIndex < 1 || ((strSize != UNKNOWN_LENGTH) && endIndex > strSize)))
     {
         if (endIndex < 1)
-            reportWarning(ERR_SUBSTR_INVALIDRANGE, idxAttr.pos, "Invalid substring range: end index %d must >= 1", endIndex);
+            reportWarning(CategoryIndex, ERR_SUBSTR_INVALIDRANGE, idxAttr.pos, "Invalid substring range: end index %d must >= 1", endIndex);
         else
-            reportWarning(ERR_SUBSTR_INVALIDRANGE, idxAttr.pos, "Invalid substring range: index %d out of bound: 1..%d", endIndex, strSize);
+            reportWarning(CategoryIndex, ERR_SUBSTR_INVALIDRANGE, idxAttr.pos, "Invalid substring range: index %d out of bound: 1..%d", endIndex, strSize);
     }
     else if (info.knownStart() && info.knownEnd() && startIndex > endIndex)
-        reportWarning(ERR_SUBSTR_INVALIDRANGE, idxAttr.pos, "Invalid substring range: start index %d > end index %d", startIndex, endIndex);
+        reportWarning(CategoryIndex, ERR_SUBSTR_INVALIDRANGE, idxAttr.pos, "Invalid substring range: start index %d > end index %d", startIndex, endIndex);
 
     unsigned resultSize = UNKNOWN_LENGTH;
 //  if (strSize != UNKNOWN_LENGTH)
@@ -4205,7 +4192,7 @@ IHqlExpression * HqlGram::createSortExpr(node_operator op, attribute & dsAttr, c
     IHqlExpression *sortOrder = processSortList(orderAttr, no_sort, input, args, &joinedClause, &attrs);
     if (!sortOrder)
     {
-        reportError(ERR_SORT_EMPTYLIST, orderAttr, "The list to be sorted on is empty");
+        reportWarning(CategoryMistake, SeverityError, ERR_SORT_EMPTYLIST, orderAttr.pos, "The list to be sorted on is empty");
         return input;
     }
 
@@ -4298,7 +4285,7 @@ void HqlGram::ensureTypeCanBeIndexed(attribute &a)
         default:
             {
                 StringBuffer typeName;
-                reportWarning(ERR_TYPEMISMATCH_STRING, a.pos, "substring applied to value of type %s", getFriendlyTypeStr(t1, typeName).str());
+                reportWarning(CategorySyntax, ERR_TYPEMISMATCH_STRING, a.pos, "substring applied to value of type %s", getFriendlyTypeStr(t1, typeName).str());
                 ensureString(a);
                 break;
             }
@@ -4906,9 +4893,9 @@ void HqlGram::promoteToSameCompareType(attribute &a1, attribute &a2, node_operat
         }
 
         if (alwaysTrue)
-            reportWarning(WRN_COND_ALWAYS_TRUE, a2.pos, "Condition is always true");
+            reportWarning(CategoryFolding, WRN_COND_ALWAYS_TRUE, a2.pos, "Condition is always true");
         if (alwaysFalse)
-            reportWarning(WRN_COND_ALWAYS_FALSE, a2.pos, "Condition is always false");
+            reportWarning(CategoryFolding, WRN_COND_ALWAYS_FALSE, a2.pos, "Condition is always false");
     }
 
 #if 0
@@ -4942,9 +4929,9 @@ void HqlGram::warnIfFoldsToConstant(IHqlExpression * expr, const attribute & err
         if (folded->queryValue())
         {
             if (folded->queryValue()->getBoolValue())
-                reportWarning(WRN_COND_ALWAYS_TRUE, errpos.pos, "Condition is always true");
+                reportWarning(CategoryFolding, WRN_COND_ALWAYS_TRUE, errpos.pos, "Condition is always true");
             else
-                reportWarning(WRN_COND_ALWAYS_FALSE, errpos.pos, "Condition is always false");
+                reportWarning(CategoryFolding, WRN_COND_ALWAYS_FALSE, errpos.pos, "Condition is always false");
         }
     }
 }
@@ -4954,7 +4941,7 @@ void HqlGram::warnIfRecordPacked(IHqlExpression * expr, const attribute & errpos
 {
     IHqlExpression * record = expr->queryRecord();
     if (record && record->hasAttribute(packedAtom))
-        reportWarning(WRN_PACKED_MAY_CHANGE, errpos.pos, "Packed record used for external input or output, packed formats may change");
+        reportWarning(CategoryFuture, WRN_PACKED_MAY_CHANGE, errpos.pos, "Packed record used for external input or output, packed formats may change");
 }
 
 
@@ -5159,7 +5146,7 @@ void HqlGram::checkCaseForDuplicates(HqlExprArray & exprs, attribute &err)
             StringBuffer s;
             s.append("Duplicate case entry: ");
             toECL(e1, s, false);
-            reportWarning(WRN_DUPLICATECASE, err.pos, "%s", s.str());
+            reportWarning(CategoryIgnored, WRN_DUPLICATECASE, err.pos, "%s", s.str());
         }
         else
             e1->setTransformExtraUnlinked(e1);
@@ -5211,7 +5198,7 @@ void HqlGram::checkReal(attribute &a1)
         Owned<ITypeInfo> realType = makeRealType(DEFAULT_REAL_SIZE);
         if (t1->getTypeCode() == type_decimal)
         {
-            reportWarning(ERR_TYPEMISMATCH_REAL, a1.pos, "Decimal implicitly converted to a real");
+            reportWarning(CategoryCast, ERR_TYPEMISMATCH_REAL, a1.pos, "Decimal implicitly converted to a real");
         }
         else
         {
@@ -5252,7 +5239,7 @@ void HqlGram::checkPositive(attribute &a1)
         //MORE: Recode to allow decimal and other types
         Owned<IValue> zero = value->queryType()->castFrom(0, (const char *)NULL);
         if (value->compare(zero) < 0)
-            reportError(ERR_TYPEMISMATCH_INT, a1, "Type mismatch - the value must be positive");
+            reportWarning(CategoryIndex, SeverityError, ERR_TYPEMISMATCH_INT, a1.pos, "Type mismatch - the value must be positive");
     }   
 }
 
@@ -5677,12 +5664,12 @@ IHqlExpression * HqlGram::processSortList(const attribute & errpos, node_operato
         else if (eop == no_constant)
         {
             if ((op != no_hash) && (op != no_hash32) && (op != no_hash64) && (op != no_crc) && (op != no_hashmd5) && (op != no_list))
-                reportWarning(ERR_CONSTANT_DAFT, errpos.pos, "Constant group/sort clauses make no sense");
+                reportWarning(CategoryUnusual, ERR_CONSTANT_DAFT, errpos.pos, "Constant group/sort clauses make no sense");
         }
         else if (!containsAnyDataset(&e))
         {
             if ((op != no_hash) && (op != no_hash32) && (op != no_hash64) && (op != no_crc) && (op != no_hashmd5) && (op != no_list))
-                reportWarning(WRN_SORT_INVARIANT, errpos.pos, "Sort/Group element is not related to the dataset");
+                reportWarning(CategoryUnusual, WRN_SORT_INVARIANT, errpos.pos, "Sort/Group element is not related to the dataset");
         }
         else if (e.isDatarow() && expandRows)
         {
@@ -5791,13 +5778,13 @@ void HqlGram::reportErrorUnexpectedX(const attribute& errpos, IAtom * unexpected
     reportError(ERR_UNEXPECTED_ATTRX, errpos, "Unexpected attribute %s", unexpected->str());
 }
 
-void HqlGram::doReportWarning(int warnNo, const char *msg, const char *filename, int lineno, int column, int pos)
+void HqlGram::doReportWarning(WarnErrorCategory category, int warnNo, const char *msg, const char *filename, int lineno, int column, int pos)
 {
-    Owned<IECLError> error = createECLError(CategoryUnknown, SeverityWarning, warnNo, msg, filename, lineno, column, pos);
+    Owned<IECLError> error = createECLError(category, queryDefaultSeverity(category), warnNo, msg, filename, lineno, column, pos);
     report(error);
 }
 
-void HqlGram::reportMacroExpansionPosition(int errNo, HqlLex * lexer, bool isError)
+void HqlGram::reportMacroExpansionPosition(IECLError * warning, HqlLex * lexer)
 {
     if (expandingMacroPosition)
         return;
@@ -5805,15 +5792,16 @@ void HqlGram::reportMacroExpansionPosition(int errNo, HqlLex * lexer, bool isErr
     if (!macro)
         return;
 
-    reportMacroExpansionPosition(errNo, macro, isError);
+    reportMacroExpansionPosition(warning, macro);
     StringBuffer s;
     s.appendf("While expanding macro %s", macro->getMacroName());
 
     expandingMacroPosition = true;
-    if (isError)
-        errorHandler->reportError(errNo, s.str(), lexer->querySourcePath()->str(), lexer->get_yyLineNo(), lexer->get_yyColumn(), 0);
+    unsigned code = warning->errorCode();
+    if (warning->getSeverity() == SeverityFatal)
+        errorHandler->reportError(code, s.str(), lexer->querySourcePath()->str(), lexer->get_yyLineNo(), lexer->get_yyColumn(), 0);
     else
-        doReportWarning(errNo, s.str(), lexer->querySourcePath()->str(), lexer->get_yyLineNo(), lexer->get_yyColumn(), 0);
+        doReportWarning(warning->getCategory(), code, s.str(), lexer->querySourcePath()->str(), lexer->get_yyLineNo(), lexer->get_yyColumn(), 0);
     expandingMacroPosition = false;
 }
 
@@ -5832,47 +5820,47 @@ void HqlGram::reportError(int errNo, const char *msg, int lineno, int column, in
     }
 }
 
-void HqlGram::reportWarning(int warnNo, const ECLlocation & pos, const char* format, ...)
+void HqlGram::reportWarning(WarnErrorCategory category, int warnNo, const ECLlocation & pos, const char* format, ...)
 {
     if (errorHandler && !errorDisabled)
     {
         va_list args;
         va_start(args, format);
-        Owned<IECLError> error = createErrorVA(CategoryUnknown, SeverityWarning, warnNo, pos, format, args);
+        Owned<IECLError> error = createErrorVA(category, queryDefaultSeverity(category), warnNo, pos, format, args);
         va_end(args);
 
         report(error);
     }
 }
 
-void HqlGram::reportWarning(ErrorSeverity severity, int warnNo, const ECLlocation & pos, const char* format, ...)
+void HqlGram::reportWarning(WarnErrorCategory category, ErrorSeverity severity, int warnNo, const ECLlocation & pos, const char* format, ...)
 {
     if (errorHandler && !errorDisabled)
     {
         StringBuffer msg;
         va_list args;
         va_start(args, format);
-        Owned<IECLError> error = createErrorVA(CategoryUnknown, severity, warnNo, pos, format, args);
+        Owned<IECLError> error = createErrorVA(category, severity, warnNo, pos, format, args);
         va_end(args);
 
         report(error);
     }
 }
 
-void HqlGram::reportWarningVa(int warnNo, const attribute& a, const char* format, va_list args)
+void HqlGram::reportWarningVa(WarnErrorCategory category, int warnNo, const attribute& a, const char* format, va_list args)
 {
     const ECLlocation & pos = a.pos;
     if (errorHandler && !errorDisabled)
     {
-        Owned<IECLError> error = createErrorVA(CategoryUnknown, SeverityWarning, warnNo, pos, format, args);
+        Owned<IECLError> error = createErrorVA(category, queryDefaultSeverity(category), warnNo, pos, format, args);
         report(error);
     }
 }
 
-void HqlGram::reportWarning(int warnNo, const char *msg, int lineno, int column)
+void HqlGram::reportWarning(WarnErrorCategory category, int warnNo, const char *msg, int lineno, int column)
 {
     if (errorHandler && !errorDisabled)
-        doReportWarning(warnNo, msg, querySourcePathText(), lineno, column, 0);
+        doReportWarning(category, warnNo, msg, querySourcePathText(), lineno, column, 0);
 }
 
 
@@ -5913,14 +5901,14 @@ void HqlGram::report(IECLError* error)
             }
         }
 
-        reportMacroExpansionPosition(error->errorCode(), lexObject, isFatalError);
+        reportMacroExpansionPosition(error, lexObject);
     }
 }
 
-void HqlGram::reportWarning(int warnNo, const char *msg, const char *filename, int lineno, int column, int pos)
+void HqlGram::reportWarning(WarnErrorCategory category, int warnNo, const char *msg, const char *filename, int lineno, int column, int pos)
 {
     if (errorHandler && !errorDisabled)
-        doReportWarning(warnNo, msg, filename, lineno, column, pos);
+        doReportWarning(category, warnNo, msg, filename, lineno, column, pos);
 }
 
 size32_t HqlGram::errCount()
@@ -6868,7 +6856,7 @@ void HqlGram::checkOutputRecord(attribute & errpos, bool outerLevel)
     bool allConstant = true;
     errpos.setExpr(checkOutputRecord(record, errpos, allConstant, outerLevel));
     if (allConstant && (record->getOperator() != no_null) && (record->numChildren() != 0))
-        reportWarning(WRN_OUTPUT_ALL_CONSTANT,errpos.pos,"All values for OUTPUT are constant - is this the intention?");
+        reportWarning(CategoryUnusual, WRN_OUTPUT_ALL_CONSTANT,errpos.pos,"All values for OUTPUT are constant - is this the intention?");
 }
 
 void HqlGram::checkSoapRecord(attribute & errpos)
@@ -7445,7 +7433,7 @@ void HqlGram::checkGrouping(const attribute& errpos, HqlExprArray & parms, IHqlE
                         if (id)
                             msg.append("'").append(id->str()).append("' ");
                         msg.append("in TABLE does not appear to be properly defined by grouping conditions");
-                        reportWarning(ERR_GROUP_BADSELECT,errpos.pos, "%s", msg.str());
+                        reportWarning(CategoryUnexpected, ERR_GROUP_BADSELECT,errpos.pos, "%s", msg.str());
                     }
                 }
                 else if (field->isDatarow())
@@ -7665,7 +7653,7 @@ void HqlGram::checkDistribution(attribute &errpos, IHqlExpression *input, bool l
             if (!inputIsGrouped || ignoreGrouping)
             {
                 const char * name = getName(input);
-                reportWarning(WRN_LOCALONEXPLICITDIST,errpos.pos,"Input %s is explicitly DISTRIBUTEd but LOCAL not specified", name);
+                reportWarning(CategoryEfficiency, WRN_LOCALONEXPLICITDIST,errpos.pos,"Input %s is explicitly DISTRIBUTEd but LOCAL not specified", name);
             }
         }
     }
@@ -7738,7 +7726,7 @@ void HqlGram::checkJoinFlags(const attribute &err, IHqlExpression * join)
     {
         //The following should be, and will become, an error.  However too many legacy queries have it, so make a warning for now.
         if (isAll)
-            reportWarning(ERR_KEYEDINDEXINVALID, err.pos, "ALL is not compatible with LOOKUP");
+            reportWarning(CategorySyntax, ERR_KEYEDINDEXINVALID, err.pos, "ALL is not compatible with LOOKUP");
         if (isSmart)
             reportError(ERR_KEYEDINDEXINVALID, err.pos, "SMART is not compatible with LOOKUP");
     }
@@ -7759,7 +7747,7 @@ void HqlGram::checkJoinFlags(const attribute &err, IHqlExpression * join)
                 IHqlExpression * indexDataset = index->queryChild(0)->queryNormalizedSelector();
 
                 if (indexDataset != rhs->queryNormalizedSelector())
-                    reportWarning(ERR_KEYEDNOTMATCHDATASET,err.pos,"Parameter to KEYED is not an index on the RIGHT dataset");
+                    reportWarning(CategoryUnusual, ERR_KEYEDNOTMATCHDATASET,err.pos,"Parameter to KEYED is not an index on the RIGHT dataset");
                 else if (!isFilteredDiskFile(rhs))
                     reportError(ERR_KEYEDNOTMATCHDATASET,err,"RIGHT side of a full keyed join must be a disk file");
                 else
@@ -7808,7 +7796,7 @@ void HqlGram::checkJoinFlags(const attribute &err, IHqlExpression * join)
         if (rowLimit && !isMany)
             reportError(ERR_BADKIND_LOOKUPJOIN, err, "%s joins do not support LIMIT (they can only match 1 entry)", joinText);
         if (isKey(join->queryChild(1)))
-            reportWarning(ERR_BADKIND_LOOKUPJOIN, err.pos, "%s specified on an unfiltered keyed join - was this intended?", joinText);
+            reportWarning(CategoryEfficiency, ERR_BADKIND_LOOKUPJOIN, err.pos, "%s specified on an unfiltered keyed join - was this intended?", joinText);
     }
     else if (isKeyedJoin(join))
     {
@@ -7856,7 +7844,7 @@ void HqlGram::checkJoinFlags(const attribute &err, IHqlExpression * join)
         while (cur->getOperator() == no_filter)
             cur = cur->queryChild(0);
         if (isKey(cur))
-            reportWarning(ERR_BAD_JOINFLAG, err.pos, "Filtered RIGHT prevents a keyed join being used.  Consider including the filter in the join condition.");
+            reportWarning(CategoryEfficiency, ERR_BAD_JOINFLAG, err.pos, "Filtered RIGHT prevents a keyed join being used.  Consider including the filter in the join condition.");
     }
 
     IHqlExpression * group = join->queryAttribute(groupAtom);
@@ -7899,9 +7887,9 @@ void HqlGram::checkLoopFlags(const attribute &err, IHqlExpression * loopExpr)
     {
         unsigned base = (loopExpr->getOperator() == no_loop ? 1 : 2);
         if (!queryRealChild(loopExpr, base))
-            reportWarning(WRN_BAD_LOOPFLAG, err.pos, "PARALLEL is currently only supported with a defined number of iterations");
+            reportWarning(CategorySyntax, WRN_BAD_LOOPFLAG, err.pos, "PARALLEL is currently only supported with a defined number of iterations");
         if (queryRealChild(loopExpr, base+2))
-            reportWarning(WRN_BAD_LOOPFLAG, err.pos, "PARALLEL is not supported with dataset loop termination condition");
+            reportWarning(CategorySyntax, WRN_BAD_LOOPFLAG, err.pos, "PARALLEL is not supported with dataset loop termination condition");
     }
 }
 
@@ -8468,7 +8456,7 @@ void HqlGram::ensureMapToRecordsMatch(OwnedHqlExpr & defaultExpr, HqlExprArray &
         if (value != checked)
         {
             args.replace(*replaceChild(&mapTo, 1, checked), i);
-            reportWarning(ERR_TYPE_INCOMPATIBLE, errpos.pos, "Datasets in list have slightly different records");
+            reportWarning(CategoryCast, ERR_TYPE_INCOMPATIBLE, errpos.pos, "Datasets in list have slightly different records");
         }
     }
 
@@ -8480,7 +8468,7 @@ void HqlGram::ensureMapToRecordsMatch(OwnedHqlExpr & defaultExpr, HqlExprArray &
         if (defaultExpr != checked)
         {
             defaultExpr.set(checked);
-            reportWarning(ERR_TYPE_INCOMPATIBLE, errpos.pos, "Default value has a slightly different record");
+            reportWarning(CategoryCast, ERR_TYPE_INCOMPATIBLE, errpos.pos, "Default value has a slightly different record");
         }
     }
 
@@ -8582,7 +8570,7 @@ void HqlGram::checkMergeInputSorted(attribute &atr, bool isLocal)
         return;
     if (!isLocal && appearsToBeSorted(expr, true, true))
     {
-        reportWarning(WRN_MERGE_NOT_SORTED, atr.pos, "INPUT to MERGE appears to be sorted locally but not globally");
+        reportWarning(CategoryUnexpected, WRN_MERGE_NOT_SORTED, atr.pos, "INPUT to MERGE appears to be sorted locally but not globally");
         return;
     }
         
@@ -8600,9 +8588,9 @@ void HqlGram::checkMergeInputSorted(attribute &atr, bool isLocal)
     }
     
     if (isGrouped(expr) && appearsToBeSorted(expr, false, false))
-        reportWarning(WRN_MERGE_NOT_SORTED, atr.pos, "Input to MERGE is only sorted with the group");
+        reportWarning(CategoryUnexpected, WRN_MERGE_NOT_SORTED, atr.pos, "Input to MERGE is only sorted with the group");
     else
-        reportWarning(WRN_MERGE_NOT_SORTED, atr.pos, "Input to MERGE doesn't appear to be sorted");
+        reportWarning(CategoryUnexpected, WRN_MERGE_NOT_SORTED, atr.pos, "Input to MERGE doesn't appear to be sorted");
 }
 
 
@@ -8641,7 +8629,7 @@ void HqlGram::checkNotAlreadyDefined(IIdAtom * name, IHqlScope * scope, const at
     if (expr)
     {
         if (legacyImportSemantics && isImport(expr))
-            reportWarning(ERR_ID_REDEFINE, idattr.pos, "Identifier '%s' hides previous import", name->str());
+            reportWarning(CategoryConfuse, ERR_ID_REDEFINE, idattr.pos, "Identifier '%s' hides previous import", name->str());
         else
             reportError(ERR_ID_REDEFINE, idattr, "Identifier '%s' is already defined", name->str());
     }
@@ -8706,7 +8694,7 @@ IHqlExpression * HqlGram::addSideEffects(IHqlExpression * expr)
             }
 
             ECLlocation location(next);
-            reportWarning(ERR_RESULT_IGNORED, location, "Expression ignored");
+            reportWarning(CategoryIgnored, ERR_RESULT_IGNORED, location, "Expression ignored");
         }
         else
             compound = createCompound(next.getClear(), compound);
@@ -8981,7 +8969,7 @@ void HqlGram::doDefineSymbol(DefineIdSt * defineid, IHqlExpression * _expr, IHql
 
         //Ignore SHARED and EXPORT flags 
         if (defineid->scope & (EXPORT_FLAG | SHARED_FLAG))
-            reportWarning(WRN_EXPORT_IGNORED, idattr.pos, "EXPORT/SHARED qualifiers are ignored in this context");
+            reportWarning(CategorySyntax, WRN_EXPORT_IGNORED, idattr.pos, "EXPORT/SHARED qualifiers are ignored in this context");
 
         defineid->scope = 0;
         defineSymbolInScope(activeScope.privateScope, defineid, expr.getClear(), failure, idattr, assignPos, semiColonPos, isParametered, activeScope.activeParameters, activeScope.createDefaults());
@@ -9002,7 +8990,7 @@ void HqlGram::doDefineSymbol(DefineIdSt * defineid, IHqlExpression * _expr, IHql
                 {
                     //Make this warning come out now - otherwise a subsequent error about an undefined symbol makes less sense.
                     RestoreValueBlock<bool> block(associateWarnings, false);
-                    reportWarning(ERR_UNEXPECTED_PUBLIC_ID, idattr.pos, "Name of exported symbol '%s' does not match the expected name '%s'", name->str(), expectedAttribute->str());
+                    reportWarning(CategorySyntax, ERR_UNEXPECTED_PUBLIC_ID, idattr.pos, "Name of exported symbol '%s' does not match the expected name '%s'", name->str(), expectedAttribute->str());
                 }
                 defineid->scope = 0;
             }
@@ -9438,7 +9426,7 @@ IHqlExpression * HqlGram::extractBranchMatch(const attribute & errpos, IHqlExpre
         // The following test is no good though, we need to check if reused only in this branch.
 //      if (curSym.isShared())
 //          return NULL;
-        reportWarning(WRN_COND_ASSIGN_NO_PREV, errpos.pos, "Conditional assignment to %s isn't defined in all branches, and has no previous definition", id->str());
+        reportWarning(CategoryMistake, WRN_COND_ASSIGN_NO_PREV, errpos.pos, "Conditional assignment to %s isn't defined in all branches, and has no previous definition", id->str());
         return NULL;
     }
 
@@ -9703,7 +9691,7 @@ IHqlExpression * HqlGram::createLibraryInstance(const attribute & errpos, IHqlEx
     }
 
     if (body->hasAttribute(libraryAtom))
-        reportWarning(WRN_NOT_INTERFACE, errpos.pos, "LIBRARY() seems to reference an implementation rather than the interface definition");
+        reportWarning(CategorySyntax, WRN_NOT_INTERFACE, errpos.pos, "LIBRARY() seems to reference an implementation rather than the interface definition");
     IHqlExpression * internalAttr = queryAttributeInList(internalAtom,name);
     if (internalAttr)
     {
@@ -9913,7 +9901,7 @@ void HqlGram::canNotAssignTypeWarn(ITypeInfo* expected, ITypeInfo* given, const
     StringBuffer msg("Incompatible types: should cast ");
     getFriendlyTypeStr(given, msg).append(" to a ");
     getFriendlyTypeStr(expected, msg);
-    reportWarning(ERR_TYPE_INCOMPATIBLE, errpos.pos, "%s", msg.str());
+    reportWarning(CategoryCast, ERR_TYPE_INCOMPATIBLE, errpos.pos, "%s", msg.str());
 }
 
 IIdAtom * HqlGram::getNameFromExpr(attribute& attr)
@@ -10188,7 +10176,7 @@ void HqlGram::defineImport(const attribute & errpos, IHqlExpression * imported,
         if (previous->queryBody() == imported->queryBody())
             return;
 
-        reportWarning(ERR_ID_REDEFINE, errpos.pos, "import hides previously defined identifier");
+        reportWarning(CategoryConfuse, ERR_ID_REDEFINE, errpos.pos, "import hides previously defined identifier");
     }
 
     parseScope->defineSymbol(newName, NULL, LINK(imported), false, false, ob_import, NULL, errpos.pos.lineno, errpos.pos.column, errpos.pos.position, 0, errpos.pos.position);

+ 6 - 6
ecl/hql/hqllex.l

@@ -99,7 +99,7 @@ int HqlLex::lookupIdentifierToken(YYSTYPE & returnToken, HqlLex * lexer, bool lo
         StringBuffer alternativeText;
         if (alternative && alternative->queryValue())
             alternative->queryValue()->getStringValue(alternativeText);
-        lexer->reportWarning(returnToken, ERR_DEPRECATED_ATTR, "Definition %s is marked as deprecated.  %s", name->str(), alternativeText.str());
+        lexer->reportWarning(CategoryDeprecated, returnToken, ERR_DEPRECATED_ATTR, "Definition %s is marked as deprecated.  %s", name->str(), alternativeText.str());
     }                   
     
 #if defined(TRACE_MACRO)
@@ -1591,7 +1591,7 @@ FUNCTIONMACRO|MACRO {
                         }
                         if (after > MAX_DECIMAL_PRECISION)
                         {
-                            lexer->reportWarning(returnToken, ERR_ILLSIZE_DECIMAL, "Decimal constant may lose significant digits (>%d)", MAX_DECIMAL_PRECISION);
+                            lexer->reportWarning(CategoryCast, returnToken, ERR_ILLSIZE_DECIMAL, "Decimal constant may lose significant digits (>%d)", MAX_DECIMAL_PRECISION);
                             after = MAX_DECIMAL_PRECISION;
                         }
                         Owned<ITypeInfo> type = makeDecimalType(before+after, after, true);
@@ -1749,7 +1749,7 @@ FUNCTIONMACRO|MACRO {
                                     *bf++ = value;
                                     if(!(isValidAsciiLikeCharacter(value) || (tc == type_data)))
                                     {
-                                        lexer->reportWarning(returnToken, ERR_STRING_NON_ASCII, "Character in string literal is not defined in encoding " ASCII_LIKE_CODEPAGE);
+                                        lexer->reportWarning(CategoryCast, returnToken, ERR_STRING_NON_ASCII, "Character in string literal is not defined in encoding " ASCII_LIKE_CODEPAGE);
                                         if (lexer->isAborting())
                                             return EOF;
                                     }
@@ -1799,7 +1799,7 @@ FUNCTIONMACRO|MACRO {
                                 {
                                     finger += extraCharsRead;
                                     if (*bf == ASCII_LIKE_SUBS_CHAR)
-                                        lexer->reportWarning(returnToken, ERR_STRING_NON_ASCII, "Character in string literal is not defined in encoding " ASCII_LIKE_CODEPAGE ", try using a unicode constant");
+                                        lexer->reportWarning(CategoryCast, returnToken, ERR_STRING_NON_ASCII, "Character in string literal is not defined in encoding " ASCII_LIKE_CODEPAGE ", try using a unicode constant");
                                 }
                                 bf++;
                             }
@@ -1874,7 +1874,7 @@ FUNCTIONMACRO|MACRO {
 [xX]\'{err_hexpairs}\'  { 
                         /* error pattern: odd hex data */
                         setupdatepos;
-                        lexer->reportWarning(returnToken, ERR_HEXDATA_ODDDIGITS,"hex data must have even number of hex digits");
+                        lexer->reportWarning(CategorySyntax, returnToken, ERR_HEXDATA_ODDDIGITS,"hex data must have even number of hex digits");
                         char* str = (char*)malloc(CUR_TOKEN_LENGTH-1);
                         str[0] = '0'; // add a leading zero
                         strncpy(str+1,(char*)CUR_TOKEN_TEXT+2,CUR_TOKEN_LENGTH-3);
@@ -1919,7 +1919,7 @@ FUNCTIONMACRO|MACRO {
 \357\273\277        {
                         setupdatepos;
                         if (lexer->yyPosition != 3)
-                            lexer->reportWarning(returnToken, ERR_STRING_ILLDELIMITER, "Misplaced BOM - should be at the start of the file");
+                            lexer->reportWarning(CategorySyntax, returnToken, ERR_STRING_ILLDELIMITER, "Misplaced BOM - should be at the start of the file");
                     }
 
 "("                 {

+ 7 - 6
ecl/hql/hqlparse.cpp

@@ -101,7 +101,7 @@ public:
     virtual StringBuffer& demangle(const char* mangled, StringBuffer& demangled) { return ::mangle(m_lookupContext.errs,mangled,demangled,true); }
 
     virtual void reportError(int errNo,const char* format,...);
-    virtual void reportWarning(WarnErrorCategory category, int warnNo,const char* format,...);
+    virtual void reportWarning(int warnNo,const char* format,...);
 };
 
 void CTemplateContext::reportError(int errNo,const char* format,...)
@@ -117,7 +117,7 @@ void CTemplateContext::reportError(int errNo,const char* format,...)
     }
 }
 
-void CTemplateContext::reportWarning(WarnErrorCategory category,int warnNo,const char* format,...)
+void CTemplateContext::reportWarning(int warnNo,const char* format,...)
 {
     if (m_lookupContext.errs)
     {
@@ -125,7 +125,8 @@ void CTemplateContext::reportWarning(WarnErrorCategory category,int warnNo,const
         va_start(args, format);
         StringBuffer msg;
         msg.valist_appendf(format,args);
-        m_lookupContext.errs->reportWarning(category,warnNo,msg.str(),NULL,m_startLine,m_startCol,0);
+        WarnErrorCategory category = CategoryUnusual; // a reasonable default
+        m_lookupContext.errs->reportWarning(category, warnNo,msg.str(),NULL,m_startLine,m_startCol,0);
         va_end(args);
     }
 }
@@ -989,7 +990,7 @@ void HqlLex::doError(YYSTYPE & returnToken, bool isError)
     if (isError)
         reportError(returnToken, ERR_HASHERROR, "#ERROR: %s", buf.str());
     else
-        reportWarning(returnToken, WRN_HASHWARNING, "#WARNING: %s", buf.str());
+        reportWarning(CategoryUnusual, returnToken, WRN_HASHWARNING, "#WARNING: %s", buf.str());
 }
 
 void HqlLex::doExport(YYSTYPE & returnToken, bool toXml)
@@ -1967,13 +1968,13 @@ void HqlLex::reportError(const YYSTYPE & returnToken, int errNo, const char *for
     }
 }
 
-void HqlLex::reportWarning(const YYSTYPE & returnToken, int warnNo, const char *format, ...)
+void HqlLex::reportWarning(WarnErrorCategory category, const YYSTYPE & returnToken, int warnNo, const char *format, ...)
 {
     if (yyParser)
     {
         va_list args;
         va_start(args, format);
-        yyParser->reportWarningVa(warnNo, returnToken, format, args);
+        yyParser->reportWarningVa(category, warnNo, returnToken, format, args);
         va_end(args);
     }
 }

+ 1 - 1
ecl/hql/hqlxmldb.hpp

@@ -59,7 +59,7 @@ interface ITemplateContext : public IInterface
     virtual StringBuffer& demangle(const char* mangled, StringBuffer& demangled) = 0;
 
     virtual void reportError(int errNo,const char* format,...) __attribute__((format(printf, 3, 4))) = 0;
-    virtual void reportWarning(WarnErrorCategory category, int warnNo,const char* format,...) __attribute__((format(printf, 4, 5))) = 0;
+    virtual void reportWarning(int warnNo,const char* format,...) __attribute__((format(printf, 3, 4))) = 0;
 
     // Ideally, the user has no need to use this.
     virtual IEclRepository* queryDataServer() = 0;

+ 3 - 2
ecl/hqlcpp/hqlcpp.cpp

@@ -2040,10 +2040,11 @@ void HqlCppTranslator::doReportWarning(WarnErrorCategory category, IHqlExpressio
     Owned<IECLError> warnError;
     if (!location)
         location = queryActiveActivityLocation();
+    ErrorSeverity severity = queryDefaultSeverity(category);
     if (location)
-        warnError.setown(createECLError(category, SeverityWarning, id, msg, location->querySourcePath()->str(), location->getStartLine(), location->getStartColumn(), 0));
+        warnError.setown(createECLError(category, severity, id, msg, location->querySourcePath()->str(), location->getStartLine(), location->getStartColumn(), 0));
     else
-        warnError.setown(createECLError(category, SeverityWarning, id, msg, NULL, 0, 0, 0));
+        warnError.setown(createECLError(category, severity, id, msg, NULL, 0, 0, 0));
 
     errorProcessor->report(warnError);
 }

+ 5 - 2
ecl/hqlcpp/hqlttcpp.cpp

@@ -7512,7 +7512,10 @@ protected:
         default:
             if (!isIndependentOfScope(expr))
             {
-                translator.WARNINGAT(CategoryMistake, queryActiveLocation(expr), HQLWRN_GlobalActionDependendOnScope);
+                //There appears to be partial support for functions generated as workflow items - which are not
+                //scope independent since they depend on their paramaters => don't complain about them
+                if (expr->getOperator() != no_return_stmt)
+                    translator.WARNINGAT(CategoryMistake, queryActiveLocation(expr), HQLWRN_GlobalActionDependendOnScope);
 
     #if 0
                 checkIndependentOfScope(expr);
@@ -10328,7 +10331,7 @@ IHqlExpression * NestedCompoundTransformer::createTransformed(IHqlExpression * e
                     //so needs to stay a warning.
 //                  translator.ERRORAT1(location, HQLERR_GlobalSideEffectDependent, s.str());
                     //GH: Make this a default error severity
-                    translator.WARNINGAT1(CategoryMistake, location, HQLWRN_GlobalSideEffectDependent, s.str());
+                    translator.WARNINGAT1(CategoryUnexpected, location, HQLWRN_GlobalSideEffectDependent, s.str());
                 }
                 break;
             }

+ 20 - 0
ecl/regress/existscheck.ecl

@@ -0,0 +1,20 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#onwarning ('mistake', warning);
+
+output(exists(true));

+ 30 - 0
ecl/regress/largefield.ecl

@@ -0,0 +1,30 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2013 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+#onwarning ('efficiency', ignore);
+
+namesRecord :=
+            RECORD
+string2000000000  surname;
+string10        forename;
+integer2        age := 25;
+            END;
+
+namesTable := dataset('x',namesRecord,FLAT);
+
+
+output(nofold(namesTable)(surname[1] in ['0','1','3']),,'out.d00',overwrite);

+ 1 - 1
ecl/regress/library10.eclxml

@@ -14,7 +14,7 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<Archive useArchivePlugins="1">
+<Archive useArchivePlugins="1" legacyImport="1">
  <Module name="example">
   <Attribute name="namesRecord">
 

+ 1 - 0
ecl/regress/serial7a_error.ecl

@@ -19,6 +19,7 @@
 //Unfortunately it gets optimized away by EXISTS(x) always being true.  Check a warning is output.
 
 #option ('pickBestEngine', false);
+#onwarning (1051, warning);
 
 IMPORT SerialTest;