- 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
- 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: Processing for #if/#elif/#else is not correct.
Red Panda C++ Version 2.24

View File

@ -347,12 +347,12 @@ void CppPreprocessor::handleBranch(const QString &line)
// return;
// }
// }
if (!getCurrentBranch()) {
setCurrentBranch(false);
if (getCurrentBranch()!=BranchResult::isTrue) {
setCurrentBranch(BranchResult::parentIsFalse);
} else {
constexpr int IFDEF_LEN = 5; //length of ifdef;
QString name = line.mid(IFDEF_LEN).trimmed();
setCurrentBranch( getDefine(name)!=nullptr );
setCurrentBranch( getDefine(name)!=nullptr?(BranchResult::isTrue):(BranchResult::isFalse) );
}
} else if (line.startsWith("ifndef")) {
@ -363,12 +363,12 @@ void CppPreprocessor::handleBranch(const QString &line)
// return;
// }
// }
if (!getCurrentBranch()) {
setCurrentBranch(false);
if (getCurrentBranch()!=BranchResult::isTrue) {
setCurrentBranch(BranchResult::parentIsFalse);
} else {
constexpr int IFNDEF_LEN = 6; //length of ifndef;
QString name = line.mid(IFNDEF_LEN).trimmed();
setCurrentBranch( getDefine(name)==nullptr );
setCurrentBranch( getDefine(name)==nullptr?(BranchResult::isTrue):(BranchResult::isFalse) );
}
} else if (line.startsWith("if")) {
// // 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;
// }
// }
if (!getCurrentBranch()) {// we are already inside an if that is NOT being taken
setCurrentBranch(false);// so don't take this one either
if (getCurrentBranch()!=BranchResult::isTrue) {// we are already inside an if that is NOT being taken
setCurrentBranch(BranchResult::parentIsFalse);// so don't take this one either
} else {
constexpr int IF_LEN = 2; //length of if;
QString ifLine = line.mid(IF_LEN).trimmed();
bool testResult = evaluateIf(ifLine);
setCurrentBranch(testResult);
setCurrentBranch(testResult?(BranchResult::isTrue):(BranchResult::isFalse));
}
} else if (line.startsWith("else")) {
bool oldResult = getCurrentBranch(); // take either if or else
BranchResult oldResult = getCurrentBranch(); // take either if or else
removeCurrentBranch();
setCurrentBranch(!oldResult);
setCurrentBranch(calcElseBranchResult(oldResult));
} else if (line.startsWith("elif")) {
bool oldResult = getCurrentBranch(); // take either if or else
BranchResult oldResult = getCurrentBranch(); // take either if or else
removeCurrentBranch();
if (oldResult) { // don't take this one, if previous has been taken
setCurrentBranch(false);
} else {
BranchResult elseResult = calcElseBranchResult(oldResult);
if (elseResult == BranchResult::isTrue) { // don't take this one, if previous has been taken
constexpr int ELIF_LEN = 4; //length of if;
QString ifLine = line.mid(ELIF_LEN).trimmed();
bool testResult = evaluateIf(ifLine);
setCurrentBranch(testResult);
setCurrentBranch(testResult?(BranchResult::isTrue):(BranchResult::isFalse));
} else {
setCurrentBranch(elseResult);
}
} else if (line.startsWith("endif")) {
removeCurrentBranch();
@ -409,7 +410,7 @@ void CppPreprocessor::handleBranch(const QString &line)
void CppPreprocessor::handleDefine(const QString &line)
{
if (getCurrentBranch()) {
if (getCurrentBranch() == BranchResult::isTrue) {
addDefineByLine(line, false);
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)
{
if (!getCurrentBranch()) // we're skipping due to a branch failure
if (getCurrentBranch()!=BranchResult::isTrue) // we're skipping due to a branch failure
return;
PParsedFile file = mIncludes.back();
@ -902,6 +903,17 @@ void CppPreprocessor::closeInclude()
.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)
{
if (mProcessed.contains(fileName))
@ -1200,7 +1212,7 @@ void CppPreprocessor::skipToPreprocessor()
int bufferCount = mBuffer.count();
// Increment until a line begins with a #
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;
QString expanded = expandMacros();
mResult.append(expanded);

View File

@ -104,6 +104,14 @@ public:
static QList<PDefineArgToken> tokenizeValue(const QString& value);
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 skipToEndOfPreprocessor();
void skipToPreprocessor();
@ -130,27 +138,32 @@ private:
void closeInclude();
// branch stuff
bool getCurrentBranch(){
BranchResult getCurrentBranch(){
if (!mBranchResults.isEmpty())
return mBranchResults.last();
else
return true;
return BranchResult::isTrue;
}
void setCurrentBranch(bool value){
if (value!=getCurrentBranch()) {
mCurrentIncludes->branches.insert(mIndex+1,value);
BranchResult calcElseBranchResult(BranchResult oldResult);
bool sameResultWithCurrentBranch(BranchResult 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);
}
void removeCurrentBranch(){
bool result = getCurrentBranch();
BranchResult value = getCurrentBranch();
if (mBranchResults.size()>0) {
mBranchResults.pop_back();
}
if (getCurrentBranch()!=result) {
mCurrentIncludes->branches.insert(mIndex,getCurrentBranch());
if (!sameResultWithCurrentBranch(value)) {
mCurrentIncludes->branches.insert(mIndex,getCurrentBranch()==BranchResult::isTrue);
}
}
};
// include stuff
PFileIncludes getFileIncludesEntry(const QString& fileName){
return mIncludesList.value(fileName,PFileIncludes());
@ -227,7 +240,6 @@ static bool isNumberChar(const QChar& ch);
int evaluateExpression(QString line);
private:
//temporary data when preprocessing single file
int mIndex; // points to current file buffer.
QString mFileName;
@ -236,7 +248,7 @@ private:
PFileIncludes mCurrentIncludes;
int mPreProcIndex;
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
QSet<QString> mProcessed; // dictionary to save filename already processed

View File

@ -206,7 +206,7 @@ struct Statement {
// definiton line/filename is valid
bool hasDefinition() {
return properties.testFlag(StatementProperty::spHasDefinition);
};
}
void setHasDefinition(bool on) {
properties.setFlag(StatementProperty::spHasDefinition,on);
}
@ -220,7 +220,7 @@ struct Statement {
// statement in system header (#include <>)
bool inSystemHeader() {
return properties.testFlag(StatementProperty::spInSystemHeader);
};
}
void setInSystemHeader(bool on) {
properties.setFlag(StatementProperty::spInSystemHeader, on);
}
@ -232,7 +232,7 @@ struct Statement {
}
bool isInherited() {
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)
{
if (depth>10)
return nullptr;
if (!parentStatement)
return mRoot;
if (!isScopeStatement(parentStatement)) {
return mRoot;
}
Q_ASSERT(depth<=10);
if (depth>10) return mRoot;
if (!parentStatement) return mRoot;
if (!isScopeStatement(parentStatement)) return mRoot;
PClassBrowserNode parentNode = mScopeNodes.value(parentStatement->fullName,PClassBrowserNode());
if (!parentNode) {
PStatement dummyParent = createDummy(parentStatement);