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;
const PersistentClassName, AncestorClassName, Identifier: string;
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;
ECodeToolManagerError = class(Exception);
@ -109,6 +109,7 @@ type
FOnAfterApplyChanges: TOnAfterApplyCTChanges;
FOnBeforeApplyChanges: TOnBeforeApplyCTChanges;
FOnCheckAbort: TOnCodeToolCheckAbort;
FOnFindFPCMangledSource: TOnFindFPCMangledSource;
FOnGatherExternalChanges: TOnGatherExternalChanges;
FOnFindDefinePropertyForContext: TOnFindDefinePropertyForContext;
FOnFindDefineProperty: TOnFindDefineProperty;
@ -832,10 +833,12 @@ type
out NewX, NewY, NewTopLine: integer): boolean;
// gdb stacktraces
function FindGBDIdentifier(GDBIdentifier: string; out aComplete: boolean;
out aMessage: string; const OnFindSource: TOnFindGDBSource;
function FindFPCMangledIdentifier(GDBIdentifier: string; out aComplete: boolean;
out aMessage: string; const OnFindSource: TOnFindFPCMangledSource;
out NewCode: TCodeBuffer;
out NewX, NewY, NewTopLine: integer): boolean;
property OnFindFPCMangledSource: TOnFindFPCMangledSource
read FOnFindFPCMangledSource write FOnFindFPCMangledSource;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -3830,9 +3833,9 @@ begin
end;
end;
function TCodeToolManager.FindGBDIdentifier(GDBIdentifier: string; out
function TCodeToolManager.FindFPCMangledIdentifier(GDBIdentifier: string; out
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;
{ Examples:
compiler built-in
@ -3904,6 +3907,9 @@ var
if Assigned(OnFindSource) then begin
OnFindSource(Self,ctnUnit,TheUnitName,aFilename);
Result:=aFilename<>'';
end else if Assigned(OnFindFPCMangledSource) then begin
OnFindFPCMangledSource(Self,ctnUnit,TheUnitName,aFilename);
Result:=aFilename<>'';
end;
end;
@ -4066,12 +4072,13 @@ begin
end;
// unknown operator => use only SrcFilename
//debugln(['TCodeToolManager.FindGBDIdentifier operator not yet supported: ',dbgstr(p^)]);
aMessage:='operator not supported: '+dbgstr(p^);
exit;
end else begin
// example: ??
end;
aMessage:='unkown identifier "'+GDBIdentifier+'"';
aMessage:='unknown identifier "'+GDBIdentifier+'"';
end;
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: Integer; 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 ParseStackTrace(trace: TStackTrace);
@ -268,57 +266,6 @@ end;
{ 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;
begin
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
inc(i);
GDBIdentifier:=copy(s,1,i-1);
CodeToolBoss.FindGBDIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource,
CodeToolBoss.FindFPCMangledIdentifier(GDBIdentifier,Complete,TheErrorMsg,nil,
SrcCode,SrcX,SrcY,SrcTopLine);
if SrcCode<>nil then begin
line.FileName:=SrcCode.Filename;
@ -635,7 +582,7 @@ begin
while (i<=length(s)) and (s[i] in ['a'..'z','A'..'Z','0'..'9','_','$','?']) do
inc(i);
GDBIdentifier:=copy(s,1,i-1);
CodeToolBoss.FindGBDIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource,
CodeToolBoss.FindFPCMangledIdentifier(GDBIdentifier,Complete,TheErrorMsg,@OnFindCTSource,
SrcCode,SrcX,SrcY,SrcTopLine);
if SrcCode<>nil then begin
line.FileName:=SrcCode.Filename;

View File

@ -147,6 +147,8 @@ type
fFileExists: TFilenameToPointerTree;
fIncludePath: string; // only valid if fIncludePathValidForWorkerDir=Tool.WorkerDirectory
fIncludePathValidForWorkerDir: string;
fUnitPath: string; // only valid if fUnitPathValidForWorkerDir=Tool.WorkerDirectory
fUnitPathValidForWorkerDir: string;
fLastWorkerImprovedMessage: array[TExtToolParserSyncPhase] of integer;
fLineToMsgID: TPatternToMsgIDs;
fMissingFPCMsgItem: TFPCMsgItem;
@ -160,6 +162,8 @@ type
fMsgItemThereWereErrorsCompiling: TFPCMsgItem;
fMsgItemUnitNotUsed: TFPCMsgItem;
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 CheckForMsgId(p: PChar): boolean; // (MsgId) message
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
p: SizeInt;
l: SizeInt;
begin
Value1:='';
Result:=false;
if length(Src)<length(Pattern)-2 then exit;
p:=Pos('$1',Pattern);
if p<1 then begin
Result:=false;
Value1:='';
end else begin
Value1:=copy(Src,p,length(Src)-length(Pattern)+2);
Result:=true;
end;
if p<1 then exit;
// check start pattern
if (p>1) and (not CompareMem(Pointer(Src),Pointer(Pattern),p-1)) then exit;
// check end pattern
l:=length(Pattern)-p-2;
if (l>0)
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;
function GetFPCMsgValues(Src, Pattern: string; out Value1, Value2: string
@ -1083,6 +1093,10 @@ begin
fIncludePathValidForWorkerDir:=Tool.WorkerDirectory;
fIncludePath:=CodeToolBoss.GetIncludePathForDirectory(
ChompPathDelim(fIncludePathValidForWorkerDir));
// get include search path
fUnitPathValidForWorkerDir:=Tool.WorkerDirectory;
fUnitPath:=CodeToolBoss.GetUnitPathForDirectory(
ChompPathDelim(fUnitPathValidForWorkerDir));
end;
procedure TIDEFPCParser.InitReading;
@ -1883,7 +1897,7 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
/path//blaunit.pas:45: undefined reference to `BLAUNIT_BLABLA'
}
function CheckForLDFileAndLineNumber: boolean;
function CheckForLinuxLDFileAndLineNumber: boolean;
var
p: PChar;
Msg: String;
@ -1925,16 +1939,52 @@ procedure TIDEFPCParser.ImproveMsgLinkerUndefinedReference(
Result:=true;
MsgLine.Msg:=copy(Msg,p-PChar(Msg)+1,length(Msg));
MsgLine.Filename:=aFilename;
MsgLine.Line:=LineNumber;
MsgLine.Column:=1;
MsgLine.SetSourcePosition(aFilename,LineNumber,1);
MsgLine.Urgency:=mluError;
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;
end;
begin
if MsgLine.SubTool<>SubToolFPCLinker then exit;
if CheckForLDFileAndLineNumber then exit;
if CheckForLinuxLDFileAndLineNumber then exit;
if CheckForDarwinLDReferencedFrom then exit;
end;
procedure TIDEFPCParser.ImproveMsgIdentifierPosition(
@ -2077,6 +2127,48 @@ begin
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;
var
MsgItem: TFPCMsgItem;
@ -2426,20 +2518,7 @@ begin
if (not FilenameIsAbsolute(aFilename)) then begin
// short file name => 2. try include path
MsgWorkerDir:=MsgLine.Attribute[FPCMsgAttrWorkerDirectory];
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;
FetchIncludePath(aPhase,MsgWorkerDir);
if (aPhase in [etpspAfterReadLine,etpspAfterSync])
and (fIncludePathValidForWorkerDir=MsgWorkerDir) then begin
// include path is valid and in worker thread

View File

@ -71,8 +71,8 @@ uses
HelpIntfs, Graphics, ExtCtrls, Dialogs, InterfaceBase, UTF8Process, LazLogger,
lazutf8classes, LazFileCache,
// codetools
FileProcs, FindDeclarationTool, LinkScanner, BasicCodeTools,
CodeToolsStructs, CodeToolManager, CodeCache, DefineTemplates, KeywordFuncLists,
FileProcs, FindDeclarationTool, LinkScanner, BasicCodeTools, CodeToolsStructs,
CodeToolManager, CodeCache, DefineTemplates, KeywordFuncLists, CodeTree,
// synedit
AllSynEdit, SynEditKeyCmds, SynBeautifier, SynEditMarks,
// IDE interface
@ -621,6 +621,9 @@ type
var CodeBuffers: TFPList; // stopping when CodeBuffers=nil
var ExpandedFilenames: TStrings
);
procedure CodeToolBossFindFPCMangledSource(Sender: TObject;
SrcType: TCodeTreeNodeDesc; const SrcName: string; out SrcFilename: string);
function CTMacroFunctionProject(Data: Pointer): boolean;
procedure OnCompilerParseStampIncreased;
procedure CodeToolBossScannerInit(Self: TCodeToolManager;
@ -1991,6 +1994,55 @@ begin
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;
var CloseAction: TCloseAction);
@ -9310,6 +9362,7 @@ begin
OnGetMethodName:=@OnCodeToolBossGetMethodName;
OnGetIndenterExamples:=@OnCodeToolBossGetIndenterExamples;
OnScannerInit:=@CodeToolBossScannerInit;
OnFindFPCMangledSource:=@CodeToolBossFindFPCMangledSource;
end;
CodeToolsOpts.AssignGlobalDefineTemplatesToTree(CodeToolBoss.DefineTree);