- fix: Processing for #if/#elif/#else is not correct.

This commit is contained in:
Roy Qu 2023-10-01 10:45:43 +08:00
parent 02a0ed049b
commit 14ba74e705
5 changed files with 63 additions and 40 deletions

View File

@ -8,6 +8,7 @@ Red Panda C++ Version 2.25
- enhancement: Option "Enable ANSI escape sequences Support" in Settings -> Executor - enhancement: Option "Enable ANSI escape sequences Support" in Settings -> Executor
- change: Use freetype as the fontengine in windows ( from cyano.CN ) - change: Use freetype as the fontengine in windows ( from cyano.CN )
- fix: Custom compile options is not used when retrieve macros defined by the compiler. - fix: Custom compile options is not used when retrieve macros defined by the compiler.
- fix: Processing for #if/#elif/#else is not correct.
Red Panda C++ Version 2.24 Red Panda C++ Version 2.24

View File

@ -347,12 +347,12 @@ void CppPreprocessor::handleBranch(const QString &line)
// return; // return;
// } // }
// } // }
if (!getCurrentBranch()) { if (getCurrentBranch()!=BranchResult::isTrue) {
setCurrentBranch(false); setCurrentBranch(BranchResult::parentIsFalse);
} else { } else {
constexpr int IFDEF_LEN = 5; //length of ifdef; constexpr int IFDEF_LEN = 5; //length of ifdef;
QString name = line.mid(IFDEF_LEN).trimmed(); QString name = line.mid(IFDEF_LEN).trimmed();
setCurrentBranch( getDefine(name)!=nullptr ); setCurrentBranch( getDefine(name)!=nullptr?(BranchResult::isTrue):(BranchResult::isFalse) );
} }
} else if (line.startsWith("ifndef")) { } else if (line.startsWith("ifndef")) {
@ -363,12 +363,12 @@ void CppPreprocessor::handleBranch(const QString &line)
// return; // return;
// } // }
// } // }
if (!getCurrentBranch()) { if (getCurrentBranch()!=BranchResult::isTrue) {
setCurrentBranch(false); setCurrentBranch(BranchResult::parentIsFalse);
} else { } else {
constexpr int IFNDEF_LEN = 6; //length of ifndef; constexpr int IFNDEF_LEN = 6; //length of ifndef;
QString name = line.mid(IFNDEF_LEN).trimmed(); QString name = line.mid(IFNDEF_LEN).trimmed();
setCurrentBranch( getDefine(name)==nullptr ); setCurrentBranch( getDefine(name)==nullptr?(BranchResult::isTrue):(BranchResult::isFalse) );
} }
} else if (line.startsWith("if")) { } else if (line.startsWith("if")) {
// // if a branch that is not at our level is false, current branch is false too; // // if a branch that is not at our level is false, current branch is false too;
@ -378,29 +378,30 @@ void CppPreprocessor::handleBranch(const QString &line)
// return; // return;
// } // }
// } // }
if (!getCurrentBranch()) {// we are already inside an if that is NOT being taken if (getCurrentBranch()!=BranchResult::isTrue) {// we are already inside an if that is NOT being taken
setCurrentBranch(false);// so don't take this one either setCurrentBranch(BranchResult::parentIsFalse);// so don't take this one either
} else { } else {
constexpr int IF_LEN = 2; //length of if; constexpr int IF_LEN = 2; //length of if;
QString ifLine = line.mid(IF_LEN).trimmed(); QString ifLine = line.mid(IF_LEN).trimmed();
bool testResult = evaluateIf(ifLine); bool testResult = evaluateIf(ifLine);
setCurrentBranch(testResult); setCurrentBranch(testResult?(BranchResult::isTrue):(BranchResult::isFalse));
} }
} else if (line.startsWith("else")) { } else if (line.startsWith("else")) {
bool oldResult = getCurrentBranch(); // take either if or else BranchResult oldResult = getCurrentBranch(); // take either if or else
removeCurrentBranch(); removeCurrentBranch();
setCurrentBranch(!oldResult); setCurrentBranch(calcElseBranchResult(oldResult));
} else if (line.startsWith("elif")) { } else if (line.startsWith("elif")) {
bool oldResult = getCurrentBranch(); // take either if or else BranchResult oldResult = getCurrentBranch(); // take either if or else
removeCurrentBranch(); removeCurrentBranch();
if (oldResult) { // don't take this one, if previous has been taken BranchResult elseResult = calcElseBranchResult(oldResult);
setCurrentBranch(false); if (elseResult == BranchResult::isTrue) { // don't take this one, if previous has been taken
} else {
constexpr int ELIF_LEN = 4; //length of if; constexpr int ELIF_LEN = 4; //length of if;
QString ifLine = line.mid(ELIF_LEN).trimmed(); QString ifLine = line.mid(ELIF_LEN).trimmed();
bool testResult = evaluateIf(ifLine); bool testResult = evaluateIf(ifLine);
setCurrentBranch(testResult); setCurrentBranch(testResult?(BranchResult::isTrue):(BranchResult::isFalse));
} else {
setCurrentBranch(elseResult);
} }
} else if (line.startsWith("endif")) { } else if (line.startsWith("endif")) {
removeCurrentBranch(); removeCurrentBranch();
@ -409,7 +410,7 @@ void CppPreprocessor::handleBranch(const QString &line)
void CppPreprocessor::handleDefine(const QString &line) void CppPreprocessor::handleDefine(const QString &line)
{ {
if (getCurrentBranch()) { if (getCurrentBranch() == BranchResult::isTrue) {
addDefineByLine(line, false); addDefineByLine(line, false);
mResult[mPreProcIndex] = '#' + line; // add define to result file so the parser can handle it mResult[mPreProcIndex] = '#' + line; // add define to result file so the parser can handle it
} }
@ -417,7 +418,7 @@ void CppPreprocessor::handleDefine(const QString &line)
void CppPreprocessor::handleInclude(const QString &line, bool fromNext) void CppPreprocessor::handleInclude(const QString &line, bool fromNext)
{ {
if (!getCurrentBranch()) // we're skipping due to a branch failure if (getCurrentBranch()!=BranchResult::isTrue) // we're skipping due to a branch failure
return; return;
PParsedFile file = mIncludes.back(); PParsedFile file = mIncludes.back();
@ -902,6 +903,17 @@ void CppPreprocessor::closeInclude()
.arg(parsedFile->index+1)); .arg(parsedFile->index+1));
} }
CppPreprocessor::BranchResult CppPreprocessor::calcElseBranchResult(BranchResult oldResult)
{
switch(oldResult) {
case BranchResult::isTrue: return BranchResult::isFalse_but_trued;
case BranchResult::isFalse: return BranchResult::isTrue;
case BranchResult::isFalse_but_trued: return BranchResult::isFalse_but_trued;
case BranchResult::parentIsFalse: return BranchResult::parentIsFalse;
}
Q_ASSERT( false ); //We should fail here.
}
void CppPreprocessor::addDefinesInFile(const QString &fileName) void CppPreprocessor::addDefinesInFile(const QString &fileName)
{ {
if (mProcessed.contains(fileName)) if (mProcessed.contains(fileName))
@ -1200,7 +1212,7 @@ void CppPreprocessor::skipToPreprocessor()
int bufferCount = mBuffer.count(); int bufferCount = mBuffer.count();
// Increment until a line begins with a # // Increment until a line begins with a #
while ((mIndex < bufferCount) && !mBuffer[mIndex].startsWith('#')) { while ((mIndex < bufferCount) && !mBuffer[mIndex].startsWith('#')) {
if (getCurrentBranch()) { // if not skipping, expand current macros if (getCurrentBranch()==BranchResult::isTrue) { // if not skipping, expand current macros
int startIndex = mIndex; int startIndex = mIndex;
QString expanded = expandMacros(); QString expanded = expandMacros();
mResult.append(expanded); mResult.append(expanded);

View File

@ -104,6 +104,14 @@ public:
static QList<PDefineArgToken> tokenizeValue(const QString& value); static QList<PDefineArgToken> tokenizeValue(const QString& value);
private: private:
enum class BranchResult {
isTrue, /* This branch is true */
isFalse_but_trued, /* This branch is false, but a previous branch is true */
isFalse, /* This branch and all previous branches is false */
parentIsFalse
};
void preprocessBuffer(); void preprocessBuffer();
void skipToEndOfPreprocessor(); void skipToEndOfPreprocessor();
void skipToPreprocessor(); void skipToPreprocessor();
@ -130,27 +138,32 @@ private:
void closeInclude(); void closeInclude();
// branch stuff // branch stuff
bool getCurrentBranch(){ BranchResult getCurrentBranch(){
if (!mBranchResults.isEmpty()) if (!mBranchResults.isEmpty())
return mBranchResults.last(); return mBranchResults.last();
else else
return true; return BranchResult::isTrue;
} }
void setCurrentBranch(bool value){ BranchResult calcElseBranchResult(BranchResult oldResult);
if (value!=getCurrentBranch()) { bool sameResultWithCurrentBranch(BranchResult value) {
mCurrentIncludes->branches.insert(mIndex+1,value); return (getCurrentBranch()==BranchResult::isTrue && value == BranchResult::isTrue)
|| (getCurrentBranch()!=BranchResult::isTrue && value != BranchResult::isTrue);
}
void setCurrentBranch(BranchResult value){
if (!sameResultWithCurrentBranch(value)) {
mCurrentIncludes->branches.insert(mIndex+1,value==BranchResult::isTrue);
} }
mBranchResults.append(value); mBranchResults.append(value);
} }
void removeCurrentBranch(){ void removeCurrentBranch(){
bool result = getCurrentBranch(); BranchResult value = getCurrentBranch();
if (mBranchResults.size()>0) { if (mBranchResults.size()>0) {
mBranchResults.pop_back(); mBranchResults.pop_back();
} }
if (getCurrentBranch()!=result) { if (!sameResultWithCurrentBranch(value)) {
mCurrentIncludes->branches.insert(mIndex,getCurrentBranch()); mCurrentIncludes->branches.insert(mIndex,getCurrentBranch()==BranchResult::isTrue);
}
} }
};
// include stuff // include stuff
PFileIncludes getFileIncludesEntry(const QString& fileName){ PFileIncludes getFileIncludesEntry(const QString& fileName){
return mIncludesList.value(fileName,PFileIncludes()); return mIncludesList.value(fileName,PFileIncludes());
@ -227,7 +240,6 @@ static bool isNumberChar(const QChar& ch);
int evaluateExpression(QString line); int evaluateExpression(QString line);
private: private:
//temporary data when preprocessing single file //temporary data when preprocessing single file
int mIndex; // points to current file buffer. int mIndex; // points to current file buffer.
QString mFileName; QString mFileName;
@ -236,7 +248,7 @@ private:
PFileIncludes mCurrentIncludes; PFileIncludes mCurrentIncludes;
int mPreProcIndex; int mPreProcIndex;
QList<PParsedFile> mIncludes; // stack of files we've stepped into. last one is current file, first one is source file QList<PParsedFile> mIncludes; // stack of files we've stepped into. last one is current file, first one is source file
QList<bool> mBranchResults;// stack of branch results (boolean). last one is current branch, first one is outermost branch QList<BranchResult> mBranchResults;// stack of branch results (boolean). last one is current branch, first one is outermost branch
DefineMap mDefines; // working set, editable DefineMap mDefines; // working set, editable
QSet<QString> mProcessed; // dictionary to save filename already processed QSet<QString> mProcessed; // dictionary to save filename already processed

View File

@ -206,7 +206,7 @@ struct Statement {
// definiton line/filename is valid // definiton line/filename is valid
bool hasDefinition() { bool hasDefinition() {
return properties.testFlag(StatementProperty::spHasDefinition); return properties.testFlag(StatementProperty::spHasDefinition);
}; }
void setHasDefinition(bool on) { void setHasDefinition(bool on) {
properties.setFlag(StatementProperty::spHasDefinition,on); properties.setFlag(StatementProperty::spHasDefinition,on);
} }
@ -220,7 +220,7 @@ struct Statement {
// statement in system header (#include <>) // statement in system header (#include <>)
bool inSystemHeader() { bool inSystemHeader() {
return properties.testFlag(StatementProperty::spInSystemHeader); return properties.testFlag(StatementProperty::spInSystemHeader);
}; }
void setInSystemHeader(bool on) { void setInSystemHeader(bool on) {
properties.setFlag(StatementProperty::spInSystemHeader, on); properties.setFlag(StatementProperty::spInSystemHeader, on);
} }
@ -232,7 +232,7 @@ struct Statement {
} }
bool isInherited() { bool isInherited() {
return properties.testFlag(StatementProperty::spInherited); return properties.testFlag(StatementProperty::spInherited);
}; // inherted member; } // inherted member;
}; };

View File

@ -439,13 +439,11 @@ PStatement ClassBrowserModel::createDummy(const PStatement& statement)
ClassBrowserNode* ClassBrowserModel::getParentNode(const PStatement &parentStatement, int depth) ClassBrowserNode* ClassBrowserModel::getParentNode(const PStatement &parentStatement, int depth)
{ {
if (depth>10) Q_ASSERT(depth<=10);
return nullptr; if (depth>10) return mRoot;
if (!parentStatement) if (!parentStatement) return mRoot;
return mRoot; if (!isScopeStatement(parentStatement)) return mRoot;
if (!isScopeStatement(parentStatement)) {
return mRoot;
}
PClassBrowserNode parentNode = mScopeNodes.value(parentStatement->fullName,PClassBrowserNode()); PClassBrowserNode parentNode = mScopeNodes.value(parentStatement->fullName,PClassBrowserNode());
if (!parentNode) { if (!parentNode) {
PStatement dummyParent = createDummy(parentStatement); PStatement dummyParent = createDummy(parentStatement);