Преглед изворни кода

HPCC-15209 Limit eclcc compile errors

Signed-off-by: James Noss <james.noss@lexisnexis.com>
James Noss пре 9 година
родитељ
комит
a41e16d033
7 измењених фајлова са 102 додато и 91 уклоњено
  1. 47 71
      ecl/eclcc/eclcc.cpp
  2. 1 0
      ecl/eclcc/eclcc.hpp
  3. 1 0
      ecl/hql/hqlerror.hpp
  4. 2 0
      ecl/hql/hqlexpr.hpp
  5. 15 7
      ecl/hql/hqlgram.hpp
  6. 3 3
      ecl/hql/hqlgram.y
  7. 33 10
      ecl/hql/hqlgram2.cpp

+ 47 - 71
ecl/eclcc/eclcc.cpp

@@ -191,12 +191,8 @@ struct EclCompileInstance
 {
 public:
     EclCompileInstance(IFile * _inputFile, IErrorReceiver & _errorProcessor, FILE * _errout, const char * _outputFilename, bool _legacyImport, bool _legacyWhen) :
-      inputFile(_inputFile), errorProcessor(&_errorProcessor), errout(_errout), outputFilename(_outputFilename)
-    {
-        legacyImport = _legacyImport;
-        legacyWhen = _legacyWhen;
-        ignoreUnknownImport = false;
-        fromArchive = false;
+      inputFile(_inputFile), errorProcessor(&_errorProcessor), errout(_errout), outputFilename(_outputFilename), legacyImport(_legacyImport), legacyWhen(_legacyWhen)
+{
         stats.parseTime = 0;
         stats.generateTime = 0;
         stats.xmlSize = 0;
@@ -223,8 +219,8 @@ public:
     Owned<IPropertyTree> globalDependTree;
     bool legacyImport;
     bool legacyWhen;
-    bool fromArchive;
-    bool ignoreUnknownImport;
+    bool fromArchive = false;
+    bool ignoreUnknownImport = false;
     struct {
         unsigned parseTime;
         unsigned generateTime;
@@ -244,37 +240,6 @@ public:
     {
         argc = _argc;
         argv = _argv;
-        logVerbose = false;
-        logTimings = false;
-        optArchive = false;
-        optCheckEclVersion = true;
-        optEvaluateResult = false;
-        optGenerateMeta = false;
-        optGenerateDepend = false;
-        optIncludeMeta = false;
-        optKeywords = false;
-        optLegacyImport = false;
-        optLegacyWhen = false;
-        optShared = false;
-        optWorkUnit = false;
-        optNoCompile = false;
-        optNoLogFile = false;
-        optNoStdInc = false;
-        optNoBundles = false;
-        optOnlyCompile = false;
-        optBatchMode = false;
-        optSaveQueryText = false;
-        optSaveQueryArchive = false;
-        optGenerateHeader = false;
-        optShowPaths = false;
-        optNoSourcePath = false;
-        optTargetClusterType = RoxieCluster;
-        optTargetCompiler = DEFAULT_COMPILER;
-        optThreads = 0;
-        optLogDetail = 0;
-        batchPart = 0;
-        batchSplit = 1;
-        batchLog = NULL;
         cclogFilename.append("cc.").append((unsigned)GetCurrentProcessId()).append(".log");
         defaultAllowed[false] = true;  // May want to change that?
         defaultAllowed[true] = true;
@@ -344,7 +309,7 @@ protected:
     StringAttr optOutputFilename;
     StringAttr optQueryRepositoryReference;
     StringAttr optComponentName;
-    FILE * batchLog;
+    FILE * batchLog = nullptr;
 
     StringAttr optManifestFilename;
     StringArray resourceManifestFiles;
@@ -364,38 +329,40 @@ protected:
     StringArray deniedPermissions;
     bool defaultAllowed[2];
 
-    ClusterType optTargetClusterType;
-    CompilerType optTargetCompiler;
-    unsigned optThreads;
-    unsigned batchPart;
-    unsigned batchSplit;
-    unsigned optLogDetail;
-    bool logVerbose;
-    bool logTimings;
-    bool optArchive;
-    bool optCheckEclVersion;
+    ClusterType optTargetClusterType = RoxieCluster;
+    CompilerType optTargetCompiler = DEFAULT_COMPILER;
+    unsigned optThreads = 0;
+    unsigned batchPart = 0;
+    unsigned batchSplit = 1;
+    unsigned optLogDetail = 0;
+    unsigned optMaxErrors = 0;
+    bool optUnsuppressImmediateSyntaxErrors = false;
+    bool logVerbose = false;
+    bool logTimings = false;
+    bool optArchive = false;
+    bool optCheckEclVersion = true;
     bool optDebugMemLeak = false;
-    bool optEvaluateResult;
-    bool optGenerateMeta;
-    bool optGenerateDepend;
-    bool optIncludeMeta;
-    bool optKeywords;
+    bool optEvaluateResult = false;
+    bool optGenerateMeta = false;
+    bool optGenerateDepend = false;
+    bool optIncludeMeta = false;
+    bool optKeywords = false;
     bool optLeakCheck = false;
-    bool optWorkUnit;
-    bool optNoCompile;
-    bool optNoLogFile;
-    bool optNoStdInc;
-    bool optNoBundles;
-    bool optBatchMode;
-    bool optShared;
-    bool optOnlyCompile;
-    bool optSaveQueryText;
-    bool optSaveQueryArchive;
-    bool optLegacyImport;
-    bool optLegacyWhen;
-    bool optGenerateHeader;
-    bool optShowPaths;
-    bool optNoSourcePath;
+    bool optWorkUnit = false;
+    bool optNoCompile = false;
+    bool optNoLogFile = false;
+    bool optNoStdInc = false;
+    bool optNoBundles = false;
+    bool optBatchMode = false;
+    bool optShared = false;
+    bool optOnlyCompile = false;
+    bool optSaveQueryText = false;
+    bool optSaveQueryArchive = false;
+    bool optLegacyImport = false;
+    bool optLegacyWhen = false;
+    bool optGenerateHeader = false;
+    bool optShowPaths = false;
+    bool optNoSourcePath = false;
     int argc;
     const char **argv;
 };
@@ -488,7 +455,7 @@ int main(int argc, const char *argv[])
     if (!optReleaseAllMemory)
     {
         //In release mode exit without calling all the clean up code.
-        //It is faster, and it helps avoids potential crashes if there are active objects which depend on objects in file hook dlls.
+        //It is faster, and it helps avoid potential crashes if there are active objects which depend on objects in file hook dlls.
         fflush(NULL);
         _exit(exitCode);
     }
@@ -1132,6 +1099,9 @@ void EclCC::processSingleQuery(EclCompileInstance & instance,
     {
         //Minimize the scope of the parse context to reduce lifetime of cached items.
         HqlParseContext parseCtx(instance.dataServer, this, instance.archive);
+        if (optMaxErrors > 0)
+            parseCtx.maxErrors = optMaxErrors;
+        parseCtx.unsuppressImmediateSyntaxErrors = optUnsuppressImmediateSyntaxErrors;
         if (!instance.archive)
             parseCtx.globalDependTree.setown(createPTree(ipt_none)); //to locate associated manifests, keep separate from user specified MetaOptions
         if (optGenerateMeta || optIncludeMeta)
@@ -2112,6 +2082,12 @@ int EclCC::parseCommandLineOptions(int argc, const char* argv[])
         {
             setDebugOption("syntaxCheck", tempBool);
         }
+        else if (iter.matchOption(optMaxErrors, "--maxErrors"))
+        {
+        }
+        else if (iter.matchFlag(optUnsuppressImmediateSyntaxErrors, "--unsuppressImmediateSyntaxErrors"))
+        {
+        }
         else if (iter.matchOption(optIniFilename, "-specs"))
         {
             if (!checkFileExists(optIniFilename))

+ 1 - 0
ecl/eclcc/eclcc.hpp

@@ -93,6 +93,7 @@ const char * const helpText[] = {
     "!   -m            Enable leak checking",
 #endif
     "    --nosourcepath Compile as if the source came from stdin",
+    "!   --maxErrors=<n> Limit the number of errors, aborting on the nth (default = 5)",
 #ifndef _WIN32
     "!   -pch          Generate precompiled header for eclinclude4.hpp",
 #endif

+ 1 - 0
ecl/hql/hqlerror.hpp

@@ -21,6 +21,7 @@
 #include "jexcept.hpp"
 #include "hql.hpp"
 
+#define DEFAULT_MAX_ERRORS 5
 #define HQLERR_ErrorAlreadyReported             4799            // special case...
 
 interface IWorkUnit;

+ 2 - 0
ecl/hql/hqlexpr.hpp

@@ -899,6 +899,8 @@ public:
     IErrorArray orphanedWarnings;
     HqlExprArray defaultFunctionCache;
     CIArrayOf<ForwardScopeItem> forwardLinks;
+    unsigned maxErrors = DEFAULT_MAX_ERRORS;
+    bool unsuppressImmediateSyntaxErrors = false;
     bool expandCallsWhenBound;
     bool ignoreUnknownImport;
     bool aborting;

+ 15 - 7
ecl/hql/hqlgram.hpp

@@ -31,7 +31,6 @@
 
 #include "hqlxmldb.hpp"
 
-#define DEFAULT_MAX_ERRORS 100
 #define EXPORT_FLAG 1
 #define VIRTUAL_FLAG 2
 #define SHARED_FLAG 4
@@ -411,7 +410,6 @@ public:
     IHqlScope * queryGlobalScope();
 
     bool canFollowCurrentState(int tok, const short * yyps);
-    void syntaxError(const char *s, int token, int *expected);
     int mapToken(int lexToken) const;
     IHqlExpression *lookupSymbol(IIdAtom * name, const attribute& errpos);
     IHqlExpression *lookupSymbol(IHqlScope * scope, IIdAtom * name);
@@ -578,6 +576,18 @@ public:
     IHqlExpression * nextEnumValue();
 
 // Error handling
+    void syntaxError(const char *s, int token, int *expected);
+    bool checkErrorCountAndAbort();
+    bool exceedsMaxCompileErrors();
+    unsigned getMaxCompileErrors()
+    {
+        return lookupCtx.queryParseContext().maxErrors;
+    }
+    bool unsuppressImmediateSyntaxErrors()
+    {
+        return lookupCtx.queryParseContext().unsuppressImmediateSyntaxErrors;
+    }
+    void reportTooManyErrors();
     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)));
@@ -691,8 +701,6 @@ public:
     IHqlExpression * processIfProduction(attribute & condAttr, attribute & trueAttr, attribute * falseAttr);
 
     IHqlExpression * createSymbolFromValue(IHqlExpression * primaryExpr, IHqlExpression * value);
-    unsigned getMaxErrorsAllowed() { return m_maxErrorsAllowed; }
-    void setMaxErrorsAllowed(unsigned n) { m_maxErrorsAllowed = n; } 
     void setAssociateWarnings(bool value) { associateWarnings = value; }
     IHqlExpression* clearFieldMap(IHqlExpression* expr);
     void setExpectedAttribute(IIdAtom * _expectedAttribute)             { expectedAttribute = _expectedAttribute; current_id = _expectedAttribute; }
@@ -753,7 +761,6 @@ protected:
 
     void canNotAssignTypeError(ITypeInfo* expected, ITypeInfo* given, const attribute& errpos);
     void canNotAssignTypeWarn(ITypeInfo* expected, ITypeInfo* given, const attribute& errpos);
-    void abortParsing();
     bool isExceptionalCase(attribute& defineid, attribute& object, attribute& failure);
     void checkSvcAttrNoValue(IHqlExpression* attr, const attribute& errpos);
     void checkFormals(IIdAtom * name, HqlExprArray & parms, HqlExprArray & defaults, attribute& object);
@@ -776,7 +783,9 @@ protected:
 
     void disableError() { errorDisabled = true; }
     void enableError() { errorDisabled = false; }
-    bool isAborting() { return errorDisabled; }
+    void abortParsing();
+    bool isAborting() { return errorDisabled || aborting || lookupCtx.isAborting(); }
+
     IIdAtom * fieldMapTo(IHqlExpression* expr, IIdAtom * name);
     IIdAtom * fieldMapFrom(IHqlExpression* expr, IIdAtom * name);
     bool requireLateBind(IHqlExpression* funcdef, const HqlExprArray & actuals);
@@ -854,7 +863,6 @@ protected:
     bool isQuery;
     bool parseConstantText;
     bool expandingMacroPosition;
-    unsigned m_maxErrorsAllowed;
     bool inSignedModule;
 
     IErrorArray pendingWarnings;

+ 3 - 3
ecl/hql/hqlgram.y

@@ -92,7 +92,7 @@ inline int eclyylex(attribute * yylval, HqlGram* parser, const short int * yyssp
 
 
 static void eclsyntaxerror(HqlGram * parser, const char * s, short yystate, int token);
-#define eclyyerror(parser, s)       eclsyntaxerror(parser, s, yystate, yychar)
+#define eclyyerror(parser, s) eclsyntaxerror(parser, s, yystate, yychar); if (parser->unsuppressImmediateSyntaxErrors()) yyerrok; if (parser->checkErrorCountAndAbort()) YYABORT;
 #define ignoreBisonWarning(x)
 #define ignoreBisonWarnings2(x,y)
 #define ignoreBisonWarnings3(x,y,z)
@@ -105,9 +105,9 @@ static void eclsyntaxerror(HqlGram * parser, const char * s, short yystate, int
 /* remember to add any new tokens to the error reporter and lexer too! */
 /* If they clash with other #defines etc then use TOK_ as a prefix */
 
-// NB: Very occassionally the same keyword in the source (e.g., MERGE, PARTITION may return a different token
+// NB: Very occasionally the same keyword in the source (e.g., MERGE, PARTITION may return a different token
 // (MERGE_ATTR, PARTITION_ATTR) depending on the context it is used in.  This is because there would be a s/r
-// error, so the _ATTR form is only allowed in the situations where the attibute is valid - enabled by a
+// error, so the _ATTR form is only allowed in the situations where the attribute is valid - enabled by a
 // call to enableAttributes() from a production in the grammar.
 
   ABS

+ 33 - 10
ecl/hql/hqlgram2.cpp

@@ -457,7 +457,6 @@ void HqlGram::init(IHqlScope * _globalScope, IHqlScope * _containerScope)
 
     errorDisabled = false;
     setIdUnknown(false);
-    m_maxErrorsAllowed = DEFAULT_MAX_ERRORS;
     sortDepth = 0;
     serviceScope.clear();
 
@@ -3065,7 +3064,7 @@ void HqlGram::processForwardModuleDefinition(const attribute & errpos)
             reportError(ERR_EXPECTED, errpos, "Missing END in FORWARD module definition");
             abortParsing();
             return;
-        case COMPLEX_MACRO: 
+        case COMPLEX_MACRO:
         case MACRO:
         case SIMPLE_TYPE:
         case CPPBODY:
@@ -6047,14 +6046,8 @@ void HqlGram::report(IError* error)
         else
         {
             errorHandler->report(error);
-
-            if (getMaxErrorsAllowed()>0 && errorHandler->errCount() >= getMaxErrorsAllowed())
-            {
-                errorHandler->reportError(ERR_ERROR_TOOMANY,"Too many errors; parsing aborted",error->getFilename(),error->getLine(),error->getColumn(),error->getPosition());
-                abortParsing();
-            }
+            checkErrorCountAndAbort();
         }
-
         reportMacroExpansionPosition(error, lexObject);
     }
 }
@@ -11050,8 +11043,38 @@ void HqlGram::simplifyExpected(int *expected)
     simplify(expected, END, '}', 0);
 }
 
+bool HqlGram::exceedsMaxCompileErrors()
+{
+    unsigned errorCount = errorHandler ? errorHandler->errCount() : 0;
+    return errorCount >= getMaxCompileErrors();
+}
+
+bool HqlGram::checkErrorCountAndAbort()
+{
+    if (isAborting())
+        return true;
+
+    if (exceedsMaxCompileErrors())
+    {
+        reportTooManyErrors();
+        abortParsing();
+        return true;
+    }
+    return false;
+}
+
+void HqlGram::reportTooManyErrors()
+{
+    if (errorHandler && !errorDisabled)
+    {
+        StringBuffer msg("Too many errors");
+        msg.append(" (max = ").append(getMaxCompileErrors()).append("); Aborting...");
+        errorHandler->reportError(ERR_ERROR_TOOMANY, msg.str(), str(lexObject->queryActualSourcePath()), lexObject->getActualLineNo(), lexObject->getActualColumn(), lexObject->get_yyPosition());
+    }
+}
+
 void HqlGram::syntaxError(const char *s, int token, int *expected)
-{ 
+{
     if (errorDisabled || !s || !errorHandler)
         return;