IDE: fpc msg parser: darwin linker reference error

git-svn-id: trunk@45383 -
This commit is contained in:
mattias 2014-06-07 19:37:21 +00:00
parent 3fb55d6ed6
commit b0b5163778
4 changed files with 175 additions and 89 deletions

View File

@ -68,7 +68,7 @@ type
TOnFindDefineProperty = procedure(Sender: TObject; TOnFindDefineProperty = procedure(Sender: TObject;
const PersistentClassName, AncestorClassName, Identifier: string; const PersistentClassName, AncestorClassName, Identifier: string;
var IsDefined: boolean) of object; var IsDefined: boolean) of object;
TOnFindGDBSource = procedure(Sender: TObject; SrcType: TCodeTreeNodeDesc; TOnFindFPCMangledSource = procedure(Sender: TObject; SrcType: TCodeTreeNodeDesc;
const SrcName: string; out SrcFilename: string) of object; const SrcName: string; out SrcFilename: string) of object;
ECodeToolManagerError = class(Exception); ECodeToolManagerError = class(Exception);
@ -109,6 +109,7 @@ type
FOnAfterApplyChanges: TOnAfterApplyCTChanges; FOnAfterApplyChanges: TOnAfterApplyCTChanges;
FOnBeforeApplyChanges: TOnBeforeApplyCTChanges; FOnBeforeApplyChanges: TOnBeforeApplyCTChanges;
FOnCheckAbort: TOnCodeToolCheckAbort; FOnCheckAbort: TOnCodeToolCheckAbort;
FOnFindFPCMangledSource: TOnFindFPCMangledSource;
FOnGatherExternalChanges: TOnGatherExternalChanges; FOnGatherExternalChanges: TOnGatherExternalChanges;
FOnFindDefinePropertyForContext: TOnFindDefinePropertyForContext; FOnFindDefinePropertyForContext: TOnFindDefinePropertyForContext;
FOnFindDefineProperty: TOnFindDefineProperty; FOnFindDefineProperty: TOnFindDefineProperty;
@ -832,10 +833,12 @@ type
out NewX, NewY, NewTopLine: integer): boolean; out NewX, NewY, NewTopLine: integer): boolean;
// gdb stacktraces // gdb stacktraces
function FindGBDIdentifier(GDBIdentifier: string; out aComplete: boolean; function FindFPCMangledIdentifier(GDBIdentifier: string; out aComplete: boolean;
out aMessage: string; const OnFindSource: TOnFindGDBSource; out aMessage: string; const OnFindSource: TOnFindFPCMangledSource;
out NewCode: TCodeBuffer; out NewCode: TCodeBuffer;
out NewX, NewY, NewTopLine: integer): boolean; out NewX, NewY, NewTopLine: integer): boolean;
property OnFindFPCMangledSource: TOnFindFPCMangledSource
read FOnFindFPCMangledSource write FOnFindFPCMangledSource;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -3830,9 +3833,9 @@ begin
end; end;
end; end;
function TCodeToolManager.FindGBDIdentifier(GDBIdentifier: string; out function TCodeToolManager.FindFPCMangledIdentifier(GDBIdentifier: string; out
aComplete: boolean; out aMessage: string; aComplete: boolean; out aMessage: string;
const OnFindSource: TOnFindGDBSource; out NewCode: TCodeBuffer; out NewX, const OnFindSource: TOnFindFPCMangledSource; out NewCode: TCodeBuffer; out NewX,
NewY, NewTopLine: integer): boolean; NewY, NewTopLine: integer): boolean;
{ Examples: { Examples:
compiler built-in compiler built-in
@ -3904,6 +3907,9 @@ var
if Assigned(OnFindSource) then begin if Assigned(OnFindSource) then begin
OnFindSource(Self,ctnUnit,TheUnitName,aFilename); OnFindSource(Self,ctnUnit,TheUnitName,aFilename);
Result:=aFilename<>''; Result:=aFilename<>'';
end else if Assigned(OnFindFPCMangledSource) then begin
OnFindFPCMangledSource(Self,ctnUnit,TheUnitName,aFilename);
Result:=aFilename<>'';
end; end;
end; end;
@ -4066,12 +4072,13 @@ begin
end; end;
// unknown operator => use only SrcFilename // unknown operator => use only SrcFilename
//debugln(['TCodeToolManager.FindGBDIdentifier operator not yet supported: ',dbgstr(p^)]); //debugln(['TCodeToolManager.FindGBDIdentifier operator not yet supported: ',dbgstr(p^)]);
aMessage:='operator not supported: '+dbgstr(p^);
exit; exit;
end else begin end else begin
// example: ?? // example: ??
end; end;
aMessage:='unkown identifier "'+GDBIdentifier+'"'; aMessage:='unknown identifier "'+GDBIdentifier+'"';
end; end;
function TCodeToolManager.CompleteCode(Code: TCodeBuffer; X,Y,TopLine: integer; function TCodeToolManager.CompleteCode(Code: TCodeBuffer; X,Y,TopLine: integer;

View File

@ -112,8 +112,6 @@ type
function TrcNumberAfter(var Num: Int64; const AfterSub: string): Boolean; function TrcNumberAfter(var Num: Int64; const AfterSub: string): Boolean;
function TrcNumberAfter(var Num: Integer; const AfterSub: string): Boolean; function TrcNumberAfter(var Num: Integer; const AfterSub: string): Boolean;
function TrcNumFirstAndAfter(var FirstNum, AfterNum: Int64; const AfterSub: string): Boolean; function TrcNumFirstAndAfter(var FirstNum, AfterNum: Int64; const AfterSub: string): Boolean;
procedure OnFindCTSource(Sender: TObject; SrcType: TCodeTreeNodeDesc;
const SrcName: string; out SrcFilename: string);
procedure ParseTraceLine(s: string; var line: TStackLine); procedure ParseTraceLine(s: string; var line: TStackLine);
procedure ParseStackTrace(trace: TStackTrace); procedure ParseStackTrace(trace: TStackTrace);
@ -268,57 +266,6 @@ end;
{ THeapTrcInfo } { THeapTrcInfo }
procedure THeapTrcInfo.OnFindCTSource(Sender: TObject;
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
var
aProject: TLazProject;
i: Integer;
SrcEdit: TSourceEditorInterface;
Code: TCodeBuffer;
Tool: TCodeTool;
begin
case SrcType of
ctnProgram:
begin
// check active project
aProject:=LazarusIDE.ActiveProject;
if (aProject<>nil) and (aProject.MainFile<>nil) then begin
SrcFilename:=aProject.MainFile.Filename;
if FilenameIsAbsolute(SrcFilename)
and ((SrcName='')
or (SysUtils.CompareText(ExtractFileNameOnly(SrcFilename),SrcName)=0))
then
exit; // found
end;
end;
end;
// search in source editor
for i:=0 to SourceEditorManagerIntf.SourceEditorCount-1 do begin
SrcEdit:=SourceEditorManagerIntf.SourceEditors[i];
SrcFilename:=SrcEdit.FileName;
if CompareText(ExtractFileNameOnly(SrcFileName),SrcName)<>0 then
continue;
case SrcType of
ctnUnit:
if not FilenameIsPascalUnit(SrcFileName) then
continue;
else
// a pascal program can have any file name
// but we don't want to open program.res or program.txt
// => check if source is Pascal
// => load source and check if codetools can parse at least one node
Code:=CodeToolBoss.LoadFile(SrcFilename,true,false);
if Code=nil then continue;
CodeToolBoss.Explore(Code,Tool,false,true);
if (Tool=nil) or (Tool.Tree.Root=nil) then
continue;
end;
exit; // found
end;
// not found
SrcFilename:='';
end;
function THeapTrcInfo.PosInTrc(const SubStr: string; CaseSensetive: Boolean): Boolean; function THeapTrcInfo.PosInTrc(const SubStr: string; CaseSensetive: Boolean): Boolean;
begin begin
Result := TrcIndex<Trc.Count; Result := TrcIndex<Trc.Count;
@ -549,7 +496,7 @@ procedure THeapTrcInfo.ParseTraceLine(s: string; var line: TStackLine);
while (i<=length(s)) and (s[i] in ['a'..'z','A'..'Z','0'..'9','_','$','?']) do while (i<=length(s)) and (s[i] in ['a'..'z','A'..'Z','0'..'9','_','$','?']) do
inc(i); inc(i);
GDBIdentifier:=copy(s,1,i-1); GDBIdentifier:=copy(s,1,i-1);
CodeToolBoss.FindGBDIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource, CodeToolBoss.FindFPCMangledIdentifier(GDBIdentifier,Complete,TheErrorMsg,nil,
SrcCode,SrcX,SrcY,SrcTopLine); SrcCode,SrcX,SrcY,SrcTopLine);
if SrcCode<>nil then begin if SrcCode<>nil then begin
line.FileName:=SrcCode.Filename; line.FileName:=SrcCode.Filename;
@ -635,7 +582,7 @@ begin
while (i<=length(s)) and (s[i] in ['a'..'z','A'..'Z','0'..'9','_','$','?']) do while (i<=length(s)) and (s[i] in ['a'..'z','A'..'Z','0'..'9','_','$','?']) do
inc(i); inc(i);
GDBIdentifier:=copy(s,1,i-1); GDBIdentifier:=copy(s,1,i-1);
CodeToolBoss.FindGBDIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource, CodeToolBoss.FindFPCMangledIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource,
SrcCode,SrcX,SrcY,SrcTopLine); SrcCode,SrcX,SrcY,SrcTopLine);
if SrcCode<>nil then begin if SrcCode<>nil then begin
line.FileName:=SrcCode.Filename; line.FileName:=SrcCode.Filename;

View File

@ -147,6 +147,8 @@ type
fFileExists: TFilenameToPointerTree; fFileExists: TFilenameToPointerTree;
fIncludePath: string; // only valid if fIncludePathValidForWorkerDir=Tool.WorkerDirectory fIncludePath: string; // only valid if fIncludePathValidForWorkerDir=Tool.WorkerDirectory
fIncludePathValidForWorkerDir: string; fIncludePathValidForWorkerDir: string;
fUnitPath: string; // only valid if fUnitPathValidForWorkerDir=Tool.WorkerDirectory
fUnitPathValidForWorkerDir: string;
fLastWorkerImprovedMessage: array[TExtToolParserSyncPhase] of integer; fLastWorkerImprovedMessage: array[TExtToolParserSyncPhase] of integer;
fLineToMsgID: TPatternToMsgIDs; fLineToMsgID: TPatternToMsgIDs;
fMissingFPCMsgItem: TFPCMsgItem; fMissingFPCMsgItem: TFPCMsgItem;
@ -160,6 +162,8 @@ type
fMsgItemThereWereErrorsCompiling: TFPCMsgItem; fMsgItemThereWereErrorsCompiling: TFPCMsgItem;
fMsgItemUnitNotUsed: TFPCMsgItem; fMsgItemUnitNotUsed: TFPCMsgItem;
fOutputIndex: integer; // current OutputIndex given by ReadLine fOutputIndex: integer; // current OutputIndex given by ReadLine
procedure FetchIncludePath(aPhase: TExtToolParserSyncPhase; MsgWorkerDir: String);
procedure FetchUnitPath(aPhase: TExtToolParserSyncPhase; MsgWorkerDir: String);
function FileExists(const Filename: string; aSynchronized: boolean): boolean; function FileExists(const Filename: string; aSynchronized: boolean): boolean;
function CheckForMsgId(p: PChar): boolean; // (MsgId) message function CheckForMsgId(p: PChar): boolean; // (MsgId) message
function CheckForFileLineColMessage(p: PChar): boolean; // the normal messages: filename(y,x): Hint: .. function CheckForFileLineColMessage(p: PChar): boolean; // the normal messages: filename(y,x): Hint: ..
@ -465,15 +469,21 @@ function GetFPCMsgValue1(const Src, Pattern: string; out Value1: string
} }
var var
p: SizeInt; p: SizeInt;
l: SizeInt;
begin begin
Value1:='';
Result:=false;
if length(Src)<length(Pattern)-2 then exit;
p:=Pos('$1',Pattern); p:=Pos('$1',Pattern);
if p<1 then begin if p<1 then exit;
Result:=false; // check start pattern
Value1:=''; if (p>1) and (not CompareMem(Pointer(Src),Pointer(Pattern),p-1)) then exit;
end else begin // check end pattern
Value1:=copy(Src,p,length(Src)-length(Pattern)+2); l:=length(Pattern)-p-2;
Result:=true; if (l>0)
end; and (not CompareMem(Pointer(Src)+length(Src)-l,Pointer(Pattern)+p+2,l)) then exit;
Value1:=copy(Src,p,length(Src)-length(Pattern)+2);
Result:=true;
end; end;
function GetFPCMsgValues(Src, Pattern: string; out Value1, Value2: string function GetFPCMsgValues(Src, Pattern: string; out Value1, Value2: string
@ -1083,6 +1093,10 @@ begin
fIncludePathValidForWorkerDir:=Tool.WorkerDirectory; fIncludePathValidForWorkerDir:=Tool.WorkerDirectory;
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory( fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
ChompPathDelim(fIncludePathValidForWorkerDir)); ChompPathDelim(fIncludePathValidForWorkerDir));
// get include search path
fUnitPathValidForWorkerDir:=Tool.WorkerDirectory;
fUnitPath:=CodeToolBoss.GetUnitPathForDirectory(
ChompPathDelim(fUnitPathValidForWorkerDir));
end; end;
procedure TIDEFPCParser.InitReading; procedure TIDEFPCParser.InitReading;
@ -1883,7 +1897,7 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
/path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA' /path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA'
} }
function CheckForLDFileAndLineNumber: boolean; function CheckForLinuxLDFileAndLineNumber: boolean;
var var
p: PChar; p: PChar;
Msg: String; Msg: String;
@ -1925,16 +1939,52 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
Result:=true; Result:=true;
MsgLine.Msg:=copy(Msg,p-PChar(Msg)+1,length(Msg)); MsgLine.Msg:=copy(Msg,p-PChar(Msg)+1,length(Msg));
MsgLine.Filename:=aFilename; MsgLine.SetSourcePosition(aFilename,LineNumber,1);
MsgLine.Line:=LineNumber; MsgLine.Urgency:=mluError;
MsgLine.Column:=1; end;
function CheckForDarwinLDReferencedFrom: boolean;
{ For example:
"_UNIT1_GIBTESNICHT", referenced from:
}
var
MangledName: string;
aComplete: boolean;
aErrorMsg: string;
NewCode: TCodeBuffer;
NewX: integer;
NewY: integer;
NewTopLine: integer;
begin
Result:=false;
if MsgLine.HasSourcePosition then exit;
// check for ' "_FPC-Mangled-Identifier", referenced from:
if not etFPCMsgParser.GetFPCMsgValue1(MsgLine.Msg,' "_$1", referenced from:',
MangledName)
then exit;
Result:=true;
case aPhase of
etpspAfterReadLine:
begin
NeedSynchronize:=true;
exit;
end;
etpspAfterSync: exit;
end;
// in main threads
CodeToolBoss.FindFPCMangledIdentifier(MangledName,aComplete,aErrorMsg,
nil,NewCode,NewX,NewY,NewTopLine);
if NewCode=nil then exit;
Result:=true;
MsgLine.SetSourcePosition(NewCode.Filename,NewY,NewX);
MsgLine.Urgency:=mluError; MsgLine.Urgency:=mluError;
end; end;
begin begin
if MsgLine.SubTool<>SubToolFPCLinker then exit; if MsgLine.SubTool<>SubToolFPCLinker then exit;
if CheckForLDFileAndLineNumber then exit; if CheckForLinuxLDFileAndLineNumber then exit;
if CheckForDarwinLDReferencedFrom then exit;
end; end;
procedure TIDEFPCParser.ImproveMsgIdentifierPosition( procedure TIDEFPCParser.ImproveMsgIdentifierPosition(
@ -2077,6 +2127,48 @@ begin
end; end;
end; end;
procedure TIDEFPCParser.FetchIncludePath(aPhase: TExtToolParserSyncPhase;
MsgWorkerDir: String);
begin
if MsgWorkerDir='' then
MsgWorkerDir:=Tool.WorkerDirectory;
if fIncludePathValidForWorkerDir<>MsgWorkerDir then begin
// fetch include path from IDE
case aPhase of
etpspAfterReadLine:
NeedSynchronize:=true;
etpspSynchronized:
begin
fIncludePathValidForWorkerDir:=MsgWorkerDir;
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
ChompPathDelim(MsgWorkerDir));
NeedAfterSync:=true;
end;
end;
end;
end;
procedure TIDEFPCParser.FetchUnitPath(aPhase: TExtToolParserSyncPhase;
MsgWorkerDir: String);
begin
if MsgWorkerDir='' then
MsgWorkerDir:=Tool.WorkerDirectory;
if fUnitPathValidForWorkerDir<>MsgWorkerDir then begin
// fetch unit path from IDE
case aPhase of
etpspAfterReadLine:
NeedSynchronize:=true;
etpspSynchronized:
begin
fUnitPathValidForWorkerDir:=MsgWorkerDir;
fUnitPath:=CodeToolBoss.GetUnitPathForDirectory(
ChompPathDelim(MsgWorkerDir));
NeedAfterSync:=true;
end;
end;
end;
end;
function TIDEFPCParser.CheckForMsgId(p: PChar): boolean; function TIDEFPCParser.CheckForMsgId(p: PChar): boolean;
var var
MsgItem: TFPCMsgItem; MsgItem: TFPCMsgItem;
@ -2426,20 +2518,7 @@ begin
if (not FilenameIsAbsolute(aFilename)) then begin if (not FilenameIsAbsolute(aFilename)) then begin
// short file name => 2. try include path // short file name => 2. try include path
MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory]; MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory];
if fIncludePathValidForWorkerDir<>MsgWorkerDir then begin FetchIncludePath(aPhase,MsgWorkerDir);
// fetch include path from IDE
case aPhase of
etpspAfterReadLine:
NeedSynchronize:=true;
etpspSynchronized:
begin
fIncludePathValidForWorkerDir:=MsgWorkerDir;
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
ChompPathDelim(MsgWorkerDir));
NeedAfterSync:=true;
end;
end;
end;
if (aPhase in [etpspAfterReadLine,etpspAfterSync]) if (aPhase in [etpspAfterReadLine,etpspAfterSync])
and (fIncludePathValidForWorkerDir=MsgWorkerDir) then begin and (fIncludePathValidForWorkerDir=MsgWorkerDir) then begin
// include path is valid and in worker thread // include path is valid and in worker thread

View File

@ -71,8 +71,8 @@ uses
HelpIntfs, Graphics, ExtCtrls, Dialogs, InterfaceBase, UTF8Process, LazLogger, HelpIntfs, Graphics, ExtCtrls, Dialogs, InterfaceBase, UTF8Process, LazLogger,
lazutf8classes, LazFileCache, lazutf8classes, LazFileCache,
// codetools // codetools
FileProcs, FindDeclarationTool, LinkScanner, BasicCodeTools, FileProcs, FindDeclarationTool, LinkScanner, BasicCodeTools, CodeToolsStructs,
CodeToolsStructs, CodeToolManager, CodeCache, DefineTemplates, KeywordFuncLists, CodeToolManager, CodeCache, DefineTemplates, KeywordFuncLists, CodeTree,
// synedit // synedit
AllSynEdit, SynEditKeyCmds, SynBeautifier, SynEditMarks, AllSynEdit, SynEditKeyCmds, SynBeautifier, SynEditMarks,
// IDE interface // IDE interface
@ -621,6 +621,9 @@ type
var CodeBuffers: TFPList; // stopping when CodeBuffers=nil var CodeBuffers: TFPList; // stopping when CodeBuffers=nil
var ExpandedFilenames: TStrings var ExpandedFilenames: TStrings
); );
procedure CodeToolBossFindFPCMangledSource(Sender: TObject;
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
function CTMacroFunctionProject(Data: Pointer): boolean; function CTMacroFunctionProject(Data: Pointer): boolean;
procedure OnCompilerParseStampIncreased; procedure OnCompilerParseStampIncreased;
procedure CodeToolBossScannerInit(Self: TCodeToolManager; procedure CodeToolBossScannerInit(Self: TCodeToolManager;
@ -1991,6 +1994,55 @@ begin
end; end;
end; end;
procedure TMainIDE.CodeToolBossFindFPCMangledSource(Sender: TObject;
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
var
i: Integer;
SrcEdit: TSourceEditorInterface;
Code: TCodeBuffer;
Tool: TCodeTool;
begin
case SrcType of
ctnProgram:
begin
// check active project
if (Project1<>nil) and (Project1.MainFile<>nil) then begin
SrcFilename:=Project1.MainFile.Filename;
if FilenameIsAbsolute(SrcFilename)
and ((SrcName='')
or (SysUtils.CompareText(ExtractFileNameOnly(SrcFilename),SrcName)=0))
then
exit; // found
end;
end;
end;
// search in source editor
for i:=0 to SourceEditorManagerIntf.SourceEditorCount-1 do begin
SrcEdit:=SourceEditorManagerIntf.SourceEditors[i];
SrcFilename:=SrcEdit.FileName;
if CompareText(ExtractFileNameOnly(SrcFileName),SrcName)<>0 then
continue;
case SrcType of
ctnUnit:
if not FilenameIsPascalUnit(SrcFileName) then
continue;
else
// a pascal program can have any file name
// but we don't want to open program.res or program.txt
// => check if source is Pascal
// => load source and check if codetools can parse at least one node
Code:=CodeToolBoss.LoadFile(SrcFilename,true,false);
if Code=nil then continue;
CodeToolBoss.Explore(Code,Tool,false,true);
if (Tool=nil) or (Tool.Tree.Root=nil) then
continue;
end;
exit; // found
end;
// not found
SrcFilename:='';
end;
{------------------------------------------------------------------------------} {------------------------------------------------------------------------------}
procedure TMainIDE.MainIDEFormClose(Sender: TObject; procedure TMainIDE.MainIDEFormClose(Sender: TObject;
var CloseAction: TCloseAction); var CloseAction: TCloseAction);
@ -9310,6 +9362,7 @@ begin
OnGetMethodName:=@OnCodeToolBossGetMethodName; OnGetMethodName:=@OnCodeToolBossGetMethodName;
OnGetIndenterExamples:=@OnCodeToolBossGetIndenterExamples; OnGetIndenterExamples:=@OnCodeToolBossGetIndenterExamples;
OnScannerInit:=@CodeToolBossScannerInit; OnScannerInit:=@CodeToolBossScannerInit;
OnFindFPCMangledSource:=@CodeToolBossFindFPCMangledSource;
end; end;
CodeToolsOpts.AssignGlobalDefineTemplatesToTree(CodeToolBoss.DefineTree); CodeToolsOpts.AssignGlobalDefineTemplatesToTree(CodeToolBoss.DefineTree);