- fix: Processing for #if/#elif/#else is not correct.
This commit is contained in:
parent
02a0ed049b
commit
14ba74e705
1
NEWS.md
1
NEWS.md
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue