diff --git a/Test/baseResults/cppComplexExpr.vert.out b/Test/baseResults/cppComplexExpr.vert.out index 67a93e43..6b8b01a8 100644 --- a/Test/baseResults/cppComplexExpr.vert.out +++ b/Test/baseResults/cppComplexExpr.vert.out @@ -2,8 +2,20 @@ cppComplexExpr.vert ERROR: 0:46: 'xyxwx' : illegal vector field selection ERROR: 0:46: 'xyxwx' : illegal vector field selection ERROR: 0:66: '#define' : Macro redefined; different substitutions: BIG -ERROR: 0:79: '' : missing #endif -ERROR: 4 compilation errors. No code generated. +ERROR: 0:81: 'preprocessor evaluation' : bad expression +ERROR: 0:81: '#if' : unexpected tokens following directive +ERROR: 0:82: '#error' : good macro +ERROR: 0:89: 'macro expansion' : unexpected '#' foobar +ERROR: 0:90: 'preprocessor evaluation' : bad expression +ERROR: 0:94: 'macro expansion' : unexpected '#' foobar +ERROR: 0:95: 'preprocessor evaluation' : bad expression +ERROR: 0:100: 'preprocessor evaluation' : bad expression +ERROR: 0:100: '#if' : unexpected tokens following directive +ERROR: 0:103: 'macro expansion' : unexpected '#' foobar +ERROR: 0:103: 'preprocessor evaluation' : undefined macro in expression +ERROR: 0:103: '#if' : unexpected tokens following directive +ERROR: 0:104: '' : missing #endif +ERROR: 16 compilation errors. No code generated. ERROR: node is still EOpNull! @@ -66,8 +78,14 @@ ERROR: node is still EOpNull! 0:47 1 (const int) 0:47 Constant: 0:47 3.000000 +0:97 Sequence +0:97 move second child to first child (highp float) +0:97 'c' (highp float) +0:98 Constant: +0:98 3.300000 0:? Linker Objects 0:? 'sum' (highp float) +0:? 'c' (highp float) 0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int) diff --git a/Test/baseResults/cppSimple.vert.out b/Test/baseResults/cppSimple.vert.out index 8d8ff798..d47c52bd 100644 --- a/Test/baseResults/cppSimple.vert.out +++ b/Test/baseResults/cppSimple.vert.out @@ -6,15 +6,15 @@ ERROR: 0:85: '#error' : good3 ERROR: 0:89: '#error' : good4 ERROR: 0:93: '#error' : good5 ERROR: 0:97: '#error' : good6 -ERROR: 0:101: 'preprocessor' : expected ')' +ERROR: 0:101: 'preprocessor evaluation' : expected ')' ERROR: 0:101: '#error' : bad1 ERROR: 0:104: '#if' : unexpected tokens following directive ERROR: 0:105: '#error' : bad2 -ERROR: 0:109: 'preprocessor' : expected ')' +ERROR: 0:109: 'preprocessor evaluation' : expected ')' ERROR: 0:109: '#error' : bad3 ERROR: 0:112: '#if' : unexpected tokens following directive ERROR: 0:113: '#error' : bad4 -ERROR: 0:117: 'preprocessor' : expected ')' +ERROR: 0:117: 'preprocessor evaluation' : expected ')' ERROR: 0:117: '#error' : bad5 ERROR: 0:120: '#if' : unexpected tokens following directive ERROR: 0:121: '#error' : bad6 @@ -44,8 +44,25 @@ ERROR: 0:192: '#define' : Macro redefined; different substitutions: m8 ERROR: 0:196: '#define' : Macro redefined; different argument names: m9 ERROR: 0:204: '#undef' : can't use with built-in names (containing consecutive underscores) ERROR: 0:205: '#undef' : can't use with built-in names ("GL_" prefix) -ERROR: 0:209: '' : missing #endif -ERROR: 45 compilation errors. No code generated. +ERROR: 0:210: '#' : invalid directive +ERROR: 0:211: '#' : invalid directive +ERROR: 0:212: '#' : invalid directive +ERROR: 0:213: '#' : invalid directive +ERROR: 0:214: '#' : invalid directive +ERROR: 0:215: '#' : invalid directive +ERROR: 0:224: '#pragma' : optimize pragma syntax is incorrect +ERROR: 0:225: '#pragma' : optimize pragma syntax is incorrect +ERROR: 0:226: '#pragma' : debug pragma syntax is incorrect +ERROR: 0:227: '#pragma' : debug pragma syntax is incorrect +ERROR: 0:229: '#pragma' : optimize pragma syntax is incorrect +ERROR: 0:230: '#pragma' : debug pragma syntax is incorrect +ERROR: 0:233: 'line continuation' : not supported for this version or the enabled extensions +ERROR: 0:235: 'line continuation' : not supported for this version or the enabled extensions +ERROR: 0:236: '#error' : good continuation +ERROR: 0:238: '#' : invalid directive: flizbit +ERROR: 0:242: '#' : invalid directive: directive +ERROR: 0:246: '' : missing #endif +ERROR: 62 compilation errors. No code generated. ERROR: node is still EOpNull! diff --git a/Test/cppComplexExpr.vert b/Test/cppComplexExpr.vert index fa43eaf0..3fb206b9 100644 --- a/Test/cppComplexExpr.vert +++ b/Test/cppComplexExpr.vert @@ -75,5 +75,30 @@ float foo() #define BIGARGS3(aonthanotehu, bonthanotehu, conthanotehu, donthanotehu, eonthanotehu, fonthanotehu, gonthanotehu, honthanotehu, ionthanotehu, jonthanotehu, konthanotehu) jonthanotehu #define BIGARGS4(aonthanotehu, bonthanotehu, conthanotehu, donthanotehu, eonthanotehu, fonthanotehu, gonthanotehu, honthanotehu, ionthanotehu, jonthanotehu, konthanotehu) jonthanotehu + +#define foobar(a, b) a + b + +#if foobar(1.1, 2.2) +#error good macro +#else +#error bad macro +#endif + +#if foobar(1 +; +# +# +#endif +#if foobar(1, +; +# +# +#endif +float c = foobar(1.1, 2.2 + ); +#if foobar(1.1, 2.2 +) +#if foobar(1.1, 2.2 + #if 0 // ERROR, EOF \ No newline at end of file diff --git a/Test/cppSimple.vert b/Test/cppSimple.vert index 59854fd2..73604e20 100644 --- a/Test/cppSimple.vert +++ b/Test/cppSimple.vert @@ -70,8 +70,8 @@ sum += 0.05; } #define A 0 -#define B 0 -#define C 0 +# define B 0 + # define C 0 #if (A == B) || (A == C) #error good1 @@ -204,6 +204,43 @@ double f = f1; #undef __VERSION__ #undef GL_ARB_texture_rectangle +# + # + # +## +# # +# 0x25 +#### +####ff +#########ff fg 0x25 +#pragma +#pragma(aoent) + # pragma +#pragma STDGL +#pragma optimize( on) +#pragma optimize(off) +#pragma debug( on) +#pragma debug(off ) +#pragma optimize( on) anoteun +#pragma optimize(off +#pragma debug( on) ( +#pragma debug(off aoeua) +#pragma optimize( on) +#pragma optimize(off,) +#pragma debug( on, aoeu) +#pragma debugoff ) +#pragma aontheu natoeh uantheo uasotea noeahuonea uonethau onethuanoeth aunotehau noeth anthoeua anoethuantoeh uantoehu natoehu naoteh unotaehu noethua onetuh aou +# \ + +# \ + error good continuation + +#flizbit + +#define directive error + +#directive directive was expanded + #if 1 #else // ERROR, missing #endif \ No newline at end of file diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 842d429e..a7af49f9 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -147,87 +147,59 @@ void TParseContext::parserError(const char *s) error(getCurrentLoc(), "", "", s, ""); } -void TParseContext::handlePragma(const char **tokens, int numTokens) +void TParseContext::handlePragma(TSourceLoc loc, const TVector& tokens) { - if (!strcmp(tokens[0], "optimize")) { - if (numTokens != 4) { - error(getCurrentLoc(), "optimize pragma syntax is incorrect", "#pragma", ""); + if (tokens.size() == 0) + return; + + if (tokens[0].compare("optimize") == 0) { + if (tokens.size() != 4) { + error(loc, "optimize pragma syntax is incorrect", "#pragma", ""); return; } - if (strcmp(tokens[1], "(")) { - error(getCurrentLoc(), "\"(\" expected after 'optimize' keyword", "#pragma", ""); + if (tokens[1].compare("(") != 0) { + error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", ""); return; } - if (!strcmp(tokens[2], "on")) + if (tokens[2].compare("on") == 0) contextPragma.optimize = true; - else if (!strcmp(tokens[2], "off")) + else if (tokens[2].compare("off") == 0) contextPragma.optimize = false; else { - error(getCurrentLoc(), "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); + error(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); return; } - if (strcmp(tokens[3], ")")) { - error(getCurrentLoc(), "\")\" expected to end 'optimize' pragma", "#pragma", ""); + if (tokens[3].compare(")") != 0) { + error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", ""); return; } - } else if (!strcmp(tokens[0], "debug")) { - if (numTokens != 4) { - error(getCurrentLoc(), "debug pragma syntax is incorrect", "#pragma", ""); + } else if (tokens[0].compare("debug") == 0) { + if (tokens.size() != 4) { + error(loc, "debug pragma syntax is incorrect", "#pragma", ""); return; } - if (strcmp(tokens[1], "(")) { - error(getCurrentLoc(), "\"(\" expected after 'debug' keyword", "#pragma", ""); + if (tokens[1].compare("(") != 0) { + error(loc, "\"(\" expected after 'debug' keyword", "#pragma", ""); return; } - if (!strcmp(tokens[2], "on")) + if (tokens[2].compare("on") == 0) contextPragma.debug = true; - else if (!strcmp(tokens[2], "off")) + else if (tokens[2].compare("off") == 0) contextPragma.debug = false; else { - error(getCurrentLoc(), "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); + error(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); return; } - if (strcmp(tokens[3], ")")) { - error(getCurrentLoc(), "\")\" expected to end 'debug' pragma", "#pragma", ""); + if (tokens[3].compare(")") != 0) { + error(loc, "\")\" expected to end 'debug' pragma", "#pragma", ""); return; } - } else { - -#ifdef PRAGMA_TABLE - // - // implementation specific pragma - // use parseContext.contextPragma.pragmaTable to store the information about pragma - // For now, just ignore the pragma that the implementation cannot recognize - // An Example of one such implementation for a pragma that has a syntax like - // #pragma pragmaname(pragmavalue) - // This implementation stores the current pragmavalue against the pragma name in pragmaTable. - // - if (numTokens == 4 && !strcmp(tokens[1], "(") && !strcmp(tokens[3], ")")) { - TPragmaTable& pragmaTable = parseContext.contextPragma.pragmaTable; - TPragmaTable::iterator iter; - iter = pragmaTable.find(TString(tokens[0])); - if (iter != pragmaTable.end()) { - iter->second = tokens[2]; - } else { - pragmaTable[tokens[0]] = tokens[2]; - } - } else if (numTokens >= 2) { - TPragmaTable& pragmaTable = parseContext.contextPragma.pragmaTable; - TPragmaTable::iterator iter; - iter = pragmaTable.find(TString(tokens[0])); - if (iter != pragmaTable.end()) { - iter->second = tokens[1]; - } else { - pragmaTable[tokens[0]] = tokens[1]; - } - } -#endif // PRAGMA_TABLE } } diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index a2ce180f..69044b11 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -79,7 +79,7 @@ public: void lineContinuationCheck(TSourceLoc); bool builtInName(const TString&); - void handlePragma(const char **tokens, int numTokens); + void handlePragma(TSourceLoc, const TVector&); TIntermTyped* handleVariable(TSourceLoc, TSymbol* symbol, TString* string); TIntermTyped* handleBracketDereference(TSourceLoc, TIntermTyped* base, TIntermTyped* index); void checkIndex(TSourceLoc, const TType&, int& index); diff --git a/glslang/MachineIndependent/preprocessor/Pp.cpp b/glslang/MachineIndependent/preprocessor/Pp.cpp index f0064d09..ead5dc4f 100644 --- a/glslang/MachineIndependent/preprocessor/Pp.cpp +++ b/glslang/MachineIndependent/preprocessor/Pp.cpp @@ -430,7 +430,7 @@ struct tunops { #define ALEN(A) (sizeof(A)/sizeof(A[0])) -int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken * ppToken) +int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken* ppToken) { int i, val; Symbol *s; @@ -444,7 +444,7 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken * ppToken token = currentInput->scan(this, currentInput, ppToken); } if (token != CPP_IDENTIFIER) { - parseContext.error(ppToken->loc, "incorrect directive, expected identifier", "preprocessor", ""); + parseContext.error(ppToken->loc, "incorrect directive, expected identifier", "preprocessor evaluation", ""); *err = 1; *res = 0; @@ -455,7 +455,7 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken * ppToken token = currentInput->scan(this, currentInput, ppToken); if (needclose) { if (token != ')') { - parseContext.error(ppToken->loc, "#else after #else", "", ""); + parseContext.error(ppToken->loc, "#else after #else", "preprocessor evaluation", ""); *err = 1; *res = 0; @@ -466,7 +466,7 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken * ppToken } else { int macroReturn = MacroExpand(ppToken->atom, ppToken, 1); if (macroReturn == 0) { - parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor", ""); + parseContext.error(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", ""); *err = 1; *res = 0; @@ -475,9 +475,9 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken * ppToken if (macroReturn == -1) { if (parseContext.profile == EEsProfile) { if (parseContext.messages & EShMsgRelaxedErrors) - parseContext.warn(ppToken->loc, "undefined macro in expression not allowed in es profile", "preprocessor", ""); + parseContext.warn(ppToken->loc, "undefined macro in expression not allowed in es profile", "preprocessor evaluation", ""); else { - parseContext.error(ppToken->loc, "undefined macro in expression", "preprocessor", ""); + parseContext.error(ppToken->loc, "undefined macro in expression", "preprocessor evaluation", ""); *err = 1; } @@ -496,7 +496,7 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken * ppToken token = eval(token, MIN_PREC, res, err, ppToken); if (!*err) { if (token != ')') { - parseContext.error(ppToken->loc, "expected ')'", "preprocessor", ""); + parseContext.error(ppToken->loc, "expected ')'", "preprocessor evaluation", ""); *err = 1; *res = 0; @@ -514,7 +514,7 @@ int TPpContext::eval(int token, int prec, int *res, int *err, TPpToken * ppToken token = eval(token, UNARY, res, err, ppToken); *res = unop[i].op(*res); } else { - parseContext.error(ppToken->loc, "", "bad expression", ""); + parseContext.error(ppToken->loc, "bad expression", "preprocessor evaluation", ""); *err = 1; *res = 0; @@ -640,66 +640,44 @@ int TPpContext::CPPerror(TPpToken * ppToken) return '\n'; } -int TPpContext::CPPpragma(TPpToken * ppToken) +int TPpContext::CPPpragma(TPpToken* ppToken) { char SrcStrName[2]; - char** allTokens; int tokenCount = 0; int maxTokenCount = 10; const char* SrcStr; - int i; + TVector tokens; + TSourceLoc loc = ppToken->loc; // because we go to the next line before processing int token = currentInput->scan(this, currentInput, ppToken); - - if (token=='\n') { - parseContext.error(ppToken->loc, "must be followed by pragma arguments", "#pragma", ""); - return token; - } - - allTokens = (char**)malloc(sizeof(char*) * maxTokenCount); - - while (token != '\n') { - if (tokenCount >= maxTokenCount) { - maxTokenCount *= 2; - allTokens = (char**)realloc((char**)allTokens, sizeof(char*) * maxTokenCount); - } + while (token != '\n' && token != EOF) { switch (token) { case CPP_IDENTIFIER: SrcStr = GetAtomString(ppToken->atom); - allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); - strcpy(allTokens[tokenCount++], SrcStr); + tokens.push_back(SrcStr); break; case CPP_INTCONSTANT: case CPP_UINTCONSTANT: case CPP_FLOATCONSTANT: case CPP_DOUBLECONSTANT: SrcStr = ppToken->name; - allTokens[tokenCount] = (char*)malloc(strlen(SrcStr) + 1); - strcpy(allTokens[tokenCount++], SrcStr); + tokens.push_back(SrcStr); break; - case EOF: - parseContext.error(ppToken->loc, "directive must end with a newline", "#pragma", ""); - return token; default: SrcStrName[0] = token; SrcStrName[1] = '\0'; - allTokens[tokenCount] = (char*)malloc(2); - strcpy(allTokens[tokenCount++], SrcStrName); + tokens.push_back(SrcStrName); } token = currentInput->scan(this, currentInput, ppToken); } - currentInput->ungetch(this, currentInput, token, ppToken); - parseContext.handlePragma((const char**)allTokens, tokenCount); - token = currentInput->scan(this, currentInput, ppToken); - - for (i = 0; i < tokenCount; ++i) { - free (allTokens[i]); - } - free (allTokens); + if (token == EOF) + parseContext.error(loc, "directive must end with a newline", "#pragma", ""); + else + parseContext.handlePragma(loc, tokens); return token; -} // CPPpragma +} // This is just for error checking: the version and profile are decided before preprocessing starts int TPpContext::CPPversion(TPpToken * ppToken) @@ -836,9 +814,10 @@ int TPpContext::readCPPline(TPpToken * ppToken) } else if (ppToken->atom == extensionAtom) { token = CPPextension(ppToken); } else { - parseContext.error(ppToken->loc, "Invalid Directive", "#", GetAtomString(ppToken->atom)); + parseContext.error(ppToken->loc, "invalid directive:", "#", GetAtomString(ppToken->atom)); } - } + } else if (token != '\n' && token > 0) + parseContext.error(ppToken->loc, "invalid directive", "#", ""); while (token != '\n' && token != 0 && token != EOF) token = currentInput->scan(this, currentInput, ppToken); @@ -959,7 +938,7 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef) { Symbol *sym = LookUpSymbol(atom); MacroInputSrc *in; - int i, j, token; + int token; int depth = 0; if (atom == __LINE__Atom) { @@ -1005,6 +984,7 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef) return -1; } + TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error in->scan = macro_scan; in->mac = &sym->mac; if (sym->mac.args) { @@ -1016,37 +996,53 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef) return 0; } in->args.resize(in->mac->argc); - for (i = 0; i < in->mac->argc; i++) + for (int i = 0; i < in->mac->argc; i++) in->args[i] = new TokenStream; - i = 0; - j = 0; + int arg = 0; + bool tokenRecorded = false; do { depth = 0; while (1) { token = currentInput->scan(this, currentInput, ppToken); if (token <= 0) { - parseContext.error(ppToken->loc, "EOF in macro", "preprocessor", GetAtomString(atom)); - + parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); return 1; } - if ((in->mac->argc==0) && (token!=')')) break; - if (depth == 0 && (token == ',' || token == ')')) break; - if (token == '(') depth++; - if (token == ')') depth--; - RecordToken(in->args[i], token, ppToken); - j=1; + if (token == '\n') { + // TODO: Preprocessor functionality: Correctly handle new line and escaped new line, for expansions that are both in and not in another preprocessor directive + + //if (in a pp line) { + // parseContext.error(loc, "missing ')':", "macro expansion", GetAtomString(atom)); + // return 1; + //} + continue; + } + if (token == '#') { + parseContext.error(ppToken->loc, "unexpected '#'", "macro expansion", GetAtomString(atom)); + return 1; + } + if (in->mac->argc == 0 && token != ')') + break; + if (depth == 0 && (token == ',' || token == ')')) + break; + if (token == '(') + depth++; + if (token == ')') + depth--; + RecordToken(in->args[arg], token, ppToken); + tokenRecorded = true; } if (token == ')') { - if ((in->mac->argc==1) &&j==0) + if (in->mac->argc == 1 && tokenRecorded == 0) break; - i++; + arg++; break; } - i++; - } while (i < in->mac->argc); + arg++; + } while (arg < in->mac->argc); - if (i < in->mac->argc) - parseContext.error(ppToken->loc, "Too few args in Macro", "preprocessor", GetAtomString(atom)); + if (arg < in->mac->argc) + parseContext.error(loc, "Too few args in Macro", "macro expansion", GetAtomString(atom)); else if (token != ')') { depth=0; while (token >= 0 && (depth > 0 || token != ')')) { @@ -1058,13 +1054,12 @@ int TPpContext::MacroExpand(int atom, TPpToken* ppToken, int expandUndef) } if (token <= 0) { - parseContext.error(ppToken->loc, "EOF in macro", "preprocessor", GetAtomString(atom)); - + parseContext.error(loc, "EOF in macro", "macro expansion", GetAtomString(atom)); return 1; } - parseContext.error(ppToken->loc, "Too many args in Macro", "preprocessor", GetAtomString(atom)); + parseContext.error(loc, "Too many args in macro", "macro expansion", GetAtomString(atom)); } - for (i = 0; i < in->mac->argc; i++) + for (int i = 0; i < in->mac->argc; i++) in->args[i] = PrescanMacroArg(in->args[i], ppToken); }