BaseTools: resolve initialization order errors in VfrFormPkg.h

clang generates many warnings
warning: field 'XXX' is uninitialized when used here [-Wuninitialized]
for VfrFormPkg.h.

VfrFormPkg.h defines many classes derived from CIfrObj (along with other
base classes.)
Each of these derived classes defines a non-static member field that serves
as a duplicate pointer to an original pointer defined in the CIfrObj base
class, but cast to a different pointer type.
The derived class constructor passes the duplicate pointer to base class
constructors:
1) Once passes the address of the duplicate pointer to the CIfrObj
   constructor to have it initialized.
2) Then passes the duplicate pointer to one or more subsequent base class
   constructors to be used.
Both 1) and 2) constitute undefined behavior in C++.  C++ prescribes that
base classes are initialized before non-static members when initializing a
derived class.  So when base class constructors are executing, it is not
permitted to assume any non-static members of the derived class exist (even
to the stage of having their storage allocated.)

clang does not issue warnings for 1), but issues warnings -Wuninitialized
for 2).

This coding methodology is resolved as follows:
a) The CIfrObj object accessor method for retrieving the original pointer
   is revised to a template member function that returns the original
   pointer cast to a desired target type.
b) The call to CIfrObj constructor is no longer used to initialize the
   duplicate pointer in the derived class.
c) Any subsequent calls to a base class constructor that need to use the
   pointer, retrieve it from the CIfrObj base class using the template
   accessor method.
d) If the derived class makes no further use of the pointer, then the
   duplicate pointer defined in it is eliminated.
e) If the derived class needs the duplicate pointer for other use, the
   duplicate pointer remains in the derived class and is initialized in
   proper order from the original pointer in CIfrObj.
f) Existing source code that previously used the CIfrObj pointer accessor
   method is revised to use the template method.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Zenith432 <zenith432@users.sourceforge.net>
Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
zenith432 2017-12-06 16:46:37 +00:00 committed by Liming Gao
parent 4e97974c1e
commit 5397bd425e
3 changed files with 257 additions and 414 deletions

View File

@ -844,7 +844,7 @@ CFormPkg::DeclarePendingQuestion (
// DisableIf
CIfrDisableIf DIObj;
DIObj.SetLineNo (LineNo);
*InsertOpcodeAddr = DIObj.GetObjBinAddr ();
*InsertOpcodeAddr = DIObj.GetObjBinAddr<CHAR8>();
//TrueOpcode
CIfrTrue TObj (LineNo);
@ -1925,7 +1925,7 @@ CIfrRecordInfoDB::IfrCreateDefaultForQuestion (
Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE);
assert (Obj != NULL);
Obj->SetLineNo (pSNode->mLineNo);
ObjBinBuf = Obj->GetObjBinAddr();
ObjBinBuf = Obj->GetObjBinAddr<CHAR8>();
memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen);
delete Obj;
pSNode = pSNode->mNext;

File diff suppressed because it is too large Load Diff

View File

@ -986,7 +986,7 @@ vfrStatementDefaultStore :
<<
if (gCVfrDefaultStore.DefaultIdRegistered (DefaultId) == FALSE) {
CIfrDefaultStore DSObj;
_PCATCH(gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), N->getText(), _STOSID(S->getText(), S->getLine()), DefaultId)), D->getLine();
_PCATCH(gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr<CHAR8>(), N->getText(), _STOSID(S->getText(), S->getLine()), DefaultId)), D->getLine();
DSObj.SetLineNo(D->getLine());
DSObj.SetDefaultName (_STOSID(S->getText(), S->getLine()));
DSObj.SetDefaultId (DefaultId);
@ -1770,7 +1770,7 @@ vfrFormDefinition :
LObj3.SetNumber (0xffff); //add end label for UEFI, label number hardcode 0xffff
}
{CIfrEnd EObj; EObj.SetLineNo (E->getLine()); mLastFormEndAddr = EObj.GetObjBinAddr (); gAdjustOpcodeOffset = EObj.GetObjBinOffset ();}
{CIfrEnd EObj; EObj.SetLineNo (E->getLine()); mLastFormEndAddr = EObj.GetObjBinAddr<CHAR8>(); gAdjustOpcodeOffset = EObj.GetObjBinOffset ();}
>>
";"
;
@ -5675,7 +5675,7 @@ EfiVfrParser::_DeclareStandardDefaultStorage (
//
CIfrDefaultStore DSObj;
gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), (CHAR8 *) "Standard Defaults", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_STANDARD);
gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr<CHAR8>(), (CHAR8 *) "Standard Defaults", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_STANDARD);
DSObj.SetLineNo (LineNo);
DSObj.SetDefaultName (EFI_STRING_ID_INVALID);
DSObj.SetDefaultId (EFI_HII_DEFAULT_CLASS_STANDARD);
@ -5685,7 +5685,7 @@ EfiVfrParser::_DeclareStandardDefaultStorage (
//
CIfrDefaultStore DSObjMF;
gCVfrDefaultStore.RegisterDefaultStore (DSObjMF.GetObjBinAddr(), (CHAR8 *) "Standard ManuFacturing", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_MANUFACTURING);
gCVfrDefaultStore.RegisterDefaultStore (DSObjMF.GetObjBinAddr<CHAR8>(), (CHAR8 *) "Standard ManuFacturing", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_MANUFACTURING);
DSObjMF.SetLineNo (LineNo);
DSObjMF.SetDefaultName (EFI_STRING_ID_INVALID);
DSObjMF.SetDefaultId (EFI_HII_DEFAULT_CLASS_MANUFACTURING);