X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/1ac6313d90a797f38280d75b2a63655579080ac6..52e90c0f77bb0e3edb043873b71a73459d4ae8ab:/src/cgrammar.y diff --git a/src/cgrammar.y b/src/cgrammar.y index 0d0e558..5c4f2d8 100644 --- a/src/cgrammar.y +++ b/src/cgrammar.y @@ -1,32 +1,37 @@ /*;-*-C-*-; -** Copyright (c) Massachusetts Institute of Technology 1994-1998. -** All Rights Reserved. -** Unpublished rights reserved under the copyright laws of -** the United States. +** Splint - annotation-assisted static program checker +** Copyright (C) 1994-2002 University of Virginia, +** Massachusetts Institute of Technology ** -** THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED -** OR IMPLIED. ANY USE IS AT YOUR OWN RISK. +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 2 of the License, or (at your +** option) any later version. +** +** This program is distributed in the hope that it will be useful, but +** WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** +** The GNU General Public License is available from http://www.gnu.org/ or +** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +** MA 02111-1307, USA. ** -** This code is distributed freely and may be used freely under the -** following conditions: -** -** 1. This notice may not be removed or altered. -** -** 2. Works derived from this code are not distributed for -** commercial gain without explicit permission from MIT -** (for permission contact lclint-request@sds.lcs.mit.edu). +** For information on splint: info@splint.org +** To report a bug: splint-bug@splint.org +** For more information: http://www.splint.org */ %{ /* ** ** cgrammar.y ** -** Yacc/Bison grammar for extended ANSI C used by LCLint. +** Yacc/Bison grammar for extended ANSI C used by Splint. ** ** original grammar by Nate Osgood --- ** hacrat@catfish.lcs.mit.edu Mon Jun 14 13:06:32 1993 ** -** changes for LCLint --- handle typedef names correctly +** changes for Splint --- handle typedef names correctly ** fix struct/union parsing bug (empty struct is accepted) ** add productions to handle macros --- require ** error correction --- main source of conflicts in grammar. @@ -43,9 +48,11 @@ extern int yylex (); extern void swallowMacro (void); +extern void yyerror (char *); -# include "lclintMacros.nf" +# include "splintMacros.nf" # include "basic.h" +# include "cscanner.h" # include "cgrammar.h" # include "exprChecks.h" @@ -53,7 +60,6 @@ extern void swallowMacro (void); /*@-matchfields@*/ # define SHOWCSYM FALSE -void yyerror (char *s); /* ** This is necessary, or else when the bison-generated code #include's malloc.h, @@ -69,31 +75,57 @@ void yyerror (char *s); # undef realloc # endif -void checkandsetBufState(idDecl id, exprNode is); %} %union { - lltok tok; - int count; - specialClauseKind sck; - qual typequal; - qualList tquallist; - ctype ctyp; - sRef sr; - /*@only@*/ qtype qtyp; - /*@only@*/ cstring cname; - /*@only@*/ idDecl ntyp; - /*@only@*/ idDeclList ntyplist; - /*@only@*/ uentryList flist; - /*@owned@*/ uentryList entrylist; - /*@observer@*/ /*@dependent@*/ uentry entry; - /*@only@*/ uentry oentry; - /*@only@*/ exprNode expr; - /*@only@*/ enumNameList enumnamelist; - /*@only@*/ exprNodeList alist; - /*@only@*/ sRefSet srset; - /*@only@*/ cstringList cstringlist; + lltok tok; + int count; + qual typequal; + qualList tquallist; + ctype ctyp; + /*@dependent@*/ sRef sr; + /*@only@*/ sRef osr; + + /*@only@*/ functionClauseList funcclauselist; + /*@only@*/ functionClause funcclause; + /*@only@*/ flagSpec flagspec; + /*@only@*/ globalsClause globsclause; + /*@only@*/ modifiesClause modsclause; + /*@only@*/ warnClause warnclause; + /*@only@*/ stateClause stateclause; + + /*@only@*/ functionConstraint fcnconstraint; + + /*@only@*/ metaStateConstraint msconstraint; + /*@only@*/ metaStateSpecifier msspec; + /*@only@*/ metaStateExpression msexpr; + /*@observer@*/ metaStateInfo msinfo; + + /*@only@*/ sRefList srlist; + /*@only@*/ globSet globset; + /*@only@*/ qtype qtyp; + /*@only@*/ cstring cname; + /*@observer@*/ annotationInfo annotation; + /*@only@*/ idDecl ntyp; + /*@only@*/ idDeclList ntyplist; + /*@only@*/ uentryList flist; + /*@owned@*/ uentryList entrylist; + /*@observer@*/ /*@dependent@*/ uentry entry; + /*@only@*/ uentry oentry; + /*@only@*/ exprNode expr; + /*@only@*/ enumNameList enumnamelist; + /*@only@*/ exprNodeList exprlist; + /*@only@*/ sRefSet srset; + /*@only@*/ cstringList cstringlist; + + /*drl + added 1/19/2001 + */ + constraint con; + constraintList conL; + constraintExpr conE; + /* drl */ } /* standard C tokens */ @@ -104,13 +136,14 @@ void checkandsetBufState(idDecl id, exprNode is); %token TSEMI TLBRACE TRBRACE TCOMMA TCOLON TASSIGN TLPAREN %token TRPAREN TLSQBR TRSQBR TDOT TAMPERSAND TEXCL TTILDE %token TMINUS TPLUS TMULT TDIV TPERCENT TLT TGT TCIRC TBAR TQUEST -%token CSIZEOF CALIGNOF ARROW_OP CTYPEDEF COFFSETOF +%token CSIZEOF CALIGNOF CTYPEOF ARROW_OP CTYPEDEF COFFSETOF %token INC_OP DEC_OP LEFT_OP RIGHT_OP %token LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP %token MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN SUB_ASSIGN %token LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN %token CSTRUCT CUNION CENUM %token VA_ARG VA_DCL +%token QWARN %token QGLOBALS %token QMODIFIES %token QNOMODS @@ -123,12 +156,13 @@ void checkandsetBufState(idDecl id, exprNode is); %token QSETS %token QRELEASES %token QPRECLAUSE -%token QPOSTCLAUSE +%token QPOSTCLAUSE +%token QINVARIANT %token QALT %token QUNDEF QKILLED %token QENDMACRO -/* additional tokens introduced by lclint pre-processor. */ +/* additional tokens introduced by splint pre-processor. */ %token LLMACRO LLMACROITER LLMACROEND TENDMACRO /* break comments: */ @@ -161,21 +195,54 @@ void checkandsetBufState(idDecl id, exprNode is); %token QREFCOUNTED QREFS QNEWREF QTEMPREF QKILLREF QRELDEF %token CGCHAR CBOOL CINT CGFLOAT CDOUBLE CVOID %token QANYTYPE QINTEGRALTYPE QUNSIGNEDINTEGRALTYPE QSIGNEDINTEGRALTYPE + %token QNULLTERMINATED +%token QSETBUFFERSIZE +%token QSETSTRINGLENGTH +%token QMAXSET +%token QMAXREAD +%token QTESTINRANGE + +%token TCAND + /* identifiers, literals */ %token IDENTIFIER %token NEW_IDENTIFIER TYPE_NAME_OR_ID -%token CCONSTANT +%token CANNOTATION +%token CCONSTANT +%type flagId +%type flagSpec +%type cconstantExpr %token ITER_NAME ITER_ENDNAME %type endIter -%type globId + +%type functionClauses functionClausesPlain +%type functionClause functionClause functionClausePlain + +%type globalsClause globalsClausePlain +%type modifiesClause modifiesClausePlain nomodsClause +%type warnClause warnClausePlain optWarnClause +%type conditionClause conditionClausePlain +%type stateClause stateClausePlain +%type metaStateConstraint +%type functionConstraint +%type metaStateSpecifier +%type metaStateExpression + +%type globId globIdListExpr +%type globIdList + %token TYPE_NAME +%token METASTATE_NAME +%type metaStateName %type enumerator newId /*@-varuse@*/ /* yacc declares yytranslate here */ %type pointers /*@=varuse@*/ -%type doHeader specialTag endSpecialTag stateSpecialClause endStateTag -%type specialClauseType +%type doHeader stateTag conditionTag startConditionClause +%type exitsQualifier checkQualifier stateQualifier + paramQualifier returnQualifier visibilityQualifier + typedefQualifier refcountQualifier definedQualifier /* type construction */ %type abstractDecl abstractDeclBase optAbstractDeclBase @@ -192,11 +259,32 @@ void checkandsetBufState(idDecl id, exprNode is); %type structNamedDeclList %type genericParamList paramTypeList paramList idList paramIdList -%type argumentExprList iterArgList -%type initList +%type argumentExprList iterArgList +%type initList namedInitializerList namedInitializerListAux %type structDeclList structDecl -%type locModifies locPlainModifies modList specClauseList +%type locModifies modList specClauseList optSpecClauseList %type mExpr modListExpr specClauseListExpr + +/*drl*/ +%type BufConstraint +%type relationalOp +%type BufBinaryOp +%type bufferModifier + +%type BufConstraintExpr + +%type BufConstraintTerm +%type BufConstraintSrefExpr + +%type BufConstraintList + +%type optStructInvariant + +%type BufUnaryOp + +/*drl 1/6/2002 either /\ or && */ +%type constraintSeperator + %type enumeratorList %type fieldDesignator @@ -219,7 +307,10 @@ void checkandsetBufState(idDecl id, exprNode is); %type compoundStmt compoundStmtAux compoundStmtRest compoundStmtAuxErr %type expressionStmt selectionStmt iterationStmt jumpStmt iterDefIterationStmt %type stmtErr stmtListErr compoundStmtErr expressionStmtErr -%type iterationStmtErr initializerList initializer ifPred whilePred forPred iterWhilePred +%type iterationStmtErr initializerList typeInitializerList initializer +%type ifPred whilePred forPred iterWhilePred typeInitializer + +%type designator designatorList designation %type storageSpecifier typeQualifier typeModifier globQual %type optGlobQuals @@ -235,8 +326,8 @@ file | externalDefs externalDefs - : externalDef - | externalDefs externalDef + : externalDef { context_checkGlobalScope (); } + | externalDefs externalDef { context_checkGlobalScope (); } externalDef : fcnDef optSemi { uentry_clearDecl (); } @@ -245,6 +336,7 @@ externalDef | iterDecl { uentry_clearDecl (); } | macroDef { uentry_clearDecl (); } | initializer { uentry_checkDecl (); exprNode_free ($1); } + | TSEMI { uentry_clearDecl (); /* evans 2002-02-08: okay to have a null statement */ } | error { uentry_clearDecl (); } constantDecl @@ -254,9 +346,11 @@ constantDecl { checkValueConstant ($2, $4, $8) ; } fcnDecl - : QFUNCTION { context_enterFunctionDecl (); } plainFcn optSemi QENDMACRO - { declareStaticFunction ($3); context_quietExitFunction (); - context_exitFunctionDecl (); } + : QFUNCTION { context_enterFunctionHeader (); } plainFcn optSemi QENDMACRO + { + declareStaticFunction ($3); context_quietExitFunction (); + context_exitFunctionHeader (); + } plainFcn : plainNamedDecl @@ -278,40 +372,42 @@ namedDeclBase | IsType TLPAREN NotType namedDecl IsType TRPAREN { $$ = idDecl_expectFunction ($4); } | namedDeclBase TLSQBR TRSQBR - { $$ = idDecl_replaceCtype ($1, ctype_makeArray (idDecl_getCtype ($1))); } + { $$ = idDecl_replaceCtype ($1, ctype_makeInnerArray (idDecl_getCtype ($1))); } | namedDeclBase TLSQBR IsType constantExpr TRSQBR NotType - { - int value; + { + exprNode_findValue ($4); + idDecl_notExpectingFunction ($1); - if (exprNode_hasValue ($4) - && multiVal_isInt (exprNode_getValue ($4))) + if (exprNode_hasValue ($4)) { - value = (int) multiVal_forceInt (exprNode_getValue ($4)); - } + $$ = idDecl_replaceCtype ($1, ctype_makeInnerFixedArray (idDecl_getCtype ($1), + exprNode_getLongValue ($4))); + } else { - value = 0; + $$ = idDecl_replaceCtype ($1, ctype_makeInnerArray (idDecl_getCtype ($1))); } - - $$ = idDecl_replaceCtype ($1, ctype_makeFixedArray (idDecl_getCtype ($1), value)); } | namedDeclBase PushType TLPAREN TRPAREN - { setCurrentParams (uentryList_missingParams); - } - optGlobMods + { setCurrentParams (uentryList_missingParams); } + functionClauses { /* need to support globals and modifies here! */ ctype ct = ctype_makeFunction (idDecl_getCtype ($1), uentryList_makeMissingParams ()); - + $$ = idDecl_replaceCtype ($1, ct); - context_popLoc (); + idDecl_addClauses ($$, $6); + context_popLoc (); + /*drl 7/25/01 added*/ + setImplictfcnConstraints(); } | namedDeclBase PushType TLPAREN genericParamList TRPAREN - { setCurrentParams ($4); - } - optGlobMods - { clearCurrentParams (); + { setCurrentParams ($4); } + functionClauses + { setImplictfcnConstraints (); + clearCurrentParams (); $$ = idDecl_replaceCtype ($1, ctype_makeFunction (idDecl_getCtype ($1), $4)); + idDecl_addClauses ($$, $7); context_popLoc (); } @@ -320,7 +416,7 @@ plainNamedDeclBase | IsType TLPAREN NotType plainNamedDecl IsType TRPAREN { $$ = idDecl_expectFunction ($4); } | plainNamedDeclBase TLSQBR TRSQBR - { $$ = idDecl_replaceCtype ($1, ctype_makeArray (idDecl_getCtype ($1))); } + { $$ = idDecl_replaceCtype ($1, ctype_makeInnerArray (idDecl_getCtype ($1))); } | plainNamedDeclBase TLSQBR IsType constantExpr TRSQBR NotType { int value; @@ -335,31 +431,32 @@ plainNamedDeclBase value = 0; } - $$ = idDecl_replaceCtype ($1, ctype_makeFixedArray (idDecl_getCtype ($1), value)); + $$ = idDecl_replaceCtype ($1, ctype_makeInnerFixedArray (idDecl_getCtype ($1), value)); } | plainNamedDeclBase PushType TLPAREN TRPAREN - { setCurrentParams (uentryList_missingParams); - } - optPlainGlobMods - { /* need to support globals and modifies here! */ + { setCurrentParams (uentryList_missingParams); } + functionClausesPlain + { ctype ct = ctype_makeFunction (idDecl_getCtype ($1), uentryList_makeMissingParams ()); - + $$ = idDecl_replaceCtype ($1, ct); + idDecl_addClauses ($$, $6); context_popLoc (); } | plainNamedDeclBase PushType TLPAREN genericParamList TRPAREN - { setCurrentParams ($4); - } - optPlainGlobMods - { clearCurrentParams (); + { setCurrentParams ($4); } + functionClausesPlain + { + clearCurrentParams (); $$ = idDecl_replaceCtype ($1, ctype_makeFunction (idDecl_getCtype ($1), $4)); + idDecl_addClauses ($$, $7); context_popLoc (); } iterDecl : QITER newId TLPAREN genericParamList TRPAREN - { setCurrentParams ($4); } optPlainGlobMods + { setCurrentParams ($4); } functionClausesPlain { clearCurrentParams (); } optSemi QENDMACRO { declareCIter ($2, $4); } @@ -370,83 +467,160 @@ macroDef | LLMACRO TENDMACRO /* no stmt */ { exprChecks_checkEmptyMacroBody (); } fcnDefHdr - : fcnDefHdrAux { declareFunction ($1); } - -optGlobMods - : { setProcessingGlobMods (); } optGlobModsRest - { clearProcessingGlobMods (); } - -optPlainGlobMods - : { setProcessingGlobMods (); } optPlainGlobModsRest - { clearProcessingGlobMods (); } + : fcnDefHdrAux { clabstract_declareFunction ($1); } + +metaStateConstraint + : metaStateSpecifier TASSIGN metaStateExpression + { $$ = metaStateConstraint_create ($1, $3); } + +metaStateSpecifier + : BufConstraintSrefExpr { cscanner_expectingMetaStateName (); } TCOLON metaStateName + { cscanner_clearExpectingMetaStateName (); + $$ = metaStateSpecifier_create ($1, $4); } + | CTOK_ELIPSIS { cscanner_expectingMetaStateName (); } TCOLON metaStateName + { cscanner_clearExpectingMetaStateName (); + $$ = metaStateSpecifier_createElipsis ($4); } + +metaStateExpression +: metaStateSpecifier { $$ = metaStateExpression_create ($1); } +| metaStateSpecifier TBAR metaStateExpression { $$ = metaStateExpression_createMerge ($1, $3); } + +metaStateName +: METASTATE_NAME + +/*drl*/ + +constraintSeperator +: TCAND +| AND_OP + +BufConstraintList +: BufConstraint constraintSeperator BufConstraintList { $$ = constraintList_add ($3, $1); } +| BufConstraint { $$ = constraintList_single ($1); } + +BufConstraint +: BufConstraintExpr relationalOp BufConstraintExpr { + $$ = makeConstraintParse3 ($1, $2, $3); + DPRINTF(("Done BufConstraint1\n")); } + +bufferModifier + : QMAXSET + | QMAXREAD + +relationalOp + : GE_OP + | LE_OP + | EQ_OP + +BufConstraintExpr + : BufConstraintTerm + | BufUnaryOp TLPAREN BufConstraintExpr TRPAREN {$$ = constraintExpr_parseMakeUnaryOp ($1, $3); DPRINTF( ("Got BufConstraintExpr UNary Op ") ); } + | TLPAREN BufConstraintExpr BufBinaryOp BufConstraintExpr TRPAREN { + DPRINTF( ("Got BufConstraintExpr BINary Op ") ); + $$ = constraintExpr_parseMakeBinaryOp ($2, $3, $4); } + +BufConstraintTerm + : BufConstraintSrefExpr { $$ = constraintExpr_makeTermsRef ($1);} + | CCONSTANT { $$ = constraintExpr_makeIntLiteral (exprNode_getLongValue ($1)); } + +BufConstraintSrefExpr +: id + { /*@-onlytrans@*/ $$ = checkbufferConstraintClausesId ($1); /*@=onlytrans@*/ /*@i523@*/ } +| NEW_IDENTIFIER + { $$ = fixStateClausesId ($1); } +| BufConstraintSrefExpr TLSQBR TRSQBR + { $$ = sRef_makeAnyArrayFetch ($1); } +| BufConstraintSrefExpr TLSQBR CCONSTANT TRSQBR + { + /* + char *t; int c; + t = cstring_toCharsSafe (exprNode_unparse($3)); + c = atoi( t ); + */ + $$ = sRef_makeArrayFetchKnown ($1, exprNode_getLongValue ($3)); + } +| TMULT BufConstraintSrefExpr + { $$ = sRef_constructPointer ($2); } +| TLPAREN BufConstraintSrefExpr TRPAREN + { $$ = $2; } +| BufConstraintSrefExpr TDOT newId + { cstring_markOwned ($3); $$ = sRef_buildField ($1, $3); } +| BufConstraintSrefExpr ARROW_OP newId + { cstring_markOwned ($3); $$ = sRef_makeArrow ($1, $3); } -optGlobModsRest - : optGlobModsAux - | specialClauses optGlobModsAux +/* +| BufConstraintTerm TLSQBR TRSQBR { $$ = sRef_makeAnyArrayFetch ($1); } + | specClauseListExpr TLSQBR mExpr TRSQBR { $$ = sRef_makeAnyArrayFetch ($1); } + | TLPAREN specClauseListExpr TRPAREN { $$ = $2; } + | specClauseListExpr TDOT newId { cstring_markOwned ($3); + $$ = sRef_buildField ($1, $3); } +*/ -optPlainGlobModsRest - : optPlainGlobModsAux - | specialClauses optPlainGlobModsAux +/*BufConstraintExpr +: BufConstraintTerm +*/ -specialClauses - : specialClause - | specialClause specialClauses - -globIdList - : globIdListExpr { ; } - | globIdList TCOMMA globIdListExpr { ; } - -globIdListExpr - : optGlobQuals globId { globListAdd ($2, $1); } +BufUnaryOp +: bufferModifier +; -globId - : id { $$ = uentry_getSref ($1); } - | NEW_IDENTIFIER { $$ = globListUnrecognized ($1); } +BufBinaryOp + : TPLUS +| TMINUS +; +/* +** Function clauses can appear in any order. +*/ -globQual - : QUNDEF { $$ = qual_createUndef (); } - | QKILLED { $$ = qual_createKilled (); } - | QOUT { $$ = qual_createOut (); } - | QIN { $$ = qual_createIn (); } - | QPARTIAL { $$ = qual_createPartial (); } +functionClauses + : { $$ = functionClauseList_new (); } + | functionClause functionClauses + { $$ = functionClauseList_prepend ($2, $1); } -optGlobQuals - : /* empty */ { $$ = qualList_undefined; } - | globQual optGlobQuals { $$ = qualList_add ($2, $1); } +/* +** Inside macro definitions, there are no end macros. +*/ -optGlobModsAux - : QGLOBALS { setProcessingGlobalsList (); } initializerList optSemi - QENDMACRO optMods - { unsetProcessingGlobals (); } - | QGLOBALS { setProcessingGlobalsList (); } globIdList optSemi - QENDMACRO optMods - { unsetProcessingGlobals (); } - | QNOMODS - { setFunctionNoGlobals (); - setFunctionModifies (sRefSet_single (sRef_makeNothing ())); - } - | fcnMods - | /* empty */ - -optPlainGlobModsAux - : QGLOBALS { setProcessingGlobalsList (); } initializerList optSemi - optMods - { unsetProcessingGlobals (); } - | QGLOBALS { setProcessingGlobalsList (); } globIdList optSemi - optMods - { unsetProcessingGlobals (); } - | QNOMODS - { setFunctionNoGlobals (); - setFunctionModifies (sRefSet_single (sRef_makeNothing ())); +functionClausesPlain + : + { $$ = functionClauseList_new (); } + | functionClausePlain functionClausesPlain + { $$ = functionClauseList_prepend ($2, $1); } + +functionClause + : globalsClause { $$ = functionClause_createGlobals ($1); } + | modifiesClause { $$ = functionClause_createModifies ($1); } + | nomodsClause { $$ = functionClause_createModifies ($1); } + | stateClause { $$ = functionClause_createState ($1); } + | conditionClause { $$ = $1; } + | warnClause { $$ = functionClause_createWarn ($1); } + +functionClausePlain + : globalsClausePlain { $$ = functionClause_createGlobals ($1); } + | modifiesClausePlain { $$ = functionClause_createModifies ($1); } + | nomodsClause { $$ = functionClause_createModifies ($1); } + | stateClausePlain { $$ = functionClause_createState ($1); } + | conditionClausePlain { $$ = $1; } + | warnClausePlain { $$ = functionClause_createWarn ($1); } + +globalsClause + : globalsClausePlain QENDMACRO { $$ = $1; } + +globalsClausePlain + : QGLOBALS { setProcessingGlobalsList (); } + globIdList optSemi + { + unsetProcessingGlobals (); + $$ = globalsClause_create ($1, $3); } - | fcnPlainMods - | /* empty */ -optMods - : fcnMods - | /* empty */ +nomodsClause + : QNOMODS { $$ = modifiesClause_createNoMods ($1); } -fcnMods +modifiesClause + : modifiesClausePlain QENDMACRO { $$ = $1; } + +modifiesClausePlain : QMODIFIES { context_setProtectVars (); enterParamsTemp (); @@ -454,79 +628,72 @@ fcnMods } locModifies { - setFunctionModifies ($3); exitParamsTemp (); + exitParamsTemp (); sRef_clearGlobalScopeSafe (); context_releaseVars (); + $$ = modifiesClause_create ($1, $3); } -fcnPlainMods - : QMODIFIES - { - context_setProtectVars (); enterParamsTemp (); - sRef_setGlobalScopeSafe (); - } - locPlainModifies - { - setFunctionModifies ($3); exitParamsTemp (); - sRef_clearGlobalScopeSafe (); - context_releaseVars (); +flagSpec + : flagId + { $$ = flagSpec_createPlain ($1); } + | flagId TBAR flagSpec + { $$ = flagSpec_createOr ($1, $3); } + +flagId + : NEW_IDENTIFIER + +optWarnClause + : warnClause + | /* empty */ { $$ = warnClause_undefined; } + +warnClause + : warnClausePlain QENDMACRO { $$ = $1; } + +warnClausePlain + : QWARN flagSpec cconstantExpr + { + llassert (exprNode_knownStringValue ($3)); + $$ = warnClause_create ($1, $2, cstring_copy (multiVal_forceString (exprNode_getValue ($3)))); + exprNode_free ($3); } + | QWARN flagSpec + { $$ = warnClause_create ($1, $2, cstring_undefined); } -specialTag +globIdList + : globIdListExpr { $$ = globSet_single ($1); } + | globIdList TCOMMA globIdListExpr { $$ = globSet_insert ($1, $3); } + +globIdListExpr + : optGlobQuals globId { $$ = clabstract_createGlobal ($2, $1); } + +optGlobQuals + : /* empty */ { $$ = qualList_undefined; } + | globQual optGlobQuals { $$ = qualList_add ($2, $1); } + +globId + : id { $$ = uentry_getSref ($1); } + | NEW_IDENTIFIER { $$ = clabstract_unrecognizedGlobal ($1); } + | initializer { $$ = clabstract_checkGlobal ($1); } + +globQual + : QUNDEF { $$ = qual_createUndef (); } + | QKILLED { $$ = qual_createKilled (); } + | QOUT { $$ = qual_createOut (); } + | QIN { $$ = qual_createIn (); } + | QPARTIAL { $$ = qual_createPartial (); } + +stateTag : QDEFINES | QUSES | QALLOCATES | QSETS | QRELEASES -endStateTag - : QENDMACRO - -endSpecialTag - : QENDMACRO - -stateSpecialClause +conditionTag : QPRECLAUSE | QPOSTCLAUSE -specialClauseType - : QONLY { $$ = SP_ISONLY; } - | QOBSERVER { $$ = SP_ISOBSERVER; } - | QEXPOSED { $$ = SP_ISEXPOSED; } - | QDEPENDENT { $$ = SP_ISDEPENDENT; } - | QOWNED { $$ = SP_ISOWNED; } - | QSHARED { $$ = SP_ISSHARED; } - | QISNULL { $$ = SP_ISNULL; } - | QNOTNULL { $$ = SP_ISNOTNULL; } - -specialClause - : specialTag NotType - { - context_setProtectVars (); - enterParamsTemp (); - sRef_setGlobalScopeSafe (); - } - specClauseList optSemi endSpecialTag IsType - { - setFunctionSpecialClause ($1, $4, $6); - exitParamsTemp (); - sRef_clearGlobalScopeSafe (); - context_releaseVars (); - } - | stateSpecialClause NotType specialClauseType - { - context_setProtectVars (); - enterParamsTemp (); - sRef_setGlobalScopeSafe (); - } - specClauseList optSemi endStateTag IsType - { - setFunctionStateSpecialClause ($1, $3, $5, $7); - exitParamsTemp (); - sRef_clearGlobalScopeSafe (); - context_releaseVars (); - } - fcnDefHdrAux : namedDecl { @@ -544,28 +711,26 @@ fcnBody exprNode_checkFunctionBody ($3); $$ = $3; context_exitInner ($3); } - | initializerList - { doneParams (); context_enterInnerContext (); } + | { context_enterOldStyleScope (); } initializerList + { oldStyleDoneParams (); context_enterInnerContext (); } compoundStmt { - context_exitInner ($3); - exprNode_checkFunctionBody ($3); - $$ = $3; /* old style */ + exprNode_checkFunctionBody ($4); + $$ = $4; /* oldstyle */ + context_exitInner ($4); } fcnDef : fcnDefHdr fcnBody { context_setFunctionDefined (exprNode_loc ($2)); - exprNode_checkFunction (context_getHeader (), $2); + exprNode_checkFunction (context_getHeader (), $2); + /* DRL 8 8 2000 */ + context_exitFunction (); } locModifies - : modList optSemi QENDMACRO { $$ = $1; } - | optSemi QENDMACRO { $$ = sRefSet_new (); } - -locPlainModifies : modList optSemi { $$ = $1; } | optSemi { $$ = sRefSet_new (); } @@ -581,8 +746,8 @@ modListExpr mExpr - : modListExpr { $$ = $1; } - | CCONSTANT { $$ = sRef_makeUnknown (); /* sRef_makeConstant ($1); ? */ } + : modListExpr { $$ = $1; } + | cconstantExpr { $$ = sRef_makeUnknown (); /* sRef_makeConstant ($1); ? */ } /* arithmetic? */ modList @@ -591,9 +756,9 @@ modList specClauseListExpr : id - { $$ = checkSpecClausesId ($1); } + { $$ = checkStateClausesId ($1); } | NEW_IDENTIFIER - { $$ = fixSpecClausesId ($1); } + { $$ = fixStateClausesId ($1); } | specClauseListExpr TLSQBR TRSQBR { $$ = sRef_makeAnyArrayFetch ($1); } | specClauseListExpr TLSQBR mExpr TRSQBR { $$ = sRef_makeAnyArrayFetch ($1); } | TMULT specClauseListExpr { $$ = sRef_constructPointer ($2); } @@ -603,6 +768,10 @@ specClauseListExpr | specClauseListExpr ARROW_OP newId { cstring_markOwned ($3); $$ = sRef_makeArrow ($1, $3); } +optSpecClauseList + : /* empty */ { $$ = sRefSet_undefined } + | specClauseList + specClauseList : specClauseListExpr { if (sRef_isValid ($1)) { $$ = sRefSet_single ($1); } @@ -622,10 +791,13 @@ specClauseList primaryExpr : id { $$ = exprNode_fromIdentifier ($1); } | NEW_IDENTIFIER { $$ = exprNode_fromUIO ($1); } - | CCONSTANT { $$ = $1; } + | cconstantExpr | TLPAREN expr TRPAREN { $$ = exprNode_addParens ($1, $2); } | TYPE_NAME_OR_ID { $$ = exprNode_fromIdentifier (coerceId ($1)); } | QEXTENSION { $$ = exprNode_makeError (); } + | TLPAREN { exprChecks_inCompoundStatementExpression (); } + compoundStmt TRPAREN + { exprChecks_leaveCompoundStatementExpression (); $$ = exprNode_compoundStatementExpression ($1, $3); } postfixExpr : primaryExpr @@ -633,11 +805,13 @@ postfixExpr | postfixExpr TLPAREN TRPAREN { $$ = exprNode_functionCall ($1, exprNodeList_new ()); } | postfixExpr TLPAREN argumentExprList TRPAREN { $$ = exprNode_functionCall ($1, $3); } | VA_ARG TLPAREN assignExpr TCOMMA typeExpression TRPAREN { $$ = exprNode_vaArg ($1, $3, $5); } - | postfixExpr NotType TDOT newId IsType { $$ = exprNode_fieldAccess ($1, $4); } - | postfixExpr NotType ARROW_OP newId IsType { $$ = exprNode_arrowAccess ($1, $4); } + | postfixExpr NotType TDOT newId IsType { $$ = exprNode_fieldAccess ($1, $3, $4); } + | postfixExpr NotType ARROW_OP newId IsType { $$ = exprNode_arrowAccess ($1, $3, $4); } | postfixExpr INC_OP { $$ = exprNode_postOp ($1, $2); } | postfixExpr DEC_OP { $$ = exprNode_postOp ($1, $2); } - + | TLPAREN typeExpression TRPAREN TLBRACE typeInitializerList optComma TRBRACE + { /* added for C99 */ $$ = exprNode_undefined; /*@i87 no checking */ } + argumentExprList : assignExpr { $$ = exprNodeList_singleton ($1); } | argumentExprList TCOMMA assignExpr { $$ = exprNodeList_push ($1, $3); } @@ -783,7 +957,8 @@ initializer | typeDecl { $$ = exprNode_makeError (); } instanceDecl - : completeTypeSpecifier IsType TSEMI { $$ = exprNode_makeError (); } + : completeTypeSpecifier IsType TSEMI + { $$ = exprNode_makeError (); } /* ** This causes r/r conflicts with function definitions. ** Instead we need to snarf one first. (gack) @@ -798,25 +973,35 @@ instanceDecl */ | completeTypeSpecifier NotType namedDecl NotType { - setProcessingVars ($1); - processNamedDecl ($3); } - IsType optDeclarators TSEMI IsType { unsetProcessingVars (); $$ = $7; } + setProcessingVars ($1); + processNamedDecl ($3); + } + IsType optDeclarators TSEMI IsType + { + unsetProcessingVars (); + $$ = exprNode_makeEmptyInitialization ($3); + DPRINTF (("Empty initialization: %s", exprNode_unparse ($$))); + } | completeTypeSpecifier NotType namedDecl NotType TASSIGN - { setProcessingVars ($1); processNamedDecl ($3); - } + { setProcessingVars ($1); processNamedDecl ($3); } IsType init optDeclarators TSEMI IsType { $$ = exprNode_concat ($9, exprNode_makeInitialization ($3, $8)); unsetProcessingVars (); } + namedInitializer - : namedDecl NotType { processNamedDecl ($1); $$ = exprNode_makeError (); } + : namedDecl NotType + { + processNamedDecl ($1); + $$ = exprNode_makeEmptyInitialization ($1); + } | namedDecl NotType TASSIGN { processNamedDecl ($1); } IsType init { $$ = exprNode_makeInitialization ($1, $6); } - typeDecl : CTYPEDEF completeTypeSpecifier { setProcessingTypedef ($2); } - NotType namedInitializerList IsType TSEMI { unsetProcessingTypedef (); } + NotType namedInitializerList IsType optWarnClause TSEMI + { clabstract_declareType ($5, $7); } | CTYPEDEF completeTypeSpecifier IsType TSEMI { /* in the ANSI grammar, semantics unclear */ } | CTYPEDEF namedInitializerList IsType TSEMI { /* in the ANSI grammar, semantics unclear */ } @@ -827,21 +1012,38 @@ PushType : { g_expectingTypeName = TRUE; context_pushLoc (); } namedInitializerList - : namedInitializerListAux IsType { ; } + : namedInitializerListAux IsType { $$ = $1; } namedInitializerListAux - : namedInitializer { ; } - | namedInitializerList TCOMMA NotType namedInitializer { ; } + : namedInitializer { $$ = exprNodeList_singleton ($1); } + | namedInitializerList TCOMMA NotType namedInitializer { $$ = exprNodeList_push ($1, $4); } optDeclarators : /* empty */ { $$ = exprNode_makeError (); } | optDeclarators TCOMMA NotType namedInitializer { $$ = exprNode_concat ($1, $4); } init - : assignExpr { $$ = $1; } + : assignExpr | TLBRACE initList TRBRACE { $$ = exprNode_makeInitBlock ($1, $2); } | TLBRACE initList TCOMMA TRBRACE { $$ = exprNode_makeInitBlock ($1, $2); } + | designation init { $$ = exprNode_undefined; } + +/* +** Splint parses these (added in ISO C99), but no checking yet... +*/ +designation + : designatorList TASSIGN { $$ = $1; } + | newId TCOLON { $$ = exprNode_undefined; + /* gcc extension, obsolete since 2.5 */ } + +designatorList + : designator { $$ = exprNode_undefined; } + | designatorList designator { $$ = exprNode_undefined; } + +designator + : TLSQBR constantExpr TRSQBR { $$ = exprNode_undefined; } + | TDOT newId { $$ = exprNode_undefined; } initList : init @@ -861,53 +1063,137 @@ storageSpecifier | QAUTO { $$ = qual_createAuto (); } | QREGISTER { $$ = qual_createRegister (); } -typeQualifier - : QCONST IsType { $$ = qual_createConst (); } - | QVOLATILE IsType { $$ = qual_createVolatile (); } - | QOUT IsType { $$ = qual_createOut (); } - | QIN IsType { $$ = qual_createIn (); } - | QPARTIAL IsType { $$ = qual_createPartial (); } - | QSPECIAL IsType { $$ = qual_createSpecial (); } - | QOWNED IsType { $$ = qual_createOwned (); } - | QDEPENDENT IsType { $$ = qual_createDependent (); } - | QYIELD IsType { $$ = qual_createYield (); } - | QTEMP IsType { $$ = qual_createTemp (); } - | QONLY IsType { $$ = qual_createOnly (); } - | QKEEP IsType { $$ = qual_createKeep (); } - | QKEPT IsType { $$ = qual_createKept (); } - | QSHARED IsType { $$ = qual_createShared (); } - | QUNIQUE IsType { $$ = qual_createUnique (); } - | QEXITS IsType { $$ = qual_createExits (); } - | QMAYEXIT IsType { $$ = qual_createMayExit (); } - | QTRUEEXIT IsType { $$ = qual_createTrueExit (); } - | QFALSEEXIT IsType { $$ = qual_createFalseExit (); } - | QNEVEREXIT IsType { $$ = qual_createNeverExit (); } - | QNULL IsType { $$ = qual_createNull (); } - | QRELNULL IsType { $$ = qual_createRelNull (); } - | QRETURNED IsType { $$ = qual_createReturned (); } - | QEXPOSED IsType { $$ = qual_createExposed (); } - | QOBSERVER IsType { $$ = qual_createObserver (); } - | QCHECKED IsType { $$ = qual_createChecked (); } - | QCHECKMOD IsType { $$ = qual_createCheckMod (); } - | QUNCHECKED IsType { $$ = qual_createUnchecked (); } - | QCHECKEDSTRICT IsType { $$ = qual_createCheckedStrict (); } - | QTRUENULL IsType { $$ = qual_createTrueNull (); } - | QFALSENULL IsType { $$ = qual_createFalseNull (); } - | QUNUSED IsType { $$ = qual_createUnused (); } - | QEXTERNAL IsType { $$ = qual_createExternal (); } - | QSEF IsType { $$ = qual_createSef (); } - | QABSTRACT IsType { $$ = qual_createAbstract (); } - | QCONCRETE IsType { $$ = qual_createConcrete (); } - | QMUTABLE IsType { $$ = qual_createMutable (); } - | QIMMUTABLE IsType { $$ = qual_createImmutable (); } - | QNOTNULL IsType { $$ = qual_createNotNull (); } - | QREFCOUNTED IsType { $$ = qual_createRefCounted (); } - | QREFS IsType { $$ = qual_createRefs (); } - | QKILLREF IsType { $$ = qual_createKillRef (); } - | QRELDEF IsType { $$ = qual_createRelDef (); } - | QNEWREF IsType { $$ = qual_createNewRef (); } - | QTEMPREF IsType { $$ = qual_createTempRef (); } - | QNULLTERMINATED IsType { $$ = qual_createNullTerminated (); } +stateClause + : stateClausePlain QENDMACRO { $$ = $1; } + +stateClausePlain + : stateTag NotType + { + context_setProtectVars (); + enterParamsTemp (); + sRef_setGlobalScopeSafe (); + } + specClauseList optSemi IsType + { + exitParamsTemp (); + sRef_clearGlobalScopeSafe (); + context_releaseVars (); + $$ = stateClause_createPlain ($1, $4); + } + +conditionClause + : conditionClausePlain QENDMACRO { $$ = $1; } + +startConditionClause +: conditionTag NotType { $$ = $1; context_enterFunctionHeader (); } + +conditionClausePlain + : startConditionClause stateQualifier + { + context_exitFunctionHeader (); + context_setProtectVars (); + enterParamsTemp (); + sRef_setGlobalScopeSafe (); + } + optSpecClauseList optSemi IsType + { + exitParamsTemp (); + sRef_clearGlobalScopeSafe (); + context_releaseVars (); + $$ = functionClause_createState (stateClause_create ($1, $2, $4)); + } + | startConditionClause + { + context_setProtectVars (); + enterParamsTemp (); + sRef_setGlobalScopeSafe (); + } + functionConstraint optSemi IsType + { + context_exitFunctionHeader (); + exitParamsTemp (); + sRef_clearGlobalScopeSafe (); + context_releaseVars (); + DPRINTF (("done optGlobBufConstraintsAux\n")); + + if (lltok_isEnsures ($1)) + { + $$ = functionClause_createEnsures ($3); + } + else if (lltok_isRequires ($1)) + { + $$ = functionClause_createRequires ($3); + } + else + { + BADBRANCH; + } + + DPRINTF (("FunctionclauseS: %s", functionClause_unparse ($$))); + } + +functionConstraint + : BufConstraintList { $$ = functionConstraint_createBufferConstraint ($1); } + | metaStateConstraint { $$ = functionConstraint_createMetaStateConstraint ($1); DPRINTF (("Made constraint: %s", functionConstraint_unparse ($$))); } + +exitsQualifier + : QEXITS { $$ = qual_createExits (); } + | QMAYEXIT { $$ = qual_createMayExit (); } + | QTRUEEXIT { $$ = qual_createTrueExit (); } + | QFALSEEXIT { $$ = qual_createFalseExit (); } + | QNEVEREXIT { $$ = qual_createNeverExit (); } + +checkQualifier + : QCHECKED { $$ = qual_createChecked (); } + | QCHECKMOD { $$ = qual_createCheckMod (); } + | QUNCHECKED { $$ = qual_createUnchecked (); } + | QCHECKEDSTRICT { $$ = qual_createCheckedStrict (); } + +stateQualifier + : QOWNED { $$ = qual_createOwned (); } + | QDEPENDENT { $$ = qual_createDependent (); } + | QYIELD { $$ = qual_createYield (); } + | QTEMP { $$ = qual_createTemp (); } + | QONLY { $$ = qual_createOnly (); } + | QKEEP { $$ = qual_createKeep (); } + | QKEPT { $$ = qual_createKept (); } + | QSHARED { $$ = qual_createShared (); } + | QUNIQUE { $$ = qual_createUnique (); } + | QNULL { $$ = qual_createNull (); } + | QISNULL { $$ = qual_createIsNull (); } + | QRELNULL { $$ = qual_createRelNull (); } + | QNOTNULL { $$ = qual_createNotNull (); } + | QEXPOSED { $$ = qual_createExposed (); } + | QOBSERVER { $$ = qual_createObserver (); } + | QNULLTERMINATED { $$ = qual_createNullTerminated (); } + | CANNOTATION { $$ = qual_createMetaState ($1); } + + +paramQualifier + : QRETURNED { $$ = qual_createReturned (); } + | QSEF { $$ = qual_createSef (); } + +visibilityQualifier + : QUNUSED { $$ = qual_createUnused (); } + | QEXTERNAL { $$ = qual_createExternal (); } + +returnQualifier + : QTRUENULL { $$ = qual_createTrueNull (); } + | QFALSENULL { $$ = qual_createFalseNull (); } + +typedefQualifier + : QABSTRACT { $$ = qual_createAbstract (); } + | QCONCRETE { $$ = qual_createConcrete (); } + | QMUTABLE { $$ = qual_createMutable (); } + | QIMMUTABLE { $$ = qual_createImmutable (); } + +refcountQualifier + : QREFCOUNTED { $$ = qual_createRefCounted (); } + | QREFS { $$ = qual_createRefs (); } + | QKILLREF { $$ = qual_createKillRef (); } + | QRELDEF { $$ = qual_createRelDef (); } + | QNEWREF { $$ = qual_createNewRef (); } + | QTEMPREF { $$ = qual_createTempRef (); } typeModifier : QSHORT { $$ = qual_createShort (); } @@ -915,6 +1201,29 @@ typeModifier | QSIGNED { $$ = qual_createSigned (); } | QUNSIGNED { $$ = qual_createUnsigned (); } +definedQualifier + : QOUT { $$ = qual_createOut (); } + | QIN { $$ = qual_createIn (); } + | QPARTIAL { $$ = qual_createPartial (); } + | QSPECIAL { $$ = qual_createSpecial (); } + +typeQualifier + : QCONST IsType { $$ = qual_createConst (); } + | QVOLATILE IsType { $$ = qual_createVolatile (); } + | definedQualifier IsType { $$ = $1; } + | stateQualifier IsType { $$ = $1; } + | exitsQualifier IsType { $$ = $1; } + | paramQualifier IsType { $$ = $1; } + | checkQualifier IsType { $$ = $1; } + | returnQualifier IsType { $$ = $1; } + | visibilityQualifier IsType { $$ = $1; } + | typedefQualifier IsType { $$ = $1; } + | refcountQualifier IsType { $$ = $1; } + +/* +** This is copied into the mtgrammar! +*/ + typeSpecifier : CGCHAR NotType | CINT NotType @@ -954,12 +1263,20 @@ optCompleteType : /* empty */ { $$ = qtype_unknown (); } | completeTypeSpecifier { $$ = $1; } + +optStructInvariant +: /* empty */ { $$ = constraintList_undefined; } +/* don't want to have support for structure invariant until we're + sure it's stable + | QINVARIANT BufConstraintList QENDMACRO { $$ = $2 } +*/ + suSpc : NotType CSTRUCT newId IsType TLBRACE { sRef_setGlobalScopeSafe (); } CreateStructInnerScope - structDeclList DeleteStructInnerScope { sRef_clearGlobalScopeSafe (); } + structDeclList DeleteStructInnerScope { sRef_clearGlobalScopeSafe (); } TRBRACE - { $$ = declareStruct ($3, $8); } + optStructInvariant { {ctype ct; ct = declareStruct ($3, $8); /* setGlobalStructInfo(ct, $12);*/ $$ = ct;} } | NotType CUNION newId IsType TLBRACE { sRef_setGlobalScopeSafe (); } CreateStructInnerScope structDeclList DeleteStructInnerScope { sRef_clearGlobalScopeSafe (); } @@ -974,9 +1291,9 @@ suSpc structDeclList DeleteStructInnerScope { sRef_clearGlobalScopeSafe (); } TRBRACE { $$ = declareUnnamedStruct ($7); } - | NotType CUNION IsType TLBRACE { sRef_setGlobalScopeSafe (); } - CreateStructInnerScope - structDeclList DeleteStructInnerScope { sRef_clearGlobalScopeSafe (); } + | NotType CUNION IsType TLBRACE { sRef_setGlobalScopeSafe (); } + CreateStructInnerScope structDeclList DeleteStructInnerScope + { sRef_clearGlobalScopeSafe (); } TRBRACE { $$ = declareUnnamedUnion ($7); } | NotType CSTRUCT IsType TLBRACE TRBRACE @@ -1137,9 +1454,11 @@ abstractDeclBase : IsType TLPAREN NotType abstractDecl TRPAREN { $$ = ctype_expectFunction ($4); } | TLSQBR TRSQBR { $$ = ctype_makeArray (ctype_unknown); } - | TLSQBR constantExpr TRSQBR { $$ = ctype_makeArray (ctype_unknown); } - | abstractDeclBase TLSQBR TRSQBR { $$ = ctype_makeArray ($1); } - | abstractDeclBase TLSQBR constantExpr TRSQBR { $$ = ctype_makeArray ($1); } + | TLSQBR constantExpr TRSQBR + { $$ = ctype_makeFixedArray (ctype_unknown, exprNode_getLongValue ($2)); } + | abstractDeclBase TLSQBR TRSQBR { $$ = ctype_makeInnerArray ($1); } + | abstractDeclBase TLSQBR constantExpr TRSQBR + { $$ = ctype_makeInnerFixedArray ($1, exprNode_getLongValue ($3)); } | IsType TLPAREN TRPAREN { $$ = ctype_makeFunction (ctype_unknown, uentryList_makeMissingParams ()); } | IsType TLPAREN paramTypeList TRPAREN @@ -1162,6 +1481,7 @@ stmt | iterStmt | jumpStmt + iterBody : iterDefStmtList { $$ = $1; } @@ -1201,7 +1521,7 @@ iterDefStmt : labeledStmt | caseStmt | defaultStmt - | openScope initializerList { $$ = $2; } + | openScope initializerList { $$ = $1; DPRINTF (("def stmt: %s", exprNode_unparse ($$))); } | openScope | closeScope | expressionStmt @@ -1213,9 +1533,9 @@ iterDefStmt | error { $$ = exprNode_makeError (); } iterSelectionStmt - : ifPred iterDefStmt + : ifPred { exprNode_checkIfPred ($1); } iterDefStmt { /* don't: context_exitTrueClause ($1, $2); */ - $$ = exprNode_if ($1, $2); + $$ = exprNode_if ($1, $3); } openScope @@ -1245,20 +1565,28 @@ labeledStmt : newId TCOLON { $$ = exprNode_labelMarker ($1); } | QNOTREACHED stmt { $$ = exprNode_notReached ($2); } +/* +** We allow more than one QFALLTHROUGH token to support mixed lint/splint markers. +*/ + +optExtraFallThroughs + : /* empty */ { ; } + | QFALLTHROUGH optExtraFallThroughs { ; } + /* Note that we can semantically check that the object to the case is indeed constant. In this case, we may not want to go through this effort */ caseStmt : CASE constantExpr { context_enterCaseClause ($2); } TCOLON { $$ = exprNode_caseMarker ($2, FALSE); } - | QFALLTHROUGH CASE constantExpr { context_enterCaseClause ($3); } - TCOLON { $$ = exprNode_caseMarker ($3, TRUE); } + | QFALLTHROUGH optExtraFallThroughs CASE constantExpr { context_enterCaseClause ($4); } + TCOLON { $$ = exprNode_caseMarker ($4, TRUE); } defaultStmt : DEFAULT { context_enterCaseClause (exprNode_undefined); } TCOLON { $$ = exprNode_defaultMarker ($1, FALSE); } - | QFALLTHROUGH DEFAULT { context_enterCaseClause (exprNode_undefined); } - TCOLON { $$ = exprNode_defaultMarker ($2, TRUE); } + | QFALLTHROUGH optExtraFallThroughs DEFAULT { context_enterCaseClause (exprNode_undefined); } + TCOLON { $$ = exprNode_defaultMarker ($3, TRUE); } compoundStmt : TLPAREN compoundStmt TRPAREN { $$ = $2; } @@ -1299,7 +1627,6 @@ compoundStmtRest lltok_getLoc ($3))); } - compoundStmtAux : TLBRACE compoundStmtRest { $$ = exprNode_makeBlock ($2); } @@ -1322,22 +1649,35 @@ initializerList : initializer { $$ = $1; } | initializerList initializer { $$ = exprNode_concat ($1, $2); } +typeInitializerList + : typeInitializer { $$ = $1; } + | typeInitializerList TCOMMA typeInitializer { $$ = exprNode_concat ($1, $3); } + +typeInitializer + : assignExpr { $$ = $1; } + | TLBRACE typeInitializerList optComma TRBRACE { $$ = $2; } + stmtList : stmt { $$ = $1; } | stmtList stmt { $$ = exprNode_concat ($1, $2); } expressionStmt : TSEMI { $$ = exprNode_createTok ($1); } - | expr TSEMI { $$ = exprNode_statement ($1); } + | expr TSEMI { $$ = exprNode_statement ($1, $2); } expressionStmtErr : TSEMI { $$ = exprNode_createTok ($1); } - | expr TSEMI { $$ = exprNode_statement ($1); } + | expr TSEMI { $$ = exprNode_statement ($1, $2); } | expr { $$ = exprNode_checkExpr ($1); } ifPred : CIF TLPAREN expr TRPAREN - { $$ = $3; exprNode_produceGuards ($3); context_enterTrueClause ($3); } + { + exprNode_produceGuards ($3); context_enterTrueClause ($3); + exprNode_checkIfPred ($3); + $$ = $3; + } + /* ** not ANSI: | CIF TLPAREN compoundStmt TRPAREN ** { $$ = $3; context_enterTrueClause (); } @@ -1349,7 +1689,7 @@ selectionStmt context_exitTrueClause ($1, $2); $$ = exprNode_if ($1, $2); } - | ifPred stmt CELSE { context_enterFalseClause ($1); } stmt + | ifPred stmt CELSE { context_enterFalseClause ($1); } stmt { context_exitClause ($1, $2, $5); $$ = exprNode_ifelse ($1, $2, $5); @@ -1400,8 +1740,12 @@ iterArgExpr ** everything is the same, EXCEPT it cannot be a NEW_IDENTIFIER */ +cconstantExpr + : CCONSTANT + | cconstantExpr CCONSTANT { $$ = exprNode_combineLiterals ($1, $2); } + primaryIterExpr - : CCONSTANT + : cconstantExpr | TLPAREN expr TRPAREN { $$ = exprNode_addParens ($1, $2); } postfixIterExpr @@ -1411,8 +1755,8 @@ postfixIterExpr | postfixExpr TLPAREN argumentExprList TRPAREN { $$ = exprNode_functionCall ($1, $3); } | VA_ARG TLPAREN assignExpr TCOMMA typeExpression TRPAREN { $$ = exprNode_vaArg ($1, $3, $5); } - | postfixExpr NotType TDOT newId IsType { $$ = exprNode_fieldAccess ($1, $4); } - | postfixExpr NotType ARROW_OP newId IsType { $$ = exprNode_arrowAccess ($1, $4); } + | postfixExpr NotType TDOT newId IsType { $$ = exprNode_fieldAccess ($1, $3, $4); } + | postfixExpr NotType ARROW_OP newId IsType { $$ = exprNode_arrowAccess ($1, $3, $4); } | postfixExpr INC_OP { $$ = exprNode_postOp ($1, $2); } | postfixExpr DEC_OP { $$ = exprNode_postOp ($1, $2); } @@ -1512,14 +1856,14 @@ iterationStmt : whilePred stmt { $$ = exprNode_while ($1, $2); context_exitWhileClause ($1, $2); } | doHeader stmt WHILE TLPAREN expr TRPAREN TSEMI - { $$ = exprNode_statement (exprNode_doWhile ($2, $5)); } + { $$ = exprNode_statement (exprNode_doWhile ($2, $5), $7); } | forPred stmt { $$ = exprNode_for ($1, $2); context_exitForClause ($1, $2); } iterationStmtErr : whilePred stmtErr { $$ = exprNode_while ($1, $2); context_exitWhileClause ($1, $2); } | doHeader stmtErr WHILE TLPAREN expr TRPAREN TSEMI - { $$ = exprNode_statement (exprNode_doWhile ($2, $5)); } + { $$ = exprNode_statement (exprNode_doWhile ($2, $5), $7); } | doHeader stmtErr WHILE TLPAREN expr TRPAREN { $$ = exprNode_doWhile ($2, $5); } | forPred stmtErr { $$ = exprNode_for ($1, $2); context_exitForClause ($1, $2); } @@ -1541,6 +1885,10 @@ optSemi : | TSEMI { ; } +optComma + : + | TCOMMA { ; } + id : IDENTIFIER @@ -1554,12 +1902,14 @@ newId typeName : TYPE_NAME | TYPE_NAME_OR_ID { $$ = ctype_unknown; } + | CTYPEOF TLPAREN expr TRPAREN { $$ = exprNode_getType ($3); exprNode_free ($3); } + | CTYPEOF TLPAREN typeExpression TRPAREN { $$ = qtype_getType ($3); } %% -/*@-redecl@*/ +/*@-redecl@*/ /*@-namechecks@*/ extern char *yytext; -/*@=redecl@*/ +/*@=redecl@*/ /*@=namechecks@*/ # include "bison.reset" @@ -1582,7 +1932,7 @@ void yyerror (/*@unused@*/ char *s) llerror (FLG_SYNTAX, message ("Macro syntax not parseable: %s", context_inFunctionName ())); - if (context_inMacroUnknown ()) + if (context_inUnknownMacro ()) { if (!givehint) { @@ -1594,6 +1944,7 @@ void yyerror (/*@unused@*/ char *s) } swallowMacro (); + context_exitAllClausesQuiet (); } else { @@ -1601,11 +1952,14 @@ void yyerror (/*@unused@*/ char *s) } } -void printState (idDecl t) { - cstring id = idDecl_getName (t); - uentry ue = usymtab_lookupSafe (id); - sRef s = uentry_getSref (ue); - - printf("State = %d\n", s->bufinfo.bufstate); -} + + + + + + + + + +