2017-07-18 3 views
4

私はDelphi 10 SeattleからDelphi 10.2 Tokyoにコードをアップグレードしており、多くのH2077ヒントを割り当て中です。割り当てについてはValue assigned to ... never usedです。
(これは過去に明示的に追加された場所であっても、「値がありません」という警告が表示されなくても)です。関数の初期化コードがシアトルから東京に変更されましたか?

これらのように初期化され、すべての機能をされています

Result := 0; 
... 

または:

Result := ftType1; // where ftType1 is an enumerated type 
... 

は、コンパイラは関数の最初の戻り値に関するこれらのか何かが変わったの検出に賢く取得しましたか?

私たちは常にこれらのヒントを「オン」にしていましたが、私は常にビルドします(コンパイルしないでください)。シアトル、
でヒントなしで構築しますが、東京での最初のResult := 0行にヒントを与えるH2077 Value assigned to 'GetDatabaseDialect' not used

例function(1)。列挙型でケースを例示東京用に最適化されていないようですサードパーティのライブラリーから

function GetDatabaseDialect(DBName, User, Pswd: string) : integer; 
var 
    status: array[1..19] of longint; 
    szDbName, szDbParam: PANSIChar; 
    dbHandle : pointer; 
    rslt: longint; 

    lDPBBuffer : ANSIString; 
    lDPBLength : integer; 

    cItem: ANSIChar; 
    szRslt: PANSIChar;  //array[0..IBResultBufferSize-1] of ANSIChar; 
begin 
    Result := 0; 
    dbHandle := nil; 
    // init database parameter block with version number 
    lDPBBuffer := ''; 
    SetLength(lDPBBuffer, 1); 
    lDPBBuffer[1] := ANSIChar(isc_dpb_version1); 
    lDPBLength := 1; 

    // fill Database Parameter Buffer with user name/password 
    lDPBBuffer := lDPBBuffer + 
      ANSIChar(isc_dpb_user_name) + 
      ANSIChar(Length(User)) + 
      ANSIString(User); 
    Inc(lDPBLength, 2 + Length(User)); 

    lDPBBuffer := lDPBBuffer + 
      ANSIChar(isc_dpb_password) + 
      ANSIChar(Length(Pswd)) + 
      ANSIString(Pswd); 
    Inc(lDPBLength, 2 + Length(Pswd)); 

    //Pointers naar naam + buffer 
    szDbName := PANSIChar(ANSISTring(DBName)); 
    szDbParam := PANSIChar(lDPBBuffer); 

    // attach to the database and set dialect 
    rslt := isc_attach_database(@status, 0, szDbName, @dbHandle, lDPBLength, szDbParam); 
    if rslt <> 0 then 
     raise EDatabaseError.Create('Error attaching database! ISC# ' + IntToStr(rslt)); 

    //Haal sql dialect op 
    szRslt := AllocMem(1000); 
    try 
     FillChar(szRslt^, 1000, 0); 
     cItem := ANSIChar(isc_info_db_SQL_dialect); 
     rslt := isc_database_info(@status, @DBHandle, 1, @cItem, 1000, szRslt); 
     if rslt <> 0 then 
     raise EDatabaseError.Create('Error retrieving database info ! ISC# ' + IntToStr(rslt)); 


     Result := Ord(szRslt[3]); //3e positie is dialect 
    finally 
     FreeMem(szRslt); 
    end; 

    // Drop the connection to the database 
    rslt := isc_detach_database(@status, @dbHandle); 
    if rslt <> 0 then 
     raise EDatabaseError.Create('Error detaching database! ISC# ' + IntToStr(rslt)); 
end; 

例(2)、
Result := ftASCII;への割り当てを変更することはないことを
H2077 Value assigned to 'TppTemplate.StreamType' not used
注意ヒントが消えてしまいます(最初のの列挙値に関連付けられていたという私の前提が間違っていました)。

type TppFormatType = (ftBinary, ftASCII); 

function TppTemplate.StreamType(aStream: TStream): TppFormatType; 
var 
    lSavePos: Integer; 
begin 
    {save stream position} 
    lSavePos := aStream.Position; 
    Result := ftBinary; 

    try 
    ComputeOffsetFromStream(aStream); 

    aStream.Seek(FOffset, soBeginning); 

    if IsValidASCIISignature(aStream) then 
     Result := ftASCII 

    else if IsValidBinarySignature(aStream) then 
     Result := ftBinary 

    else 
     raise EInvalidTemplateError.Create(ppLoadStr(49)); 

    finally 
    {restore stream position} 
    aStream.Seek(lSavePos, soBeginning); 
    end; 
end; {function, StreamType} 

共通の分母は、try/finallyブロックにある結果の割り当てのようです。

+0

FWIWは、よりスマートなコンパイラであり、変更された関数の初期化コードではありません。 –

+2

コンパイラが、変数または結果がすべてのコードパスに設定されていることを正しく認識しなかったケースがありました。今では、以前に割り当てられた値がもう必要でないことを認識しています。 –

+0

@David、ええとあなたは両方のバージョンでそのMCVEをビルドし、そうだと言っているのですが、違いはありますが、他のものはヒントを生成しますが、なぜか分かりません。これは、EMBTがバグ報告に応答すべきものです。 – Victoria

答えて

6

シナリオの最小限の再生にこのコードを考えてみましょう: 'に割り当てられH2077値:

[DCC32ヒント]:

function Bar: Boolean; 
begin 
    Result := Random<0.5; 
end; 

function Foo: Integer; 
begin 
    Result := 0; 
    if Bar then 
    Result := 1 
    else 
    raise Exception.Create(''); 
end; 

コンパイラ、さらに古いバージョンで、次のヒントを発しますFoo 'は決して使用されない

これは合理的です。 Resultへの最初の割り当ては意味がなく、削除することができます。

は今、この変化を考慮していない:コンパイラの

function Foo: Integer; 
begin 
    Result := 0; 
    try 
    if Bar then 
     Result := 1 
    else 
     raise Exception.Create(''); 
    finally 
    end; 
end; 

古いバージョンでは、もはやヒントを発するが、コンパイラの最新バージョンがありません。古いバージョンの場合、これはコンパイラーの欠陥とみなされます。上に示したFooの2つの変種は、意味的に同一です。コンパイラは、同一のコードを生成することを正当化される。

あなたが推測しているように、try/finallyブロック内の割り当ては、以前のバージョンの不具合を引き起こすために必要です。

エンバカデロの開発者は東京に不具合を修正したと結論づけられます。偽の初期割り当てを削除することによって、ヒントを解決できます。

もちろん、古いバージョンのコンパイラでも新しいバージョンでもコードをコンパイルする場合は、バインドされています。現在のコードでは、新しいバージョンのコンパイラによってヒントが生成されます。初期割り当てを削除し、古いバージョンのコンパイラによってヒントが生成されます。

+0

私は単に、この特定のヒントをオフに切り替える(これは可能ですか?)古いバージョンでは可能ですか?最新のバージョンでヒントなしでコンパイルすると、最新のものがない限り、以前のバージョンのヒントは無視されます。 –

+0

@RudyVelthuis個々の警告を抑制することができますが、ヒントはすべてまたは何もありません。 –

+0

ここに何か不足していますか?列挙型の2番目の例では、初期化が 'Result:= ftAscii;'であったとします。今私はコンパイラのヒントを取得し、その行を削除します。 ComputeOffsetFromStreamで例外が発生した場合はどうなりますか?実行はfinallyにジャンプし、Resultは未定義になります。 **しかし、コンパイラは私に警告していません**過去と同じように。私はそれが改善されているかどうかはわかりません... –

関連する問題